pytme 0.2.9__cp311-cp311-macosx_15_0_arm64.whl → 0.3b0__cp311-cp311-macosx_15_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.
Files changed (63) hide show
  1. pytme-0.2.9.data/scripts/estimate_ram_usage.py → pytme-0.3b0.data/scripts/estimate_memory_usage.py +16 -33
  2. {pytme-0.2.9.data → pytme-0.3b0.data}/scripts/match_template.py +224 -223
  3. {pytme-0.2.9.data → pytme-0.3b0.data}/scripts/postprocess.py +283 -163
  4. {pytme-0.2.9.data → pytme-0.3b0.data}/scripts/preprocess.py +11 -8
  5. {pytme-0.2.9.data → pytme-0.3b0.data}/scripts/preprocessor_gui.py +10 -9
  6. {pytme-0.2.9.dist-info → pytme-0.3b0.dist-info}/METADATA +11 -9
  7. {pytme-0.2.9.dist-info → pytme-0.3b0.dist-info}/RECORD +61 -58
  8. {pytme-0.2.9.dist-info → pytme-0.3b0.dist-info}/entry_points.txt +1 -1
  9. scripts/{estimate_ram_usage.py → estimate_memory_usage.py} +16 -33
  10. scripts/extract_candidates.py +224 -0
  11. scripts/match_template.py +224 -223
  12. scripts/postprocess.py +283 -163
  13. scripts/preprocess.py +11 -8
  14. scripts/preprocessor_gui.py +10 -9
  15. scripts/refine_matches.py +626 -0
  16. tests/preprocessing/test_frequency_filters.py +9 -4
  17. tests/test_analyzer.py +143 -138
  18. tests/test_matching_cli.py +85 -29
  19. tests/test_matching_exhaustive.py +1 -2
  20. tests/test_matching_optimization.py +4 -9
  21. tests/test_orientations.py +0 -1
  22. tme/__version__.py +1 -1
  23. tme/analyzer/__init__.py +2 -0
  24. tme/analyzer/_utils.py +25 -17
  25. tme/analyzer/aggregation.py +385 -220
  26. tme/analyzer/base.py +138 -0
  27. tme/analyzer/peaks.py +150 -88
  28. tme/analyzer/proxy.py +122 -0
  29. tme/backends/__init__.py +4 -3
  30. tme/backends/_cupy_utils.py +25 -24
  31. tme/backends/_jax_utils.py +4 -3
  32. tme/backends/cupy_backend.py +4 -13
  33. tme/backends/jax_backend.py +6 -8
  34. tme/backends/matching_backend.py +4 -3
  35. tme/backends/mlx_backend.py +4 -3
  36. tme/backends/npfftw_backend.py +7 -5
  37. tme/backends/pytorch_backend.py +14 -4
  38. tme/cli.py +126 -0
  39. tme/density.py +4 -3
  40. tme/filters/__init__.py +1 -1
  41. tme/filters/_utils.py +4 -3
  42. tme/filters/bandpass.py +6 -4
  43. tme/filters/compose.py +5 -4
  44. tme/filters/ctf.py +426 -214
  45. tme/filters/reconstruction.py +58 -28
  46. tme/filters/wedge.py +139 -61
  47. tme/filters/whitening.py +36 -36
  48. tme/matching_data.py +4 -3
  49. tme/matching_exhaustive.py +17 -16
  50. tme/matching_optimization.py +5 -4
  51. tme/matching_scores.py +4 -3
  52. tme/matching_utils.py +6 -4
  53. tme/memory.py +4 -3
  54. tme/orientations.py +9 -6
  55. tme/parser.py +5 -4
  56. tme/preprocessor.py +4 -3
  57. tme/rotations.py +10 -7
  58. tme/structure.py +4 -3
  59. tests/data/Maps/.DS_Store +0 -0
  60. tests/data/Structures/.DS_Store +0 -0
  61. {pytme-0.2.9.dist-info → pytme-0.3b0.dist-info}/WHEEL +0 -0
  62. {pytme-0.2.9.dist-info → pytme-0.3b0.dist-info}/licenses/LICENSE +0 -0
  63. {pytme-0.2.9.dist-info → pytme-0.3b0.dist-info}/top_level.txt +0 -0
