Skip to content

Commit 19919d1

Browse files
committed
Refactor geometry transformation logic: consolidate transformation functions into a single apply_geometry_transform function and remove deprecated geometry_transforms module.
1 parent f018ea4 commit 19919d1

4 files changed

Lines changed: 79 additions & 117 deletions

File tree

datalab/__init__.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,3 @@
2222
# Dear (Debian, RPM, ...) package makers, please feel free to customize the
2323
# following path to module's data (images) and translations:
2424
DATAPATH = LOCALEPATH = ""
25-
26-
27-
# Compatibility implementations for removed Sigima methods:
28-
#
29-
# 1. Geometry transformations (replaces "transform_shapes"):
30-
# - Implemented in datalab.utils.geometry_transforms.apply_geometry_transform
31-
# - Used by image geometric operations (rotate, rotate90, rotate270, fliph, flipv)
32-
# - Automatically applied via wrapper functions in ImageProcessor
33-
#

datalab/gui/processor/image.py

Lines changed: 78 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from __future__ import annotations
1010

1111
import importlib
12+
from typing import Literal
1213

1314
import numpy as np
1415
import sigima.params
@@ -17,21 +18,83 @@
1718
from guidata.qthelpers import exec_dialog
1819
from plotpy.widgets.resizedialog import ResizeDialog
1920
from qtpy import QtWidgets as QW
20-
from sigima.objects import ImageROI, ROI2DParam
21+
from sigima.objects import ImageObj, ImageROI, ROI2DParam
2122
from sigima.objects.scalar import GeometryResult
2223
from sigima.proc.decorator import ComputationMetadata
2324
from sigima.proc.transformations import transformer
2425

26+
from datalab.adapters_metadata import GeometryAdapter
2527
from datalab.config import APP_NAME, _
2628
from datalab.gui.processor.base import BaseProcessor
2729
from datalab.gui.profiledialog import ProfileExtractionDialog
2830
from datalab.gui.roigrideditor import ImageGridROIEditor
2931
from datalab.objectmodel import get_uuid
30-
from datalab.utils.geometry_transforms import apply_geometry_transform
3132
from datalab.utils.qthelpers import create_progress_bar, qt_try_except
3233
from datalab.widgets import imagebackground
3334

3435

