Skip to content

Commit

Permalink
Merge pull request #26 from kouwenhovenlab/master
Browse files Browse the repository at this point in the history
sync from lab repo
  • Loading branch information
wpfff committed Jan 29, 2019
2 parents 932dba5 + 08257f3 commit 3ccd121
Show file tree
Hide file tree
Showing 20 changed files with 401 additions and 4,304 deletions.
73 changes: 17 additions & 56 deletions doc/examples/Live plotting qcodes data.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-01-19T21:54:45.474182Z",
"start_time": "2019-01-19T21:54:40.211282Z"
"end_time": "2019-01-29T22:40:58.213604Z",
"start_time": "2019-01-29T22:40:57.052710Z"
}
},
"outputs": [],
Expand All @@ -53,38 +53,11 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We can launch the inspectr tool either interactively, or from the command line in a separate process. You can either run the launching cell below, or, from within the plottr root directory, run \n",
"Next, we need to run the inspectr tool from the command line in a separate process. From within the plottr root directory, run \n",
"\n",
"``\n",
"$ python apps/inspectr.py --dbpath=<path to .db file>\n",
"``\n",
"\n",
"Note: initialization from within this notebook will show you the data only after the measurement has finished (because data generation and plotting run in the same thread). So for *real* live plotting, you should run the inspectr separately."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2018-12-31T13:09:21.497150Z",
"start_time": "2018-12-31T13:09:20.610659Z"
}
},
"outputs": [],
"source": [
"# only use if you're not launching the inspectr tool from a separate command line\n",
"\n",
"from plottr.apps.inspectr import inspectr\n",
"from plottr import log as plottrlog\n",
"\n",
"# make a log window as well. the plotting tools can use it for user information.\n",
"logwin = plottrlog.setupLogging(makeDialog=True)\n",
"logwin.show()\n",
"\n",
"# this launches the db inspection tool\n",
"win = inspectr(DBPATH)\n",
"win.show()"
"$ python apps/inspectr.py --dbpath=./doc/examples/qcodes_liveplot_demo.db\n",
"``"
]
},
{
Expand Down Expand Up @@ -126,8 +99,8 @@
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-01-19T21:56:21.823404Z",
"start_time": "2019-01-19T21:56:21.819408Z"
"end_time": "2019-01-29T22:41:00.407503Z",
"start_time": "2019-01-29T22:41:00.403513Z"
}
},
"outputs": [],
Expand All @@ -149,8 +122,8 @@
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-01-19T21:56:24.537389Z",
"start_time": "2019-01-19T21:56:24.531405Z"
"end_time": "2019-01-29T22:41:12.251621Z",
"start_time": "2019-01-29T22:41:12.246635Z"
}
},
"outputs": [],
Expand All @@ -175,8 +148,8 @@
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-01-19T21:57:00.641436Z",
"start_time": "2019-01-19T21:56:31.661911Z"
"end_time": "2019-01-29T22:42:08.163848Z",
"start_time": "2019-01-29T22:41:13.906794Z"
}
},
"outputs": [],
Expand All @@ -196,21 +169,9 @@
" (y, yval),\n",
" (y2, y2val),\n",
" )\n",
" time.sleep(0.5)"
" time.sleep(0.2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-01-01T20:34:20.302660Z",
"start_time": "2019-01-01T20:34:20.296648Z"
}
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
Expand All @@ -223,8 +184,8 @@
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-01-19T21:57:09.891603Z",
"start_time": "2019-01-19T21:57:09.885617Z"
"end_time": "2019-01-29T22:42:22.035442Z",
"start_time": "2019-01-29T22:42:22.029458Z"
}
},
"outputs": [],
Expand All @@ -250,8 +211,8 @@
"execution_count": null,
"metadata": {
"ExecuteTime": {
"end_time": "2019-01-19T21:57:45.806610Z",
"start_time": "2019-01-19T21:57:17.911683Z"
"end_time": "2019-01-29T22:42:35.803916Z",
"start_time": "2019-01-29T22:42:23.945335Z"
}
},
"outputs": [],
Expand All @@ -271,7 +232,7 @@
" (y, yval),\n",
" (z, zval),\n",
" )\n",
" time.sleep(0.5)"
" time.sleep(0.2)"
]
},
{
Expand Down
64 changes: 50 additions & 14 deletions plottr/data/datadict.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@

# TODO: serialization (json...)
# TODO: functionality that returns axes values given a set of slices.
# FIXME: treatment of nested dims: expand or flatten-method; detection of
# nested dims. MISSING!
# TODO: an easier way to access data and meta values.
# maybe with getattr/setattr?
# TODO: direct slicing of full datasets. implement getitem/setitem?
Expand Down Expand Up @@ -400,6 +398,7 @@ def validate(self):
"""
msg = '\n'
for n, v in self.data_items():

if 'axes' in v:
for na in v['axes']:
if na not in self:
Expand All @@ -416,7 +415,10 @@ def validate(self):
if 'unit' not in v:
v['unit'] = ''

v['values'] = np.array(v.get('values', []))
vals = v.get('values', [])
if type(vals) not in [np.ndarray, np.ma.core.MaskedArray]:
vals = np.array(vals)
v['values'] = vals

if '__shape__' in v and not self.__class__ == DataDictBase:
v['__shape__'] = np.array(v['values']).shape
Expand Down Expand Up @@ -512,6 +514,36 @@ def copy(self) -> 'DataDictBase':
"""
return cp.deepcopy(self)

def astype(self, dtype) -> 'DataDictBase':
"""
Convert all data values to given dtype.
:param dtype: np dtype.
:return: copy of the dataset, with values as given type.
"""
ret = self.copy()
for k, v in ret.data_items():
vals = v['values']
if type(v['values']) not in [np.ndarray, np.ma.core.MaskedArray]:
vals = np.array(v['values'])
ret[k]['values'] = vals.astype(dtype)

return ret

def mask_invalid(self) -> 'DataDictBase':
"""
Mask all invalid data in all values.
:return: copy of the dataset with invalid entries (nan/None) masked.
"""
ret = self.copy()
for d, _ in self.data_items():
arr = self.data_vals(d)
vals = np.ma.masked_where(num.is_invalid(arr), arr, copy=True)
vals.fill_value = np.nan
ret[d]['values'] = vals

return ret


class DataDict(DataDictBase):
"""
Expand Down Expand Up @@ -542,14 +574,11 @@ def __add__(self, newdata: 'DataDict') -> 'DataDict':
for k, v in self.data_items():
val0 = self[k]['values']
val1 = newdata[k]['values']
if isinstance(val0, list) and isinstance(val1, list):
s[k]['values'] = self[k]['values'] + newdata[k]['values']
else:
s[k]['values'] = np.append(
np.array(self[k]['values']),
np.array(newdata[k]['values']),
axis=0
)
s[k]['values'] = np.append(
self[k]['values'],
newdata[k]['values'],
axis=0
)
return s
else:
raise ValueError('Incompatible data structures.')
Expand All @@ -568,8 +597,8 @@ def append(self, newdata):
self[k]['values'] += v['values']
else:
self[k]['values'] = np.append(
np.array(self[k]['values']),
np.array(v['values']),
self[k]['values'],
v['values'],
axis=0
)
else:
Expand Down Expand Up @@ -648,7 +677,7 @@ def expand(self) -> 'DataDict':
reps = size // np.prod(ishp[k])
if reps > 1:
ret[k]['values'] = \
np.array(self[k]['values']).repeat(reps, axis=0).reshape(-1)
self[k]['values'].repeat(reps, axis=0).reshape(-1)
else:
ret[k]['values'] = self[k]['values'].reshape(-1)

Expand All @@ -672,6 +701,10 @@ def validate(self) -> bool:
msg = '\n'

for n, v in self.data_items():
if type(v['values']) not in [np.ndarray,
np.ma.core.MaskedArray]:
self[n]['values'] = np.array(v['values'])

if nvals is None:
nvals = len(v['values'])
nvalsrc = n
Expand Down Expand Up @@ -836,6 +869,9 @@ def validate(self):
shp = None
shpsrc = ''
for n, v in self.data_items():
if type(v['values']) not in [np.ndarray, np.ma.core.MaskedArray]:
self[n]['values'] = np.array(v['values'])

if shp is None:
shp = v['values'].shape
shpsrc = n
Expand Down
21 changes: 17 additions & 4 deletions plottr/node/data_selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
from .node import Node, NodeWidget
from ..data import datadict as dd
from ..data.datadict import DataDict
from ..utils import num

__author__ = 'Wolfgang Pfaff'
__license__ = 'MIT'


class DataDisplayWidget(QtGui.QTreeWidget, NodeWidget):
"""
Simple Tree widget to show data and their dependencies in the node data.
Expand Down Expand Up @@ -123,6 +123,8 @@ class DataSelector(Node):
* selectedData : a list/tuple of data field names
"""

# TODO: allow the user to control dtypes.

nodeName = "DataSelector"
uiClass = DataDisplayWidget

Expand All @@ -136,6 +138,8 @@ class DataSelector(Node):
newDataStructure = QtCore.pyqtSignal(object)
dataShapeChanged = QtCore.pyqtSignal(object)

force_numerical_data = True

def __init__(self, *arg, **kw):
super().__init__(*arg, **kw)

Expand Down Expand Up @@ -178,12 +182,11 @@ def validateOptions(self, data):
self.logger().error(
f'Datasets {self.selectedData[0]} (with axes {allowed_axes}) '
f'and {d}(with axes {data.axes(d)}) are not compatible '
f'and cannot be selected simultanously.'
f'and cannot be selected simultaneously.'
)
return False
return True


def _reduceData(self, data):
if isinstance(self.selectedData, str):
dnames = [self.selectedData]
Expand All @@ -192,7 +195,17 @@ def _reduceData(self, data):
if len(self.selectedData) == 0:
return None

return data.extract(dnames)
ret = data.extract(dnames)
if self.force_numerical_data:
for d, _ in ret.data_items():
dt = num.largest_numtype(ret.data_vals(d),
include_integers=False)
if dt is not None:
ret[d]['values'] = ret[d]['values'].astype(dt)
else:
return None

return ret

def process(self, **kw):
data = super().process(**kw)
Expand Down

0 comments on commit 3ccd121

Please sign in to comment.