@@ -1,34 +1,35 @@
1
- """ Utility functions for cupy backend.
1
+ """
2
+ Utility functions for cupy backend.
2
3
 
3
- The functions spline_filter, _prepad_for_spline_filter, _filter_input,
4
- _get_coord_affine_batched and affine_transform are largely copied from
5
- cupyx.scipy.ndimage which operates under the following license
4
+ The functions spline_filter, _prepad_for_spline_filter, _filter_input,
5
+ _get_coord_affine_batched and affine_transform are largely copied from
6
+ cupyx.scipy.ndimage which operates under the following license
6
7
 
7
- Copyright (c) 2015 Preferred Infrastructure, Inc.
8
- Copyright (c) 2015 Preferred Networks, Inc.
8
+ Copyright (c) 2015 Preferred Infrastructure, Inc.
9
+ Copyright (c) 2015 Preferred Networks, Inc.
9
10
 
10
- Permission is hereby granted, free of charge, to any person obtaining a copy
11
- of this software and associated documentation files (the "Software"), to deal
12
- in the Software without restriction, including without limitation the rights
13
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
- copies of the Software, and to permit persons to whom the Software is
15
- furnished to do so, subject to the following conditions:
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
16
17
 
17
- The above copyright notice and this permission notice shall be included in
18
- all copies or substantial portions of the Software.
18
+ The above copyright notice and this permission notice shall be included in
19
+ all copies or substantial portions of the Software.
19
20
 
20
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26
- THE SOFTWARE.
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
+ THE SOFTWARE.
27
28
 
28
- I have since extended the functionality of the cupyx.scipy.ndimage functions
29
- in question to support batched inputs.
29
+ I have since extended the functionality of the cupyx.scipy.ndimage functions
30
+ in question to support batched inputs.
30
31
 
31
- Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
32
+ Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
32
33
  """
33
34
 
34
35
  import numpy
@@ -1,8 +1,9 @@
1
- """ Utility functions for jax backend.
1
+ """
2
+ Utility functions for jax backend.
2
3
 
3
- Copyright (c) 2023-2024 European Molecular Biology Laboratory
4
+ Copyright (c) 2023-2024 European Molecular Biology Laboratory
4
5
 
5
- Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
+ Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
7
  """
7
8
 
8
9
  from typing import Tuple
@@ -1,8 +1,9 @@
1
- """ Backend using cupy for template matching.
1
+ """
2
+ Backend using cupy for template matching.
2
3
 
3
- Copyright (c) 2023 European Molecular Biology Laboratory
4
+ Copyright (c) 2023 European Molecular Biology Laboratory
4
5
 
5
- Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
+ Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
7
  """
7
8
 
8
9
  import warnings
@@ -113,16 +114,6 @@ class CupyBackend(NumpyFFTWBackend):
113
114
  def unravel_index(self, indices, shape):
114
115
  return self._array_backend.unravel_index(indices=indices, dims=shape)
115
116
 
116
- def unique(self, ar, axis=None, *args, **kwargs):
117
- if axis is None:
118
- return self._array_backend.unique(ar=ar, axis=axis, *args, **kwargs)
119
-
120
- warnings.warn("Axis argument not yet supported in CupY, falling back to NumPy.")
121
- ret = np.unique(ar=self.to_numpy_array(ar), axis=axis, *args, **kwargs)
122
- if not isinstance(ret, tuple):
123
- return self.to_backend_array(ret)
124
- return tuple(self.to_backend_array(k) for k in ret)
125
-
126
117
  def build_fft(
127
118
  self,
128
119
  fwd_shape: Tuple[int],
@@ -1,8 +1,9 @@
1
- """ Backend using jax for template matching.
1
+ """
2
+ Backend using jax for template matching.
2
3
 
3
- Copyright (c) 2023-2024 European Molecular Biology Laboratory
4
+ Copyright (c) 2023-2024 European Molecular Biology Laboratory
4
5
 
5
- Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
+ Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
7
  """
