py4D-browser-transform 0.1.0__tar.gz → 0.1.1__tar.gz
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.
- {py4d_browser_transform-0.1.0/src/py4D_browser_transform.egg-info → py4d_browser_transform-0.1.1}/PKG-INFO +1 -1
- {py4d_browser_transform-0.1.0 → py4d_browser_transform-0.1.1/src/py4D_browser_transform.egg-info}/PKG-INFO +1 -1
- {py4d_browser_transform-0.1.0 → py4d_browser_transform-0.1.1}/src/py4d_browser_plugin/transform/__init__.py +1 -1
- {py4d_browser_transform-0.1.0 → py4d_browser_transform-0.1.1}/src/py4d_browser_plugin/transform/checkpoints.py +17 -4
- {py4d_browser_transform-0.1.0 → py4d_browser_transform-0.1.1}/src/py4d_browser_plugin/transform/datacube_ops.py +8 -4
- {py4d_browser_transform-0.1.0 → py4d_browser_transform-0.1.1}/tests/test_transform_datacube_updates.py +54 -1
- {py4d_browser_transform-0.1.0 → py4d_browser_transform-0.1.1}/LICENSE.txt +0 -0
- {py4d_browser_transform-0.1.0 → py4d_browser_transform-0.1.1}/README.md +0 -0
- {py4d_browser_transform-0.1.0 → py4d_browser_transform-0.1.1}/pyproject.toml +0 -0
- {py4d_browser_transform-0.1.0 → py4d_browser_transform-0.1.1}/setup.cfg +0 -0
- {py4d_browser_transform-0.1.0 → py4d_browser_transform-0.1.1}/src/py4D_browser_transform.egg-info/SOURCES.txt +0 -0
- {py4d_browser_transform-0.1.0 → py4d_browser_transform-0.1.1}/src/py4D_browser_transform.egg-info/dependency_links.txt +0 -0
- {py4d_browser_transform-0.1.0 → py4d_browser_transform-0.1.1}/src/py4D_browser_transform.egg-info/requires.txt +0 -0
- {py4d_browser_transform-0.1.0 → py4d_browser_transform-0.1.1}/src/py4D_browser_transform.egg-info/top_level.txt +0 -0
- {py4d_browser_transform-0.1.0 → py4d_browser_transform-0.1.1}/src/py4d_browser_plugin/transform/dialogs.py +0 -0
- {py4d_browser_transform-0.1.0 → py4d_browser_transform-0.1.1}/src/py4d_browser_plugin/transform/transform.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: py4D-browser-transform
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: py4D-browser plugin that adds utility functions which transform the datacube
|
|
5
5
|
Author-email: Chia-Hao Lee <chia-hao.lee@cornell.edu>
|
|
6
6
|
Project-URL: Homepage, https://github.com/chiahao3/py4D-browser-transform
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: py4D-browser-transform
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: py4D-browser plugin that adds utility functions which transform the datacube
|
|
5
5
|
Author-email: Chia-Hao Lee <chia-hao.lee@cornell.edu>
|
|
6
6
|
Project-URL: Homepage, https://github.com/chiahao3/py4D-browser-transform
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
from .transform import TransformPlugin
|
|
2
|
-
__version__ = '0.1.
|
|
2
|
+
__version__ = '0.1.1' # 2026.07.21
|
|
@@ -22,10 +22,23 @@ class DatacubeCheckpoint:
|
|
|
22
22
|
|
|
23
23
|
def copy_datacube(datacube):
|
|
24
24
|
if hasattr(datacube, "copy"):
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
copied = datacube.copy()
|
|
26
|
+
else:
|
|
27
|
+
copied = type(datacube)(datacube.data.copy())
|
|
28
|
+
if hasattr(datacube, "calibration"):
|
|
29
|
+
copied.calibration = datacube.calibration.copy()
|
|
30
|
+
|
|
31
|
+
# py4DSTEM's DataCube.copy() rebuilds a fresh Root, and constructing a
|
|
32
|
+
# DataCube with an explicit calibration object names that root
|
|
33
|
+
# "py4DSTEM_root" instead of preserving the original's name. That
|
|
34
|
+
# silently breaks py4D-browser's calibration reload for any file whose
|
|
35
|
+
# root name it hardcodes (e.g. "datacube_root"), so keep the original
|
|
36
|
+
# root's name on the copy.
|
|
37
|
+
original_root = getattr(datacube, "root", None)
|
|
38
|
+
copied_root = getattr(copied, "root", None)
|
|
39
|
+
if original_root is not None and copied_root is not None:
|
|
40
|
+
copied_root.name = original_root.name
|
|
41
|
+
|
|
29
42
|
return copied
|
|
30
43
|
|
|
31
44
|
|
|
@@ -71,20 +71,24 @@ def _update_transform_calibration(datacube, starts, spacing_factors):
|
|
|
71
71
|
)
|
|
72
72
|
|
|
73
73
|
q_factors = (spacing_factors[2], spacing_factors[3])
|
|
74
|
-
old_q_pixel_size = calibration.get_Q_pixel_size()
|
|
75
74
|
if q_factors[0] == q_factors[1] and q_factors[0] != 1:
|
|
75
|
+
old_q_pixel_size = calibration.get_Q_pixel_size()
|
|
76
76
|
_set_calibration_value(
|
|
77
77
|
calibration, "set_Q_pixel_size", old_q_pixel_size * q_factors[0]
|
|
78
78
|
)
|
|
79
79
|
|
|
80
|
+
# The origin (qx0, qy0) is stored in *pixel* coordinates of the Q axes,
|
|
81
|
+
# not physical units, so it must be re-expressed in the transformed
|
|
82
|
+
# array's own pixel grid: shift by the crop start, then rescale by
|
|
83
|
+
# however many old pixels now make up one new pixel (step * bin).
|
|
80
84
|
origin = calibration.get_origin() if hasattr(calibration, "get_origin") else None
|
|
81
|
-
if origin is not None
|
|
85
|
+
if origin is not None:
|
|
82
86
|
qx0, qy0 = origin
|
|
83
87
|
if qx0 is not None and qy0 is not None:
|
|
84
88
|
calibration.set_origin(
|
|
85
89
|
(
|
|
86
|
-
qx0 - starts[2]
|
|
87
|
-
qy0 - starts[3]
|
|
90
|
+
(qx0 - starts[2]) / spacing_factors[2],
|
|
91
|
+
(qy0 - starts[3]) / spacing_factors[3],
|
|
88
92
|
)
|
|
89
93
|
)
|
|
90
94
|
|
|
@@ -319,10 +319,31 @@ def test_apply_datacube_operations_adjusts_q_origin_for_slices(monkeypatch):
|
|
|
319
319
|
],
|
|
320
320
|
)
|
|
321
321
|
|
|
322
|
-
assert transformed.calibration.get_origin() == (
|
|
322
|
+
assert transformed.calibration.get_origin() == (8.0, 16.0)
|
|
323
323
|
assert datacube.calibration.get_origin() == (10.0, 20.0)
|
|
324
324
|
|
|
325
325
|
|
|
326
|
+
def test_apply_datacube_operations_adjusts_q_origin_for_binning(monkeypatch):
|
|
327
|
+
module = _load_datacube_ops_module(monkeypatch)
|
|
328
|
+
data = np.arange(2 * 2 * 8 * 8).reshape(2, 2, 8, 8)
|
|
329
|
+
datacube = _Datacube(data.copy(), _Calibration(q_pixel_size=0.5, origin=(6.0, 8.0)))
|
|
330
|
+
|
|
331
|
+
transformed = module.apply_datacube_operations(
|
|
332
|
+
datacube,
|
|
333
|
+
[
|
|
334
|
+
{"slice": ":", "bin": 1},
|
|
335
|
+
{"slice": ":", "bin": 1},
|
|
336
|
+
{"slice": "2:", "bin": 2},
|
|
337
|
+
{"slice": "0:", "bin": 2},
|
|
338
|
+
],
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
# New origin = (old_origin - crop_start) / (step * bin), in the
|
|
342
|
+
# transformed array's own pixel grid.
|
|
343
|
+
assert transformed.calibration.get_origin() == (2.0, 4.0)
|
|
344
|
+
assert datacube.calibration.get_origin() == (6.0, 8.0)
|
|
345
|
+
|
|
346
|
+
|
|
326
347
|
def test_apply_datacube_operations_preserves_pixel_size_for_asymmetric_spacing(monkeypatch):
|
|
327
348
|
module = _load_datacube_ops_module(monkeypatch)
|
|
328
349
|
data = np.arange(4 * 4 * 6 * 6).reshape(4, 4, 6, 6)
|
|
@@ -342,6 +363,38 @@ def test_apply_datacube_operations_preserves_pixel_size_for_asymmetric_spacing(m
|
|
|
342
363
|
assert transformed.calibration.get_Q_pixel_size() == 3
|
|
343
364
|
|
|
344
365
|
|
|
366
|
+
class _Root:
|
|
367
|
+
def __init__(self, name):
|
|
368
|
+
self.name = name
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
class _DatacubeWithRoot(_Datacube):
|
|
372
|
+
def __init__(self, data, calibration=None, root_name="datacube_root"):
|
|
373
|
+
super().__init__(data, calibration)
|
|
374
|
+
self.root = _Root(root_name)
|
|
375
|
+
|
|
376
|
+
def copy(self):
|
|
377
|
+
# Mimic py4DSTEM's DataCube.copy(): rebuilding via the constructor
|
|
378
|
+
# gives the new object a differently-named root.
|
|
379
|
+
copied = _DatacubeWithRoot(
|
|
380
|
+
self.data.copy(), self.calibration.copy(), root_name="py4DSTEM_root"
|
|
381
|
+
)
|
|
382
|
+
return copied
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def test_copy_datacube_preserves_original_root_name(monkeypatch):
|
|
386
|
+
_install_pyqt_stubs(monkeypatch)
|
|
387
|
+
module = importlib.import_module("py4d_browser_plugin.transform.checkpoints")
|
|
388
|
+
|
|
389
|
+
datacube = _DatacubeWithRoot(np.arange(2 * 2 * 2 * 2).reshape(2, 2, 2, 2))
|
|
390
|
+
assert datacube.root.name == "datacube_root"
|
|
391
|
+
|
|
392
|
+
copied = module.copy_datacube(datacube)
|
|
393
|
+
|
|
394
|
+
assert copied.root.name == "datacube_root"
|
|
395
|
+
assert datacube.root.name == "datacube_root"
|
|
396
|
+
|
|
397
|
+
|
|
345
398
|
def test_apply_datacube_operations_invalid_input_does_not_mutate(monkeypatch):
|
|
346
399
|
module = _load_datacube_ops_module(monkeypatch)
|
|
347
400
|
data = np.arange(2 * 3 * 4 * 5).reshape(2, 3, 4, 5)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|