pytme 0.1.8__cp311-cp311-macosx_14_0_arm64.whl → 0.2.0__cp311-cp311-macosx_14_0_arm64.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.
- pytme-0.2.0.data/scripts/match_template.py +1019 -0
- pytme-0.2.0.data/scripts/postprocess.py +570 -0
- {pytme-0.1.8.data → pytme-0.2.0.data}/scripts/preprocessor_gui.py +244 -60
- {pytme-0.1.8.dist-info → pytme-0.2.0.dist-info}/METADATA +3 -1
- pytme-0.2.0.dist-info/RECORD +72 -0
- {pytme-0.1.8.dist-info → pytme-0.2.0.dist-info}/WHEEL +1 -1
- scripts/extract_candidates.py +218 -0
- scripts/match_template.py +459 -218
- pytme-0.1.8.data/scripts/match_template.py → scripts/match_template_filters.py +459 -218
- scripts/postprocess.py +380 -435
- scripts/preprocessor_gui.py +244 -60
- scripts/refine_matches.py +218 -0
- tme/__init__.py +2 -1
- tme/__version__.py +1 -1
- tme/analyzer.py +533 -78
- tme/backends/cupy_backend.py +80 -15
- tme/backends/npfftw_backend.py +35 -6
- tme/backends/pytorch_backend.py +15 -7
- tme/density.py +173 -78
- tme/extensions.cpython-311-darwin.so +0 -0
- tme/matching_constrained.py +195 -0
- tme/matching_data.py +78 -32
- tme/matching_exhaustive.py +369 -221
- tme/matching_memory.py +1 -0
- tme/matching_optimization.py +753 -649
- tme/matching_utils.py +152 -8
- tme/orientations.py +561 -0
- tme/preprocessing/__init__.py +2 -0
- tme/preprocessing/_utils.py +176 -0
- tme/preprocessing/composable_filter.py +30 -0
- tme/preprocessing/compose.py +52 -0
- tme/preprocessing/frequency_filters.py +322 -0
- tme/preprocessing/tilt_series.py +967 -0
- tme/preprocessor.py +35 -25
- tme/structure.py +2 -37
- pytme-0.1.8.data/scripts/postprocess.py +0 -625
- pytme-0.1.8.dist-info/RECORD +0 -61
- {pytme-0.1.8.data → pytme-0.2.0.data}/scripts/estimate_ram_usage.py +0 -0
- {pytme-0.1.8.data → pytme-0.2.0.data}/scripts/preprocess.py +0 -0
- {pytme-0.1.8.dist-info → pytme-0.2.0.dist-info}/LICENSE +0 -0
- {pytme-0.1.8.dist-info → pytme-0.2.0.dist-info}/entry_points.txt +0 -0
- {pytme-0.1.8.dist-info → pytme-0.2.0.dist-info}/top_level.txt +0 -0
tme/matching_utils.py
CHANGED
@@ -229,6 +229,7 @@ def compute_parallelization_schedule(
|
|
229
229
|
max_cores: int,
|
230
230
|
max_ram: int,
|
231
231
|
matching_method: str,
|
232
|
+
split_axes: Tuple[int] = None,
|
232
233
|
backend: str = None,
|
233
234
|
split_only_outer: bool = False,
|
234
235
|
shape1_padding: NDArray = None,
|
@@ -259,6 +260,8 @@ def compute_parallelization_schedule(
|
|
259
260
|
The maximum amount of memory that can be used.
|
260
261
|
matching_method : str
|
261
262
|
The metric used for scoring the computations.
|
263
|
+
split_axes : tuple
|
264
|
+
Axes that can be used for splitting. By default all are considered.
|
262
265
|
backend : str, optional
|
263
266
|
Backend used for computations.
|
264
267
|
split_only_outer : bool, optional
|
@@ -303,6 +306,13 @@ def compute_parallelization_schedule(
|
|
303
306
|
core_assignments = [(1, max_cores)]
|
304
307
|
|
305
308
|
possible_params, split_axis = [], np.argmax(shape1)
|
309
|
+
|
310
|
+
split_axis_index = split_axis
|
311
|
+
if split_axes is not None:
|
312
|
+
split_axis, split_axis_index = split_axes[0], 0
|
313
|
+
else:
|
314
|
+
split_axes = tuple(i for i in range(len(shape1)))
|
315
|
+
|
306
316
|
split_factor, n_splits = [1 for _ in range(len(shape1))], 0
|
307
317
|
while n_splits <= max_splits:
|
308
318
|
splits = {k: split_factor[k] for k in range(len(split_factor))}
|
@@ -341,9 +351,11 @@ def compute_parallelization_schedule(
|
|
341
351
|
(*split_factor, outer_cores, inner_cores, n_splits, inits)
|
342
352
|
)
|
343
353
|
split_factor[split_axis] += 1
|
344
|
-
|
345
|
-
|
346
|
-
|
354
|
+
|
355
|
+
split_axis_index += 1
|
356
|
+
if split_axis_index == len(split_axes):
|
357
|
+
split_axis_index = 0
|
358
|
+
split_axis = split_axes[split_axis_index]
|
347
359
|
|
348
360
|
possible_params = np.array(possible_params)
|
349
361
|
if not len(possible_params):
|
@@ -609,6 +621,91 @@ def get_rotation_matrices(
|
|
609
621
|
return ret
|
610
622
|
|
611
623
|
|
624
|
+
def get_rotations_around_vector(
|
625
|
+
cone_angle: float,
|
626
|
+
cone_sampling: float,
|
627
|
+
axis_angle: float = 360.0,
|
628
|
+
axis_sampling: float = None,
|
629
|
+
vector: Tuple[float] = (1, 0, 0),
|
630
|
+
n_symmetry: int = 1,
|
631
|
+
convention: str = None,
|
632
|
+
) -> NDArray:
|
633
|
+
"""
|
634
|
+
Generate rotations describing the possible placements of a vector in a cone.
|
635
|
+
|
636
|
+
Parameters
|
637
|
+
----------
|
638
|
+
cone_angle : float
|
639
|
+
The half-angle of the cone in degrees.
|
640
|
+
cone_sampling : float
|
641
|
+
Angular increment used for sampling points on the cone in degrees.
|
642
|
+
axis_angle : float, optional
|
643
|
+
The total angle of rotation around the vector axis in degrees (default is 360.0).
|
644
|
+
axis_sampling : float, optional
|
645
|
+
Angular increment used for sampling points around the vector axis in degrees.
|
646
|
+
If None, it takes the value of `cone_sampling`.
|
647
|
+
vector : Tuple[float], optional
|
648
|
+
Cartesian coordinates in zyx convention.
|
649
|
+
n_symmetry : int, optional
|
650
|
+
Number of symmetry axis around the vector axis.
|
651
|
+
convention : str, optional
|
652
|
+
Convention for angles. By default returns rotation matrices.
|
653
|
+
|
654
|
+
Returns
|
655
|
+
-------
|
656
|
+
NDArray
|
657
|
+
An array of rotation angles represented as Euler angles (phi, theta, psi) in degrees.
|
658
|
+
The shape of the array is (n, 3), where `n` is the total number of rotation angles.
|
659
|
+
Each row represents a set of rotation angles.
|
660
|
+
|
661
|
+
References
|
662
|
+
----------
|
663
|
+
.. [1] https://stackoverflow.com/questions/9600801/evenly-distributing-n-points-on-a-sphere
|
664
|
+
|
665
|
+
"""
|
666
|
+
if axis_sampling is None:
|
667
|
+
axis_sampling = cone_sampling
|
668
|
+
|
669
|
+
# Heuristic to estimate necessary number of points on sphere
|
670
|
+
theta = np.linspace(0, cone_angle, round(cone_angle / cone_sampling) + 1)
|
671
|
+
number_of_points = np.ceil(
|
672
|
+
360 * np.divide(np.sin(np.radians(theta)), cone_sampling),
|
673
|
+
)
|
674
|
+
number_of_points = int(np.sum(number_of_points + 1) + 2)
|
675
|
+
|
676
|
+
# Golden Spiral
|
677
|
+
indices = np.arange(0, number_of_points, dtype=float) + 0.5
|
678
|
+
radius = cone_angle * np.sqrt(indices / number_of_points)
|
679
|
+
theta = np.pi * (1 + np.sqrt(5)) * indices
|
680
|
+
|
681
|
+
angles_vector = Rotation.from_euler(
|
682
|
+
angles=rotation_aligning_vectors([1, 0, 0], vector, convention="zyx"),
|
683
|
+
seq="zyx",
|
684
|
+
degrees=True,
|
685
|
+
)
|
686
|
+
|
687
|
+
# phi, theta, psi
|
688
|
+
axis_angle /= n_symmetry
|
689
|
+
phi_steps = np.maximum(np.round(axis_angle / axis_sampling), 1).astype(int)
|
690
|
+
phi = np.linspace(0, axis_angle, phi_steps + 1)[:-1]
|
691
|
+
np.add(phi, angles_vector.as_euler("zyx", degrees=True)[0], out=phi)
|
692
|
+
angles = np.stack(
|
693
|
+
[radius * np.cos(theta), radius * np.sin(theta), np.zeros_like(radius)], axis=1
|
694
|
+
)
|
695
|
+
angles = np.repeat(angles, phi_steps, axis=0)
|
696
|
+
angles[:, 2] = np.tile(phi, radius.size)
|
697
|
+
|
698
|
+
angles = Rotation.from_euler(angles=angles, seq="zyx", degrees=True)
|
699
|
+
angles = angles_vector * angles
|
700
|
+
|
701
|
+
if convention is None:
|
702
|
+
rotation_angles = angles.as_matrix()
|
703
|
+
else:
|
704
|
+
rotation_angles = angles.as_euler(seq=convention, degrees=True)
|
705
|
+
|
706
|
+
return rotation_angles
|
707
|
+
|
708
|
+
|
612
709
|
def minimum_enclosing_box(
|
613
710
|
coordinates: NDArray,
|
614
711
|
margin: NDArray = None,
|
@@ -749,7 +846,7 @@ def crop_input(
|
|
749
846
|
return reference_fit
|
750
847
|
|
751
848
|
|
752
|
-
def euler_to_rotationmatrix(angles: Tuple[float]) -> NDArray:
|
849
|
+
def euler_to_rotationmatrix(angles: Tuple[float], convention: str = "zyx") -> NDArray:
|
753
850
|
"""
|
754
851
|
Convert Euler angles to a rotation matrix.
|
755
852
|
|
@@ -757,6 +854,8 @@ def euler_to_rotationmatrix(angles: Tuple[float]) -> NDArray:
|
|
757
854
|
----------
|
758
855
|
angles : tuple
|
759
856
|
A tuple representing the Euler angles in degrees.
|
857
|
+
convention : str, optional
|
858
|
+
Euler angle convention.
|
760
859
|
|
761
860
|
Returns
|
762
861
|
-------
|
@@ -764,7 +863,7 @@ def euler_to_rotationmatrix(angles: Tuple[float]) -> NDArray:
|
|
764
863
|
The generated rotation matrix.
|
765
864
|
"""
|
766
865
|
n_angles = len(angles)
|
767
|
-
angle_convention =
|
866
|
+
angle_convention = convention[:n_angles]
|
768
867
|
if n_angles == 1:
|
769
868
|
angles = (angles, 0, 0)
|
770
869
|
rotation_matrix = (
|
@@ -775,7 +874,9 @@ def euler_to_rotationmatrix(angles: Tuple[float]) -> NDArray:
|
|
775
874
|
return rotation_matrix
|
776
875
|
|
777
876
|
|
778
|
-
def euler_from_rotationmatrix(
|
877
|
+
def euler_from_rotationmatrix(
|
878
|
+
rotation_matrix: NDArray, convention: str = "zyx"
|
879
|
+
) -> Tuple:
|
779
880
|
"""
|
780
881
|
Convert a rotation matrix to euler angles.
|
781
882
|
|
@@ -783,7 +884,8 @@ def euler_from_rotationmatrix(rotation_matrix: NDArray) -> Tuple:
|
|
783
884
|
----------
|
784
885
|
rotation_matrix : NDArray
|
785
886
|
A 2 x 2 or 3 x 3 rotation matrix in z y x form.
|
786
|
-
|
887
|
+
convention : str, optional
|
888
|
+
Euler angle convention.
|
787
889
|
Returns
|
788
890
|
-------
|
789
891
|
Tuple
|
@@ -795,12 +897,54 @@ def euler_from_rotationmatrix(rotation_matrix: NDArray) -> Tuple:
|
|
795
897
|
rotation_matrix = temp_matrix
|
796
898
|
euler_angles = (
|
797
899
|
Rotation.from_matrix(rotation_matrix)
|
798
|
-
.as_euler(
|
900
|
+
.as_euler(convention, degrees=True)
|
799
901
|
.astype(np.float32)
|
800
902
|
)
|
801
903
|
return euler_angles
|
802
904
|
|
803
905
|
|
906
|
+
def rotation_aligning_vectors(
|
907
|
+
initial_vector: NDArray, target_vector: NDArray = [1, 0, 0], convention: str = None
|
908
|
+
):
|
909
|
+
"""
|
910
|
+
Compute the rotation matrix or Euler angles required to align an initial vector with a target vector.
|
911
|
+
|
912
|
+
Parameters
|
913
|
+
----------
|
914
|
+
initial_vector : NDArray
|
915
|
+
The initial vector to be rotated.
|
916
|
+
target_vector : NDArray, optional
|
917
|
+
The target vector to align the initial vector with. Default is [1, 0, 0].
|
918
|
+
convention : str, optional
|
919
|
+
The generate euler angles in degrees. If None returns a rotation matrix instead.
|
920
|
+
|
921
|
+
Returns
|
922
|
+
-------
|
923
|
+
rotation_matrix_or_angles : NDArray or tuple
|
924
|
+
Rotation matrix if convention is None else tuple of euler angles.
|
925
|
+
"""
|
926
|
+
initial_vector = np.asarray(initial_vector, dtype=np.float32)
|
927
|
+
target_vector = np.asarray(target_vector, dtype=np.float32)
|
928
|
+
initial_vector /= np.linalg.norm(initial_vector)
|
929
|
+
target_vector /= np.linalg.norm(target_vector)
|
930
|
+
|
931
|
+
rotation_matrix = np.eye(len(initial_vector))
|
932
|
+
if not np.allclose(initial_vector, target_vector):
|
933
|
+
rotation_axis = np.cross(initial_vector, target_vector)
|
934
|
+
rotation_angle = np.arccos(np.dot(initial_vector, target_vector))
|
935
|
+
k = rotation_axis / np.linalg.norm(rotation_axis)
|
936
|
+
K = np.array([[0, -k[2], k[1]], [k[2], 0, -k[0]], [-k[1], k[0], 0]])
|
937
|
+
rotation_matrix = np.eye(3)
|
938
|
+
rotation_matrix += np.sin(rotation_angle) * K
|
939
|
+
rotation_matrix += (1 - np.cos(rotation_angle)) * np.dot(K, K)
|
940
|
+
|
941
|
+
if convention is None:
|
942
|
+
return rotation_matrix
|
943
|
+
|
944
|
+
angles = euler_from_rotationmatrix(rotation_matrix, convention=convention)
|
945
|
+
return angles
|
946
|
+
|
947
|
+
|
804
948
|
def rigid_transform(
|
805
949
|
coordinates: NDArray,
|
806
950
|
rotation_matrix: NDArray,
|