pymodaq 3.6.12__py3-none-any.whl → 4.0.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.

Files changed (233) hide show
  1. pymodaq/__init__.py +13 -6
  2. pymodaq/control_modules/__init__.py +0 -7
  3. pymodaq/control_modules/daq_move.py +965 -2
  4. pymodaq/control_modules/daq_move_ui.py +319 -0
  5. pymodaq/control_modules/daq_viewer.py +1573 -3
  6. pymodaq/control_modules/daq_viewer_ui.py +393 -0
  7. pymodaq/control_modules/mocks.py +51 -0
  8. pymodaq/control_modules/move_utility_classes.py +709 -8
  9. pymodaq/control_modules/utils.py +256 -0
  10. pymodaq/control_modules/viewer_utility_classes.py +663 -6
  11. pymodaq/daq_utils.py +89 -0
  12. pymodaq/dashboard.py +91 -72
  13. pymodaq/examples/custom_app.py +12 -11
  14. pymodaq/examples/custom_viewer.py +10 -10
  15. pymodaq/examples/function_plotter.py +16 -13
  16. pymodaq/examples/nonlinearscanner.py +8 -6
  17. pymodaq/examples/parameter_ex.py +7 -7
  18. pymodaq/examples/preset_MockCamera.xml +1 -0
  19. pymodaq/extensions/__init__.py +16 -0
  20. pymodaq/extensions/console.py +76 -0
  21. pymodaq/{daq_logger.py → extensions/daq_logger.py} +115 -65
  22. pymodaq/extensions/daq_scan.py +1339 -0
  23. pymodaq/extensions/daq_scan_ui.py +240 -0
  24. pymodaq/extensions/h5browser.py +23 -0
  25. pymodaq/{pid → extensions/pid}/__init__.py +4 -2
  26. pymodaq/{pid → extensions/pid}/daq_move_PID.py +2 -2
  27. pymodaq/{pid → extensions/pid}/pid_controller.py +48 -36
  28. pymodaq/{pid → extensions/pid}/utils.py +52 -6
  29. pymodaq/extensions/utils.py +40 -0
  30. pymodaq/post_treatment/__init__.py +6 -0
  31. pymodaq/{daq_analysis → post_treatment/daq_analysis}/daq_analysis_main.py +17 -17
  32. pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_main.py +8 -14
  33. pymodaq/post_treatment/load_and_plot.py +219 -0
  34. pymodaq/post_treatment/process_to_scalar.py +263 -0
  35. pymodaq/resources/QtDesigner_Ressources/Icon_Library/run_all.png +0 -0
  36. pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop_all.png +0 -0
  37. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.bat +1 -1
  38. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.qrc +1 -0
  39. pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources_rc.py +109784 -109173
  40. pymodaq/resources/QtDesigner_Ressources/icons.svg +142 -0
  41. pymodaq/resources/VERSION +1 -1
  42. pymodaq/resources/config_template.toml +32 -13
  43. pymodaq/resources/preset_default.xml +1 -1
  44. pymodaq/{daq_utils → utils}/Tuto innosetup/script_full_setup.iss +1 -1
  45. pymodaq/utils/__init__.py +0 -29
  46. pymodaq/utils/abstract/__init__.py +48 -0
  47. pymodaq/{daq_utils → utils}/abstract/logger.py +7 -3
  48. pymodaq/utils/array_manipulation.py +379 -8
  49. pymodaq/{daq_utils → utils}/calibration_camera.py +6 -6
  50. pymodaq/{daq_utils → utils}/chrono_timer.py +1 -1
  51. pymodaq/utils/config.py +448 -0
  52. pymodaq/utils/conftests.py +5 -0
  53. pymodaq/utils/daq_utils.py +828 -8
  54. pymodaq/utils/data.py +1873 -7
  55. pymodaq/{daq_utils → utils}/db/db_logger/db_logger.py +86 -47
  56. pymodaq/{daq_utils → utils}/db/db_logger/db_logger_models.py +31 -10
  57. pymodaq/{daq_utils → utils}/enums.py +12 -7
  58. pymodaq/utils/exceptions.py +37 -0
  59. pymodaq/utils/factory.py +82 -0
  60. pymodaq/{daq_utils → utils}/gui_utils/__init__.py +1 -1
  61. pymodaq/utils/gui_utils/custom_app.py +129 -0
  62. pymodaq/utils/gui_utils/file_io.py +66 -0
  63. pymodaq/{daq_utils → utils}/gui_utils/layout.py +2 -2
  64. pymodaq/{daq_utils → utils}/gui_utils/utils.py +13 -3
  65. pymodaq/{daq_utils → utils}/gui_utils/widgets/__init__.py +2 -2
  66. pymodaq/utils/gui_utils/widgets/label.py +24 -0
  67. pymodaq/{daq_utils → utils}/gui_utils/widgets/lcd.py +12 -7
  68. pymodaq/{daq_utils → utils}/gui_utils/widgets/push.py +66 -2
  69. pymodaq/{daq_utils → utils}/gui_utils/widgets/qled.py +6 -4
  70. pymodaq/utils/gui_utils/widgets/spinbox.py +24 -0
  71. pymodaq/{daq_utils → utils}/gui_utils/widgets/table.py +2 -2
  72. pymodaq/utils/h5modules/__init__.py +1 -0
  73. pymodaq/{daq_utils/h5backend.py → utils/h5modules/backends.py} +200 -112
  74. pymodaq/utils/h5modules/browsing.py +683 -0
  75. pymodaq/utils/h5modules/data_saving.py +839 -0
  76. pymodaq/utils/h5modules/h5logging.py +110 -0
  77. pymodaq/utils/h5modules/module_saving.py +350 -0
  78. pymodaq/utils/h5modules/saving.py +914 -0
  79. pymodaq/utils/h5modules/utils.py +85 -0
  80. pymodaq/utils/logger.py +64 -6
  81. pymodaq/utils/managers/action_manager.py +460 -0
  82. pymodaq/{daq_utils → utils}/managers/batchscan_manager.py +144 -112
  83. pymodaq/{daq_utils → utils}/managers/modules_manager.py +188 -114
  84. pymodaq/{daq_utils → utils}/managers/overshoot_manager.py +3 -3
  85. pymodaq/utils/managers/parameter_manager.py +110 -0
  86. pymodaq/{daq_utils → utils}/managers/preset_manager.py +17 -13
  87. pymodaq/{daq_utils → utils}/managers/preset_manager_utils.py +8 -7
  88. pymodaq/{daq_utils → utils}/managers/remote_manager.py +7 -6
  89. pymodaq/{daq_utils → utils}/managers/roi_manager.py +148 -57
  90. pymodaq/utils/math_utils.py +546 -10
  91. pymodaq/{daq_utils → utils}/messenger.py +5 -1
  92. pymodaq/utils/parameter/__init__.py +2 -15
  93. pymodaq/{daq_utils → utils}/parameter/ioxml.py +12 -6
  94. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/__init__.py +1 -3
  95. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/filedir.py +1 -1
  96. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/itemselect.py +3 -0
  97. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/led.py +1 -1
  98. pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py +161 -0
  99. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/slide.py +1 -1
  100. pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/table.py +1 -1
  101. pymodaq/utils/parameter/utils.py +206 -11
  102. pymodaq/utils/plotting/data_viewers/__init__.py +6 -0
  103. pymodaq/utils/plotting/data_viewers/viewer.py +393 -0
  104. pymodaq/utils/plotting/data_viewers/viewer0D.py +251 -0
  105. pymodaq/utils/plotting/data_viewers/viewer1D.py +574 -0
  106. pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer1Dbasic.py +8 -3
  107. pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D.py +292 -357
  108. pymodaq/{daq_utils → utils}/plotting/data_viewers/viewer2D_basic.py +58 -75
  109. pymodaq/utils/plotting/data_viewers/viewerND.py +738 -0
  110. pymodaq/{daq_utils → utils}/plotting/gant_chart.py +2 -2
  111. pymodaq/{daq_utils → utils}/plotting/items/axis_scaled.py +4 -2
  112. pymodaq/{daq_utils → utils}/plotting/items/image.py +8 -6
  113. pymodaq/utils/plotting/navigator.py +355 -0
  114. pymodaq/utils/plotting/scan_selector.py +480 -0
  115. pymodaq/utils/plotting/utils/axes_viewer.py +88 -0
  116. pymodaq/utils/plotting/utils/filter.py +538 -0
  117. pymodaq/utils/plotting/utils/lineout.py +224 -0
  118. pymodaq/{daq_utils → utils}/plotting/utils/plot_utils.py +196 -84
  119. pymodaq/{daq_utils → utils}/plotting/utils/signalND.py +21 -13
  120. pymodaq/utils/plotting/widgets.py +76 -0
  121. pymodaq/utils/scanner/__init__.py +10 -0
  122. pymodaq/utils/scanner/scan_factory.py +204 -0
  123. pymodaq/utils/scanner/scanner.py +271 -0
  124. pymodaq/utils/scanner/scanners/_1d_scanners.py +117 -0
  125. pymodaq/utils/scanner/scanners/_2d_scanners.py +293 -0
  126. pymodaq/utils/scanner/scanners/sequential.py +192 -0
  127. pymodaq/utils/scanner/scanners/tabular.py +294 -0
  128. pymodaq/utils/scanner/utils.py +83 -0
  129. pymodaq/utils/slicing.py +47 -0
  130. pymodaq/utils/svg/__init__.py +6 -0
  131. pymodaq/utils/svg/svg_renderer.py +20 -0
  132. pymodaq/utils/svg/svg_view.py +35 -0
  133. pymodaq/utils/svg/svg_viewer2D.py +51 -0
  134. pymodaq/{daq_utils → utils}/tcp_server_client.py +36 -37
  135. pymodaq/{daq_utils → utils}/tree_layout/tree_layout_main.py +50 -35
  136. pymodaq/utils/units.py +216 -0
  137. pymodaq-4.0.1.dist-info/METADATA +159 -0
  138. {pymodaq-3.6.12.dist-info → pymodaq-4.0.1.dist-info}/RECORD +167 -170
  139. {pymodaq-3.6.12.dist-info → pymodaq-4.0.1.dist-info}/WHEEL +1 -2
  140. pymodaq-4.0.1.dist-info/entry_points.txt +8 -0
  141. pymodaq/daq_move/daq_move_gui.py +0 -279
  142. pymodaq/daq_move/daq_move_gui.ui +0 -534
  143. pymodaq/daq_move/daq_move_main.py +0 -1042
  144. pymodaq/daq_move/process_from_QtDesigner_DAQ_Move_GUI.bat +0 -2
  145. pymodaq/daq_move/utility_classes.py +0 -671
  146. pymodaq/daq_scan.py +0 -2160
  147. pymodaq/daq_utils/array_manipulation.py +0 -386
  148. pymodaq/daq_utils/config.py +0 -273
  149. pymodaq/daq_utils/conftests.py +0 -7
  150. pymodaq/daq_utils/custom_parameter_tree.py +0 -9
  151. pymodaq/daq_utils/daq_enums.py +0 -133
  152. pymodaq/daq_utils/daq_utils.py +0 -1402
  153. pymodaq/daq_utils/exceptions.py +0 -71
  154. pymodaq/daq_utils/gui_utils/custom_app.py +0 -103
  155. pymodaq/daq_utils/gui_utils/file_io.py +0 -75
  156. pymodaq/daq_utils/gui_utils/widgets/spinbox.py +0 -9
  157. pymodaq/daq_utils/h5exporter_hyperspy.py +0 -115
  158. pymodaq/daq_utils/h5exporters.py +0 -242
  159. pymodaq/daq_utils/h5modules.py +0 -1559
  160. pymodaq/daq_utils/h5utils.py +0 -241
  161. pymodaq/daq_utils/managers/action_manager.py +0 -236
  162. pymodaq/daq_utils/managers/parameter_manager.py +0 -57
  163. pymodaq/daq_utils/math_utils.py +0 -705
  164. pymodaq/daq_utils/parameter/__init__.py +0 -1
  165. pymodaq/daq_utils/parameter/oldpymodaq_ptypes.py +0 -1626
  166. pymodaq/daq_utils/parameter/pymodaq_ptypes/pixmap.py +0 -85
  167. pymodaq/daq_utils/parameter/utils.py +0 -136
  168. pymodaq/daq_utils/plotting/data_viewers/__init__.py +0 -0
  169. pymodaq/daq_utils/plotting/data_viewers/process_from_QtDesigner_0DViewer_GUI.bat +0 -2
  170. pymodaq/daq_utils/plotting/data_viewers/viewer0D.py +0 -204
  171. pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.py +0 -89
  172. pymodaq/daq_utils/plotting/data_viewers/viewer0D_GUI.ui +0 -131
  173. pymodaq/daq_utils/plotting/data_viewers/viewer1D.py +0 -781
  174. pymodaq/daq_utils/plotting/data_viewers/viewerND.py +0 -894
  175. pymodaq/daq_utils/plotting/data_viewers/viewerbase.py +0 -64
  176. pymodaq/daq_utils/plotting/items/__init__.py +0 -0
  177. pymodaq/daq_utils/plotting/navigator.py +0 -500
  178. pymodaq/daq_utils/plotting/scan_selector.py +0 -289
  179. pymodaq/daq_utils/plotting/utils/__init__.py +0 -0
  180. pymodaq/daq_utils/plotting/utils/filter.py +0 -236
  181. pymodaq/daq_utils/plotting/viewer0D/__init__.py +0 -0
  182. pymodaq/daq_utils/plotting/viewer0D/viewer0D_main.py +0 -4
  183. pymodaq/daq_utils/plotting/viewer1D/__init__.py +0 -0
  184. pymodaq/daq_utils/plotting/viewer1D/viewer1D_main.py +0 -4
  185. pymodaq/daq_utils/plotting/viewer1D/viewer1Dbasic.py +0 -4
  186. pymodaq/daq_utils/plotting/viewer2D/viewer_2D_basic.py +0 -4
  187. pymodaq/daq_utils/plotting/viewer2D/viewer_2D_main.py +0 -4
  188. pymodaq/daq_utils/plotting/viewerND/__init__.py +0 -0
  189. pymodaq/daq_utils/plotting/viewerND/viewerND_main.py +0 -4
  190. pymodaq/daq_utils/scanner.py +0 -1289
  191. pymodaq/daq_utils/tree_layout/__init__.py +0 -0
  192. pymodaq/daq_viewer/__init__.py +0 -0
  193. pymodaq/daq_viewer/daq_gui_settings.py +0 -237
  194. pymodaq/daq_viewer/daq_gui_settings.ui +0 -441
  195. pymodaq/daq_viewer/daq_viewer_main.py +0 -2225
  196. pymodaq/daq_viewer/process_from_QtDesigner_DAQ_GUI_settings.bat +0 -2
  197. pymodaq/daq_viewer/utility_classes.py +0 -673
  198. pymodaq/examples/logger_image/__init__.py +0 -0
  199. pymodaq/examples/logger_image/logger_displayer.py +0 -121
  200. pymodaq/examples/logger_image/setup.svg +0 -3119
  201. pymodaq/examples/logger_image/setup_svg.py +0 -114
  202. pymodaq/h5browser.py +0 -39
  203. pymodaq/utils/scanner.py +0 -15
  204. pymodaq-3.6.12.dist-info/METADATA +0 -39
  205. pymodaq-3.6.12.dist-info/entry_points.txt +0 -8
  206. pymodaq-3.6.12.dist-info/top_level.txt +0 -1
  207. /pymodaq/{daq_analysis → post_treatment/daq_analysis}/__init__.py +0 -0
  208. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/__init__.py +0 -0
  209. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.py +0 -0
  210. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/daq_measurement_GUI.ui +0 -0
  211. /pymodaq/{daq_measurement → post_treatment/daq_measurement}/process_from_QtDesigner_DAQ_Measurement_GUI.bat +0 -0
  212. /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.odt +0 -0
  213. /pymodaq/{daq_utils → utils}/Tuto innosetup/Tuto innosetup.pdf +0 -0
  214. /pymodaq/{daq_move → utils/db}/__init__.py +0 -0
  215. /pymodaq/{daq_utils → utils/db/db_logger}/__init__.py +0 -0
  216. /pymodaq/{daq_utils → utils}/gui_utils/dock.py +0 -0
  217. /pymodaq/{daq_utils → utils}/gui_utils/list_picker.py +0 -0
  218. /pymodaq/{daq_utils/abstract → utils/managers}/__init__.py +0 -0
  219. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/bool.py +0 -0
  220. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/date.py +0 -0
  221. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/list.py +0 -0
  222. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/numeric.py +0 -0
  223. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/tableview.py +0 -0
  224. /pymodaq/{daq_utils → utils}/parameter/pymodaq_ptypes/text.py +0 -0
  225. /pymodaq/{daq_utils/db → utils/plotting}/__init__.py +0 -0
  226. /pymodaq/{daq_utils → utils}/plotting/image_viewer.py +0 -0
  227. /pymodaq/{daq_utils/db/db_logger → utils/plotting/items}/__init__.py +0 -0
  228. /pymodaq/{daq_utils → utils}/plotting/items/crosshair.py +0 -0
  229. /pymodaq/{daq_utils/managers → utils/plotting/utils}/__init__.py +0 -0
  230. /pymodaq/{daq_utils → utils}/qvariant.py +0 -0
  231. /pymodaq/{daq_utils/plotting/viewer2D → utils/scanner/scanners}/__init__.py +0 -0
  232. /pymodaq/{daq_utils/plotting → utils/tree_layout}/__init__.py +0 -0
  233. {pymodaq-3.6.12.dist-info → pymodaq-4.0.1.dist-info/licenses}/LICENSE +0 -0