7
8
 
8
9
  from functools import wraps
@@ -288,13 +289,10 @@ class JaxBackend(NumpyFFTWBackend):
288
289
  for index in range(scores.shape[0]):
289
290
  temp = callback_class(
290
291
  shape=scores.shape,
291
- scores=scores[index],
292
- rotations=rotations[index],
293
- thread_safe=False,
294
292
  offset=translation_offsets[index],
295
293
  )
296
- temp.rotation_mapping = rotation_mapping
297
- ret.append(tuple(temp._postprocess(**analyzer_args)))
294
+ state = (scores, rotations, rotation_mapping)
295
+ ret.append(temp.result(state, **analyzer_args))
298
296
 
299
297
  return ret
300
298
 
@@ -1,8 +1,9 @@
1
- """ Strategy pattern to allow for flexible array / FFT backends.
1
+ """
2
+ Strategy pattern to allow for flexible array / FFT backends.
2
3
 
3
- Copyright (c) 2023 European Molecular Biology Laboratory
4
+ Copyright (c) 2023 European Molecular Biology Laboratory
4
5
 
5
- Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
+ Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
7
  """
7
8
 
8
9
  from abc import ABC, abstractmethod
@@ -1,8 +1,9 @@
1
- """ Backend using Apple's MLX library for template matching.
1
+ """
2
+ Backend using Apple's MLX library for template matching.
2
3
 
3
- Copyright (c) 2024 European Molecular Biology Laboratory
4
+ Copyright (c) 2024 European Molecular Biology Laboratory
4
5
 
5
- Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
+ Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
7
  """
7
8
 
8
9
  from typing import Tuple, List, Callable
@@ -1,8 +1,9 @@
1
- """ Backend using numpy and pyFFTW for template matching.
1
+ """
2
+ Backend using numpy and pyFFTW for template matching.
2
3
 
3
- Copyright (c) 2023 European Molecular Biology Laboratory
4
+ Copyright (c) 2023 European Molecular Biology Laboratory
4
5
 
5
- Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
+ Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
7
  """
7
8
 
8
9
  import os
@@ -159,8 +160,9 @@ class NumpyFFTWBackend(_NumpyWrapper, MatchingBackend):
159
160
  temp = self._array_backend.zeros(1, dtype=dtype)
160
161
  return temp.nbytes
161
162
 
162
- @staticmethod
163
- def astype(arr, dtype: Type) -> NDArray:
163
+ def astype(self, arr, dtype: Type) -> NDArray:
164
+ if self._array_backend.iscomplexobj(arr):
165
+ arr = arr.real
164
166
  return arr.astype(dtype)
165
167
 
166
168
  @staticmethod
@@ -1,9 +1,10 @@
1
- """ Backend using pytorch and optionally GPU acceleration for
2
- template matching.
1
+ """
2
+ Backend using pytorch and optionally GPU acceleration for
3
+ template matching.
3
4
 
4
- Copyright (c) 2023 European Molecular Biology Laboratory
5
+ Copyright (c) 2023 European Molecular Biology Laboratory
5
6
 
6
- Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
7
+ Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
7
8
  """
8
9
 
9
10
  from typing import Tuple, Callable
@@ -134,6 +135,15 @@ class PytorchBackend(NumpyFFTWBackend):
134
135
  def astype(self, arr: TorchTensor, dtype: type) -> TorchTensor:
135
136
  return arr.to(dtype)
136
137
 