36+
def apply_geometry_transform(
37+
obj: ImageObj,
38+
operation: Literal[
39+
"translate", "scale", "rotate90", "rotate270", "fliph", "flipv", "transpose"
40+
],
41+
**kwargs,
42+
) -> None:
43+
"""Apply a geometric transformation to all geometry results in an object.
44+
45+
This uses the Sigima transformation system for proper geometric operations.
46+
For image objects, rotations are performed around the image center to match
47+
how the image data is transformed.
48+
49+
Args:
50+
obj: The object containing geometry results to transform
51+
operation: The transformation operation name
52+
**kwargs: Optional parameters for the transformation (e.g., angle for rotate)
53+
"""
54+
assert operation in [
55+
"translate",
56+
"scale",
57+
"rotate90",
58+
"rotate270",
59+
"fliph",
60+
"flipv",
61+
"transpose",
62+
], f"Unknown operation: {operation}"
63+
if operation == "translate":
64+
if not kwargs or "dx" not in kwargs or "dy" not in kwargs:
65+
raise ValueError("translate operation requires 'dx' and 'dy' parameters")
66+
dx, dy = kwargs["dx"], kwargs["dy"]
67+
elif operation == "scale":
68+
if not kwargs or "sx" not in kwargs or "sy" not in kwargs:
69+
raise ValueError("scale operation requires 'sx' and 'sy' parameters")
70+
sx, sy = kwargs["sx"], kwargs["sy"]
71+
for adapter in list(GeometryAdapter.iterate_from_obj(obj)):
72+
geometry = adapter.geometry
73+
assert geometry is not None, "Geometry should not be None"
74+
assert len(geometry.coords) > 0, "Geometry coordinates should not be empty"
75+
if operation == "translate":
76+
tr_geometry = transformer.translate(geometry, dx, dy)
77+
elif operation == "scale":
78+
tr_geometry = transformer.scale(geometry, sx, sy, (obj.xc, obj.yc))
79+
elif operation == "rotate90":
80+
tr_geometry = transformer.rotate(geometry, -np.pi / 2, (obj.xc, obj.yc))
81+
elif operation == "rotate270":
82+
tr_geometry = transformer.rotate(geometry, np.pi / 2, (obj.xc, obj.yc))
83+
elif operation == "fliph":
84+
tr_geometry = transformer.fliph(geometry, obj.xc)
85+
elif operation == "flipv":
86+
tr_geometry = transformer.flipv(geometry, obj.yc)
87+
elif operation == "transpose":
88+
tr_geometry = transformer.transpose(geometry)
89+
else:
90+
raise ValueError(f"Unknown operation: {operation}")
91+
92+
# Remove the old geometry and add the transformed one
93+
adapter.remove_from(obj)
94+
tr_adapter = GeometryAdapter(tr_geometry)
95+
tr_adapter.add_to(obj)
96+
97+
3598
class GeometricTransformWrapper:
3699
"""Pickleable wrapper for geometric transformation functions.
37100
@@ -72,24 +135,7 @@ def __call__(self, src_obj, param=None):
72135
dst_obj = self.func(src_obj, param)
73136
else:
74137
dst_obj = self.func(src_obj)
75-
76-
# Apply geometry transformation to geometry results (if any)
77-
if self.operation == "rotate90":
78-
apply_geometry_transform(dst_obj, "rotate90", None)
79-
elif self.operation == "rotate270":
80-
apply_geometry_transform(dst_obj, "rotate270", None)
81-
elif self.operation == "fliph":
82-
apply_geometry_transform(dst_obj, "fliph", None)
83-
elif self.operation == "flipv":
84-
apply_geometry_transform(dst_obj, "flipv", None)
85-
elif self.operation == "transpose":
86-
# For diagonal flip/transpose
87-
apply_geometry_transform(dst_obj, "transpose", None)
88-
else:
89-
raise NotImplementedError(
90-
f"Geometry operation '{self.operation}' is not implemented."
91-
)
92-
138+
apply_geometry_transform(dst_obj, operation=self.operation)
93139
return dst_obj
94140

95141
def __getstate__(self):
@@ -786,7 +832,7 @@ def distribute_on_grid(self, param: sigima.params.GridParam | None = None) -> No
786832
return
787833
objs = self.panel.objview.get_sel_objects(include_groups=True)
788834
g_row, g_col, x0, y0, x0_0, y0_0 = 0, 0, 0.0, 0.0, 0.0, 0.0
789-
delta_x0, delta_y0 = 0.0, 0.0
835+
dx0, dy0 = 0.0, 0.0
790836
with create_progress_bar(self.panel, title, max_=len(objs)) as progress:
791837
for i_row, obj in enumerate(objs):
792838
progress.setValue(i_row + 1)
@@ -796,15 +842,11 @@ def distribute_on_grid(self, param: sigima.params.GridParam | None = None) -> No
796842
if i_row == 0:
797843
x0_0, y0_0 = x0, y0 = obj.x0, obj.y0
798844
else:
799-
delta_x0, delta_y0 = x0 - obj.x0, y0 - obj.y0
800-
obj.x0 += delta_x0
801-
obj.y0 += delta_y0
802-
apply_geometry_transform(
803-
obj, "translate", {"dx": delta_x0, "dy": delta_y0}
804-
)
805-
transformer.transform_roi(
806-
obj, "translate", dx=delta_x0, dy=delta_y0
807-
)
845+
dx0, dy0 = x0 - obj.x0, y0 - obj.y0
846+
obj.x0 += dx0
847+
obj.y0 += dy0
848+
apply_geometry_transform(obj, "translate", dx=dx0, dy=dy0)
849+
transformer.transform_roi(obj, "translate", dx=dx0, dy=dy0)
808850
if param.direction == "row":
809851
# Distributing images over rows
810852
sign = np.sign(param.rows)
@@ -829,19 +871,17 @@ def distribute_on_grid(self, param: sigima.params.GridParam | None = None) -> No
829871
def reset_positions(self) -> None:
830872
"""Reset image positions"""
831873
x0_0, y0_0 = 0.0, 0.0
832-
delta_x0, delta_y0 = 0.0, 0.0
874+
dx0, dy0 = 0.0, 0.0
833875
objs = self.panel.objview.get_sel_objects(include_groups=True)
834876
for i_row, obj in enumerate(objs):
835877
if i_row == 0:
836878
x0_0, y0_0 = obj.x0, obj.y0
837879
else:
838-
delta_x0, delta_y0 = x0_0 - obj.x0, y0_0 - obj.y0
839-
obj.x0 += delta_x0
840-
obj.y0 += delta_y0
841-
apply_geometry_transform(
842-
obj, "translate", {"dx": delta_x0, "dy": delta_y0}
843-
)
844-
transformer.transform_roi(obj, "translate", dx=delta_x0, dy=delta_y0)
880+
dx0, dy0 = x0_0 - obj.x0, y0_0 - obj.y0
881+
obj.x0 += dx0
882+
obj.y0 += dy0
883+
apply_geometry_transform(obj, "translate", dx=dx0, dy=dy0)
884+
transformer.transform_roi(obj, "translate", dx=dx0, dy=dy0)
845885
self.panel.refresh_plot("selected", True, False)
846886

847887
# ------Image Processing

datalab/tests/features/image/geometry_transform_unit_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
from sigima.tests import data as test_data
1616

1717
from datalab.adapters_metadata.geometry_adapter import GeometryAdapter
18+
from datalab.gui.processor.image import apply_geometry_transform
1819
from datalab.tests import datalab_test_app_context
19-
from datalab.utils.geometry_transforms import apply_geometry_transform
2020

2121

2222
def __create_test_image() -> sio.ImageObj:

datalab/utils/geometry_transforms.py

Lines changed: 0 additions & 69 deletions
This file was deleted.

0 commit comments

Comments
 (0)