-
Notifications
You must be signed in to change notification settings - Fork 55
/
freedataset.py
184 lines (152 loc) · 6.71 KB
/
freedataset.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
"""
Defines the FreeformDataSet class and supporting classes and functions
"""
#***************************************************************************************************
# Copyright 2015, 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
# Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government retains certain rights
# in this software.
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
# in compliance with the License. You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0 or in the LICENSE file in the root pyGSTi directory.
#***************************************************************************************************
import copy as _copy
from collections import OrderedDict as _OrderedDict
from pygsti.circuits import circuit as _cir
from pygsti.tools import NamedDict as _NamedDict
class FreeformDataSet(object):
"""
An association between Circuits and arbitrary data.
Parameters
----------
circuits : list of (tuples or Circuits), optional
Each element is a tuple of operation labels or a Circuit object. Indices for these strings
are assumed to ascend from 0. These indices must correspond to the time series of spam-label
indices (above). Only specify this argument OR circuit_indices, not both.
circuit_indices : ordered dictionary, optional
An OrderedDict with keys equal to circuits (tuples of operation labels) and values equal to
integer indices associating a row/element of counts with the circuit. Only
specify this argument OR circuits, not both.
"""
def __init__(self, circuits=None, circuit_indices=None):
# uuid for efficient hashing (set when done adding data or loading from file)
self.uuid = None
# self.cirIndex : Ordered dictionary where keys = Circuit objects,
# values = slices into oli, time, & rep arrays (static case) or
# integer list indices (non-static case)
if circuit_indices is not None:
self.cirIndex = _OrderedDict([(opstr if isinstance(opstr, _cir.Circuit) else _cir.Circuit(opstr), i)
for opstr, i in circuit_indices.items()])
#convert keys to Circuits if necessary
else: # if not static:
if circuits is not None:
dictData = [(opstr if isinstance(opstr, _cir.Circuit) else _cir.Circuit(opstr), i)
for (i, opstr) in enumerate(circuits)] # convert to Circuits if necessary
self.cirIndex = _OrderedDict(dictData)
else:
self.cirIndex = _OrderedDict()
#FUTURE - make this more like DataSet and hold some/all columns more efficiently?
self._info = {i: {} for i in self.cirIndex.values()}
# comment
#self.comment = comment
def to_dataframe(self, pivot_valuename=None, pivot_value="Value", drop_columns=False):
"""
Create a Pandas dataframe with the data from this free-form dataset.
Parameters
----------
pivot_valuename : str, optional
If not None, the resulting dataframe is pivoted using `pivot_valuename`
as the column whose values name the pivoted table's column names.
If None and `pivot_value` is not None,`"ValueName"` is used.
pivot_value : str, optional
If not None, the resulting dataframe is pivoted such that values of
the `pivot_value` column are rearranged into new columns whose names
are given by the values of the `pivot_valuename` column. If None and
`pivot_valuename` is not None,`"Value"` is used.
drop_columns : bool or list, optional
A list of column names to drop (prior to performing any pivot). If
`True` appears in this list or is given directly, then all
constant-valued columns are dropped as well. No columns are dropped
when `drop_columns == False`.
Returns
-------
pandas.DataFrame
"""
from pygsti.tools.dataframetools import _process_dataframe
cdict = _NamedDict('Circuit', None)
for cir, i in self.cirIndex.items():
cdict[cir.str] = _NamedDict('ValueName', 'category', items=self._info[i])
df = cdict.to_dataframe()
return _process_dataframe(df, pivot_valuename, pivot_value, drop_columns)
def __iter__(self):
return self.cirIndex.__iter__() # iterator over circuits
def __len__(self):
return len(self.cirIndex)
def __contains__(self, circuit):
"""
Test whether data set contains a given circuit.
Parameters
----------
circuit : tuple or Circuit
A tuple of operation labels or a Circuit instance
which specifies the the circuit to check for.
Returns
-------
bool
whether circuit was found.
"""
if not isinstance(circuit, _cir.Circuit):
circuit = _cir.Circuit(circuit)
return circuit in self.cirIndex
def __hash__(self):
if self.uuid is not None:
return hash(self.uuid)
else:
raise TypeError('Use digest hash')
def __getitem__(self, circuit):
return self._info[self.cirIndex[circuit]]
def __setitem__(self, circuit, info_dict):
#collision action?
if circuit not in self.cirIndex:
self.cirIndex[circuit] = len(self.cirIndex) # add a new circuit index
self._info[self.cirIndex[circuit]] = info_dict
def __delitem__(self, circuit):
if not isinstance(circuit, _cir.Circuit):
circuit = _cir.Circuit(circuit)
del self._info[self.cirIndex[circuit]]
del self.cirIndex[circuit]
def keys(self):
"""
Returns the circuits used as keys of this DataSet.
Returns
-------
list
A list of Circuit objects which index the data
counts within this data set.
"""
yield from self.cirIndex.keys()
def items(self):
"""
Iterator over `(circuit, info_dict)` pairs.
Returns
-------
Iterator
"""
return self.cirIndex.keys()
def values(self):
"""
Iterator over info-dicts for each circuit.
Returns
-------
Iterator
"""
return self._info.values
def copy(self):
"""
Make a copy of this FreeformDataSet.
Returns
-------
DataSet
"""
copyOfMe = FreeformDataSet(circuit_indices=self.cirIndex)
copyOfMe._info = _copy.deepcopy(self._info)
return copyOfMe