138
+ @staticmethod
139
+ def at(arr, idx, value) -> NDArray:
140
+ arr[idx] = value
141
+ return arr
142
+
143
+ @staticmethod
144
+ def addat(arr, indices, *args, **kwargs) -> NDArray:
145
+ return arr.index_put_(indices, *args, accumulate=True, **kwargs)
146
+
137
147
  def flip(self, a, axis, **kwargs):
138
148
  return self._array_backend.flip(input=a, dims=axis, **kwargs)
139
149
 
tme/cli.py ADDED
@@ -0,0 +1,126 @@
1
+ #!python3
2
+ """
3
+ CLI utility functions.
4
+
5
+ Copyright (c) 2025 European Molecular Biology Laboratory
6
+
7
+ Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
8
+ """
9
+
10
+ import argparse
11
+
12
+ import numpy as np
13
+ from . import __version__
14
+ from .types import BackendArray
15
+
16
+
17
+ def match_template(
18
+ target: BackendArray,
19
+ template: BackendArray,
20
+ template_mask: BackendArray = None,
21
+ score="FLCSphericalMask",
22
+ rotations=None,
23
+ ):
24
+ """
25
+ Simple template matching run.
26
+
27
+ Parameters
28
+ ----------
29
+ target : BackendArray
30
+ Target array.
31
+ template : BackendArray
32
+ Template to be matched against target.
33
+ template_mask : BackendArray, optional
34
+ Template mask for normalization, defaults to None.
35
+ score : str, optional
36
+ Scoring method to use, defaults to 'FLCSphericalMask'.
37
+ rotations: BackendArray, optional
38
+ Rotation matrices with shape (n, d, d), where d is the dimension
39
+ of the target. Defaults to the identity rotation matrix.
40
+
41
+ Returns
42
+ -------
43
+ tuple
44
+ scores : BackendArray
45
+ Computed cross-correlation scores.
46
+ offset : BackendArray
47
+ Offset in target, defaults to 0.
48
+ rotations : BackendArray
49
+ Map between translations and rotation indices
50
+ rotation_mapping : dict
51
+ Map between rotation indices and rotation matrices
52
+ """
53
+ from .matching_data import MatchingData
54
+ from .analyzer import MaxScoreOverRotations
55
+ from .matching_exhaustive import scan_subsets, MATCHING_EXHAUSTIVE_REGISTER
56
+
57
+ if rotations is None:
58
+ rotations = np.eye(target.ndim).reshape(1, target.ndim, target.ndim)
59
+
60
+ if rotations.shape[-1] != target.ndim:
61
+ print(
62
+ f"Dimension of rotation matrix {rotations.shape[-1]} does not "
63
+ "match target dimension."
64
+ )
65
+
66
+ matching_data = MatchingData(
67
+ target=target,
68
+ template=template,
69
+ template_mask=template_mask,
70
+ rotations=rotations,
71
+ )
72
+ matching_data.template_mask = template_mask
73
+ matching_setup, matching_score = MATCHING_EXHAUSTIVE_REGISTER[score]
74
+
75
+ candidates = list(
76
+ scan_subsets(
77
+ matching_data=matching_data,
78
+ matching_score=matching_score,
79
+ matching_setup=matching_setup,
80
+ callback_class=MaxScoreOverRotations,
81
+ callback_class_args={
82
+ "score_threshold": -1,
83
+ },
84
+ pad_target_edges=True,
85
+ job_schedule=(1, 1),
86
+ )
87
+ )
88
+ return candidates
89
+
90
+
91
+ def sanitize_name(name: str):
92
+ return name.title().replace("_", " ").replace("-", " ")
93
+
94
+
95
+ def print_entry() -> None:
96
+ width = 80
97
+ text = f" pytme v{__version__} "
98
+ padding_total = width - len(text) - 2
99
+ padding_left = padding_total // 2
100
+ padding_right = padding_total - padding_left
101
+
102
+ print("*" * width)
103
+ print(f"*{ ' ' * padding_left }{text}{ ' ' * padding_right }*")
104
+ print("*" * width)
105
+
106
+
107
+ def get_func_fullname(func) -> str:
108
+ """Returns the full name of the given function, including its module."""
109
+ return f"<function '{func.__module__}.{func.__name__}'>"
110
+
111
+
112
+ def print_block(name: str, data: dict, label_width=20) -> None:
113
+ """Prints a formatted block of information."""
114
+ print(f"\n> {name}")
115
+ for key, value in data.items():
116
+ if isinstance(value, np.ndarray):
117
+ value = value.shape
118
+ formatted_value = str(value)
119
+ print(f" - {str(key) + ':':<{label_width}} {formatted_value}")
120
+
121
+
122
+ def check_positive(value):
123
+ ivalue = float(value)
124
+ if ivalue <= 0:
125
+ raise argparse.ArgumentTypeError("%s is an invalid positive float." % value)
126
+ return ivalue
tme/density.py CHANGED
@@ -1,8 +1,9 @@
1
- """ Representation of N-dimensional densities
1
+ """
2
+ Representation of N-dimensional densities
2
3
 
