Skip to content

Commit de17e30

Browse files
committed
Add roi_creator test to test creating an ROI
1 parent 716a0f5 commit de17e30

File tree

8 files changed

+182
-122
lines changed

8 files changed

+182
-122
lines changed

examples/plotting.ipynb

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"source": [
1919
"import scipp as sc\n",
2020
"\n",
21-
"from easyimaging import Measurement\n"
21+
"from easyimaging import Measurement"
2222
]
2323
},
2424
{
@@ -36,7 +36,7 @@
3636
"metadata": {},
3737
"outputs": [],
3838
"source": [
39-
"measurement = Measurement.from_scitiff(filename = '../small_scitiff.tiff')"
39+
"measurement = Measurement.from_scitiff(filename='../small_scitiff.tiff')"
4040
]
4141
},
4242
{
@@ -56,9 +56,9 @@
5656
"source": [
5757
"measurement = Measurement.from_tiff_stack(\n",
5858
" filename='../small_tiff.tiff',\n",
59-
" time_of_flights=sc.arange('t', 0, 240, 1, unit='s'), # mandatory\n",
60-
" #x_positions=sc.arange('x', 0, 50, 1, unit='mm'), # optional\n",
61-
" #y_positions=sc.arange('y', 0, 50, 1, unit='mm'), # optional\n",
59+
" time_of_flights=sc.arange('t', 0, 240, 1, unit='s'), # mandatory\n",
60+
" # x_positions=sc.arange('x', 0, 50, 1, unit='mm'), # optional\n",
61+
" # y_positions=sc.arange('y', 0, 50, 1, unit='mm'), # optional\n",
6262
")"
6363
]
6464
},
@@ -99,8 +99,8 @@
9999
"outputs": [],
100100
"source": [
101101
"tof = sc.arange('t', 0, 10, 1, unit='s')\n",
102-
"x = sc.arange('x', 0, 7, 1, unit='m') # optional\n",
103-
"y = sc.arange('y', 0, 7, 1, unit='m') # optional\n",
102+
"x = sc.arange('x', 0, 7, 1, unit='m') # optional\n",
103+
"y = sc.arange('y', 0, 7, 1, unit='m') # optional\n",
104104
"data = sc.ones(dims=['x', 'y', 't'], shape=[6, 6, 10])\n",
105105
"scipp_array = sc.DataArray(data=data, coords={'tof': tof, 'x': x, 'y': y})"
106106
]
@@ -160,8 +160,8 @@
160160
"metadata": {},
161161
"outputs": [],
162162
"source": [
163-
"display(measurement.x_positions) # If available\n",
164-
"display(measurement.y_positions) # If available\n",
163+
"display(measurement.x_positions) # If available\n",
164+
"display(measurement.y_positions) # If available\n",
165165
"display(measurement.time_of_flights)"
166166
]
167167
},
@@ -220,7 +220,7 @@
220220
"metadata": {},
221221
"outputs": [],
222222
"source": [
223-
"measurement.rebin(dimensions={'x':2, 'y':2})"
223+
"measurement.rebin(dimensions={'x': 2, 'y': 2})"
224224
]
225225
},
226226
{
@@ -386,11 +386,11 @@
386386
"outputs": [],
387387
"source": [
388388
"roi = RectROI(\n",
389-
" x_pixel_range=(15, 35), # mandatory\n",
390-
" y_pixel_range=(15, 35), # mandatory\n",
391-
" x_range=(sc.scalar(-0.05, unit='m'), sc.scalar(0.05, unit='m')), # optional\n",
392-
" y_range=(sc.scalar(-0.05, unit='m'), sc.scalar(0.05, unit='m')), # optional\n",
393-
" unique_name='center_roi' # custom name for the ROI, optional, has to be unique in computer memory\n",
389+
" x_pixel_range=(15, 35), # mandatory\n",
390+
" y_pixel_range=(15, 35), # mandatory\n",
391+
" x_range=(sc.scalar(-0.05, unit='m'), sc.scalar(0.05, unit='m')), # optional\n",
392+
" y_range=(sc.scalar(-0.05, unit='m'), sc.scalar(0.05, unit='m')), # optional\n",
393+
" unique_name='center_roi', # custom name for the ROI, optional, has to be unique in computer memory\n",
394394
")"
395395
]
396396
},
@@ -517,7 +517,7 @@
517517
"metadata": {},
518518
"outputs": [],
519519
"source": [
520-
"measurement.regions_of_interest[1].unique_name = 'best_roi' # Requires that an ROI was drawn using the roi_creator tool."
520+
"measurement.regions_of_interest[1].unique_name = 'best_roi' # Requires that an ROI was drawn using the roi_creator tool."
521521
]
522522
},
523523
{

pixi.lock

Lines changed: 1 addition & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/easyimaging/measurement/measurement.py

Lines changed: 51 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -464,11 +464,13 @@ def slicer_plot(self, **kwargs) -> None:
464464
See https://scipp.github.io/plopp/generated/plopp.slicer.html for options.
465465
"""
466466
slicer_kwargs_defaults = self._plot_defaults()
467-
slicer_kwargs_defaults.update({
468-
'title': self.display_name + ' - Time of Flight Slicer',
469-
'keep': ['x_pixels', 'y_pixels'] if not self._has_physical_coords else ['x', 'y'],
470-
'mode': 'single'
471-
})
467+
slicer_kwargs_defaults.update(
468+
{
469+
'title': self.display_name + ' - Time of Flight Slicer',
470+
'keep': ['x_pixels', 'y_pixels'] if not self._has_physical_coords else ['x', 'y'],
471+
'mode': 'single',
472+
}
473+
)
472474
slicer_kwargs_defaults['coords'].append('tof')
473475

474476
# Overwrite defaults with any user-provided kwargs
@@ -494,14 +496,16 @@ def spectrum_inspector(self, **kwargs) -> None:
494496
"""
495497
inspector_kwargs_defaults = self._plot_defaults()
496498
inspector_kwargs_defaults['ymax'] = inspector_kwargs_defaults['cmax']
497-
inspector_kwargs_defaults.update({
498-
'title': self.display_name + ' - Spectrum Inspector',
499-
'ymin': 0.0,
500-
'dim': 't',
501-
'orientation': 'vertical',
502-
'operation': 'mean',
503-
'mode': 'point',
504-
})
499+
inspector_kwargs_defaults.update(
500+
{
501+
'title': self.display_name + ' - Spectrum Inspector',
502+
'ymin': 0.0,
503+
'dim': 't',
504+
'orientation': 'vertical',
505+
'operation': 'mean',
506+
'mode': 'point',
507+
}
508+
)
505509
# Overwrite defaults with any user-provided kwargs
506510
inspector_kwargs_defaults.update(kwargs)
507511

@@ -535,21 +539,20 @@ def roi_creator(self, **kwargs) -> None:
535539

536540
roi_selector_kwargs_defaults = self._plot_defaults()
537541
roi_selector_kwargs_defaults['ymax'] = roi_selector_kwargs_defaults['cmax']
538-
roi_selector_kwargs_defaults.update({
539-
'title': self.display_name + ' - ROI Creator',
540-
'ymin': 0.0,
541-
'dim': 't',
542-
'orientation': 'vertical',
543-
'operation': 'mean',
544-
'mode': 'rectangle',
545-
})
542+
roi_selector_kwargs_defaults.update(
543+
{
544+
'title': self.display_name + ' - ROI Creator',
545+
'ymin': 0.0,
546+
'dim': 't',
547+
'orientation': 'vertical',
548+
'operation': 'mean',
549+
'mode': 'rectangle',
550+
}
551+
)
546552
# Overwrite defaults with any user-provided kwargs
547553
roi_selector_kwargs_defaults.update(kwargs)
548-
549-
plots = pp.inspector(
550-
self._data_array,
551-
**roi_selector_kwargs_defaults
552-
)
554+
555+
plots = pp.inspector(self._data_array, **roi_selector_kwargs_defaults)
553556

554557
# -------------------------------------------------------------------------------------------------
555558
# -------------------------- Plot the existing ROIs on the plot -----------------------------------
@@ -574,11 +577,13 @@ def roi_creator(self, **kwargs) -> None:
574577
x_end = roi.x_pixel_end
575578
y_end = roi.y_pixel_end
576579
plots[0].toolbar['inspect']._tool.start()
577-
plots[0].toolbar['inspect']._tool.click(x=x_start, y=y_start, button=1) # button 1 is left-click
580+
plots[0].toolbar['inspect']._tool.click(x=x_start, y=y_start, button=1) # button 1 is left-click
578581
plots[0].toolbar['inspect']._tool.click(x=x_end, y=y_end, button=1)
579582
plots[0].toolbar['inspect']._tool.stop()
580583
if hasattr(roi, '_rect_ids'):
581-
roi._rect_ids.append(plots[0].toolbar['inspect']._tool.children[-1].id) # Store the rectangle ID for reference when dragging corners # noqa: E501
584+
roi._rect_ids.append(
585+
plots[0].toolbar['inspect']._tool.children[-1].id
586+
) # Store the rectangle ID for reference when dragging corners # noqa: E501
582587
else:
583588
roi._rect_ids = [plots[0].toolbar['inspect']._tool.children[-1].id]
584589

@@ -622,27 +627,20 @@ def delete_rectangle_roi(rect, roi_list):
622627
# -------------------------- Connect the callbacks to the RectangleTool ---------------------------
623628
# -------------------------------------------------------------------------------------------------
624629

625-
plots[0].toolbar['inspect']._tool.on_create(partial(
626-
create_rectangle_roi,
627-
roi_list=self.regions_of_interest,
628-
data_array=self._data_array
629-
))
630-
631-
plots[0].toolbar['inspect']._tool.on_change(partial(
632-
edit_rectangle_roi,
633-
roi_list=self.regions_of_interest,
634-
data_array=self._data_array
635-
))
636-
637-
plots[0].toolbar['inspect']._tool.on_remove(partial(
638-
delete_rectangle_roi,
639-
roi_list=self.regions_of_interest
640-
))
630+
plots[0].toolbar['inspect']._tool.on_create(
631+
partial(create_rectangle_roi, roi_list=self.regions_of_interest, data_array=self._data_array)
632+
)
633+
634+
plots[0].toolbar['inspect']._tool.on_change(
635+
partial(edit_rectangle_roi, roi_list=self.regions_of_interest, data_array=self._data_array)
636+
)
637+
638+
plots[0].toolbar['inspect']._tool.on_remove(partial(delete_rectangle_roi, roi_list=self.regions_of_interest))
641639

642640
plots[0].toolbar['inspect'].tooltip = 'Activate ROI creator tool'
643641

644642
return plots
645-
643+
646644
def spectrum(self, roi: RectROI | str | None = None) -> sc.DataArray:
647645
"""
648646
Extract the spectrum (intensity vs. time-of-flight) for a specified region of interest (ROI).
@@ -752,11 +750,13 @@ def _validate_provided_coord(
752750
return coord
753751

754752
@staticmethod
755-
def _ranges_from_rectangle(rect, data_array: sc.DataArray) -> tuple[tuple[int, int], None] | tuple[tuple[int, int], tuple[sc.Variable, sc.Variable]]: # noqa: E501
756-
# To be used in the roi_selector method to convert the rectangle vertices to pixel and
753+
def _ranges_from_rectangle(
754+
rect, data_array: sc.DataArray
755+
) -> tuple[tuple[int, int], None] | tuple[tuple[int, int], tuple[sc.Variable, sc.Variable]]: # noqa: E501
756+
# To be used in the roi_selector method to convert the rectangle vertices to pixel and
757757
# physical coordinate ranges for the new ROI.
758758
x_vertex_list, y_vertex_list = rect.vertices
759-
if 'x' not in data_array.coords: # If 'x' exists, so does 'y' due to our constructor.
759+
if 'x' not in data_array.coords: # If 'x' exists, so does 'y' due to our constructor.
760760
x_pixel_range = (int(min(x_vertex_list)), int(max(x_vertex_list)))
761761
y_pixel_range = (int(min(y_vertex_list)), int(max(y_vertex_list)))
762762
x_range = None
@@ -768,7 +768,7 @@ def _ranges_from_rectangle(rect, data_array: sc.DataArray) -> tuple[tuple[int, i
768768
x_range = (sc.scalar(min(x_vertex_list), unit=x_unit), sc.scalar(max(x_vertex_list), unit=x_unit))
769769
y_range = (sc.scalar(min(y_vertex_list), unit=y_unit), sc.scalar(max(y_vertex_list), unit=y_unit))
770770

771-
sliced_data_array = data_array['x', x_range[0]:x_range[1]]['y', y_range[0]:y_range[1]]
771+
sliced_data_array = data_array['x', x_range[0] : x_range[1]]['y', y_range[0] : y_range[1]]
772772

773773
sliced_x_pixels = sliced_data_array.coords['x_pixels'].values
774774
sliced_y_pixels = sliced_data_array.coords['y_pixels'].values
@@ -784,8 +784,8 @@ def _plot_defaults(self):
784784
'cmin': 0.0,
785785
'cmax': min(3.0, float(self._data_array.max().value * 1.1)),
786786
'mask_color': 'red',
787-
'coords' : ['x_pixels', 'y_pixels'] if not self._has_physical_coords else ['x', 'y'],
787+
'coords': ['x_pixels', 'y_pixels'] if not self._has_physical_coords else ['x', 'y'],
788788
}
789789

790790
def __repr__(self):
791-
return f"{self.display_name} with shape {self._data_array.shape} and regions of interest: {[roi.display_name for roi in self.regions_of_interest]}" # noqa: E501
791+
return f'{self.display_name} with shape {self._data_array.shape} and regions of interest: {[roi.display_name for roi in self.regions_of_interest]}' # noqa: E501

src/easyimaging/measurement/regions.py

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,7 @@ def __init__(
5151
else:
5252
raise ValueError('Both x_range and y_range must be provided together or not at all.')
5353

54-
def set_pixel_coord_range(
55-
self,
56-
x_pixel_range: Sequence[int],
57-
y_pixel_range: Sequence[int]
58-
) -> None:
54+
def set_pixel_coord_range(self, x_pixel_range: Sequence[int], y_pixel_range: Sequence[int]) -> None:
5955
"""Set the pixel coordinate ranges for the ROI.
6056
Parameters:
6157
x_pixel_range (Sequence[int]): The start and end pixel coordinates in the x direction.
@@ -69,11 +65,7 @@ def set_pixel_coord_range(
6965
self._x_pixel_start, self._x_pixel_end = sc.array(values=x_pixel_range, dims='x')
7066
self._y_pixel_start, self._y_pixel_end = sc.array(values=y_pixel_range, dims='y')
7167

72-
def set_physical_coord_range(
73-
self,
74-
x_range: Sequence[sc.Variable],
75-
y_range: Sequence[sc.Variable]
76-
) -> None:
68+
def set_physical_coord_range(self, x_range: Sequence[sc.Variable], y_range: Sequence[sc.Variable]) -> None:
7769
"""Set the physical coordinate ranges for the ROI.
7870
Parameters:
7971
x_range (Sequence[sc.Variable]): The start and end physical coordinates in the x direction.
@@ -263,22 +255,14 @@ def to_dict(self, skip: List[str] | None = None) -> Dict[str, Any]:
263255
out_dict['x_pixel_range'] = [int(self.x_pixel_start), int(self.x_pixel_end)]
264256
out_dict['y_pixel_range'] = [int(self.y_pixel_start), int(self.y_pixel_end)]
265257
if self._has_physical_coords:
266-
out_dict['x_range'] = [{'@module': 'scipp',
267-
'@version': sc.__version__,
268-
'@class' : 'scalar',
269-
'dict' : sc.to_dict(self.x_start)},
270-
{'@module': 'scipp',
271-
'@version': sc.__version__,
272-
'@class' : 'scalar',
273-
'dict' : sc.to_dict(self.x_end)}]
274-
out_dict['y_range'] = [{'@module': 'scipp',
275-
'@version': sc.__version__,
276-
'@class' : 'scalar',
277-
'dict' : sc.to_dict(self.y_start)},
278-
{'@module': 'scipp',
279-
'@version': sc.__version__,
280-
'@class' : 'scalar',
281-
'dict' : sc.to_dict(self.y_end)}]
258+
out_dict['x_range'] = [
259+
{'@module': 'scipp', '@version': sc.__version__, '@class': 'scalar', 'dict': sc.to_dict(self.x_start)},
260+
{'@module': 'scipp', '@version': sc.__version__, '@class': 'scalar', 'dict': sc.to_dict(self.x_end)},
261+
]
262+
out_dict['y_range'] = [
263+
{'@module': 'scipp', '@version': sc.__version__, '@class': 'scalar', 'dict': sc.to_dict(self.y_start)},
264+
{'@module': 'scipp', '@version': sc.__version__, '@class': 'scalar', 'dict': sc.to_dict(self.y_end)},
265+
]
282266
return out_dict
283267

284268
@classmethod

src/easyimaging/utils/jupyter_notebook_utilities.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
def _is_notebook() -> bool:
32
"""
43
Check if the code is running in a Jupyter notebook environment.
@@ -13,4 +12,3 @@ def _is_notebook() -> bool:
1312
return False # Other type (possibly other IDE)
1413
except NameError:
1514
return False # Probably standard Python interpreter
16-

src/easyimaging/utils/scipp_utilities.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ def _to_edges(centers: sc.Variable) -> sc.Variable:
1313
2 * centers[-1] - interior_edges[-1],
1414
],
1515
dim=centers.dim,
16-
)
16+
)

0 commit comments

Comments
 (0)