@@ -3,29 +3,31 @@ import copy
3
3
  import datetime
4
4
  import numpy as np
5
5
  import sys
6
+ from typing import Union, Iterable
6
7
 
7
- import pymodaq.daq_utils.messenger
8
+ import pymodaq.utils.messenger
8
9
  from qtpy import QtCore, QtGui, QtWidgets
9
10
  from qtpy.QtCore import QObject, Slot, Signal
10
11
  import pyqtgraph as pg
11
12
  from pyqtgraph.graphicsItems.GradientEditorItem import Gradients
12
13
  from pyqtgraph import ROI as pgROI
13
14
 
14
- from pymodaq.daq_utils.managers.roi_manager import ROIManager
15
- from pymodaq.daq_utils.managers.action_manager import ActionManager
16
- from pymodaq.daq_utils.plotting.data_viewers.viewer2D_basic import ImageWidget
17
- from pyqtgraph import PlotCurveItem
18
- from pymodaq.daq_utils.plotting.data_viewers.viewerbase import ViewerBase
19
- from pymodaq.daq_utils.plotting.items.image import UniformImageItem, SpreadImageItem
20
- from pymodaq.daq_utils.plotting.items.axis_scaled import AXIS_POSITIONS
21
- from pymodaq.daq_utils.plotting.items.crosshair import Crosshair
22
- from pymodaq.daq_utils.plotting.utils.plot_utils import Data0DWithHistory, AxisInfosExtractor
23
- from pymodaq.daq_utils.plotting.utils.filter import FilterFromCrosshair, FilterFromRois
24
- import pymodaq.daq_utils.daq_utils as utils
25
- import pymodaq.daq_utils.gui_utils as gutils
26
- from pymodaq.daq_utils.exceptions import ViewerError
27
-
28
- logger = utils.set_logger(utils.get_module_name(__file__))
15
+ from pymodaq.utils.data import Axis, DataToExport, DataFromRoi, DataFromPlugins, DataRaw, DataDistribution, DataWithAxes
16
+ from pymodaq.utils.logger import set_logger, get_module_name
17
+ from pymodaq.utils.managers.roi_manager import ROIManager, SimpleRectROI
18
+ from pymodaq.utils.managers.action_manager import ActionManager
19
+ from pymodaq.utils.plotting.widgets import ImageWidget
20
+
21
+ from pymodaq.utils.plotting.data_viewers.viewer import ViewerBase
22
+ from pymodaq.utils.plotting.items.image import UniformImageItem, SpreadImageItem
23
+ from pymodaq.utils.plotting.items.axis_scaled import AXIS_POSITIONS, AxisItem_Scaled
24
+ from pymodaq.utils.plotting.items.crosshair import Crosshair
25
+ from pymodaq.utils.plotting.utils.filter import Filter2DFromCrosshair, Filter2DFromRois
26
+ import pymodaq.utils.daq_utils as utils
27
+ from pymodaq.utils.plotting.utils.lineout import LineoutPlotter, curve_item_factory
28
+
29
+
30
+ logger = set_logger(get_module_name(__file__))
29
31
 
