pymodaq 4.1.5__py3-none-any.whl → 4.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pymodaq might be problematic. Click here for more details.
- pymodaq/__init__.py +23 -4
- pymodaq/control_modules/daq_move.py +32 -73
- pymodaq/control_modules/daq_viewer.py +73 -98
- pymodaq/control_modules/daq_viewer_ui.py +2 -1
- pymodaq/control_modules/move_utility_classes.py +17 -7
- pymodaq/control_modules/utils.py +153 -5
- pymodaq/control_modules/viewer_utility_classes.py +31 -20
- pymodaq/dashboard.py +23 -5
- pymodaq/examples/tcp_client.py +97 -0
- pymodaq/extensions/__init__.py +4 -0
- pymodaq/extensions/bayesian/__init__.py +2 -0
- pymodaq/extensions/bayesian/bayesian_optimisation.py +673 -0
- pymodaq/extensions/bayesian/utils.py +403 -0
- pymodaq/extensions/daq_scan.py +4 -4
- pymodaq/extensions/daq_scan_ui.py +2 -1
- pymodaq/extensions/pid/pid_controller.py +12 -7
- pymodaq/extensions/pid/utils.py +9 -26
- pymodaq/extensions/utils.py +3 -0
- pymodaq/post_treatment/load_and_plot.py +42 -19
- pymodaq/resources/VERSION +1 -1
- pymodaq/resources/config_template.toml +9 -24
- pymodaq/resources/setup_plugin.py +1 -1
- pymodaq/utils/config.py +103 -5
- pymodaq/utils/daq_utils.py +35 -134
- pymodaq/utils/data.py +614 -95
- pymodaq/utils/enums.py +17 -1
- pymodaq/utils/factory.py +2 -2
- pymodaq/utils/gui_utils/custom_app.py +5 -2
- pymodaq/utils/gui_utils/dock.py +33 -4
- pymodaq/utils/gui_utils/utils.py +14 -1
- pymodaq/utils/h5modules/backends.py +9 -1
- pymodaq/utils/h5modules/data_saving.py +254 -57
- pymodaq/utils/h5modules/saving.py +1 -0
- pymodaq/utils/leco/__init__.py +25 -0
- pymodaq/utils/leco/daq_move_LECODirector.py +172 -0
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +170 -0
- pymodaq/utils/leco/desktop.ini +2 -0
- pymodaq/utils/leco/director_utils.py +58 -0
- pymodaq/utils/leco/leco_director.py +88 -0
- pymodaq/utils/leco/pymodaq_listener.py +279 -0
- pymodaq/utils/leco/utils.py +41 -0
- pymodaq/utils/managers/action_manager.py +20 -6
- pymodaq/utils/managers/parameter_manager.py +6 -4
- pymodaq/utils/managers/roi_manager.py +63 -54
- pymodaq/utils/math_utils.py +1 -1
- pymodaq/utils/plotting/data_viewers/__init__.py +3 -1
- pymodaq/utils/plotting/data_viewers/base.py +286 -0
- pymodaq/utils/plotting/data_viewers/viewer.py +29 -202
- pymodaq/utils/plotting/data_viewers/viewer0D.py +94 -47
- pymodaq/utils/plotting/data_viewers/viewer1D.py +341 -174
- pymodaq/utils/plotting/data_viewers/viewer1Dbasic.py +1 -1
- pymodaq/utils/plotting/data_viewers/viewer2D.py +271 -181
- pymodaq/utils/plotting/data_viewers/viewerND.py +26 -22
- pymodaq/utils/plotting/items/crosshair.py +3 -3
- pymodaq/utils/plotting/items/image.py +2 -1
- pymodaq/utils/plotting/plotter/plotter.py +94 -0
- pymodaq/utils/plotting/plotter/plotters/__init__.py +0 -0
- pymodaq/utils/plotting/plotter/plotters/matplotlib_plotters.py +134 -0
- pymodaq/utils/plotting/plotter/plotters/qt_plotters.py +78 -0
- pymodaq/utils/plotting/utils/axes_viewer.py +1 -1
- pymodaq/utils/plotting/utils/filter.py +194 -147
- pymodaq/utils/plotting/utils/lineout.py +13 -11
- pymodaq/utils/plotting/utils/plot_utils.py +89 -12
- pymodaq/utils/scanner/__init__.py +0 -3
- pymodaq/utils/scanner/scan_config.py +1 -9
- pymodaq/utils/scanner/scan_factory.py +10 -36
- pymodaq/utils/scanner/scanner.py +3 -2
- pymodaq/utils/scanner/scanners/_1d_scanners.py +7 -5
- pymodaq/utils/scanner/scanners/_2d_scanners.py +36 -49
- pymodaq/utils/scanner/scanners/sequential.py +10 -4
- pymodaq/utils/scanner/scanners/tabular.py +10 -5
- pymodaq/utils/slicing.py +1 -1
- pymodaq/utils/tcp_ip/serializer.py +38 -5
- pymodaq/utils/tcp_ip/tcp_server_client.py +25 -17
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/METADATA +4 -2
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/RECORD +79 -63
- pymodaq/resources/config_scan_template.toml +0 -42
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/WHEEL +0 -0
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/entry_points.txt +0 -0
- {pymodaq-4.1.5.dist-info → pymodaq-4.2.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -14,6 +14,7 @@ from pymodaq.utils.plotting.items.crosshair import Crosshair
|
|
|
14
14
|
from pymodaq.utils.plotting.items.image import UniformImageItem
|
|
15
15
|
from pymodaq.utils.plotting.data_viewers.viewer1Dbasic import Viewer1DBasic
|
|
16
16
|
from pymodaq.utils.logger import set_logger, get_module_name
|
|
17
|
+
from pymodaq.utils.data import DataFromRoi, DataToExport, Axis, DataWithAxes
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
from pymodaq.post_treatment.process_to_scalar import DataProcessorFactory
|
|
@@ -47,7 +48,7 @@ class Filter:
|
|
|
47
48
|
if filtered_data is not None and self._slot_to_send_data is not None:
|
|
48
49
|
self._slot_to_send_data(filtered_data)
|
|
49
50
|
|
|
50
|
-
def _filter_data(self, data: data_mod.DataFromPlugins):
|
|
51
|
+
def _filter_data(self, data: data_mod.DataFromPlugins) -> DataToExport:
|
|
51
52
|
raise NotImplementedError
|
|
52
53
|
|
|
53
54
|
|
|
@@ -67,18 +68,22 @@ class Filter1DFromCrosshair(Filter):
|
|
|
67
68
|
def update_axis(self, axis: data_mod.Axis):
|
|
68
69
|
self._axis = axis
|
|
69
70
|
|
|
70
|
-
def _filter_data(self, data: data_mod.DataFromPlugins):
|
|
71
|
-
|
|
71
|
+
def _filter_data(self, data: data_mod.DataFromPlugins) -> DataToExport:
|
|
72
|
+
dte = DataToExport('Crosshair')
|
|
72
73
|
if data is not None:
|
|
73
74
|
axis = data.get_axis_from_index(0, create=False)[0]
|
|
74
75
|
if axis is not None:
|
|
75
76
|
self.update_axis(axis)
|
|
76
77
|
|
|
77
78
|
self._x, self._y = self.crosshair.get_positions()
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
dwa = data.isig[data.axes[0].find_indexes([self._x])[0]]
|
|
80
|
+
dwa.axes = [Axis('x', data=np.array([self._x]))]
|
|
81
|
+
dte.append(dwa)
|
|
82
|
+
# for label, dat in zip(data.labels, data.data):
|
|
83
|
+
# dte.append(DataFromRoi('crosshair', data=[np.array([dat[ind_x]]) for dat in data.data],
|
|
84
|
+
# axes=[Axis(data=np.array([self._axis.get_data()[ind_x]]))],
|
|
85
|
+
# labels=data.labels))
|
|
86
|
+
return dte
|
|
82
87
|
|
|
83
88
|
|
|
84
89
|
class Filter2DFromCrosshair(Filter):
|
|
@@ -107,70 +112,95 @@ class Filter2DFromCrosshair(Filter):
|
|
|
107
112
|
if activate:
|
|
108
113
|
self.crosshair.crosshair_dragged.emit(*self.crosshair.get_positions())
|
|
109
114
|
|
|
110
|
-
def _filter_data(self,
|
|
111
|
-
|
|
112
|
-
if
|
|
115
|
+
def _filter_data(self, dwa: data_mod.DataFromPlugins) -> DataToExport:
|
|
116
|
+
dte = DataToExport('Crosshair')
|
|
117
|
+
if dwa is not None:
|
|
113
118
|
self._x, self._y = self.crosshair.get_positions()
|
|
114
|
-
data_type =
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
return data_dict
|
|
124
|
-
|
|
125
|
-
def get_data_from_uniform(self, data_key, data):
|
|
126
|
-
hor_axis, ver_axis = \
|
|
127
|
-
np.linspace(0, self._graph_items[data_key].width() - 1, self._graph_items[data_key].width()),\
|
|
128
|
-
np.linspace(0, self._graph_items[data_key].height() - 1, self._graph_items[data_key].height())
|
|
129
|
-
|
|
130
|
-
indx, indy = self.mapfromview(self._x, self._y, data_key)
|
|
119
|
+
data_type = dwa.distribution
|
|
120
|
+
if data_type == 'uniform':
|
|
121
|
+
dte = self.get_data_from_uniform(dwa)
|
|
122
|
+
elif data_type == 'spread':
|
|
123
|
+
dte = self.get_data_from_spread(dwa)
|
|
124
|
+
return dte
|
|
125
|
+
|
|
126
|
+
def get_data_from_uniform(self, dwa: DataWithAxes) -> DataToExport:
|
|
127
|
+
indx, indy = self.mapfromview(self._x, self._y, 'red')
|
|
131
128
|
|
|
132
129
|
data_H_index = slice(None, None, 1)
|
|
133
130
|
data_V_index = slice(None, None, 1)
|
|
134
131
|
H_indexes = (utils.rint(indy), data_H_index)
|
|
135
132
|
V_indexes = (data_V_index, utils.rint(indx))
|
|
133
|
+
dte = DataToExport('Crosshair')
|
|
134
|
+
try:
|
|
135
|
+
if not (0 <= utils.rint(indy) < dwa.shape[0]):
|
|
136
|
+
raise IndexError
|
|
137
|
+
dwa_hor = dwa.isig[H_indexes]
|
|
138
|
+
dwa_hor.labels = [f'Crosshair/{label}' for label in dwa_hor.labels]
|
|
139
|
+
dwa_hor.name = 'hor'
|
|
140
|
+
dte.append(dwa_hor)
|
|
141
|
+
except IndexError:
|
|
142
|
+
pass
|
|
143
|
+
try:
|
|
144
|
+
if not (0 <= utils.rint(indx) < dwa.shape[1]):
|
|
145
|
+
raise IndexError
|
|
146
|
+
dwa_ver = dwa.isig[V_indexes]
|
|
147
|
+
dwa_ver.labels = [f'Crosshair/{label}' for label in dwa_ver.labels]
|
|
148
|
+
dwa_ver.name = 'ver'
|
|
149
|
+
dte.append(dwa_ver)
|
|
150
|
+
except IndexError:
|
|
151
|
+
pass
|
|
152
|
+
try:
|
|
153
|
+
if not (0 <= utils.rint(indy) < dwa.shape[0]) \
|
|
154
|
+
or \
|
|
155
|
+
not (0 <= utils.rint(indx) < dwa.shape[1]):
|
|
156
|
+
raise IndexError
|
|
157
|
+
dwa_int = dwa.isig[utils.rint(indy), utils.rint(indx)]
|
|
158
|
+
dwa_int.labels = [f'Crosshair/{label}' for label in dwa_int.labels]
|
|
159
|
+
dwa_int.name = 'int'
|
|
160
|
+
dte.append(dwa_int)
|
|
161
|
+
except IndexError:
|
|
162
|
+
pass
|
|
163
|
+
return dte
|
|
136
164
|
|
|
137
|
-
|
|
138
|
-
if 0 <= H_indexes[0] < len(ver_axis):
|
|
139
|
-
hor_data = data[H_indexes]
|
|
140
|
-
else:
|
|
141
|
-
out_of_bounds = True
|
|
142
|
-
hor_data = np.zeros(hor_axis.shape)
|
|
143
|
-
if 0 <= V_indexes[1] < len(hor_axis):
|
|
144
|
-
ver_data = data[V_indexes]
|
|
145
|
-
else:
|
|
146
|
-
out_of_bounds = True
|
|
147
|
-
ver_data = np.zeros(ver_axis.shape)
|
|
148
|
-
if out_of_bounds:
|
|
149
|
-
ind_data = 0.
|
|
150
|
-
else:
|
|
151
|
-
ind_data = data[utils.rint(indy), utils.rint(indx)]
|
|
152
|
-
return LineoutData(hor_axis=hor_axis, ver_axis=ver_axis, hor_data=hor_data, ver_data=ver_data,
|
|
153
|
-
int_data=ind_data)
|
|
165
|
+
def get_data_from_spread(self, dwa: DataWithAxes) -> DataToExport:
|
|
154
166
|
|
|
155
|
-
def get_data_from_spread(self, data_key, data):
|
|
156
167
|
data_H_index = slice(None, None, 1)
|
|
157
168
|
data_V_index = slice(None, None, 1)
|
|
158
|
-
posx, posy = self.mapfromview(self._x, self._y,
|
|
169
|
+
posx, posy = self.mapfromview(self._x, self._y, 'red')
|
|
170
|
+
|
|
171
|
+
hor_data = []
|
|
172
|
+
ver_data = []
|
|
173
|
+
int_data = []
|
|
174
|
+
hor_axis = None
|
|
175
|
+
ver_axis = None
|
|
176
|
+
|
|
177
|
+
for ind, data_key in enumerate(self._graph_items):
|
|
178
|
+
if ind < len(dwa):
|
|
179
|
+
points, data = self._graph_items[data_key].get_points_at(axis='y', val=posy)
|
|
180
|
+
x_sorted_indexes = np.argsort(points[:, 0])
|
|
181
|
+
hor_axis = points[x_sorted_indexes, 0][data_H_index]
|
|
159
182
|
|
|
160
|
-
|
|
161
|
-
x_sorted_indexes = np.argsort(points[:, 0])
|
|
162
|
-
hor_axis = points[x_sorted_indexes, 0][data_H_index]
|
|
183
|
+
hor_data.append(data[x_sorted_indexes][data_H_index])
|
|
163
184
|
|
|
164
|
-
|
|
185
|
+
points, data = self._graph_items[data_key].get_points_at(axis='x', val=posx)
|
|
186
|
+
y_sorted_indexes = np.argsort(points[:, 1])
|
|
187
|
+
ver_axis = points[y_sorted_indexes, 1][data_V_index]
|
|
165
188
|
|
|
166
|
-
|
|
167
|
-
y_sorted_indexes = np.argsort(points[:, 1])
|
|
168
|
-
ver_axis = points[y_sorted_indexes, 1][data_V_index]
|
|
189
|
+
ver_data.append(data[y_sorted_indexes][data_V_index])
|
|
169
190
|
|
|
170
|
-
|
|
191
|
+
int_data.append(np.array([self._graph_items[data_key].get_val_at((posx, posy))]))
|
|
171
192
|
|
|
172
|
-
|
|
173
|
-
|
|
193
|
+
dte = DataToExport('Crosshair')
|
|
194
|
+
if len(hor_data) > 0 and len(hor_axis) > 0:
|
|
195
|
+
dte.append(DataFromRoi('hor', data=hor_data,
|
|
196
|
+
axes=[Axis(dwa.axes[1].label, dwa.axes[1].units, data=hor_axis)]),)
|
|
197
|
+
if len(ver_data) > 0 and len(ver_axis) > 0:
|
|
198
|
+
dte.append(DataFromRoi('ver', data=ver_data,
|
|
199
|
+
axes=[Axis(dwa.axes[0].label, dwa.axes[0].units, data=ver_axis)]))
|
|
200
|
+
if len(int_data) > 0:
|
|
201
|
+
dte.append(DataFromRoi('int', data=int_data))
|
|
202
|
+
|
|
203
|
+
return dte
|
|
174
204
|
|
|
175
205
|
def mapfromview(self, x, y, item_key='red'):
|
|
176
206
|
"""
|
|
@@ -207,39 +237,53 @@ class Filter1DFromRois(Filter):
|
|
|
207
237
|
def update_axis(self, axis: data_mod.Axis):
|
|
208
238
|
self._axis = axis
|
|
209
239
|
|
|
210
|
-
def _filter_data(self, data: data_mod.DataFromPlugins) ->
|
|
211
|
-
|
|
240
|
+
def _filter_data(self, data: data_mod.DataFromPlugins) -> DataToExport:
|
|
241
|
+
dte = DataToExport('roi1D')
|
|
212
242
|
try:
|
|
213
243
|
axis = data.get_axis_from_index(0, create=False)[0]
|
|
214
244
|
if axis is not None:
|
|
215
245
|
self.update_axis(axis)
|
|
216
246
|
if data is not None:
|
|
217
247
|
for roi_key, roi in self._ROIs.items():
|
|
218
|
-
|
|
219
|
-
data_index = data.labels
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
248
|
+
if self._roi_settings['ROIs', roi_key, 'use_channel'] == 'All':
|
|
249
|
+
data_index = list(range(len(data.labels)))
|
|
250
|
+
else:
|
|
251
|
+
try:
|
|
252
|
+
data_index = [data.labels.index(self._roi_settings['ROIs', roi_key,
|
|
253
|
+
'use_channel'])]
|
|
254
|
+
except ValueError:
|
|
255
|
+
data_index = [0]
|
|
256
|
+
dte_tmp = self.get_data_from_roi(roi, self._roi_settings.child('ROIs', roi_key),
|
|
257
|
+
data)
|
|
258
|
+
if self._roi_settings['ROIs', roi_key, 'use_channel'] == 'All':
|
|
259
|
+
dte.append(dte_tmp.data)
|
|
260
|
+
else:
|
|
261
|
+
for index in data_index:
|
|
262
|
+
for dwa in dte_tmp.data:
|
|
263
|
+
dte.append(dwa.pop(index))
|
|
264
|
+
|
|
224
265
|
except Exception as e:
|
|
225
266
|
pass
|
|
226
|
-
|
|
267
|
+
finally:
|
|
268
|
+
return dte
|
|
227
269
|
|
|
228
|
-
def get_data_from_roi(self, roi: LinearROI, roi_param: Parameter, data: data_mod.DataWithAxes
|
|
270
|
+
def get_data_from_roi(self, roi: LinearROI, roi_param: Parameter, data: data_mod.DataWithAxes) -> DataToExport:
|
|
229
271
|
if data is not None:
|
|
272
|
+
dte = DataToExport('ROI1D')
|
|
230
273
|
_slice = self.get_slice_from_roi(roi, data)
|
|
231
|
-
sub_data = data.isig[_slice]
|
|
274
|
+
sub_data: DataFromRoi = data.isig[_slice]
|
|
275
|
+
sub_data.name = 'HorData'
|
|
276
|
+
sub_data.origin = roi_param.name()
|
|
277
|
+
sub_data.labels = [f'{roi_param.name()}/{label}' for label in sub_data.labels]
|
|
278
|
+
dte.append(sub_data)
|
|
232
279
|
if sub_data.size != 0:
|
|
233
280
|
processed_data = data_processors.get(roi_param['math_function']).process(sub_data)
|
|
234
281
|
else:
|
|
235
282
|
processed_data = None
|
|
236
|
-
if processed_data is None:
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
pass
|
|
241
|
-
return LineoutData(hor_axis=sub_data.axes[0], hor_data=sub_data.data[data_index],
|
|
242
|
-
int_data=processed_data.data[data_index])
|
|
283
|
+
if processed_data is not None:
|
|
284
|
+
processed_data.name = 'IntData'
|
|
285
|
+
dte.append(processed_data)
|
|
286
|
+
return dte
|
|
243
287
|
|
|
244
288
|
def get_slice_from_roi(self, roi: RectROI, data: data_mod.DataWithAxes) -> slice:
|
|
245
289
|
ind_x_min, ind_x_max = data.get_axis_from_index(data.sig_indexes[0])[0].find_indexes(roi.getRegion())
|
|
@@ -269,39 +313,47 @@ class Filter2DFromRois(Filter):
|
|
|
269
313
|
self.axes = (0, 1)
|
|
270
314
|
self._ROIs = roi_manager.ROIs
|
|
271
315
|
|
|
272
|
-
def _filter_data(self,
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
316
|
+
def _filter_data(self, dwa: data_mod.DataFromPlugins) -> DataToExport:
|
|
317
|
+
dte = DataToExport('ROI')
|
|
318
|
+
if dwa is not None:
|
|
319
|
+
try:
|
|
320
|
+
labels = []
|
|
276
321
|
for roi_key, roi in self._ROIs.items():
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
322
|
+
label = self._roi_settings['ROIs', roi_key, 'use_channel']
|
|
323
|
+
if label is not None:
|
|
324
|
+
if label != 'All':
|
|
325
|
+
sub_data = dwa.deepcopy()
|
|
326
|
+
sub_data.data = [dwa[dwa.labels.index(label)]]
|
|
327
|
+
sub_data.labels = [label]
|
|
328
|
+
else:
|
|
329
|
+
sub_data = dwa
|
|
330
|
+
dte_temp = self.get_xydata_from_roi(roi, sub_data,
|
|
331
|
+
self._roi_settings['ROIs',
|
|
332
|
+
roi_key, 'math_function'])
|
|
333
|
+
|
|
334
|
+
dte.append(dte_temp)
|
|
335
|
+
except Exception as e:
|
|
336
|
+
logger.warning(f'Issue with the ROI: {str(e)}')
|
|
337
|
+
return dte
|
|
338
|
+
|
|
339
|
+
def get_slices_from_roi(self, roi: RectROI, data_shape: tuple) -> Tuple[slice, slice]:
|
|
289
340
|
x, y = roi.pos().x(), roi.pos().y()
|
|
290
341
|
width, height = roi.size().x(), roi.size().y()
|
|
291
|
-
size_x =
|
|
292
|
-
size_y = data.get_axis_from_index(0)[0].size
|
|
342
|
+
size_y, size_x = data_shape
|
|
293
343
|
ind_x_min = int(min(max(x, 0), size_x))
|
|
294
344
|
ind_y_min = int(min(max(y, 0), size_y))
|
|
295
345
|
ind_x_max = int(max(0, min(x+width, size_x)))
|
|
296
346
|
ind_y_max = int(max(0, min(y+height, size_y)))
|
|
297
|
-
|
|
298
347
|
return slice(ind_y_min,ind_y_max), slice(ind_x_min, ind_x_max)
|
|
299
348
|
|
|
300
|
-
def get_xydata_from_roi(self, roi,
|
|
301
|
-
|
|
302
|
-
if
|
|
303
|
-
|
|
304
|
-
|
|
349
|
+
def get_xydata_from_roi(self, roi: RectROI, dwa: DataWithAxes, math_function: str) -> DataToExport:
|
|
350
|
+
dte = DataToExport(roi.name)
|
|
351
|
+
if dwa is not None:
|
|
352
|
+
labels = [f'{roi.name}/{label}' for label in dwa.labels]
|
|
353
|
+
if dwa.distribution.name == 'spread':
|
|
354
|
+
xvals, yvals, data = self.get_xydata_spread(dwa, roi)
|
|
355
|
+
if len(data) == 0:
|
|
356
|
+
return dte
|
|
305
357
|
ind_xaxis = np.argsort(xvals)
|
|
306
358
|
ind_yaxis = np.argsort(yvals)
|
|
307
359
|
xvals = xvals[ind_xaxis]
|
|
@@ -309,34 +361,51 @@ class Filter2DFromRois(Filter):
|
|
|
309
361
|
data_H = data[ind_xaxis]
|
|
310
362
|
data_V = data[ind_yaxis]
|
|
311
363
|
int_data = np.array([np.mean(data)])
|
|
312
|
-
math_data = int_data
|
|
313
|
-
else:
|
|
314
|
-
xvals, yvals, data_array = self.get_xydata(data.data[0], roi)
|
|
315
|
-
slices = self.get_slices_from_roi(roi, data)
|
|
316
|
-
sub_data = data.isig[slices[0], slices[1]]
|
|
317
|
-
data_H = np.mean(data_array, axis=0)
|
|
318
|
-
data_V = np.mean(data_array, axis=1)
|
|
319
|
-
int_data = np.array([np.mean(data_array)])
|
|
320
|
-
math_data = data_processors.get(math_function).process(sub_data).data
|
|
321
|
-
|
|
322
|
-
return LineoutData(hor_axis=xvals, ver_axis=yvals, hor_data=data_H, ver_data=data_V, int_data=int_data,
|
|
323
|
-
math_data=math_data)
|
|
324
|
-
|
|
325
|
-
def get_xydata(self, data: np.ndarray, roi: RectROI):
|
|
326
|
-
data, coords = self.data_from_roi(data, roi)
|
|
327
364
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
365
|
+
_x_axis = dwa.get_axis_from_index_spread(0, 0)
|
|
366
|
+
x_axis = Axis(_x_axis.label, _x_axis.units, data=xvals, index=0, spread_order=0)
|
|
367
|
+
_y_axis = dwa.get_axis_from_index_spread(0, 1)
|
|
368
|
+
y_axis = Axis(_y_axis.label, _y_axis.units, data=yvals, index=0, spread_order=0)
|
|
369
|
+
sub_data_hor = DataFromRoi('hor', distribution='spread', data=[data_H], axes=[x_axis],)
|
|
370
|
+
sub_data_ver = DataFromRoi('ver', distribution='spread', data=[data_V], axes=[y_axis])
|
|
371
|
+
math_data = DataFromRoi('int', data=int_data)
|
|
372
|
+
else:
|
|
373
|
+
slices = self.get_slices_from_roi(roi, dwa.shape)
|
|
374
|
+
sub_data: DataFromRoi = dwa.isig[slices[0], slices[1]]
|
|
375
|
+
sub_data_hor = sub_data.mean(0)
|
|
376
|
+
sub_data_ver = sub_data.mean(1)
|
|
377
|
+
math_data = data_processors.get(math_function).process(sub_data)
|
|
378
|
+
|
|
379
|
+
sub_data_hor.name = 'hor'
|
|
380
|
+
sub_data_hor.origin = roi.name
|
|
381
|
+
sub_data_hor.labels = labels
|
|
382
|
+
sub_data_ver.name = 'ver'
|
|
383
|
+
sub_data_ver.origin = roi.name
|
|
384
|
+
sub_data_ver.labels = labels
|
|
385
|
+
math_data.name = 'int'
|
|
386
|
+
math_data.origin = roi.name
|
|
387
|
+
math_data.labels = labels
|
|
388
|
+
|
|
389
|
+
dte.append([sub_data_hor, sub_data_ver, math_data])
|
|
390
|
+
return dte
|
|
391
|
+
|
|
392
|
+
#TODO possibly not used anymore to be deleted
|
|
393
|
+
#
|
|
394
|
+
# def get_xydata(self, data: np.ndarray, roi: RectROI):
|
|
395
|
+
# data, coords = self.data_from_roi(data, roi)
|
|
396
|
+
#
|
|
397
|
+
# if data is not None:
|
|
398
|
+
# xvals = np.linspace(np.min(np.min(coords[1, :, :])), np.max(np.max(coords[1, :, :])),
|
|
399
|
+
# data.shape[1])
|
|
400
|
+
# yvals = np.linspace(np.min(np.min(coords[0, :, :])), np.max(np.max(coords[0, :, :])),
|
|
401
|
+
# data.shape[0])
|
|
402
|
+
# else:
|
|
403
|
+
# xvals = yvals = data = np.array([])
|
|
404
|
+
# return xvals, yvals, data
|
|
405
|
+
#
|
|
406
|
+
# def data_from_roi(self, data, roi):
|
|
407
|
+
# data, coords = roi.getArrayRegion(data, self._graph_item, self.axes, returnMappedCoords=True)
|
|
408
|
+
# return data, coords
|
|
340
409
|
|
|
341
410
|
def get_xydata_spread(self, data, roi):
|
|
342
411
|
xvals = []
|
|
@@ -355,28 +424,6 @@ class Filter2DFromRois(Filter):
|
|
|
355
424
|
return xvals, yvals, data_out
|
|
356
425
|
|
|
357
426
|
|
|
358
|
-
class LineoutData:
|
|
359
|
-
def __init__(self, hor_axis=np.array([]), ver_axis=np.array([]), hor_data=np.array([]), ver_data=np.array([]),
|
|
360
|
-
int_data: np.ndarray = None, math_data: List[np.ndarray] = None):
|
|
361
|
-
super().__init__()
|
|
362
|
-
if len(hor_axis) != len(hor_data):
|
|
363
|
-
raise ValueError(f'Horizontal lineout data and axis must have the same size')
|
|
364
|
-
if len(ver_axis) != len(ver_data):
|
|
365
|
-
raise ValueError(f'Horizontal lineout data and axis must have the same size')
|
|
366
|
-
|
|
367
|
-
self.hor_axis = hor_axis
|
|
368
|
-
self.ver_axis = ver_axis
|
|
369
|
-
self.hor_data = hor_data
|
|
370
|
-
self.ver_data = ver_data
|
|
371
|
-
if int_data is None:
|
|
372
|
-
self.int_data = np.array([np.sum(self.ver_data)])
|
|
373
|
-
else:
|
|
374
|
-
self.int_data = int_data
|
|
375
|
-
if math_data is None:
|
|
376
|
-
math_data = self.int_data
|
|
377
|
-
self.math_data = math_data
|
|
378
|
-
|
|
379
|
-
|
|
380
427
|
class FourierFilterer(QObject):
|
|
381
428
|
filter_changed = Signal(dict)
|
|
382
429
|
|
|
@@ -13,7 +13,7 @@ from pymodaq.utils.plotting.items.crosshair import Crosshair
|
|
|
13
13
|
from pymodaq.utils.logger import set_logger, get_module_name
|
|
14
14
|
import pymodaq.utils.daq_utils as utils
|
|
15
15
|
from pymodaq.utils.logger import set_logger, get_module_name
|
|
16
|
-
|
|
16
|
+
from pymodaq.utils.data import DataCalculated
|
|
17
17
|
|
|
18
18
|
logger = set_logger(get_module_name(__file__))
|
|
19
19
|
IMAGE_TYPES = ['red', 'green', 'blue']
|
|
@@ -81,14 +81,15 @@ class LineoutPlotter(QObject):
|
|
|
81
81
|
|
|
82
82
|
def plot_roi_lineouts(self, roi_dicts):
|
|
83
83
|
self.integrated_data.add_datas({roi_key: roi_dicts[roi_key].int_data for roi_key in roi_dicts})
|
|
84
|
-
for roi_key, lineout_data in roi_dicts.items():
|
|
85
|
-
if roi_key in self._roi_curves:
|
|
86
|
-
self._roi_curves[roi_key]['int'].setData(self.integrated_data.xaxis,
|
|
87
|
-
self.integrated_data.datas[roi_key])
|
|
88
|
-
self.plot_other_lineouts(roi_dicts)
|
|
89
84
|
|
|
90
|
-
|
|
91
|
-
self.
|
|
85
|
+
# for roi_key, lineout_data in roi_dicts.items():
|
|
86
|
+
# if roi_key in self._roi_curves:
|
|
87
|
+
# self._roi_curves[roi_key]['int'].setData(self.integrated_data.xaxis,
|
|
88
|
+
# self.integrated_data.datas[roi_key])
|
|
89
|
+
# self.plot_other_lineouts(roi_dicts)
|
|
90
|
+
#
|
|
91
|
+
# logger.debug('roi lineouts plotted')
|
|
92
|
+
# self.roi_lineout_plotted.emit(roi_dicts)
|
|
92
93
|
|
|
93
94
|
def plot_other_lineouts(self, roi_dicts):
|
|
94
95
|
raise NotImplementedError
|
|
@@ -112,8 +113,9 @@ class LineoutPlotter(QObject):
|
|
|
112
113
|
param, param_value = param_changed
|
|
113
114
|
|
|
114
115
|
if param.name() == 'Color':
|
|
115
|
-
|
|
116
|
-
curve.
|
|
116
|
+
if roi_key in self._roi_curves:
|
|
117
|
+
for curve in self._roi_curves[roi_key].values():
|
|
118
|
+
curve.setPen(param_value)
|
|
117
119
|
|
|
118
120
|
self.roi_changed.emit(self._roi_manager.ROIs)
|
|
119
121
|
|
|
@@ -130,7 +132,7 @@ class LineoutPlotter(QObject):
|
|
|
130
132
|
item_param = self._roi_manager.settings.child('ROIs', 'ROI_{:02d}'.format(newindex))
|
|
131
133
|
color = item_param.child('Color').value()
|
|
132
134
|
|
|
133
|
-
self.add_roi_lineout_items(newindex, color)
|
|
135
|
+
#self.add_roi_lineout_items(newindex, color)
|
|
134
136
|
self.roi_changed.emit(self._roi_manager.ROIs)
|
|
135
137
|
|
|
136
138
|
def add_roi_lineout_items(self, index, pen):
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from collections.abc import Iterable
|
|
2
|
+
from dataclasses import dataclass, field
|
|
2
3
|
|
|
3
4
|
import copy
|
|
4
5
|
from numbers import Real, Number
|
|
5
|
-
from typing import List, Union
|
|
6
|
+
from typing import List, Union, Tuple
|
|
6
7
|
from typing import Iterable as IterableType
|
|
7
8
|
|
|
8
9
|
from easydict import EasyDict as edict
|
|
@@ -13,10 +14,15 @@ from qtpy import QtGui, QtCore, QtWidgets
|
|
|
13
14
|
from scipy.spatial import Delaunay as Triangulation
|
|
14
15
|
|
|
15
16
|
from pymodaq.utils import data as data_mod
|
|
16
|
-
from pymodaq.utils.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
from pymodaq.utils.managers.roi_manager import LinearROI, RectROI, EllipseROI, pgROI, pgLinearROI
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def make_dashed_pens(color: tuple, nstyle=3):
|
|
21
|
+
pens = [dict(color=color)]
|
|
22
|
+
if nstyle > 1:
|
|
23
|
+
for ind in range(nstyle - 1):
|
|
24
|
+
pens.append(dict(color=color, dash=np.array([5, 5]) * (ind + 1)))
|
|
25
|
+
return pens
|
|
20
26
|
|
|
21
27
|
|
|
22
28
|
class Point:
|
|
@@ -30,7 +36,7 @@ class Point:
|
|
|
30
36
|
if len(elt) == 1 and isinstance(elt[0], Iterable):
|
|
31
37
|
elt = elt[0]
|
|
32
38
|
|
|
33
|
-
self._coordinates = np.atleast_1d(np.squeeze(elt))
|
|
39
|
+
self._coordinates: np.ndarray = np.atleast_1d(np.squeeze(elt))
|
|
34
40
|
self._ndim = len(elt)
|
|
35
41
|
|
|
36
42
|
@property
|
|
@@ -40,8 +46,8 @@ class Point:
|
|
|
40
46
|
def copy(self):
|
|
41
47
|
return Point(self.coordinates.copy())
|
|
42
48
|
|
|
43
|
-
def __getitem__(self, item: int):
|
|
44
|
-
return self._coordinates[item]
|
|
49
|
+
def __getitem__(self, item: int) -> float:
|
|
50
|
+
return float(self._coordinates[item])
|
|
45
51
|
|
|
46
52
|
def __setitem__(self, key: int, value: float):
|
|
47
53
|
self._coordinates[key] = value
|
|
@@ -53,6 +59,12 @@ class Point:
|
|
|
53
59
|
if len(self) != len(other):
|
|
54
60
|
raise ValueError('Those points should be expressed in the same coordinate system and dimensions')
|
|
55
61
|
|
|
62
|
+
def __eq__(self, other):
|
|
63
|
+
if isinstance(other, Point):
|
|
64
|
+
return np.allclose(self.coordinates, other.coordinates)
|
|
65
|
+
else:
|
|
66
|
+
return False
|
|
67
|
+
|
|
56
68
|
def __add__(self, other: Union['Point', 'Vector']):
|
|
57
69
|
self._compare_length(other)
|
|
58
70
|
return Point(*(self._coordinates + other._coordinates))
|
|
@@ -403,6 +415,7 @@ class Data0DWithHistory:
|
|
|
403
415
|
def __init__(self, Nsamples=200):
|
|
404
416
|
super().__init__()
|
|
405
417
|
self._datas = dict([])
|
|
418
|
+
self.last_data: data_mod.DataRaw = None
|
|
406
419
|
self._Nsamples = Nsamples
|
|
407
420
|
self._xaxis = None
|
|
408
421
|
self._data_length = 0
|
|
@@ -424,19 +437,21 @@ class Data0DWithHistory:
|
|
|
424
437
|
return self.length
|
|
425
438
|
|
|
426
439
|
@dispatch(data_mod.DataWithAxes)
|
|
427
|
-
def add_datas(self, data: data_mod.
|
|
440
|
+
def add_datas(self, data: data_mod.DataWithAxes):
|
|
441
|
+
self.last_data = data
|
|
428
442
|
datas = {data.labels[ind]: data.data[ind] for ind in range(len(data))}
|
|
429
443
|
self.add_datas(datas)
|
|
430
444
|
|
|
431
445
|
@dispatch(list)
|
|
432
|
-
def add_datas(self,
|
|
446
|
+
def add_datas(self, data: list):
|
|
433
447
|
"""
|
|
434
448
|
Add datas to the history
|
|
435
449
|
Parameters
|
|
436
450
|
----------
|
|
437
|
-
|
|
451
|
+
data: (list) list of floats or np.array(float)
|
|
438
452
|
"""
|
|
439
|
-
|
|
453
|
+
self.last_data = data_mod.DataRaw('Data0D', data=[np.array([dat]) for dat in data])
|
|
454
|
+
datas = {f'data_{ind:02d}': data[ind] for ind in range(len(data))}
|
|
440
455
|
self.add_datas(datas)
|
|
441
456
|
|
|
442
457
|
@dispatch(dict)
|
|
@@ -500,3 +515,65 @@ class View_cust(pg.ViewBox):
|
|
|
500
515
|
if ev.double():
|
|
501
516
|
pos = self.mapToView(ev.pos())
|
|
502
517
|
self.sig_double_clicked.emit(pos.x(), pos.y())
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
@dataclass
|
|
521
|
+
class RoiInfo:
|
|
522
|
+
""" DataClass holding info about a given ROI
|
|
523
|
+
|
|
524
|
+
Parameters
|
|
525
|
+
----------
|
|
526
|
+
origin
|
|
527
|
+
size
|
|
528
|
+
angle
|
|
529
|
+
centered
|
|
530
|
+
color
|
|
531
|
+
roi_class
|
|
532
|
+
index
|
|
533
|
+
"""
|
|
534
|
+
|
|
535
|
+
origin: Union[Point, IterableType[float]]
|
|
536
|
+
size: Union[Point, IterableType[float]]
|
|
537
|
+
angle: float = None
|
|
538
|
+
centered: bool = False
|
|
539
|
+
color: Tuple[int, int, int] = (255, 0, 0)
|
|
540
|
+
roi_class: type = None
|
|
541
|
+
index: int = 0
|
|
542
|
+
|
|
543
|
+
@classmethod
|
|
544
|
+
def info_from_linear_roi(cls, roi: LinearROI):
|
|
545
|
+
pos = roi.pos()
|
|
546
|
+
return cls(Point((pos[0],)), size=Point((pos[1] - pos[0],)), color=roi.color,
|
|
547
|
+
roi_class=type(roi), index=roi.index)
|
|
548
|
+
|
|
549
|
+
@classmethod
|
|
550
|
+
def info_from_rect_roi(cls, roi: RectROI):
|
|
551
|
+
return cls(Point(list(roi.pos())[::-1]), size=Point((roi.height(), roi.width())),
|
|
552
|
+
color=roi.color, roi_class=type(roi), index=roi.index)
|
|
553
|
+
|
|
554
|
+
def center_origin(self):
|
|
555
|
+
if not self.centered:
|
|
556
|
+
self.origin += Point((self.size[0] / 2, self.size[1] / 2))
|
|
557
|
+
self.centered = True
|
|
558
|
+
|
|
559
|
+
def to_slices(self) -> IterableType[slice]:
|
|
560
|
+
"""Get slices to be used directly to slice DataWithAxes"""
|
|
561
|
+
if issubclass(self.roi_class, pgROI):
|
|
562
|
+
if self.centered:
|
|
563
|
+
return (slice(int(self.origin[0] - self.size[0] / 2),
|
|
564
|
+
int(self.origin[0] + self.size[0] / 2)),
|
|
565
|
+
slice(int(self.origin[1] - self.size[1] / 2),
|
|
566
|
+
int(self.origin[1] + self.size[1] / 2)),
|
|
567
|
+
)
|
|
568
|
+
else:
|
|
569
|
+
return (slice(int(self.origin[0]),
|
|
570
|
+
int(self.origin[0] + self.size[0])),
|
|
571
|
+
slice(int(self.origin[1]),
|
|
572
|
+
int(self.origin[1] + self.size[1])),
|
|
573
|
+
)
|
|
574
|
+
elif issubclass(self.roi_class, pgLinearROI):
|
|
575
|
+
if self.centered:
|
|
576
|
+
return (slice(int(self.origin[0] - self.size[0] / 2),
|
|
577
|
+
int(self.origin[0] + self.size[0] / 2)),)
|
|
578
|
+
else:
|
|
579
|
+
return (slice(int(self.origin[0]), int(self.origin[0] + self.size[0])),)
|