3
- Copyright (c) 2023 European Molecular Biology Laboratory
4
+ Copyright (c) 2023 European Molecular Biology Laboratory
4
5
 
5
- Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
+ Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
7
  """
7
8
 
8
9
  import warnings
tme/filters/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- from .ctf import CTF
1
+ from .ctf import CTF, CTFReconstructed
2
2
  from .compose import Compose, ComposableFilter
3
3
  from .bandpass import BandPassFilter
4
4
  from .whitening import LinearWhiteningFilter
tme/filters/_utils.py CHANGED
@@ -1,8 +1,9 @@
1
- """ Utilities for the generation of frequency grids.
1
+ """
2
+ Utilities for the generation of frequency grids.
2
3
 
3
- Copyright (c) 2024 European Molecular Biology Laboratory
4
+ Copyright (c) 2024 European Molecular Biology Laboratory
4
5
 
5
- Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
+ Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
7
  """
7
8
 
8
9
  from typing import Tuple, List, Dict
tme/filters/bandpass.py CHANGED
@@ -1,8 +1,9 @@
1
- """ Implements class BandPassFilter to create Fourier filter representations.
1
+ """
2
+ Implements class BandPassFilter to create Fourier filter representations.
2
3
 
3
- Copyright (c) 2024 European Molecular Biology Laboratory
4
+ Copyright (c) 2024 European Molecular Biology Laboratory
4
5
 
5
- Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
+ Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
7
  """
7
8
 
8
9
  from typing import Tuple
@@ -225,6 +226,7 @@ class BandPassFilter(ComposableFilter):
225
226
 
226
227
  return {
227
228
  "data": be.to_backend_array(mask),
228
- "sampling_rate": func_args.get("sampling_rate", 1),
229
+ "shape": func_args["shape"],
230
+ "return_real_fourier": func_args.get("return_real_fourier"),
229
231
  "is_multiplicative_filter": True,
230
232
  }
tme/filters/compose.py CHANGED
@@ -1,8 +1,9 @@
1
- """ Combine filters using an interface analogous to pytorch's Compose.
1
+ """
2
+ Combine filters using an interface analogous to pytorch's Compose.
2
3
 
3
- Copyright (c) 2024 European Molecular Biology Laboratory
4
+ Copyright (c) 2024 European Molecular Biology Laboratory
4
5
 
5
- Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
+ Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
6
7
  """
7
8
 
8
9
  from typing import Tuple, Dict
@@ -60,7 +61,7 @@ class Compose:
60
61
 
61
62
  class ComposableFilter(ABC):
62
63
  """
63
- Strategy class for composable filters.
64
+ Base class for composable filters.
64
65
  """
65
66
 
66
67
  @abstractmethod