datalab-platform 1.0.1__py3-none-any.whl → 1.0.3__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.
- datalab/__init__.py +1 -1
- datalab/adapters_metadata/common.py +2 -2
- datalab/adapters_plotpy/converters.py +3 -1
- datalab/adapters_plotpy/coordutils.py +157 -0
- datalab/adapters_plotpy/roi/image.py +35 -6
- datalab/adapters_plotpy/roi/signal.py +8 -1
- datalab/config.py +88 -26
- datalab/control/baseproxy.py +70 -0
- datalab/control/proxy.py +33 -0
- datalab/control/remote.py +35 -0
- datalab/data/doc/DataLab_en.pdf +0 -0
- datalab/data/doc/DataLab_fr.pdf +0 -0
- datalab/data/icons/create/linear_chirp.svg +1 -1
- datalab/data/icons/create/logistic.svg +1 -1
- datalab/gui/actionhandler.py +16 -2
- datalab/gui/h5io.py +25 -0
- datalab/gui/macroeditor.py +37 -6
- datalab/gui/main.py +62 -5
- datalab/gui/newobject.py +7 -0
- datalab/gui/objectview.py +18 -3
- datalab/gui/panel/base.py +89 -16
- datalab/gui/panel/macro.py +26 -0
- datalab/gui/plothandler.py +20 -2
- datalab/gui/processor/base.py +72 -26
- datalab/gui/processor/image.py +6 -2
- datalab/gui/processor/signal.py +10 -0
- datalab/gui/roieditor.py +2 -2
- datalab/locale/fr/LC_MESSAGES/datalab.mo +0 -0
- datalab/locale/fr/LC_MESSAGES/datalab.po +3288 -0
- datalab/objectmodel.py +1 -1
- datalab/tests/features/common/auto_analysis_recompute_unit_test.py +81 -0
- datalab/tests/features/common/coordutils_unit_test.py +212 -0
- datalab/tests/features/common/result_deletion_unit_test.py +121 -1
- datalab/tests/features/common/roi_plotitem_unit_test.py +4 -2
- datalab/tests/features/common/update_tree_robustness_test.py +65 -0
- datalab/tests/features/control/remoteclient_unit.py +10 -0
- datalab/tests/features/hdf5/h5workspace_unit_test.py +133 -0
- datalab/tests/features/image/roigrid_unit_test.py +75 -0
- datalab/tests/features/macro/macroeditor_unit_test.py +104 -3
- datalab/tests/features/signal/custom_signal_bug_unit_test.py +96 -0
- datalab/widgets/imagebackground.py +13 -4
- datalab/widgets/instconfviewer.py +2 -2
- datalab/widgets/signalcursor.py +7 -2
- datalab/widgets/signaldeltax.py +4 -1
- {datalab_platform-1.0.1.dist-info → datalab_platform-1.0.3.dist-info}/METADATA +3 -3
- {datalab_platform-1.0.1.dist-info → datalab_platform-1.0.3.dist-info}/RECORD +50 -43
- {datalab_platform-1.0.1.dist-info → datalab_platform-1.0.3.dist-info}/WHEEL +0 -0
- {datalab_platform-1.0.1.dist-info → datalab_platform-1.0.3.dist-info}/entry_points.txt +0 -0
- {datalab_platform-1.0.1.dist-info → datalab_platform-1.0.3.dist-info}/licenses/LICENSE +0 -0
- {datalab_platform-1.0.1.dist-info → datalab_platform-1.0.3.dist-info}/top_level.txt +0 -0
datalab/__init__.py
CHANGED
|
@@ -24,7 +24,7 @@ except RuntimeError:
|
|
|
24
24
|
# this module is imported more than once, e.g. when running tests)
|
|
25
25
|
pass
|
|
26
26
|
|
|
27
|
-
__version__ = "1.0.
|
|
27
|
+
__version__ = "1.0.3"
|
|
28
28
|
__docurl__ = __homeurl__ = "https://datalab-platform.com/"
|
|
29
29
|
__supporturl__ = "https://github.com/DataLab-Platform/DataLab/issues/new/choose"
|
|
30
30
|
|
|
@@ -88,7 +88,7 @@ class ResultData:
|
|
|
88
88
|
if "roi_index" in df.columns:
|
|
89
89
|
i_roi = int(df.iloc[i_row_res]["roi_index"])
|
|
90
90
|
roititle = ""
|
|
91
|
-
if i_roi >= 0:
|
|
91
|
+
if i_roi >= 0 and obj.roi is not None:
|
|
92
92
|
roititle = obj.roi.get_single_roi_title(i_roi)
|
|
93
93
|
ylabel += f"|{roititle}"
|
|
94
94
|
self.ylabels.append(ylabel)
|
|
@@ -365,7 +365,7 @@ def resultadapter_to_html(
|
|
|
365
365
|
num_cols = max_display_cols
|
|
366
366
|
|
|
367
367
|
# Calculate number of cells (rows × columns)
|
|
368
|
-
num_rows = len(
|
|
368
|
+
num_rows = len(df)
|
|
369
369
|
num_cells = num_rows * num_cols
|
|
370
370
|
|
|
371
371
|
# Check if truncation is needed BEFORE calling to_html()
|
|
@@ -39,11 +39,13 @@ def plotitem_to_singleroi(
|
|
|
39
39
|
| AnnotatedRectangle
|
|
40
40
|
| AnnotatedCircle
|
|
41
41
|
| AnnotatedPolygon,
|
|
42
|
+
obj: SignalObj | ImageObj | None = None,
|
|
42
43
|
) -> SegmentROI | RectangularROI | CircularROI | PolygonalROI:
|
|
43
44
|
"""Create a single ROI from the given PlotPy item to integrate with DataLab
|
|
44
45
|
|
|
45
46
|
Args:
|
|
46
47
|
plot_item: The PlotPy item for which to create a single ROI
|
|
48
|
+
obj: Optional signal or image object for coordinate rounding
|
|
47
49
|
|
|
48
50
|
Returns:
|
|
49
51
|
A single ROI instance
|
|
@@ -66,7 +68,7 @@ def plotitem_to_singleroi(
|
|
|
66
68
|
adapter = PolygonalROIPlotPyAdapter
|
|
67
69
|
else:
|
|
68
70
|
raise TypeError(f"Unsupported PlotPy item type: {type(plot_item)}")
|
|
69
|
-
return adapter.from_plot_item(plot_item)
|
|
71
|
+
return adapter.from_plot_item(plot_item, obj)
|
|
70
72
|
|
|
71
73
|
|
|
72
74
|
def singleroi_to_plotitem(
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
ROI Coordinate Utilities
|
|
5
|
+
=========================
|
|
6
|
+
|
|
7
|
+
This module provides utility functions for rounding ROI coordinates to appropriate
|
|
8
|
+
precision based on the sampling characteristics of signals and images.
|
|
9
|
+
|
|
10
|
+
These functions are used when converting interactive PlotPy shapes to ROI objects
|
|
11
|
+
to ensure coordinates are displayed with reasonable precision.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
from sigima.objects import ImageObj, ROI1DParam, ROI2DParam, SignalObj
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def round_signal_coords(
|
|
21
|
+
obj: SignalObj, coords: list[float], precision_factor: float = 0.1
|
|
22
|
+
) -> list[float]:
|
|
23
|
+
"""Round signal coordinates to appropriate precision based on sampling period.
|
|
24
|
+
|
|
25
|
+
Rounds to a fraction of the median sampling period to avoid excessive decimal
|
|
26
|
+
places while maintaining reasonable precision.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
obj: signal object
|
|
30
|
+
coords: coordinates to round
|
|
31
|
+
precision_factor: fraction of sampling period to use as rounding precision.
|
|
32
|
+
Default is 0.1 (1/10th of sampling period).
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Rounded coordinates
|
|
36
|
+
"""
|
|
37
|
+
if len(obj.x) < 2:
|
|
38
|
+
# Cannot compute sampling period, return coords as-is
|
|
39
|
+
return coords
|
|
40
|
+
# Compute median sampling period
|
|
41
|
+
sampling_period = float(np.median(np.diff(obj.x)))
|
|
42
|
+
if sampling_period == 0:
|
|
43
|
+
# Avoid division by zero for constant x arrays
|
|
44
|
+
return coords
|
|
45
|
+
# Round to specified fraction of sampling period
|
|
46
|
+
precision = sampling_period * precision_factor
|
|
47
|
+
# Determine number of decimal places
|
|
48
|
+
if precision > 0:
|
|
49
|
+
decimals = max(0, int(-np.floor(np.log10(precision))))
|
|
50
|
+
return [round(c, decimals) for c in coords]
|
|
51
|
+
return coords
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def round_image_coords(
|
|
55
|
+
obj: ImageObj, coords: list[float], precision_factor: float = 0.1
|
|
56
|
+
) -> list[float]:
|
|
57
|
+
"""Round image coordinates to appropriate precision based on pixel spacing.
|
|
58
|
+
|
|
59
|
+
Rounds to a fraction of the pixel spacing to avoid excessive decimal places
|
|
60
|
+
while maintaining reasonable precision. Uses separate precision for X and Y.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
obj: image object
|
|
64
|
+
coords: flat list of coordinates [x0, y0, x1, y1, ...] to round
|
|
65
|
+
precision_factor: fraction of pixel spacing to use as rounding precision.
|
|
66
|
+
Default is 0.1 (1/10th of pixel spacing).
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
Rounded coordinates
|
|
70
|
+
|
|
71
|
+
Raises:
|
|
72
|
+
ValueError: if coords does not contain an even number of elements
|
|
73
|
+
"""
|
|
74
|
+
if len(coords) % 2 != 0:
|
|
75
|
+
raise ValueError("coords must contain an even number of elements (x, y pairs).")
|
|
76
|
+
if len(coords) == 0:
|
|
77
|
+
return coords
|
|
78
|
+
|
|
79
|
+
rounded = list(coords)
|
|
80
|
+
if obj.is_uniform_coords:
|
|
81
|
+
# Use dx, dy for uniform coordinates
|
|
82
|
+
precision_x = abs(obj.dx) * precision_factor
|
|
83
|
+
precision_y = abs(obj.dy) * precision_factor
|
|
84
|
+
else:
|
|
85
|
+
# Compute average spacing for non-uniform coordinates
|
|
86
|
+
if len(obj.xcoords) > 1:
|
|
87
|
+
avg_dx = float(np.mean(np.abs(np.diff(obj.xcoords))))
|
|
88
|
+
precision_x = avg_dx * precision_factor
|
|
89
|
+
else:
|
|
90
|
+
precision_x = 0
|
|
91
|
+
if len(obj.ycoords) > 1:
|
|
92
|
+
avg_dy = float(np.mean(np.abs(np.diff(obj.ycoords))))
|
|
93
|
+
precision_y = avg_dy * precision_factor
|
|
94
|
+
else:
|
|
95
|
+
precision_y = 0
|
|
96
|
+
|
|
97
|
+
# Round X coordinates (even indices)
|
|
98
|
+
if precision_x > 0:
|
|
99
|
+
decimals_x = max(0, int(-np.floor(np.log10(precision_x))))
|
|
100
|
+
for i in range(0, len(rounded), 2):
|
|
101
|
+
rounded[i] = round(rounded[i], decimals_x)
|
|
102
|
+
|
|
103
|
+
# Round Y coordinates (odd indices)
|
|
104
|
+
if precision_y > 0:
|
|
105
|
+
decimals_y = max(0, int(-np.floor(np.log10(precision_y))))
|
|
106
|
+
for i in range(1, len(rounded), 2):
|
|
107
|
+
rounded[i] = round(rounded[i], decimals_y)
|
|
108
|
+
|
|
109
|
+
return rounded
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def round_signal_roi_param(
|
|
113
|
+
obj: SignalObj, param: ROI1DParam, precision_factor: float = 0.1
|
|
114
|
+
) -> None:
|
|
115
|
+
"""Round signal ROI parameter coordinates in-place.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
obj: signal object
|
|
119
|
+
param: ROI parameter to round (modified in-place)
|
|
120
|
+
precision_factor: fraction of sampling period to use as rounding precision
|
|
121
|
+
"""
|
|
122
|
+
coords = round_signal_coords(obj, [param.xmin, param.xmax], precision_factor)
|
|
123
|
+
param.xmin, param.xmax = coords
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def round_image_roi_param(
|
|
127
|
+
obj: ImageObj, param: ROI2DParam, precision_factor: float = 0.1
|
|
128
|
+
) -> None:
|
|
129
|
+
"""Round image ROI parameter coordinates in-place.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
obj: image object
|
|
133
|
+
param: ROI parameter to round (modified in-place)
|
|
134
|
+
precision_factor: fraction of pixel spacing to use as rounding precision
|
|
135
|
+
"""
|
|
136
|
+
if param.geometry == "rectangle":
|
|
137
|
+
# Round x0, y0, dx, dy
|
|
138
|
+
x0, y0, x1, y1 = param.x0, param.y0, param.x0 + param.dx, param.y0 + param.dy
|
|
139
|
+
coords = round_image_coords(obj, [x0, y0, x1, y1], precision_factor)
|
|
140
|
+
param.x0, param.y0 = coords[0], coords[1]
|
|
141
|
+
# Round dx and dy to avoid floating-point errors in subtraction
|
|
142
|
+
dx_dy_rounded = round_image_coords(
|
|
143
|
+
obj, [coords[2] - coords[0], coords[3] - coords[1]], precision_factor
|
|
144
|
+
)
|
|
145
|
+
param.dx = dx_dy_rounded[0]
|
|
146
|
+
param.dy = dx_dy_rounded[1]
|
|
147
|
+
elif param.geometry == "circle":
|
|
148
|
+
# Round xc, yc, r
|
|
149
|
+
coords = round_image_coords(obj, [param.xc, param.yc], precision_factor)
|
|
150
|
+
param.xc, param.yc = coords
|
|
151
|
+
# Round radius using X precision
|
|
152
|
+
r_rounded = round_image_coords(obj, [param.r, 0], precision_factor)[0]
|
|
153
|
+
param.r = r_rounded
|
|
154
|
+
elif param.geometry == "polygon":
|
|
155
|
+
# Round polygon points
|
|
156
|
+
rounded = round_image_coords(obj, param.points.tolist(), precision_factor)
|
|
157
|
+
param.points = np.array(rounded)
|
|
@@ -13,6 +13,7 @@ from plotpy.items import AnnotatedCircle, AnnotatedPolygon, AnnotatedRectangle
|
|
|
13
13
|
from sigima.objects import CircularROI, ImageObj, ImageROI, PolygonalROI, RectangularROI
|
|
14
14
|
from sigima.tools import coordinates
|
|
15
15
|
|
|
16
|
+
from datalab.adapters_plotpy.coordutils import round_image_coords
|
|
16
17
|
from datalab.adapters_plotpy.roi.base import (
|
|
17
18
|
BaseROIPlotPyAdapter,
|
|
18
19
|
BaseSingleROIPlotPyAdapter,
|
|
@@ -64,14 +65,21 @@ class PolygonalROIPlotPyAdapter(
|
|
|
64
65
|
return item
|
|
65
66
|
|
|
66
67
|
@classmethod
|
|
67
|
-
def from_plot_item(
|
|
68
|
+
def from_plot_item(
|
|
69
|
+
cls, item: AnnotatedPolygon, obj: ImageObj | None = None
|
|
70
|
+
) -> PolygonalROI:
|
|
68
71
|
"""Create ROI from plot item
|
|
69
72
|
|
|
70
73
|
Args:
|
|
71
74
|
item: plot item
|
|
75
|
+
obj: image object for coordinate rounding (optional)
|
|
72
76
|
"""
|
|
77
|
+
coords = item.get_points().flatten().tolist()
|
|
78
|
+
# Round coordinates to appropriate precision
|
|
79
|
+
if obj is not None:
|
|
80
|
+
coords = round_image_coords(obj, coords)
|
|
73
81
|
title = str(item.title().text())
|
|
74
|
-
return PolygonalROI(
|
|
82
|
+
return PolygonalROI(coords, False, title)
|
|
75
83
|
|
|
76
84
|
|
|
77
85
|
class RectangularROIPlotPyAdapter(
|
|
@@ -116,15 +124,22 @@ class RectangularROIPlotPyAdapter(
|
|
|
116
124
|
return item
|
|
117
125
|
|
|
118
126
|
@classmethod
|
|
119
|
-
def from_plot_item(
|
|
127
|
+
def from_plot_item(
|
|
128
|
+
cls, item: AnnotatedRectangle, obj: ImageObj | None = None
|
|
129
|
+
) -> RectangularROI:
|
|
120
130
|
"""Create ROI from plot item
|
|
121
131
|
|
|
122
132
|
Args:
|
|
123
133
|
item: plot item
|
|
134
|
+
obj: image object for coordinate rounding (optional)
|
|
124
135
|
"""
|
|
125
136
|
rect = item.get_rect()
|
|
137
|
+
coords = RectangularROI.rect_to_coords(*rect)
|
|
138
|
+
# Round coordinates to appropriate precision
|
|
139
|
+
if obj is not None:
|
|
140
|
+
coords = round_image_coords(obj, coords)
|
|
126
141
|
title = str(item.title().text())
|
|
127
|
-
return RectangularROI(
|
|
142
|
+
return RectangularROI(coords, False, title)
|
|
128
143
|
|
|
129
144
|
|
|
130
145
|
class CircularROIPlotPyAdapter(
|
|
@@ -166,15 +181,29 @@ class CircularROIPlotPyAdapter(
|
|
|
166
181
|
return item
|
|
167
182
|
|
|
168
183
|
@classmethod
|
|
169
|
-
def from_plot_item(
|
|
184
|
+
def from_plot_item(
|
|
185
|
+
cls, item: AnnotatedCircle, obj: ImageObj | None = None
|
|
186
|
+
) -> CircularROI:
|
|
170
187
|
"""Create ROI from plot item
|
|
171
188
|
|
|
172
189
|
Args:
|
|
173
190
|
item: plot item
|
|
191
|
+
obj: image object for coordinate rounding (optional)
|
|
174
192
|
"""
|
|
175
193
|
rect = item.get_rect()
|
|
194
|
+
coords = CircularROI.rect_to_coords(*rect)
|
|
195
|
+
# Round coordinates to appropriate precision
|
|
196
|
+
# For circular ROI: [xc, yc, r] - round center (xc, yc) as pair, then radius
|
|
197
|
+
if obj is not None:
|
|
198
|
+
xc, yc, r = coords
|
|
199
|
+
# Round center coordinates
|
|
200
|
+
xc_rounded, yc_rounded = round_image_coords(obj, [xc, yc])
|
|
201
|
+
# Round radius using average of X and Y precision
|
|
202
|
+
# For radius, we use the X precision (could also average X and Y)
|
|
203
|
+
r_rounded = round_image_coords(obj, [r, 0])[0]
|
|
204
|
+
coords = [xc_rounded, yc_rounded, r_rounded]
|
|
176
205
|
title = str(item.title().text())
|
|
177
|
-
return CircularROI(
|
|
206
|
+
return CircularROI(coords, False, title)
|
|
178
207
|
|
|
179
208
|
|
|
180
209
|
class ImageROIPlotPyAdapter(BaseROIPlotPyAdapter[ImageROI]):
|
|
@@ -11,6 +11,7 @@ from plotpy.builder import make
|
|
|
11
11
|
from plotpy.items import AnnotatedXRange
|
|
12
12
|
from sigima.objects import SegmentROI, SignalObj, SignalROI
|
|
13
13
|
|
|
14
|
+
from datalab.adapters_plotpy.coordutils import round_signal_coords
|
|
14
15
|
from datalab.adapters_plotpy.roi.base import (
|
|
15
16
|
BaseROIPlotPyAdapter,
|
|
16
17
|
BaseSingleROIPlotPyAdapter,
|
|
@@ -36,11 +37,14 @@ class SegmentROIPlotPyAdapter(BaseSingleROIPlotPyAdapter[SegmentROI, AnnotatedXR
|
|
|
36
37
|
return item
|
|
37
38
|
|
|
38
39
|
@classmethod
|
|
39
|
-
def from_plot_item(
|
|
40
|
+
def from_plot_item(
|
|
41
|
+
cls, item: AnnotatedXRange, obj: SignalObj | None = None
|
|
42
|
+
) -> SegmentROI:
|
|
40
43
|
"""Create ROI from plot item
|
|
41
44
|
|
|
42
45
|
Args:
|
|
43
46
|
item: plot item
|
|
47
|
+
obj: signal object for coordinate rounding (optional)
|
|
44
48
|
|
|
45
49
|
Returns:
|
|
46
50
|
ROI
|
|
@@ -48,6 +52,9 @@ class SegmentROIPlotPyAdapter(BaseSingleROIPlotPyAdapter[SegmentROI, AnnotatedXR
|
|
|
48
52
|
if not isinstance(item, AnnotatedXRange):
|
|
49
53
|
raise TypeError("Invalid plot item type")
|
|
50
54
|
coords = sorted(item.get_range())
|
|
55
|
+
# Round coordinates to appropriate precision
|
|
56
|
+
if obj is not None:
|
|
57
|
+
coords = round_signal_coords(obj, coords)
|
|
51
58
|
title = str(item.title().text())
|
|
52
59
|
return SegmentROI(coords, False, title)
|
|
53
60
|
|
datalab/config.py
CHANGED
|
@@ -301,6 +301,7 @@ class ViewSection(conf.Section, metaclass=conf.SectionMeta):
|
|
|
301
301
|
ima_def_interpolation = conf.Option()
|
|
302
302
|
ima_def_alpha = conf.Option()
|
|
303
303
|
ima_def_alpha_function = conf.Option()
|
|
304
|
+
ima_def_keep_lut_range = conf.Option()
|
|
304
305
|
|
|
305
306
|
# Annotated shape and marker visualization settings for signals
|
|
306
307
|
sig_shape_param = conf.DataSetOption()
|
|
@@ -459,6 +460,7 @@ def initialize():
|
|
|
459
460
|
Conf.view.ima_def_interpolation.get(5)
|
|
460
461
|
Conf.view.ima_def_alpha.get(1.0)
|
|
461
462
|
Conf.view.ima_def_alpha_function.get(LUTAlpha.NONE.value)
|
|
463
|
+
Conf.view.ima_def_keep_lut_range.get(False)
|
|
462
464
|
|
|
463
465
|
# Datetime format strings: % must be escaped as %% for ConfigParser
|
|
464
466
|
Conf.view.sig_datetime_format_s.get("%%H:%%M:%%S")
|
|
@@ -485,6 +487,8 @@ initialize()
|
|
|
485
487
|
|
|
486
488
|
ROI_LINE_COLOR = "#5555ff"
|
|
487
489
|
ROI_SEL_LINE_COLOR = "#9393ff"
|
|
490
|
+
MARKER_LINE_COLOR = "#A11818"
|
|
491
|
+
MARKER_TEXT_COLOR = "#440909"
|
|
488
492
|
|
|
489
493
|
PLOTPY_DEFAULTS = {
|
|
490
494
|
"plot": {
|
|
@@ -506,11 +510,27 @@ PLOTPY_DEFAULTS = {
|
|
|
506
510
|
"selected_curve_symbol/alpha": 0.3,
|
|
507
511
|
"selected_curve_symbol/size": 5,
|
|
508
512
|
"marker/curve/text/textcolor": "black",
|
|
509
|
-
|
|
513
|
+
# Cross marker style (shown when pressing Alt key on plot)
|
|
514
|
+
"marker/cross/symbol/marker": "Cross",
|
|
515
|
+
"marker/cross/symbol/edgecolor": MAIN_FG_COLOR,
|
|
516
|
+
"marker/cross/symbol/facecolor": "#ff0000",
|
|
517
|
+
"marker/cross/symbol/alpha": 1.0,
|
|
518
|
+
"marker/cross/symbol/size": 8,
|
|
519
|
+
"marker/cross/text/font/family": "default",
|
|
520
|
+
"marker/cross/text/font/size": 8,
|
|
521
|
+
"marker/cross/text/font/bold": False,
|
|
522
|
+
"marker/cross/text/font/italic": False,
|
|
523
|
+
"marker/cross/text/textcolor": "#000000",
|
|
524
|
+
"marker/cross/text/background_color": "#ffffff",
|
|
510
525
|
"marker/cross/text/background_alpha": 0.7,
|
|
526
|
+
"marker/cross/line/style": "DashLine",
|
|
527
|
+
"marker/cross/line/color": MARKER_LINE_COLOR,
|
|
528
|
+
"marker/cross/line/width": 1.0,
|
|
529
|
+
"marker/cross/markerstyle": "Cross",
|
|
530
|
+
"marker/cross/spacing": 7,
|
|
511
531
|
# Cursor line and symbol style
|
|
512
532
|
"marker/cursor/line/style": "SolidLine",
|
|
513
|
-
"marker/cursor/line/color":
|
|
533
|
+
"marker/cursor/line/color": MARKER_LINE_COLOR,
|
|
514
534
|
"marker/cursor/line/width": 1.0,
|
|
515
535
|
"marker/cursor/symbol/marker": "NoSymbol",
|
|
516
536
|
"marker/cursor/symbol/size": 11,
|
|
@@ -518,41 +538,83 @@ PLOTPY_DEFAULTS = {
|
|
|
518
538
|
"marker/cursor/symbol/facecolor": "#ff9393",
|
|
519
539
|
"marker/cursor/symbol/alpha": 1.0,
|
|
520
540
|
"marker/cursor/sel_line/style": "SolidLine",
|
|
521
|
-
"marker/cursor/sel_line/color":
|
|
541
|
+
"marker/cursor/sel_line/color": MARKER_LINE_COLOR,
|
|
522
542
|
"marker/cursor/sel_line/width": 2.0,
|
|
523
543
|
"marker/cursor/sel_symbol/marker": "NoSymbol",
|
|
524
544
|
"marker/cursor/sel_symbol/size": 11,
|
|
525
545
|
"marker/cursor/sel_symbol/edgecolor": MAIN_BG_COLOR,
|
|
526
|
-
"marker/cursor/sel_symbol/facecolor":
|
|
546
|
+
"marker/cursor/sel_symbol/facecolor": MARKER_LINE_COLOR,
|
|
527
547
|
"marker/cursor/sel_symbol/alpha": 0.8,
|
|
528
548
|
"marker/cursor/text/font/size": 9,
|
|
529
549
|
"marker/cursor/text/font/family": "default",
|
|
530
550
|
"marker/cursor/text/font/bold": False,
|
|
531
551
|
"marker/cursor/text/font/italic": False,
|
|
532
|
-
"marker/cursor/text/textcolor":
|
|
552
|
+
"marker/cursor/text/textcolor": MARKER_TEXT_COLOR,
|
|
533
553
|
"marker/cursor/text/background_color": "#ffffff",
|
|
534
554
|
"marker/cursor/text/background_alpha": 0.7,
|
|
535
555
|
"marker/cursor/sel_text/font/size": 9,
|
|
536
556
|
"marker/cursor/sel_text/font/family": "default",
|
|
537
557
|
"marker/cursor/sel_text/font/bold": False,
|
|
538
558
|
"marker/cursor/sel_text/font/italic": False,
|
|
539
|
-
"marker/cursor/sel_text/textcolor":
|
|
559
|
+
"marker/cursor/sel_text/textcolor": MARKER_TEXT_COLOR,
|
|
540
560
|
"marker/cursor/sel_text/background_color": "#ffffff",
|
|
541
561
|
"marker/cursor/sel_text/background_alpha": 0.7,
|
|
562
|
+
# Default annotation text style for segments:
|
|
563
|
+
"shape/segment/line/style": "SolidLine",
|
|
564
|
+
"shape/segment/line/color": "#00ff55",
|
|
565
|
+
"shape/segment/line/width": 1.0,
|
|
566
|
+
"shape/segment/sel_line/style": "SolidLine",
|
|
567
|
+
"shape/segment/sel_line/color": "#00ff55",
|
|
568
|
+
"shape/segment/sel_line/width": 2.0,
|
|
569
|
+
"shape/segment/fill/style": "NoBrush",
|
|
570
|
+
"shape/segment/sel_fill/style": "NoBrush",
|
|
571
|
+
"shape/segment/symbol/marker": "XCross",
|
|
572
|
+
"shape/segment/symbol/size": 9,
|
|
573
|
+
"shape/segment/symbol/edgecolor": "#00ff55",
|
|
574
|
+
"shape/segment/symbol/facecolor": "#00ff55",
|
|
575
|
+
"shape/segment/symbol/alpha": 1.0,
|
|
576
|
+
"shape/segment/sel_symbol/marker": "XCross",
|
|
577
|
+
"shape/segment/sel_symbol/size": 12,
|
|
578
|
+
"shape/segment/sel_symbol/edgecolor": "#00ff55",
|
|
579
|
+
"shape/segment/sel_symbol/facecolor": "#00ff55",
|
|
580
|
+
"shape/segment/sel_symbol/alpha": 0.7,
|
|
581
|
+
# Default style for drag shapes: (global annotations style)
|
|
582
|
+
"shape/drag/line/style": "SolidLine",
|
|
583
|
+
"shape/drag/line/color": "#00ff55",
|
|
584
|
+
"shape/drag/line/width": 1.0,
|
|
585
|
+
"shape/drag/fill/style": "SolidPattern",
|
|
586
|
+
"shape/drag/fill/color": MAIN_BG_COLOR,
|
|
587
|
+
"shape/drag/fill/alpha": 0.1,
|
|
588
|
+
"shape/drag/symbol/marker": "Rect",
|
|
589
|
+
"shape/drag/symbol/size": 3,
|
|
590
|
+
"shape/drag/symbol/edgecolor": "#00ff55",
|
|
591
|
+
"shape/drag/symbol/facecolor": "#00ff55",
|
|
592
|
+
"shape/drag/symbol/alpha": 1.0,
|
|
593
|
+
"shape/drag/sel_line/style": "SolidLine",
|
|
594
|
+
"shape/drag/sel_line/color": "#00ff55",
|
|
595
|
+
"shape/drag/sel_line/width": 2.0,
|
|
596
|
+
"shape/drag/sel_fill/style": "SolidPattern",
|
|
597
|
+
"shape/drag/sel_fill/color": MAIN_BG_COLOR,
|
|
598
|
+
"shape/drag/sel_fill/alpha": 0.1,
|
|
599
|
+
"shape/drag/sel_symbol/marker": "Rect",
|
|
600
|
+
"shape/drag/sel_symbol/size": 7,
|
|
601
|
+
"shape/drag/sel_symbol/edgecolor": "#00ff55",
|
|
602
|
+
"shape/drag/sel_symbol/facecolor": "#00ff00",
|
|
603
|
+
"shape/drag/sel_symbol/alpha": 0.7,
|
|
542
604
|
},
|
|
543
605
|
"results": {
|
|
544
606
|
# Annotated shape style for result shapes:
|
|
545
607
|
# Signals:
|
|
546
608
|
"s/annotation/line/style": "SolidLine",
|
|
547
|
-
"s/annotation/line/color":
|
|
548
|
-
"s/annotation/line/width":
|
|
549
|
-
"s/annotation/fill/style": "
|
|
609
|
+
"s/annotation/line/color": "#00aa00",
|
|
610
|
+
"s/annotation/line/width": 2,
|
|
611
|
+
"s/annotation/fill/style": "NoBrush",
|
|
550
612
|
"s/annotation/fill/color": MAIN_BG_COLOR,
|
|
551
613
|
"s/annotation/fill/alpha": 0.1,
|
|
552
614
|
"s/annotation/symbol/marker": "XCross",
|
|
553
615
|
"s/annotation/symbol/size": 7,
|
|
554
|
-
"s/annotation/symbol/edgecolor":
|
|
555
|
-
"s/annotation/symbol/facecolor":
|
|
616
|
+
"s/annotation/symbol/edgecolor": "#00aa00",
|
|
617
|
+
"s/annotation/symbol/facecolor": "#00aa00",
|
|
556
618
|
"s/annotation/symbol/alpha": 1.0,
|
|
557
619
|
"s/annotation/sel_line/style": "DashLine",
|
|
558
620
|
"s/annotation/sel_line/color": "#00ff00",
|
|
@@ -591,65 +653,65 @@ PLOTPY_DEFAULTS = {
|
|
|
591
653
|
# Marker styles for results:
|
|
592
654
|
# Signals:
|
|
593
655
|
"s/marker/cursor/line/style": "DashLine",
|
|
594
|
-
"s/marker/cursor/line/color":
|
|
656
|
+
"s/marker/cursor/line/color": MARKER_LINE_COLOR,
|
|
595
657
|
"s/marker/cursor/line/width": 1.0,
|
|
596
658
|
"s/marker/cursor/symbol/marker": "Ellipse",
|
|
597
659
|
"s/marker/cursor/symbol/size": 11,
|
|
598
660
|
"s/marker/cursor/symbol/edgecolor": MAIN_BG_COLOR,
|
|
599
|
-
"s/marker/cursor/symbol/facecolor":
|
|
661
|
+
"s/marker/cursor/symbol/facecolor": MARKER_LINE_COLOR,
|
|
600
662
|
"s/marker/cursor/symbol/alpha": 0.7,
|
|
601
663
|
"s/marker/cursor/sel_line/style": "DashLine",
|
|
602
|
-
"s/marker/cursor/sel_line/color":
|
|
664
|
+
"s/marker/cursor/sel_line/color": MARKER_LINE_COLOR,
|
|
603
665
|
"s/marker/cursor/sel_line/width": 2.0,
|
|
604
666
|
"s/marker/cursor/sel_symbol/marker": "Ellipse",
|
|
605
667
|
"s/marker/cursor/sel_symbol/size": 11,
|
|
606
|
-
"s/marker/cursor/sel_symbol/edgecolor":
|
|
607
|
-
"s/marker/cursor/sel_symbol/facecolor":
|
|
668
|
+
"s/marker/cursor/sel_symbol/edgecolor": MARKER_LINE_COLOR,
|
|
669
|
+
"s/marker/cursor/sel_symbol/facecolor": MARKER_LINE_COLOR,
|
|
608
670
|
"s/marker/cursor/sel_symbol/alpha": 0.7,
|
|
609
671
|
"s/marker/cursor/text/font/size": 9,
|
|
610
672
|
"s/marker/cursor/text/font/family": "default",
|
|
611
673
|
"s/marker/cursor/text/font/bold": False,
|
|
612
674
|
"s/marker/cursor/text/font/italic": False,
|
|
613
|
-
"s/marker/cursor/text/textcolor":
|
|
675
|
+
"s/marker/cursor/text/textcolor": MARKER_TEXT_COLOR,
|
|
614
676
|
"s/marker/cursor/text/background_color": "#ffffff",
|
|
615
677
|
"s/marker/cursor/text/background_alpha": 0.7,
|
|
616
678
|
"s/marker/cursor/sel_text/font/size": 9,
|
|
617
679
|
"s/marker/cursor/sel_text/font/family": "default",
|
|
618
680
|
"s/marker/cursor/sel_text/font/bold": False,
|
|
619
681
|
"s/marker/cursor/sel_text/font/italic": False,
|
|
620
|
-
"s/marker/cursor/sel_text/textcolor":
|
|
682
|
+
"s/marker/cursor/sel_text/textcolor": MARKER_TEXT_COLOR,
|
|
621
683
|
"s/marker/cursor/sel_text/background_color": "#ffffff",
|
|
622
684
|
"s/marker/cursor/sel_text/background_alpha": 0.7,
|
|
623
685
|
"s/marker/cursor/markerstyle": "Cross",
|
|
624
686
|
# Images:
|
|
625
687
|
"i/marker/cursor/line/style": "DashLine",
|
|
626
|
-
"i/marker/cursor/line/color":
|
|
688
|
+
"i/marker/cursor/line/color": MARKER_LINE_COLOR,
|
|
627
689
|
"i/marker/cursor/line/width": 1.0,
|
|
628
690
|
"i/marker/cursor/symbol/marker": "Diamond",
|
|
629
691
|
"i/marker/cursor/symbol/size": 11,
|
|
630
|
-
"i/marker/cursor/symbol/edgecolor":
|
|
631
|
-
"i/marker/cursor/symbol/facecolor":
|
|
692
|
+
"i/marker/cursor/symbol/edgecolor": MARKER_LINE_COLOR,
|
|
693
|
+
"i/marker/cursor/symbol/facecolor": MARKER_LINE_COLOR,
|
|
632
694
|
"i/marker/cursor/symbol/alpha": 0.7,
|
|
633
695
|
"i/marker/cursor/sel_line/style": "DashLine",
|
|
634
|
-
"i/marker/cursor/sel_line/color":
|
|
696
|
+
"i/marker/cursor/sel_line/color": MARKER_LINE_COLOR,
|
|
635
697
|
"i/marker/cursor/sel_line/width": 2.0,
|
|
636
698
|
"i/marker/cursor/sel_symbol/marker": "Diamond",
|
|
637
699
|
"i/marker/cursor/sel_symbol/size": 11,
|
|
638
|
-
"i/marker/cursor/sel_symbol/edgecolor":
|
|
639
|
-
"i/marker/cursor/sel_symbol/facecolor":
|
|
700
|
+
"i/marker/cursor/sel_symbol/edgecolor": MARKER_LINE_COLOR,
|
|
701
|
+
"i/marker/cursor/sel_symbol/facecolor": MARKER_LINE_COLOR,
|
|
640
702
|
"i/marker/cursor/sel_symbol/alpha": 0.7,
|
|
641
703
|
"i/marker/cursor/text/font/size": 9,
|
|
642
704
|
"i/marker/cursor/text/font/family": "default",
|
|
643
705
|
"i/marker/cursor/text/font/bold": False,
|
|
644
706
|
"i/marker/cursor/text/font/italic": False,
|
|
645
|
-
"i/marker/cursor/text/textcolor":
|
|
707
|
+
"i/marker/cursor/text/textcolor": MARKER_TEXT_COLOR,
|
|
646
708
|
"i/marker/cursor/text/background_color": "#ffffff",
|
|
647
709
|
"i/marker/cursor/text/background_alpha": 0.7,
|
|
648
710
|
"i/marker/cursor/sel_text/font/size": 9,
|
|
649
711
|
"i/marker/cursor/sel_text/font/family": "default",
|
|
650
712
|
"i/marker/cursor/sel_text/font/bold": False,
|
|
651
713
|
"i/marker/cursor/sel_text/font/italic": False,
|
|
652
|
-
"i/marker/cursor/sel_text/textcolor":
|
|
714
|
+
"i/marker/cursor/sel_text/textcolor": MARKER_TEXT_COLOR,
|
|
653
715
|
"i/marker/cursor/sel_text/background_color": "#ffffff",
|
|
654
716
|
"i/marker/cursor/sel_text/background_alpha": 0.7,
|
|
655
717
|
"i/marker/cursor/markerstyle": "Cross",
|
datalab/control/baseproxy.py
CHANGED
|
@@ -198,6 +198,41 @@ class AbstractDLControl(abc.ABC):
|
|
|
198
198
|
reset_all: Reset all application data. Defaults to None.
|
|
199
199
|
"""
|
|
200
200
|
|
|
201
|
+
@abc.abstractmethod
|
|
202
|
+
def load_h5_workspace(self, h5files: list[str], reset_all: bool = False) -> None:
|
|
203
|
+
"""Load native DataLab HDF5 workspace files without any GUI elements.
|
|
204
|
+
|
|
205
|
+
This method can be safely called from scripts (e.g., internal console,
|
|
206
|
+
macros) as it does not create any Qt widgets, dialogs, or progress bars.
|
|
207
|
+
|
|
208
|
+
.. warning::
|
|
209
|
+
|
|
210
|
+
This method only supports native DataLab HDF5 files. For importing
|
|
211
|
+
arbitrary HDF5 files (non-native), use :meth:`open_h5_files` or
|
|
212
|
+
:meth:`import_h5_file` instead.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
h5files: List of native DataLab HDF5 filenames
|
|
216
|
+
reset_all: Reset all application data before importing. Defaults to False.
|
|
217
|
+
|
|
218
|
+
Raises:
|
|
219
|
+
ValueError: If a file is not a valid native DataLab HDF5 file
|
|
220
|
+
"""
|
|
221
|
+
|
|
222
|
+
@abc.abstractmethod
|
|
223
|
+
def save_h5_workspace(self, filename: str) -> None:
|
|
224
|
+
"""Save current workspace to a native DataLab HDF5 file without GUI elements.
|
|
225
|
+
|
|
226
|
+
This method can be safely called from scripts (e.g., internal console,
|
|
227
|
+
macros) as it does not create any Qt widgets, dialogs, or progress bars.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
filename: HDF5 filename to save to
|
|
231
|
+
|
|
232
|
+
Raises:
|
|
233
|
+
IOError: If file cannot be saved
|
|
234
|
+
"""
|
|
235
|
+
|
|
201
236
|
@abc.abstractmethod
|
|
202
237
|
def load_from_files(self, filenames: list[str]) -> None:
|
|
203
238
|
"""Open objects from files in current panel (signals/images).
|
|
@@ -607,6 +642,41 @@ class BaseProxy(AbstractDLControl, metaclass=abc.ABCMeta):
|
|
|
607
642
|
"""
|
|
608
643
|
self._datalab.import_h5_file(filename, reset_all)
|
|
609
644
|
|
|
645
|
+
def load_h5_workspace(self, h5files: list[str], reset_all: bool = False) -> None:
|
|
646
|
+
"""Load native DataLab HDF5 workspace files without any GUI elements.
|
|
647
|
+
|
|
648
|
+
This method can be safely called from scripts (e.g., internal console,
|
|
649
|
+
macros) as it does not create any Qt widgets, dialogs, or progress bars.
|
|
650
|
+
|
|
651
|
+
.. warning::
|
|
652
|
+
|
|
653
|
+
This method only supports native DataLab HDF5 files. For importing
|
|
654
|
+
arbitrary HDF5 files (non-native), use :meth:`open_h5_files` or
|
|
655
|
+
:meth:`import_h5_file` instead.
|
|
656
|
+
|
|
657
|
+
Args:
|
|
658
|
+
h5files: List of native DataLab HDF5 filenames
|
|
659
|
+
reset_all: Reset all application data before importing. Defaults to False.
|
|
660
|
+
|
|
661
|
+
Raises:
|
|
662
|
+
ValueError: If a file is not a valid native DataLab HDF5 file
|
|
663
|
+
"""
|
|
664
|
+
self._datalab.load_h5_workspace(h5files, reset_all)
|
|
665
|
+
|
|
666
|
+
def save_h5_workspace(self, filename: str) -> None:
|
|
667
|
+
"""Save current workspace to a native DataLab HDF5 file without GUI elements.
|
|
668
|
+
|
|
669
|
+
This method can be safely called from scripts (e.g., internal console,
|
|
670
|
+
macros) as it does not create any Qt widgets, dialogs, or progress bars.
|
|
671
|
+
|
|
672
|
+
Args:
|
|
673
|
+
filename: HDF5 filename to save to
|
|
674
|
+
|
|
675
|
+
Raises:
|
|
676
|
+
IOError: If file cannot be saved
|
|
677
|
+
"""
|
|
678
|
+
self._datalab.save_h5_workspace(filename)
|
|
679
|
+
|
|
610
680
|
def load_from_files(self, filenames: list[str]) -> None:
|
|
611
681
|
"""Open objects from files in current panel (signals/images).
|
|
612
682
|
|