30
32
  Gradients.update(OrderedDict([
31
33
  ('red', {'ticks': [(0.0, (0, 0, 0, 255)), (1.0, (255, 0, 0, 255))], 'mode': 'rgb'}),
@@ -35,7 +37,7 @@ Gradients.update(OrderedDict([
35
37
 
36
38
  COLORS_DICT = dict(red=(255, 0, 0), green=(0, 255, 0), blue=(0, 0, 255), spread=(128, 128, 128))
37
39
  IMAGE_TYPES = ['red', 'green', 'blue']
38
- LINEOUT_WIDGETS = ['hor', 'ver', 'int']
40
+
39
41
  COLOR_LIST = utils.plot_colors
40
42
 
41
43
 
@@ -73,24 +75,6 @@ def histogram_factory(image_item=None, gradient='red'):
73
75
  return histo
74
76
 
75
77
 
76
- def curve_item_factory(pen='red'):
77
- """
78
- Create a PlotCurveItem with the given pen
79
- Parameters
80
- ----------
81
- pen: any type of arguments accepted by pyqtgraph.function.mkColor or one of the COLORS_DICT key
82
-
83
- Returns
84
- -------
85
- PlotCurveItem
86
- """
87
- if isinstance(pen, str):
88
- if pen in COLORS_DICT:
89
- pen = COLORS_DICT[pen]
90
-
91
- return PlotCurveItem(pen=pen)
92
-
93
-
94
78
  class ImageDisplayer(QObject):
95
79
  """
96
80
  This Object deals with the display of 2D data with a plotitem
@@ -98,10 +82,10 @@ class ImageDisplayer(QObject):
98
82
 
99
83
  updated_item = Signal(dict)
100
84
 
101
- def __init__(self, plotitem):
85
+ def __init__(self, plotitem, data_distribution: DataDistribution):
102
86
  super().__init__()
103
87
  self._plotitem = plotitem
104
- self.display_type = 'uniform'
88
+ self.display_type = data_distribution
105
89
  self._image_items = dict([])
106
90
  self._autolevels = False
107
91
 
@@ -124,13 +108,18 @@ class ImageDisplayer(QObject):
124
108
  def set_autolevels(self, isautolevel):
125
109
  self._autolevels = isautolevel
126
110
 
127
- def update_data(self, datas):
128
- if datas['distribution'] != self.display_type:
129
- self.display_type = datas['distribution']
111
+ def update_data(self, data):
112
+ if data.distribution != self.display_type:
113
+ self.display_type = data.distribution
130
114
  self.update_display_items()
131
- for ind_data, data in enumerate(datas['data']):
132
- if data.size > 0:
133
- self._image_items[IMAGE_TYPES[ind_data]].setImage(data, self.autolevels)
115
+ for ind_data, data_array in enumerate(data.data):
116
+ if data_array.size > 0:
117
+ if self.display_type == 'uniform':
118
+ self._image_items[IMAGE_TYPES[ind_data]].setImage(data_array, self.autolevels)
119
+ else:
120
+ nav_axes = data.get_nav_axes()
121
+ data_array = np.stack((nav_axes[0].data, nav_axes[1].data, data_array), axis=0).T
122
+ self._image_items[IMAGE_TYPES[ind_data]].setImage(data_array, self.autolevels)
134
123
 
135
124
  def update_display_items(self):
136
125
  while len(self._image_items) > 0:
@@ -268,170 +257,42 @@ class IsoCurver(QObject):
268
257
  self._isoLine.hide()
269
258
 
270
259
 
271
- class LineoutPlotter(QObject):
272
-
273
- roi_changed = Signal(dict)
274
- crosshair_lineout_plotted = Signal(dict)
275
- roi_lineout_plotted = Signal(dict)
276
-
277
- def __init__(self, graph_widgets, roi_manager, crosshair):
278
- super().__init__()
279
-
280
- self._roi_manager = roi_manager
281
- self._crosshair = crosshair
282
-
283
- self._lineout_widgets = graph_widgets['lineouts']
260
+ class LineoutPlotter(LineoutPlotter):
261
+ """class to manage and display data filtered out into lineouts (1D, 0D)
284
262
 
285
- self.integrated_data = Data0DWithHistory()
263
+ Should be inherited and subclass some methods as appropriate
286
264
 
287
- self._roi_curves = OrderedDict()
288
- self._crosshair_curves = OrderedDict()
289
- self._data_integrated = []
290
-
291
- self.setup_crosshair()
265
+ Parameters
266
+ ----------
267
+ graph_widgets: OrderedDict
268
+ Includes plotwidgets to display data
269
+ roi_manager:
270
+ The ROIManager to create ROIs and manage their properties
271
+ crosshair:
272
+ The Crosshair object
273
+ """
274
+ lineout_widgets = ['hor', 'ver', 'int']
292
275
 
293
- self._roi_manager.new_ROI_signal.connect(self.add_ROI)
294
- self._roi_manager.remove_ROI_signal.connect(self.remove_ROI)
295
- self._roi_manager.roi_value_changed.connect(self.update_roi)
276
+ def __init__(self, graph_widgets: OrderedDict, roi_manager: ROIManager, crosshair: Crosshair):
277
+ super().__init__(graph_widgets, roi_manager, crosshair)
296
278
 
297
- def plot_roi_lineouts(self, roi_dicts):
298
- self.integrated_data.add_datas({roi_key: roi_dicts[roi_key].int_data for roi_key in roi_dicts})
279
+ def plot_other_lineouts(self, roi_dicts):
299
280
  for roi_key, lineout_data in roi_dicts.items():
300
281
  if roi_key in self._roi_curves:
301
282
  if lineout_data.hor_data.size > 0:
302
283
  self._roi_curves[roi_key]['hor'].setData(lineout_data.hor_axis, lineout_data.hor_data)
303
284
  self._roi_curves[roi_key]['ver'].setData(lineout_data.ver_data, lineout_data.ver_axis)
304
- self._roi_curves[roi_key]['int'].setData(self.integrated_data.xaxis,
305
- self.integrated_data.datas[roi_key])
306
- logger.debug('roi lineouts plotted')
307
- self.roi_lineout_plotted.emit(roi_dicts)
308
285
 
309
- def plot_crosshair_lineouts(self, crosshair_dict):
286
+ def plot_other_crosshair_lineouts(self, crosshair_dict):
310
287
  for data_key, lineout_data in crosshair_dict.items():
311
288
  if data_key in self._crosshair_curves:
312
289
  self._crosshair_curves[data_key]['hor'].setData(lineout_data.hor_axis, lineout_data.hor_data)
313
290
  self._crosshair_curves[data_key]['ver'].setData(lineout_data.ver_data, lineout_data.ver_axis)
314
- logger.debug('crosshair lineouts plotted')
315
- self.crosshair_lineout_plotted.emit(crosshair_dict)
316
-
317
- def get_lineout_widget(self, name):
318
- if name not in LINEOUT_WIDGETS:
319
- raise KeyError(f'The lineout_widget reference should be within {LINEOUT_WIDGETS} not {name}')
320
- return self._lineout_widgets[name]
321
-
322
- @Slot(str, tuple)
323
- def update_roi(self, roi_key, param_changed):
324
- param, param_value = param_changed
325
-
326
- if param.name() == 'Color':
327
- for curve in self._roi_curves[roi_key].values():
328
- curve.setPen(param_value)
329
-
330
- self.roi_changed.emit(self._roi_manager.ROIs)
331
-
332
- @Slot(str)
333
- def remove_ROI(self, roi_name):
334
- index = int(roi_name.split('_')[1])
335
- self.remove_roi_lineout_items(index)
336
-
337
- self.roi_changed.emit(self._roi_manager.ROIs)
338
-
339
- @Slot(int, str)
340
- def add_ROI(self, newindex, roi_type):
341
- item = self._roi_manager.get_roi_from_index(newindex)
342
- item.sigRegionChanged.connect(lambda: self.roi_changed.emit(self._roi_manager.ROIs))
343
- item_param = self._roi_manager.settings.child('ROIs', 'ROI_{:02d}'.format(newindex))
344
- color = item_param.child(('Color')).value()
345
-
346
- self.add_roi_lineout_items(newindex, color)
347
- self.roi_changed.emit(self._roi_manager.ROIs)
348
-
349
- def add_roi_lineout_items(self, index, pen):
350
- """
351
- Add specifics lineouts generated from ROIs
352
- Parameters
353
- ----------
354
- index: (int) index of the ROI generating these lineouts
355
- pen: (str, tuple) any argument able to generate a QPen, see pyqtgraph.functions.mkPen
356
- """
357
- self._roi_curves[f'ROI_{index:02d}'] = \
358
- {curv_key: curve_item_factory(pen) for curv_key in LINEOUT_WIDGETS}
359
- self.add_lineout_items(*self._roi_curves[f'ROI_{index:02d}'].values())
360
-
361
- def remove_roi_lineout_items(self, index):
362
- """
363
- Remove specifics lineouts generated from ROI referenced by a unique integer
364
- Parameters
365
- ----------
366
- index: (int) index of the ROI generating these lineouts
367
- """
368
- items = self._roi_curves.pop(f'ROI_{index:02d}')
369
- self.remove_lineout_items(*items.values())
370
-
371
- def add_lineout_items(self, *curve_items):
372
- """
373
- Add Curve items sequentially to lineouts widgets: (hor, ver and int)
374
- Parameters
375
- ----------
376
- curve_items: (PlotCurveItem) at most 3 of them
377
- """
378
- for ind, curve_item in enumerate(curve_items):
379
- self.get_lineout_widget(LINEOUT_WIDGETS[ind]).addItem(curve_item)
380
-
381
- def remove_lineout_items(self, *curve_items):
382
- """
383
- Remove Curve items sequentially to lineouts widgets: (hor, ver and int)
384
- Parameters
385
- ----------
386
- curve_items: (PlotCurveItem) at most 3 of them
387
- """
388
-
389
- for ind, curve_item in enumerate(curve_items):
390
- self.get_lineout_widget(LINEOUT_WIDGETS[ind]).removeItem(curve_item)
391
-
392
- @Slot(bool)
393
- def roi_clicked(self, isroichecked=True):
394
- self._roi_manager.roiwidget.setVisible(isroichecked)
395
-
396
- for k, roi in self._roi_manager.ROIs.items():
397
- roi.setVisible(isroichecked)
398
- for item in self.get_roi_curves_triplet()[k].values():
399
- item.setVisible(isroichecked)
400
-
401
- Slot(bool)
402
- def crosshair_clicked(self, iscrosshairchecked=True):
403
- for image_key in IMAGE_TYPES:
404
- self.show_crosshair_curves(image_key, iscrosshairchecked)
405
-
406
- def get_roi_curves_triplet(self):
407
- """
408
- Get the dictionary (one key by ROI) containing dicts with ROI PlotCurveItem
409
-
410
- Example:
411
- --------
412
- >>> roi_dict_triplet = self.get_roi_cruves_triplet()
413
- >>> hor_curve = roi_dict_triplet['ROI_00']['hor'] # where 'hor' is an entry of LINEOUT_WIDGETS
414
- """
415
- return self._roi_curves
416
-
417
- def get_crosshair_curves_triplet(self):
418
- """
419
- Get the dictionary (one key by ImageItem, see IMAGE_TYPES) containing dicts with PlotCurveItem
420
-
421
- Example:
422
- --------
423
- >>> crosshair_dict_triplet = self.get_crosshair_curves_triplet()
424
- >>> hor_curve = crosshair_dict_triplet['blue']['hor'] # where 'hor' is an entry of LINEOUT_WIDGETS
425
- """
426
- return self._crosshair_curves
427
-
428
- def get_crosshair_curve_triplet(self, curve_name):
429
- return self._crosshair_curves[curve_name]
430
291
 
431
292
  def setup_crosshair(self):
432
293
  for image_key in IMAGE_TYPES:
433
294
  self._crosshair_curves[image_key] = \
434
- {curv_key: curve_item_factory(image_key) for curv_key in LINEOUT_WIDGETS}
295
+ {curv_key: curve_item_factory(image_key) for curv_key in self.lineout_widgets}
435
296
  self.add_lineout_items(self._crosshair_curves[image_key]['hor'], self._crosshair_curves[image_key]['ver'])
436
297
 
437
298
  def show_crosshair_curves(self, curve_key, show=True):
@@ -440,9 +301,12 @@ class LineoutPlotter(QObject):
440
301
 
441
302
 
442
303
  class View2D(ActionManager, QtCore.QObject):
304
+
443
305
  def __init__(self, parent_widget=None):
444
306
  QtCore.QObject.__init__(self)
445
307
  ActionManager.__init__(self, toolbar=QtWidgets.QToolBar())
308
+ self.ROIselect = SimpleRectROI([0, 0], [10, 10], centered=True, sideScalers=True)
309
+
446
310
  self.setup_actions()
447
311
 
448
312
  self.parent_widget = parent_widget
@@ -452,45 +316,66 @@ class View2D(ActionManager, QtCore.QObject):
452
316
 
453
317
  self.image_widget = ImageWidget()
454
318
  self.roi_manager = ROIManager(self.image_widget, '2D')
455
- self.ROIselect = pg.RectROI([0, 0], [10, 10], centered=True, sideScalers=True)
319
+
456
320
  self.roi_target = pgROI(pos=(0, 0), size=(20,20), movable=False, rotatable=False, resizable=False)
457
321
  self.roi_target.setVisible(False)
458
322
 
459
323
  self.setup_widgets()
460
324
 
461
325
  self.histogrammer = Histogrammer(self.widget_histo)
462
- self.data_displayer = ImageDisplayer(self.plotitem)
463
- self.isocurver = IsoCurver(self.data_displayer.get_image('red'), self.histogrammer.get_histogram('red'))
326
+ self.data_displayer: ImageDisplayer = None
327
+ self.isocurver: IsoCurver = None
464
328
 
465
329
  self.crosshair = Crosshair(self.image_widget)
466
330
  self.lineout_plotter = LineoutPlotter(self.graphical_widgets, self.roi_manager, self.crosshair)
467
331
 
468
-
469
-
470
332
  self.connect_things()
471
333
  self.prepare_ui()
472
334
 
473
335
  self.set_axis_label('bottom', label='', units='Pxls')
474
336
  self.set_axis_label('left', label='', units='Pxls')
475
337
 
338
+ self.set_image_displayer(DataDistribution['uniform'])
339
+
340
+ def clear_plot_item(self):
341
+ for item in self.plotitem.items[:]:
342
+ if isinstance(item, SpreadImageItem) or isinstance(item, UniformImageItem):
343
+ self.plotitem.removeItem(item)
344
+
345
+ def set_image_displayer(self, data_distribution: DataDistribution):
346
+ self.clear_plot_item()
347
+ self.data_displayer = ImageDisplayer(self.plotitem, data_distribution)
348
+ self.isocurver = IsoCurver(self.data_displayer.get_image('red'), self.histogrammer.get_histogram('red'))
349
+ self.data_displayer.updated_item.connect(self.histogrammer.affect_histo_to_imageitems)
350
+ self.connect_action('autolevels', self.data_displayer.set_autolevels)
351
+ for key in IMAGE_TYPES:
352
+ self.connect_action(key, self.notify_visibility_data_displayer)
353
+ self.connect_action('isocurve', self.isocurver.show_hide_iso)
354
+ self.histogrammer.affect_histo_to_imageitems(self.data_displayer.get_images())
355
+
476
356
  def show_roi_target(self, show=True):
477
357
  self.roi_target.setVisible(show)
478
358
 
479
359
  def move_scale_roi_target(self, pos=None, size=None):
480
360
  """
481
- Move and scale the target ROI (used to displat a particular area, for instance the currently scanned points
361
+ Move and scale the target ROI (used to display a particular area, for instance the currently scanned points
482
362
  during a scan
483
363
  Parameters
484
364
  ----------
485
365
  pos: (iterable) precising the central position of the ROI in the view
486
366
  size: (iterable) precising the size of the ROI
487
367
  """
368
+ if size is not None:
369
+ x_offset, x_scaling, y_offset, y_scaling = self._get_axis_scaling_offset()
370
+ size = list(np.divide(list(size), [x_scaling, y_scaling]))
371
+ if list(self.roi_target.size()) != size:
372
+ self.roi_target.setSize(size, center=(0.5, 0.5))
373
+
488
374
  if pos is not None:
489
- if self.roi_target.pos() != pos:
375
+ pos = self.unscale_axis(*list(pos))
376
+ pos = list(pos)
377
+ if list(self.roi_target.pos()) != pos:
490
378
  self.roi_target.setPos(pos)
491
- if size is not None:
492
- if self.roi_target.size() != size:
493
- self.roi_target.setSize(size)
494
379
 
495
380
  def setup_widgets(self):
496
381
  vertical_layout = QtWidgets.QVBoxLayout()
@@ -498,26 +383,21 @@ class View2D(ActionManager, QtCore.QObject):
498
383
  self.parent_widget.setLayout(vertical_layout)
499
384
  splitter_vertical = QtWidgets.QSplitter(QtCore.Qt.Vertical)
500
385
  vertical_layout.addWidget(splitter_vertical)
501
-
502
-
503
386
  splitter_vertical.addWidget(self.toolbar)
504
387
 
505
- # ####### Graphs, ImageItem, Histograms ############
506
388
  self.graphs_widget = QtWidgets.QWidget()
507
389
  self.graphs_widget.setLayout(QtWidgets.QHBoxLayout())
508
390
  self.graphs_widget.layout().setContentsMargins(0, 0, 0, 0)
509
- self.setupGraphs(self.graphs_widget.layout())
391
+ self.setup_graphs(self.graphs_widget.layout())
510
392
  splitter_vertical.addWidget(self.graphs_widget)
511
393
 
512
-
513
394
  self.plotitem.addItem(self.ROIselect)
514
-
515
395
  self.plotitem.addItem(self.roi_target)
516
396
 
517
397
  self.splitter_VLeft.splitterMoved[int, int].connect(self.move_right_splitter)
518
398
  self.splitter_VRight.splitterMoved[int, int].connect(self.move_left_splitter)
519
399
 
520
- def setupGraphs(self, graphs_layout):
400
+ def setup_graphs(self, graphs_layout):
521
401
  self.splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
522
402
  graphs_layout.addWidget(self.splitter)
523
403
 
@@ -531,7 +411,7 @@ class View2D(ActionManager, QtCore.QObject):
531
411
  self.splitter.addWidget(self.splitter_VLeft)
532
412
  self.splitter.addWidget(self.splitter_VRight)
533
413
 
534
- self._lineout_widgets = {widg_key: pg.PlotWidget() for widg_key in LINEOUT_WIDGETS}
414
+ self._lineout_widgets = {widg_key: pg.PlotWidget() for widg_key in LineoutPlotter.lineout_widgets}
535
415
  self.graphical_widgets = dict(lineouts=self._lineout_widgets, image=self.image_widget)
536
416
  self.splitter_VLeft.addWidget(self.image_widget)
537
417
  self.splitter_VLeft.addWidget(self._lineout_widgets['hor'])
@@ -572,14 +452,14 @@ class View2D(ActionManager, QtCore.QObject):
572
452
  tip='Rotate the image', checkable=True)
573
453
 
574
454
  def connect_things(self):
575
- self.data_displayer.updated_item.connect(self.histogrammer.affect_histo_to_imageitems)
576
- self.connect_action('autolevels', self.data_displayer.set_autolevels)
455
+
456
+
457
+
577
458
  self.connect_action('histo', self.histogrammer.activated)
578
459
  self.connect_action('autolevels', self.histogrammer.set_autolevels)
579
- self.connect_action('isocurve', self.isocurver.show_hide_iso)
460
+
580
461
  self.connect_action('isocurve', self.get_action('histo').trigger)
581
- for key in IMAGE_TYPES:
582
- self.connect_action(key, self.notify_visibility_data_displayer)
462
+
583
463
  self.connect_action('aspect_ratio', self.lock_aspect_ratio)
584
464
  self.connect_action('histo', self.show_hide_histogram)
585
465
  self.connect_action('roi', self.lineout_plotter.roi_clicked)
@@ -588,18 +468,18 @@ class View2D(ActionManager, QtCore.QObject):
588
468
  self.connect_action('crosshair', self.show_hide_crosshair)
589
469
  self.connect_action('crosshair', self.show_lineout_widgets)
590
470
  self.connect_action('crosshair', self.lineout_plotter.crosshair_clicked)
591
- self.histogrammer.affect_histo_to_imageitems(self.data_displayer.get_images())
471
+
592
472
 
593
473
  def prepare_ui(self):
594
474
  self.ROIselect.setVisible(False)
595
475
  self.show_hide_crosshair(False)
596
476
  self.show_lineout_widgets()
597
477
 
598
- @Slot(utils.DataFromPlugins)
478
+ @Slot(DataRaw)
599
479
  def display_images(self, datas):
600
480
  self.data_displayer.update_data(datas)
601
481
  if self.is_action_checked('isocurve'):
602
- self.isocurver.set_isocurve_data(datas['data'][0])
482
+ self.isocurver.set_isocurve_data(datas.data[0])
603
483
 
604
484
  def display_roi_lineouts(self, roi_dict):
605
485
  self.lineout_plotter.plot_roi_lineouts(roi_dict)
@@ -609,7 +489,7 @@ class View2D(ActionManager, QtCore.QObject):
609
489
 
610
490
  def show_lineout_widgets(self):
611
491
  state = self.is_action_checked('roi') or self.is_action_checked('crosshair')
612
- for lineout_name in LINEOUT_WIDGETS:
492
+ for lineout_name in LineoutPlotter.lineout_widgets:
613
493
  lineout = self.lineout_plotter.get_lineout_widget(lineout_name)
614
494
  lineout.setMouseEnabled(state, state)
615
495
  lineout.showAxis('left', state)
@@ -665,7 +545,7 @@ class View2D(ActionManager, QtCore.QObject):
665
545
  def get_double_clicked(self):
666
546
  return self.image_widget.view.sig_double_clicked
667
547
 
668
- def get_axis(self, position='left'):
548
+ def get_axis(self, position='left') -> AxisItem_Scaled:
669
549
  if position not in AXIS_POSITIONS:
670
550
  raise KeyError(f'{position} is not a possible position for Axis: {AXIS_POSITIONS}')
671
551
  return self.image_widget.getAxis(position)
@@ -715,7 +595,6 @@ class View2D(ActionManager, QtCore.QObject):
715
595
  axis = self.get_axis(position)
716
596
  return axis.axis_label, axis.axis_units
717
597
 
718
-
719
598
  def set_axis_scaling(self, position='top', scaling=1, offset=0, label='', units='Pxls'):
720
599
  """
721
600
  Method used to update the scaling of the right and top axes in order to translate pixels to real coordinates
@@ -727,16 +606,21 @@ class View2D(ActionManager, QtCore.QObject):
727
606
  label: (str) text of the axis label
728
607
  units: (str) units of the axis label
729
608
  """
730
-
609
+ if scaling is None:
610
+ scaling = 1
611
+ if offset is None:
612
+ offset = 0
731
613
  self.get_axis(position).axis_scaling = scaling
732
614
  self.get_axis(position).axis_offset = offset
733
615
  self.set_axis_label(position, label=label, units=units)
734
616
 
735
617
  def scale_axis(self, xaxis, yaxis):
618
+ """scale view coordinates from the regular axes to the scaled/offset ones"""
736
619
  x_offset, x_scaling, y_offset, y_scaling = self._get_axis_scaling_offset()
737
620
  return xaxis * x_scaling + x_offset, yaxis * y_scaling + y_offset
738
621
 
739
622
  def unscale_axis(self, xaxis, yaxis):
623
+ """scale view coordinates from the scaled/offset axes to the regular ones"""
740
624
  x_offset, x_scaling, y_offset, y_scaling = self._get_axis_scaling_offset()
741
625
  return (xaxis - x_offset) / x_scaling, (yaxis - y_offset) / y_scaling
742
626
 
@@ -749,12 +633,10 @@ class View2D(ActionManager, QtCore.QObject):
749
633
 
750
634
 
751
635
  class Viewer2D(ViewerBase):
636
+ """Object managing plotting and manipulation of 2D data using a View2D"""
637
+
752
638
  crosshair_clicked = Signal(bool)
753
639
  ROI_select_signal = Signal(QtCore.QRectF)
754
- convenience_attributes = ('is_action_checked', 'is_action_visible', 'set_action_checked', 'set_action_visible',
755
- 'get_action', 'ROIselect', 'addAction', 'toolbar', 'crosshair', 'histogrammer',
756
- 'image_widget', 'scale_axis', 'unscale_axis', 'roi_manager', 'show_roi_target',
757
- 'move_scale_roi_target', 'get_data_at')
758
640
 
759
641
  def __init__(self, parent=None, title=''):
760
642
  super().__init__(parent, title)
@@ -764,20 +646,53 @@ class Viewer2D(ViewerBase):
764
646
  self._is_gradient_manually_set = False
765
647
 
766
648
  self.view = View2D(parent)
767
-
768
- self.filter_from_rois = FilterFromRois(self.view.roi_manager, self.view.data_displayer.get_image('red'),
769
- IMAGE_TYPES)
649
+ self.filter_from_rois = Filter2DFromRois(self.view.roi_manager, self.view.data_displayer.get_image('red'),
650
+ IMAGE_TYPES)
770
651
  self.filter_from_rois.register_activation_signal(self.view.get_action('roi').triggered)
771
652
  self.filter_from_rois.register_target_slot(self.process_roi_lineouts)
772
653
 
773
- self.filter_from_crosshair = FilterFromCrosshair(self.view.crosshair, self.view.data_displayer.get_images(),
774
- IMAGE_TYPES)
654
+ self.filter_from_crosshair = Filter2DFromCrosshair(self.view.crosshair, self.view.data_displayer.get_images(),
655
+ IMAGE_TYPES)
775
656
  self.filter_from_crosshair.register_activation_signal(self.view.get_action('crosshair').triggered)
776
657
  self.filter_from_crosshair.register_target_slot(self.process_crosshair_lineouts)
777
658
 
778
659
  self.prepare_connect_ui()
779
660
 
780
- self.add_attributes_from_view()
661
+ @property
662
+ def roi_manager(self):
663
+ """Convenience method """
664
+ return self.view.roi_manager
665
+
666
+ @property
667
+ def roi_target(self) -> pgROI:
668
+ return self.view.roi_target
669
+
670
+ def move_roi_target(self, pos: Iterable[float] = None, size: Iterable[float] = (1, 1)):
671
+ """move a specific read only ROI at the given position on the viewer"""
672
+ self.view.move_scale_roi_target(pos, size)
673
+
674
+ @property
675
+ def crosshair(self):
676
+ """Convenience method """
677
+ return self.view.crosshair
678
+
679
+ @property
680
+ def image_widget(self):
681
+ """Convenience method """
682
+ return self.view.image_widget
683
+
684
+ def get_data_at(self):
685
+ """Convenience method """
686
+ return self.view.get_data_at()
687
+
688
+ def set_crosshair_position(self, xpos, ypos):
689
+ """Convenience method to set the crosshair positions"""
690
+ self.view.crosshair.set_crosshair_position(xpos=xpos, ypos=ypos)
691
+
692
+ def activate_roi(self, activate=True):
693
+ """Activate the Roi manager using the corresponding action"""
694
+ self.view.set_action_checked('roi', activate)
695
+ self.view.get_action('roi').triggered.emit(activate)
781
696
 
782
697
  @Slot(dict)
783
698
  def roi_changed(self):
@@ -786,70 +701,68 @@ class Viewer2D(ViewerBase):
786
701
  def crosshair_changed(self):
787
702
  self.filter_from_crosshair.filter_data(self._datas)
788
703
 
789
- def setImage(self, data_red=None, data_green=None, data_blue=None, data_spread=None):
790
- pymodaq.daq_utils.messenger.deprecation_msg(f'setImage for PyMoDAQ Viewer2D is deprecated, use *show_data* with'
791
- f'one argument as utils.DataFromPlugins', stacklevel=3)
792
- datas = self.format_data_as_datafromplugins(data_red=data_red, data_green=data_green,
793
- data_blue=data_blue, data_spread=data_spread)
794
- self.show_data(datas)
795
-
796
- def setImageTemp(self, data_red=None, data_green=None, data_blue=None, data_spread=None):
797
- pymodaq.daq_utils.messenger.deprecation_msg(f'setImageTemp for PyMoDAQ Viewer2D is deprecated, use *show_data_temp* with'
798
- f'one argument as utils.DataFromPlugins')
799
- datas = self.format_data_as_datafromplugins(data_red=data_red, data_green=data_green,
800
- data_blue=data_blue, data_spread=data_spread)
801
- self.show_data_temp(datas)
802
-
803
- @staticmethod
804
- def format_data_as_datafromplugins(data_red=None, data_green=None, data_blue=None, data_spread=None):
805
- if data_spread is None:
806
- distribution = 'uniform'
807
- shape = (0, 0)
808
- for data in [data_red, data_green, data_blue]:
809
- if data is not None:
810
- shape = data.shape
811
- break
812
-
813
- data_list = [data_red if data_red is not None else np.zeros(shape),
814
- data_green if data_green is not None else np.zeros(shape),
815
- data_blue if data_blue is not None else np.zeros(shape),
816
- ]
817
- else:
818
- distribution = 'spread'
819
- data_list = [data_spread]
820
-
821
- datas = utils.DataFromPlugins(name='', distribution=distribution, data=data_list)
822
- return datas
823
-
824
704
  def set_gradient(self, image_key, gradient):
825
705
  """convenience function"""
826
- self.view.histogrammer.set_gradient(image_key, 'grey')
706
+ self.view.histogrammer.set_gradient(image_key, gradient)
707
+
708
+ def _show_data(self, data: DataFromPlugins):
709
+ """Data to be plotted and eventually filtered using ROI...
827
710
 
828
- def _show_data(self, datas: utils.DataFromPlugins):
829
- """
830
- numpy arrays to be plotted and eventually filtered using ROI...
831
711
  Parameters
832
712
  ----------
833
- datas: (utils.DataToExport)
713
+ data: DataFromPlugins
834
714
 
835
715
  """
836
716
 
837
- if len(datas['data']) == 1 and not self._is_gradient_manually_set:
717
+ if len(data) == 1 and not self._is_gradient_manually_set:
838
718
  self.set_gradient('red', 'grey')
719
+ if len(data) > 3:
720
+ logger.warning('Cannot plot on 2D plot more than 3 channels')
721
+ data.data = data.data[:3]
722
+ if data.distribution != self.view.data_displayer.display_type:
723
+ self.view.set_image_displayer(data.distribution)
724
+ self.filter_from_crosshair.set_graph_items(self.view.data_displayer.get_images())
839
725
 
840
- self.isdata['red'] = len(datas['data']) > 0
841
- self.isdata['green'] = len(datas['data']) > 1
842
- self.isdata['blue'] = len(datas['data']) > 2
726
+ self.get_axes_from_view(data) # in case axes were not specified into data, one try to get them from the view
727
+
728
+ self.isdata['red'] = len(data) > 0
729
+ self.isdata['green'] = len(data) > 1
730
+ self.isdata['blue'] = len(data) > 2
843
731
 
844
732
  self.set_visible_items()
845
733
  self.update_data()
846
734
  if not self.view.is_action_checked('roi'):
847
735
  self.data_to_export_signal.emit(self.data_to_export)
848
736
 
737
+ def get_axes_from_view(self, data: DataWithAxes):
738
+ """Obtain axes info from the view
739
+
740
+ Only for uniform data
741
+ """
742
+ if data.distribution == DataDistribution['uniform']:
743
+ if data.get_axis_from_index(0)[0] is None:
744
+ axis_view = self.view.get_axis('right')
745
+ axis = Axis(axis_view.axis_label, units=axis_view.axis_units,
746
+ scaling=axis_view.axis_scaling, offset=axis_view.axis_offset, index=0)
747
+ axis.create_linear_data(data.shape[0])
748
+ data.axes.append(axis)
749
+ if data.get_axis_from_index(1)[0] is None:
750
+ axis_view = self.view.get_axis('top')
751
+ axis = Axis(axis_view.axis_label, units=axis_view.axis_units,
752
+ scaling=axis_view.axis_scaling, offset=axis_view.axis_offset, index=1)
753
+ axis.create_linear_data(data.shape[1])
754
+ data.axes.append(axis)
755
+
849
756
  def update_data(self):
850
- if self._raw_datas is not None:
757
+ if self._raw_data is not None:
851
758
  self._datas = self.set_image_transform()
852
- self._data_to_show_signal.emit(self._datas)
759
+ if self._datas.distribution.name == 'uniform':
760
+ self.x_axis = self._datas.get_axis_from_index(1)[0]
761
+ self.y_axis = self._datas.get_axis_from_index(0)[0]
762
+ else:
763
+ self.x_axis = self._datas.get_axis_from_index(0)[0]
764
+ self.y_axis = self._datas.get_axis_from_index(0)[1]
765
+ self.view.display_images(self._datas)
853
766
 
854
767
  if self.view.is_action_checked('roi'):
855
768
  self.roi_changed()
@@ -857,18 +770,17 @@ class Viewer2D(ViewerBase):
857
770
  if self.view.is_action_checked('crosshair'):
858
771
  self.crosshair_changed()
859
772
 
860
-
861
- def set_image_transform(self):
773
+ def set_image_transform(self) -> DataRaw:
862
774
  """
863
775
  Deactivate some tool buttons if data type is "spread" then apply transform_image
864
776
  """
865
- data = copy.deepcopy(self._raw_datas)
866
- self.view.set_action_visible('flip_ud', data['distribution'] != 'spread')
867
- self.view.set_action_visible('flip_lr', data['distribution'] != 'spread')
868
- self.view.set_action_visible('rotate', data['distribution'] != 'spread')
869
- if data['distribution'] != 'spread':
870
- for ind_data in range(len(data['data'])):
871
- data['data'][ind_data] = self.transform_image(data['data'][ind_data])
777
+ data = copy.deepcopy(self._raw_data)
778
+ self.view.set_action_visible('flip_ud', data.distribution != 'spread')
779
+ self.view.set_action_visible('flip_lr', data.distribution != 'spread')
780
+ self.view.set_action_visible('rotate', data.distribution != 'spread')
781
+ if data.distribution != 'spread':
782
+ for ind_data in range(len(data)):
783
+ data.data[ind_data] = self.transform_image(data.data[ind_data])
872
784
  return data
873
785
 
874
786
  def transform_image(self, data):
@@ -894,8 +806,8 @@ class Viewer2D(ViewerBase):
894
806
 
895
807
  def show_roi(self, show=True, show_roi_widget=True):
896
808
  """convenience function to control roi"""
897
- if show == (not self.is_action_checked('roi')):
898
- self.get_action('roi').trigger()
809
+ if show == (not self.view.is_action_checked('roi')):
810
+ self.view.get_action('roi').trigger()
899
811
 
900
812
  self.view.roi_manager.roiwidget.setVisible(show_roi_widget)
901
813
 
@@ -924,7 +836,6 @@ class Viewer2D(ViewerBase):
924
836
  self.view.connect_action('isocurve', slot=self.update_data)
925
837
  self.view.histogrammer.gradient_changed.connect(lambda: setattr(self, '_is_gradient_manually_set', True))
926
838
 
927
- self._data_to_show_signal.connect(self.view.display_images)
928
839
  self.view.lineout_plotter.roi_changed.connect(self.roi_changed)
929
840
  self.view.get_crosshair_signal().connect(self.crosshair_changed)
930
841
 
@@ -941,36 +852,30 @@ class Viewer2D(ViewerBase):
941
852
  if self.view.is_action_checked('crosshair'):
942
853
  self.view.crosshair.set_crosshair_position(posx, posy)
943
854
  self.crosshair_changed()
855
+ #scale positions of double_click with respect to real axes
856
+ posx, posy = self.view.scale_axis(posx, posy)
944
857
  self.sig_double_clicked.emit(posx, posy)
945
858
 
946
- def set_scaling_axes(self, scaling_options: utils.ScalingOptions):
947
- """
948
- metod used to update the scaling of the right and top axes in order to translate pixels to real coordinates
949
- scaling_options=dict(scaled_xaxis=dict(label="",units=None,offset=0,scaling=1),scaled_yaxis=dict(label="",units=None,offset=0,scaling=1))
950
- """
951
- self.view.set_axis_scaling(position='top', **scaling_options['scaled_xaxis'])
952
- self.view.set_axis_scaling(position='right', **scaling_options['scaled_yaxis'])
953
-
954
- self.x_axis.linkedViewChanged(self.view.image_widget.view)
955
- self.y_axis.linkedViewChanged(self.view.image_widget.view)
956
859
 
957
860
  @property
958
861
  def x_axis(self):
959
862
  return self.view.get_axis('top')
960
863
 
961
864
  @x_axis.setter
962
- def x_axis(self, axis):
963
- scaling, offset, label, units = AxisInfosExtractor.extract_axis_info(axis)
964
- self.view.set_axis_scaling('top', scaling=scaling, offset=offset, label=label, units=units)
865
+ def x_axis(self, axis: Axis = None):
866
+ if axis is not None:
867
+ self.view.set_axis_scaling('top', scaling=axis.scaling, offset=axis.offset,
868
+ label=axis.label, units=axis.units)
965
869
 
966
870
  @property
967
871
  def y_axis(self):
968
872
  return self.view.get_axis('right')
969
873
 
970
874
  @y_axis.setter
971
- def y_axis(self, axis):
972
- scaling, offset, label, units = AxisInfosExtractor.extract_axis_info(axis)
973
- self.view.set_axis_scaling('right', scaling=scaling, offset=offset, label=label, units=units)
875
+ def y_axis(self, axis: Axis = None):
876
+ if axis is not None:
877
+ self.view.set_axis_scaling('right', scaling=axis.scaling, offset=axis.offset,
878
+ label=axis.label, units=axis.units)
974
879
 
975
880
  def scale_lineout_dicts(self, lineout_dicts):
976
881
  for lineout_data in lineout_dicts.values():
@@ -992,22 +897,28 @@ class Viewer2D(ViewerBase):
992
897
  self.measure_data_dict = dict([])
993
898
  for roi_key, lineout_data in roi_dict.items():
994
899
  if not self._display_temporary:
995
- self.data_to_export['data1D'][f'{self.title}_Hlineout_{roi_key}'] = \
996
- utils.DataToExport(name=self.title, data=lineout_data.hor_data, source='roi',
997
- x_axis=utils.Axis(data=lineout_data.hor_axis,
998
- units=self.x_axis.axis_units,
999
- label=self.x_axis.axis_label))
1000
-
1001
- self.data_to_export['data1D'][f'{self.title}_Vlineout_{roi_key}'] = \
1002
- utils.DataToExport(name=self.title, data=lineout_data.ver_data, source='roi',
1003
- x_axis=utils.Axis(data=lineout_data.ver_axis,
1004
- units=self.y_axis.axis_units,
1005
- label=self.y_axis.axis_units))
1006
-
1007
- self.data_to_export['data0D'][f'{self.title}_Integrated_{roi_key}'] = \
1008
- utils.DataToExport(name=self.title, data=lineout_data.int_data, source='roi', )
1009
-
1010
- self.measure_data_dict[f'{roi_key}:'] = lineout_data.int_data
900
+ self.data_to_export.append(
901
+ DataFromRoi(name=f'Hlineout_{roi_key}', data=[lineout_data.hor_data],
902
+ origin=self.title,
903
+ axes=[Axis(data=lineout_data.hor_axis,
904
+ units=self.x_axis.axis_units,
905
+ label=self.x_axis.axis_label)]))
906
+
907
+ self.data_to_export.append(
908
+ DataFromRoi(name=f'Vlineout_{roi_key}', data=[lineout_data.ver_data],
909
+ origin=self.title,
910
+ axes=[Axis(data=lineout_data.ver_axis,
911
+ units=self.y_axis.axis_units,
912
+ label=self.y_axis.axis_label)]))
913
+
914
+ self.data_to_export.append(DataFromRoi(name=f'Integrated_{roi_key}', data=[lineout_data.int_data],
915
+ origin=self.title))
916
+
917
+ if not isinstance(lineout_data.math_data, list):
918
+ self.measure_data_dict[f'{roi_key}:'] = lineout_data.math_data
919
+ else:
920
+ for ind, dat in enumerate(lineout_data.math_data):
921
+ self.measure_data_dict[f'{roi_key}/{ind:02d}:'] = dat
1011
922
 
1012
923
  QtWidgets.QApplication.processEvents()
1013
924
 
@@ -1017,58 +928,81 @@ class Viewer2D(ViewerBase):
1017
928
  self.ROI_changed.emit()
1018
929
 
1019
930
 
931
+ def main_spread():
932
+ app = QtWidgets.QApplication(sys.argv)
933
+ widget = QtWidgets.QWidget()
934
+ prog = Viewer2D(widget)
935
+ widget.show()
1020
936
 
937
+ def print_data(data: DataToExport):
938
+ print(data)
939
+ print('******')
940
+ print(data.get_data_from_dim('Data1D'))
1021
941
 
1022
- def main_controller():
1023
- app = QtWidgets.QApplication(sys.argv)
1024
- form = QtWidgets.QWidget()
1025
- Nx = 100
1026
- Ny = 200
1027
- data_random = np.random.normal(size=(Ny, Nx))
1028
- x = np.linspace(0, Nx - 1, Nx)
1029
- y = np.linspace(0, Ny - 1, Ny)
1030
- from pymodaq.daq_utils.daq_utils import gauss2D
1031
-
1032
- data_red = 3 * gauss2D(x, 0.2 * Nx, Nx / 5, y, 0.3 * Ny, Ny / 5, 1, 90) * np.sin(x/5)**2 + 0.1 * data_random
1033
- # data_red = pg.gaussianFilter(data_red, (2, 2))
1034
- data_green = 24 * gauss2D(x, 0.2 * Nx, Nx / 5, y, 0.3 * Ny, Ny / 5, 1, 0)
1035
- # data_green = pg.gaussianFilter(data_green, (2, 2))
1036
- data_green[70:80, 7:12] = np.nan
1037
-
1038
- data_blue = 10 * gauss2D(x, 0.7 * Nx, Nx / 5, y, 0.2 * Ny, Ny / 5, 1)
1039
- data_blue = pg.gaussianFilter(data_blue, (2, 2))
1040
-
1041
- prog = Viewer2D(form)
1042
- # prog.set_axis_scaling(scaling_options=utils.ScalingOptions(
1043
- # scaled_xaxis=utils.ScaledAxis(label="eV", units=None, offset=100, scaling=0.1),
1044
- # scaled_yaxis=utils.ScaledAxis(label="time", units='s', offset=-20, scaling=2)))
1045
- form.show()
1046
- #prog.auto_levels_action_sym.trigger()
1047
- #prog.view.actions['autolevels'].trigger()
942
+
943
+ prog.data_to_export_signal.connect(print_data)
1048
944
 
1049
945
  data_spread = np.load('../../../resources/triangulation_data.npy')
1050
946
  # data_shuffled = data
1051
947
  # np.random.shuffle(data_shuffled)
1052
948
  # prog.show_data(utils.DataFromPlugins(name='mydata', distribution='spread',
1053
949
  # data=[data, data_shuffled]))
950
+
1054
951
  prog.view.get_action('histo').trigger()
1055
952
  prog.view.get_action('autolevels').trigger()
1056
953
 
1057
- prog.show_data(utils.DataFromPlugins(name='mydata', distribution='uniform', data=[data_red, data_green]))
1058
- #prog.show_data(utils.DataFromPlugins(name='mydata', distribution='spread', data=[data_spread]))
954
+ prog.show_data(DataFromPlugins(name='mydata', distribution='spread', data=[data_spread],
955
+ axes=[]))
956
+
957
+ sys.exit(app.exec_())
1059
958
 
1060
- #prog.ROI_select_signal.connect(print_roi_select)
1061
- #prog.view.get_action('ROIselect').trigger()
1062
- #prog.view.ROIselect.setSize((20, 35))
1063
- #prog.view.ROIselect.setPos((45, 123))
1064
- prog.show_roi_target(True)
1065
- prog.move_scale_roi_target((50, 40), (20, 20))
1066
959
 
1067
- QtWidgets.QApplication.processEvents()
960
+ def main(data_distribution='uniform'):
961
+ """either 'uniform' or 'spread'"""
962
+ from pymodaq.utils.math_utils import gauss2D
1068
963
 
1069
- # prog.setImage(data_spread=data)
1070
- #app.processEvents()
964
+ app = QtWidgets.QApplication(sys.argv)
965
+ widget = QtWidgets.QWidget()
966
+
967
+ def print_data(data: DataToExport):
968
+ print(data)
969
+ print('******')
970
+ print(data.get_data_from_dim('Data1D'))
971
+
972
+ if data_distribution == 'uniform':
973
+ Nx = 100
974
+ Ny = 2 * Nx
975
+ data_random = np.random.normal(size=(Ny, Nx))
976
+ x = 0.5 * np.linspace(-Nx / 2, Nx / 2 - 1, Nx)
977
+ y = 0.2 * np.linspace(-Ny / 2, Ny / 2 - 1, Ny)
978
+ data_red = 3 * np.sin(x/5)**2 * gauss2D(x, 5, Nx / 10, y, -1, Ny / 10, 1, 90) + 0.1 * data_random
979
+ data_green = 10 * gauss2D(x, -20, Nx / 10, y, -10, Ny / 20, 1, 0)
980
+ data_green[70:80, 7:12] = np.nan
981
+
982
+ data_to_plot = DataFromPlugins(name='mydata', distribution='uniform', data=[data_red, data_green],
983
+ axes=[Axis('xaxis', units='xpxl', data=x, index=1),
984
+ Axis('yaxis', units='ypxl', data=y, index=0), ])
985
+
986
+ elif data_distribution == 'spread':
987
+ data_spread = np.load('../../../resources/triangulation_data.npy')
988
+ data_to_plot = DataFromPlugins(name='mydata', distribution='spread', data=[data_spread[:,2]],
989
+ nav_indexes=(0,),
990
+ axes=[Axis('xaxis', units='xpxl', data=data_spread[:,0], index=0, spread_order=0),
991
+ Axis('yaxis', units='ypxl', data=data_spread[:,1], index=0, spread_order=1),])
992
+
993
+ prog = Viewer2D(widget)
994
+ widget.show()
995
+ prog.data_to_export_signal.connect(print_data)
1071
996
 
997
+ prog.view.get_action('histo').trigger()
998
+ prog.view.get_action('autolevels').trigger()
999
+
1000
+ prog.show_data(data_to_plot)
1001
+
1002
+ prog.view.show_roi_target(True)
1003
+ prog.view.move_scale_roi_target((50, 40), (10, 20))
1004
+
1005
+ QtWidgets.QApplication.processEvents()
1072
1006
  sys.exit(app.exec_())
1073
1007
 
1074
1008
 
@@ -1087,4 +1021,5 @@ def main_view():
1087
1021
  if __name__ == '__main__': # pragma: no cover
1088
1022
 
1089
1023
  #main_view()
1090
- main_controller()
1024
+ main('uniform')
1025
+ #main('spread')