pytme 0.1.6__cp311-cp311-macosx_14_0_arm64.whl → 0.1.8__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.
@@ -29,17 +29,17 @@ preprocessor = Preprocessor()
29
29
  SLIDER_MIN, SLIDER_MAX = 0, 25
30
30
 
31
31
 
32
- def gaussian_filter(template, sigma: float, **kwargs: dict):
32
+ def gaussian_filter(template: NDArray, sigma: float, **kwargs: dict) -> NDArray:
33
33
  return preprocessor.gaussian_filter(template=template, sigma=sigma, **kwargs)
34
34
 
35
35
 
36
36
  def bandpass_filter(
37
- template,
37
+ template: NDArray,
38
38
  minimum_frequency: float,
39
39
  maximum_frequency: float,
40
40
  gaussian_sigma: float,
41
41
  **kwargs: dict,
42
- ):
42
+ ) -> NDArray:
43
43
  return preprocessor.bandpass_filter(
44
44
  template=template,
45
45
  minimum_frequency=minimum_frequency,
@@ -51,8 +51,8 @@ def bandpass_filter(
51
51
 
52
52
 
53
53
  def difference_of_gaussian_filter(
54
- template, sigmas: Tuple[float, float], **kwargs: dict
55
- ):
54
+ template: NDArray, sigmas: Tuple[float, float], **kwargs: dict
55
+ ) -> NDArray:
56
56
  low_sigma, high_sigma = sigmas
57
57
  return preprocessor.difference_of_gaussian_filter(
58
58
  template=template, low_sigma=low_sigma, high_sigma=high_sigma, **kwargs
@@ -60,7 +60,7 @@ def difference_of_gaussian_filter(
60
60
 
61
61
 
62
62
  def edge_gaussian_filter(
63
- template,
63
+ template: NDArray,
64
64
  sigma: float,
65
65
  edge_algorithm: Annotated[
66
66
  str,
@@ -68,7 +68,7 @@ def edge_gaussian_filter(
68
68
  ],
69
69
  reverse: bool = False,
70
70
  **kwargs: dict,
71
- ):
71
+ ) -> NDArray:
72
72
  return preprocessor.edge_gaussian_filter(
73
73
  template=template,
74
74
  sigma=sigma,
@@ -78,13 +78,13 @@ def edge_gaussian_filter(
78
78
 
79
79
 
80
80
  def local_gaussian_filter(
81
- template,
81
+ template: NDArray,
82
82
  lbd: float,
83
83
  sigma_range: Tuple[float, float],
84
84
  gaussian_sigma: float,
85
85
  reverse: bool = False,
86
86
  **kwargs: dict,
87
- ):
87
+ ) -> NDArray:
88
88
  return preprocessor.local_gaussian_filter(
89
89
  template=template,
90
90
  lbd=lbd,
@@ -94,21 +94,76 @@ def local_gaussian_filter(
94
94
 
95
95
 
96
96
  def ntree(
97
- template,
97
+ template: NDArray,
98
98
  sigma_range: Tuple[float, float],
99
99
  **kwargs: dict,
100
- ):
100
+ ) -> NDArray:
101
101
  return preprocessor.ntree_filter(template=template, sigma_range=sigma_range)
102
102
 
103
103
 
104
104
  def mean(
105
- template,
105
+ template: NDArray,
106
106
  width: int,
107
107
  **kwargs: dict,
108
- ):
108
+ ) -> NDArray:
109
109
  return preprocessor.mean_filter(template=template, width=width)
110
110
 
111
111
 
112
+ def resolution_sphere(
113
+ template: NDArray,
114
+ cutoff_angstrom: float,
115
+ highpass: bool = False,
116
+ sampling_rate=None,
117
+ ) -> NDArray:
118
+ if cutoff_angstrom == 0:
119
+ return template
120
+
121
+ cutoff_frequency = np.max(2 * sampling_rate / cutoff_angstrom)
122
+
123
+ min_freq, max_freq = 0, cutoff_frequency
124
+ if highpass:
125
+ min_freq, max_freq = cutoff_frequency, 1e10
126
+
127
+ mask = preprocessor.bandpass_mask(
128
+ shape=template.shape,
129
+ minimum_frequency=min_freq,
130
+ maximum_frequency=max_freq,
131
+ omit_negative_frequencies=False,
132
+ )
133
+
134
+ template_ft = np.fft.fftn(template)
135
+ np.multiply(template_ft, mask, out=template_ft)
136
+ return np.fft.ifftn(template_ft).real
137
+
138
+
139
+ def resolution_gaussian(
140
+ template: NDArray,
141
+ cutoff_angstrom: float,
142
+ highpass: bool = False,
143
+ sampling_rate=None,
144
+ ) -> NDArray:
145
+ if cutoff_angstrom == 0:
146
+ return template
147
+
148
+ grid = preprocessor.fftfreqn(
149
+ shape=template.shape, sampling_rate=sampling_rate / sampling_rate.max()
150
+ )
151
+
152
+ sigma_fourier = np.divide(
153
+ np.max(2 * sampling_rate / cutoff_angstrom), np.sqrt(2 * np.log(2))
154
+ )
155
+
156
+ mask = np.exp(-(grid**2) / (2 * sigma_fourier**2))
157
+ if highpass:
158
+ mask = 1 - mask
159
+
160
+ mask = np.fft.ifftshift(mask)
161
+
162
+ template_ft = np.fft.fftn(template)
163
+ np.multiply(template_ft, mask, out=template_ft)
164
+ return np.fft.ifftn(template_ft).real
165
+
166
+
112
167
  def wedge(
113
168
  template: NDArray,
114
169
  tilt_start: float,
@@ -120,7 +175,7 @@ def wedge(
120
175
  omit_negative_frequencies: bool = True,
121
176
  extrude_plane: bool = True,
122
177
  infinite_plane: bool = True,
123
- ):
178
+ ) -> NDArray:
124
179
  template_ft = np.fft.rfftn(template)
125
180
 
126
181
  if tilt_step <= 0:
@@ -139,15 +194,14 @@ def wedge(
139
194
  template = np.real(np.fft.irfftn(template_ft))
140
195
  return template
141
196
 
142
- tilt_angles = np.arange(-tilt_start, tilt_stop, tilt_step)
143
- angles = np.zeros((template.ndim, tilt_angles.size))
144
- angles[tilt_axis, :] = tilt_angles
145
-
146
- wedge_mask = preprocessor.wedge_mask(
147
- tilt_angles=angles,
197
+ wedge_mask = preprocessor.step_wedge_mask(
198
+ start_tilt=tilt_start,
199
+ stop_tilt=tilt_stop,
200
+ tilt_axis=tilt_axis,
201
+ tilt_step=tilt_step,
202
+ opening_axis=opening_axis,
148
203
  shape=template.shape,
149
204
  sigma=gaussian_sigma,
150
- opening_axes=opening_axis,
151
205
  omit_negative_frequencies=omit_negative_frequencies,
152
206
  )
153
207
  np.multiply(template_ft, wedge_mask, out=template_ft)
@@ -155,7 +209,7 @@ def wedge(
155
209
  return template
156
210
 
157
211
 
158
- def compute_power_spectrum(template: NDArray):
212
+ def compute_power_spectrum(template: NDArray) -> NDArray:
159
213
  return np.fft.fftshift(np.log(np.abs(np.fft.fftn(template))))
160
214
 
161
215
 
@@ -220,6 +274,8 @@ WRAPPED_FUNCTIONS = {
220
274
  "mean_filter": mean,
221
275
  "wedge_filter": wedge,
222
276
  "power_spectrum": compute_power_spectrum,
277
+ "resolution_gaussian": resolution_gaussian,
278
+ "resolution_sphere": resolution_sphere,
223
279
  }
224
280
 
225
281
  EXCLUDED_FUNCTIONS = [
@@ -332,6 +388,9 @@ class FilterWidget(widgets.Container):
332
388
  function_name = self.name_mapping.get(self.method_dropdown.value)
333
389
  function = self._get_function(function_name)
334
390
 
391
+ if "sampling_rate" in inspect.getfullargspec(function).args:
392
+ kwargs["sampling_rate"] = selected_layer_metadata["sampling_rate"]
393
+
335
394
  processed_data = function(selected_layer.data, **kwargs)
336
395
 
337
396
  new_layer_name = f"{selected_layer.name} ({self.method_dropdown.value})"
@@ -358,7 +417,7 @@ class FilterWidget(widgets.Container):
358
417
 
359
418
  def sphere_mask(
360
419
  template: NDArray, center_x: float, center_y: float, center_z: float, radius: float
361
- ):
420
+ ) -> NDArray:
362
421
  return create_mask(
363
422
  mask_type="ellipse",
364
423
  shape=template.shape,
@@ -375,7 +434,7 @@ def ellipsod_mask(
375
434
  radius_x: float,
376
435
  radius_y: float,
377
436
  radius_z: float,
378
- ):
437
+ ) -> NDArray:
379
438
  return create_mask(
380
439
  mask_type="ellipse",
381
440
  shape=template.shape,
@@ -392,7 +451,7 @@ def box_mask(
392
451
  height_x: int,
393
452
  height_y: int,
394
453
  height_z: int,
395
- ):
454
+ ) -> NDArray:
396
455
  return create_mask(
397
456
  mask_type="box",
398
457
  shape=template.shape,
@@ -410,7 +469,7 @@ def tube_mask(
410
469
  inner_radius: float,
411
470
  outer_radius: float,
412
471
  height: int,
413
- ):
472
+ ) -> NDArray:
414
473
  return create_mask(
415
474
  mask_type="tube",
416
475
  shape=template.shape,
@@ -433,7 +492,7 @@ def wedge_mask(
433
492
  omit_negative_frequencies: bool = False,
434
493
  extrude_plane: bool = True,
435
494
  infinite_plane: bool = True,
436
- ):
495
+ ) -> NDArray:
437
496
  if tilt_step <= 0:
438
497
  wedge_mask = preprocessor.continuous_wedge_mask(
439
498
  start_tilt=tilt_start,
@@ -449,25 +508,24 @@ def wedge_mask(
449
508
  wedge_mask = np.fft.fftshift(wedge_mask)
450
509
  return wedge_mask
451
510
 
452
- tilt_angles = np.arange(-tilt_start, tilt_stop + tilt_step, tilt_step)
453
- angles = np.zeros((template.ndim, tilt_angles.size))
454
-
455
- angles[tilt_axis, :] = tilt_angles
456
-
457
- wedge_mask = preprocessor.wedge_mask(
458
- tilt_angles=angles,
511
+ wedge_mask = preprocessor.step_wedge_mask(
512
+ start_tilt=tilt_start,
513
+ stop_tilt=tilt_stop,
514
+ tilt_axis=tilt_axis,
515
+ tilt_step=tilt_step,
516
+ opening_axis=opening_axis,
459
517
  shape=template.shape,
460
518
  sigma=gaussian_sigma,
461
- opening_axes=opening_axis,
462
519
  omit_negative_frequencies=omit_negative_frequencies,
463
520
  )
521
+
464
522
  wedge_mask = np.fft.fftshift(wedge_mask)
465
523
  return wedge_mask
466
524
 
467
525
 
468
526
  def threshold_mask(
469
527
  template: NDArray, standard_deviation: float = 5.0, invert: bool = False
470
- ):
528
+ ) -> NDArray:
471
529
  template_mean = template.mean()
472
530
  template_deviation = standard_deviation * template.std()
473
531
  upper = template_mean + template_deviation
@@ -479,6 +537,15 @@ def threshold_mask(
479
537
  return mask
480
538
 
481
539
 
540
+ def lowpass_mask(template: NDArray, sigma: float = 1.0):
541
+ template = template / template.max()
542
+ template = (template > np.exp(-2)) * 128.0
543
+ template = preprocessor.gaussian_filter(template=template, sigma=sigma)
544
+ mask = template > np.exp(-2)
545
+
546
+ return mask
547
+
548
+
482
549
  class MaskWidget(widgets.Container):
483
550
  def __init__(self, viewer):
484
551
  super().__init__(layout="vertical")
@@ -496,6 +563,7 @@ class MaskWidget(widgets.Container):
496
563
  "Box": box_mask,
497
564
  "Wedge": wedge_mask,
498
565
  "Threshold": threshold_mask,
566
+ "Lowpass": lowpass_mask,
499
567
  }
500
568
 
501
569
  self.method_dropdown = widgets.ComboBox(
@@ -509,7 +577,6 @@ class MaskWidget(widgets.Container):
509
577
 
510
578
  self.adapt_button = widgets.PushButton(text="Adapt to layer", enabled=False)
511
579
  self.adapt_button.changed.connect(self._update_initial_values)
512
-
513
580
  self.viewer.layers.selection.events.active.connect(
514
581
  self._update_action_button_state
515
582
  )
@@ -520,8 +587,9 @@ class MaskWidget(widgets.Container):
520
587
  # self.density_field.value = f"Positive Density in Mask: {0:.2f}%"
521
588
 
522
589
  self.append(self.method_dropdown)
523
- self.append(self.percentile_range_edit)
524
590
  self.append(self.adapt_button)
591
+ self.append(self.percentile_range_edit)
592
+
525
593
  self.append(self.align_button)
526
594
  self.append(self.action_button)
527
595
  self.append(self.density_field)
@@ -559,6 +627,7 @@ class MaskWidget(widgets.Container):
559
627
  arr=active_layer.data,
560
628
  rotation_matrix=rotation_matrix,
561
629
  use_geometric_center=False,
630
+ order=1,
562
631
  )
563
632
  eps = np.finfo(rotated_data.dtype).eps
564
633
  rotated_data[rotated_data < eps] = 0
@@ -589,10 +658,10 @@ class MaskWidget(widgets.Container):
589
658
  dict(zip(["height_x", "height_y", "height_z"], coordinates_heights))
590
659
  )
591
660
 
592
- defaults["radius"] = np.min(coordinate_radius)
661
+ defaults["radius"] = np.max(coordinate_radius)
593
662
  defaults["inner_radius"] = np.min(coordinate_radius)
594
663
  defaults["outer_radius"] = np.max(coordinate_radius)
595
- defaults["height"] = defaults["radius"]
664
+ defaults["height"] = np.max(coordinates_heights)
596
665
 
597
666
  for widget in self.action_widgets:
598
667
  if widget.name in defaults:
@@ -804,6 +873,7 @@ def parse_args():
804
873
  args = parser.parse_args()
805
874
  return args
806
875
 
876
+
807
877
  if __name__ == "__main__":
808
878
  parse_args()
809
879
  main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pytme
3
- Version: 0.1.6
3
+ Version: 0.1.8
4
4
  Summary: Python Template Matching Engine
5
5
  Author: Valentin Maurer
6
6
  Author-email: Valentin Maurer <valentin.maurer@embl-hamburg.de>
@@ -31,7 +31,7 @@ A software for template matching on electron microscopy data.
31
31
 
32
32
  ### Installation
33
33
 
34
- There are three ways to get PyTME up and running:
34
+ There are three ways to get pyTME up and running:
35
35
 
36
36
  1. **Install from Source:**
37
37
  ```bash
@@ -44,7 +44,7 @@ pip install pytme
44
44
  ```
45
45
 
46
46
  3. **Docker Container:**
47
- Build and use the PyTME container from Docker. This assumes a linux/amd64 platform.
47
+ Build and use the pyTME container from Docker. This assumes a linux/amd64 platform.
48
48
  ```bash
49
49
  docker build \
50
50
  -t pytme \
@@ -58,12 +58,14 @@ docker build \
58
58
 
59
59
  ### Publication
60
60
 
61
- The pyTME publication is available on [bioRxiv](https://www.biorxiv.org/content/10.1101/2023.10.23.563472v1).
61
+ The pyTME publication is available on [SoftwareX](https://www.sciencedirect.com/science/article/pii/S2352711024000074).
62
62
 
63
63
  ```
64
- @article{Maurer2023.10.23.563472,
65
- author = {Valentin J. Maurer and Marc Siggel and Jan Kosinski},
66
- journal = {bioRxiv},
64
+ @article{Maurer:2024aa,
65
+ author = {Maurer, Valentin J. and Siggel, Marc and Kosinski, Jan},
66
+ journal = {SoftwareX},
67
+ pages = {101636},
67
68
  title = {PyTME (Python Template Matching Engine): A fast, flexible, and multi-purpose template matching library for cryogenic electron microscopy data},
68
- year = {2023}}
69
+ volume = {25},
70
+ year = {2024}}
69
71
  ```
@@ -1,34 +1,35 @@
1
- pytme-0.1.6.data/scripts/estimate_ram_usage.py,sha256=gaLkgAfbm_zccp3NVXgcb8PGQu0TyiumlCvrkgMYN_M,2766
2
- pytme-0.1.6.data/scripts/match_template.py,sha256=p12HrNKdb5upCp__Ey--f788ajRUb1mF9oec5vn6uFk,25573
3
- pytme-0.1.6.data/scripts/postprocess.py,sha256=H0FLceZNM5tAnCJQq1oWtUXOM6O0Nl9kUtTBkTYPPm0,19997
4
- pytme-0.1.6.data/scripts/preprocess.py,sha256=zog-l2Je-GeouJ6SnamOMuHgTn7fFPiGnO5X03y5qSY,2527
5
- pytme-0.1.6.data/scripts/preprocessor_gui.py,sha256=raLO2H-g5nA9UUJJToHdxO93g-sMlWvu9clxubNvB_s,26931
1
+ pytme-0.1.8.data/scripts/estimate_ram_usage.py,sha256=R1NDpFajcF-MonJ4a43SfDlA-nxBYwK7D2quzCdsVFM,2767
2
+ pytme-0.1.8.data/scripts/match_template.py,sha256=moMpH8mLk42ZkW0vXzd_TMCWsTUKXohxuWrqHLh8lks,25743
3
+ pytme-0.1.8.data/scripts/postprocess.py,sha256=MKyIgsXWRlO6cU8qGqe_tSSKIF2pNTRSuaDoyXZ22G8,21938
4
+ pytme-0.1.8.data/scripts/preprocess.py,sha256=zog-l2Je-GeouJ6SnamOMuHgTn7fFPiGnO5X03y5qSY,2527
5
+ pytme-0.1.8.data/scripts/preprocessor_gui.py,sha256=AKT_ovrdbPiOJ_ampRK3s0jslUKwdVQRF6XUuJ-6GDo,29000
6
6
  scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- scripts/estimate_ram_usage.py,sha256=mLJEym3Hf9BJUY-Fm9Y3Xs0wWsq1y-o0sxE-0PR9IGA,2767
8
- scripts/match_template.py,sha256=v5D7DIM-ukjn5oPaRISGROTWj9WEUGMMGSoTHs2gY3o,25574
9
- scripts/postprocess.py,sha256=p9YR-Yyq9831UrqnGyP8kEMGw49345Ei3RWgbMVY7kM,19998
7
+ scripts/estimate_ram_usage.py,sha256=rN7haobnHg3YcgGJIp81FNiCzy8-saJGeEurQlmQmNQ,2768
8
+ scripts/match_template.py,sha256=dEvw9KDqgR7vZcIVn5Bld6FcRt_rp7nblybVuJhLYbs,25744
9
+ scripts/postprocess.py,sha256=NDTo9qbnAzhxo_tbnR8oWlDrsflUGu-Sj4ULqOPix1U,21939
10
10
  scripts/preprocess.py,sha256=ebJVLxbRlB6TI5YHNr0VavZ4lmaRdf8QVafyiDhh_oU,2528
11
- scripts/preprocessor_gui.py,sha256=-kh_Q1-3NtdswpggJ-sx7v__CvYRgxoxS4ecYdZ_SbE,26932
11
+ scripts/preprocessor_gui.py,sha256=E0F6quZnu32yZsBle38KDel5naHpC3Aci0uMCyo8DzY,29001
12
12
  tme/__init__.py,sha256=NiPnYfrwb8e04ETubqwd3yzCGBliLBXRvCylD-T59jY,212
13
- tme/__version__.py,sha256=n3oM6B_EMz93NsTI18NNZd-jKFcUPzUkbIKj5VFK5ok,22
14
- tme/analyzer.py,sha256=5uxC_U4AnuA6gwjI_X0vZw7XHJ0nxX9znuV6-9FuotY,39019
15
- tme/density.py,sha256=YmYum058euDNbIoZTPd9YpdinZXkU6RfFs2oHaV-r4A,83640
13
+ tme/__version__.py,sha256=C69ADlbQREQlR15trneyA2sk8x0-oH4rDAX5fsv19_U,22
14
+ tme/analyzer.py,sha256=Yh1o4kpjlRSq6ki5KiRsipF3tBwtSrL3KYfEm87NNOc,39188
15
+ tme/density.py,sha256=AwHhi5sHvOzXeXCnYHB_Mpw1kCG0x0cBg8NmwDalwKA,84326
16
16
  tme/extensions.cpython-311-darwin.so,sha256=vSNHvFMev0jvKCEwE4lzqgg9520Ucxf27gy3qqixYns,395056
17
17
  tme/helpers.py,sha256=TMtBuJoZk6q4M_rfkr8yPpGzJD74ycqyN3yXMuU9mr4,23625
18
- tme/matching_data.py,sha256=1SA8kENb-TQALFC5UdDtO8wDEk-V7Bu7T4qcLsiEsz8,13068
19
- tme/matching_exhaustive.py,sha256=zLQ_qZNMlgB6xoH2uqyLmB9p4vuqaW3_gicTfxmTsvM,53009
18
+ tme/matching_data.py,sha256=M6Iq4dnIlLzTvnHLrjC9uoeyNEDAsCdCwI9Pga-k9pE,22140
19
+ tme/matching_exhaustive.py,sha256=b3I2zzclEnCXYgjQ0l8C2O2UbH9pF1WKFRyDRLsrvTs,53862
20
20
  tme/matching_memory.py,sha256=GB71b7m-h0fF1A5HCUlAYQh62-Aq2lHgIoRGPYEzZrU,11245
21
21
  tme/matching_optimization.py,sha256=oo9HJV65Ji1oL2JumxgmtrHSMUQsKrpDhdOO5o-fAdM,37388
22
- tme/matching_utils.py,sha256=eVJ4wvopivy6PkeMw4yqhZW42pAcE1BC-EYg2XxPs1w,36204
23
- tme/parser.py,sha256=3ItaYd8F9dm7aX0cf8qKCk8nNmXwMbtOSp05eEnKPmY,13883
24
- tme/preprocessor.py,sha256=ygVDRLGEpELOu4NX85gtEWD5cNJuOAmPn-iqS2qfdW8,46464
22
+ tme/matching_utils.py,sha256=-cs3Nq8d9snaZ0mlgkSqdEc0c9A1TkX1sz93YY7TE_k,37227
23
+ tme/parser.py,sha256=tA9ABeV95cZn8lJCukVUaocQ9RguR6ZZzQsMXf_-ud0,13887
24
+ tme/preprocessor.py,sha256=UkWKBR9Z7FU-xUZ0ER_4c6lgLW9-MGmm-YN5Cs2mWD0,50631
25
25
  tme/structure.py,sha256=AKGZML8bnsqZOpAOQADU1XDXZ-ITPhr3Dc0udQUMP6E,54134
26
- tme/types.py,sha256=zEXAvmPegwFc5AAxoYmAZ6ZmSKk0ST6U3jVvPrQijac,258
27
- tme/backends/__init__.py,sha256=_5bg5jutlfejVdoDjReaYGviaCCtNPtvv0q0EuZICec,4330
28
- tme/backends/cupy_backend.py,sha256=eRReSzpbU1LDsEkQqRTroaHpVVoKznzvRlitzqFlx4M,10503
29
- tme/backends/matching_backend.py,sha256=l_Jh_Sq0wEi8zqNAYJYduOiv40TYwlpHW9g4s0IQwCw,29229
30
- tme/backends/npfftw_backend.py,sha256=XexwAwRUZXQiwZOPeq6lOLkJlSInEL6CGyKrR-dRMbU,26232
31
- tme/backends/pytorch_backend.py,sha256=at2f9lIf1MMJq-F-lOrEmilWQGpl2zRfqY3mJ-5yl_A,17984
26
+ tme/types.py,sha256=2Tyh_xnMLxIWYb3aJDAUb6GWpaL6gcYMUm2YNbJlAPI,295
27
+ tme/backends/__init__.py,sha256=xB2GBUFRskppvEs6S74VH0Pi-nXnIvu9_QFhESlcl3Y,4366
28
+ tme/backends/cupy_backend.py,sha256=CRwGqtycawTIfSfEDWpCQh4mcG03wad9mEODqzy75yQ,10648
29
+ tme/backends/matching_backend.py,sha256=E3cMXnMEazYJUr9RP5Q5rMEAf3vbkiOwzWrx5amt_nI,29311
30
+ tme/backends/mlx_backend.py,sha256=MrwICZpUiAcpZXON70r4SH-KsWxfhq1PdHUe80WbT-k,8467
31
+ tme/backends/npfftw_backend.py,sha256=VsoKwMmusUxW81b2YSa6KO0_pfUw-51fdv9O6BkN0cQ,26200
32
+ tme/backends/pytorch_backend.py,sha256=lKv_7q0gDrCfbwHR38tfj5ixpD1lfCpqpfqS1KnOqdU,17978
32
33
  tme/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
34
  tme/data/c48n309.npy,sha256=NwH64mOEbm3tStq5c98o81fY1vMOoq4nvXDAh7Z7iZg,296768
34
35
  tme/data/c48n527.npy,sha256=saSUMTa1R0MisPvgFL02a7IHQSwEZ-mJu0v3qJjg5AU,506048
@@ -52,9 +53,9 @@ tme/data/c600v.npy,sha256=JqSu3ALoL1A9iguehc0YGUMFPsh2fprHHp76VXeFXIw,2528
52
53
  tme/data/c600vc.npy,sha256=Yht-GFXDSjjGvsjFBvyxxEZAI-ODADPd5gEgFNZQVTA,14528
53
54
  tme/data/metadata.yaml,sha256=fAgX-mEzB0QMHTEtYDG4cSMbJhYxBbDJH3sdvJvL7a8,750
54
55
  tme/data/quat_to_numpy.py,sha256=-gkDZb10fKBxwfYrSLCUWvMB76TzZWELCeKsYProwws,1333
55
- pytme-0.1.6.dist-info/LICENSE,sha256=K1IUNSVAz8BXbpH5EA8y5FpaHdvFXnAF2zeK95Lr2bY,18467
56
- pytme-0.1.6.dist-info/METADATA,sha256=1jQPWMupChz28i5QxYpWlLQXhqUp3p3VYON0IkK0EHY,2081
57
- pytme-0.1.6.dist-info/WHEEL,sha256=-A_a4qtPtE7THspi2apYwdQWhv5IW90gRqlNhh7cwR4,110
58
- pytme-0.1.6.dist-info/entry_points.txt,sha256=ff3LQL3FCWfCYOwFiP9zatm7laUbnwCkuPELkQVyUO4,241
59
- pytme-0.1.6.dist-info/top_level.txt,sha256=J8FUkazOb2fZ0n_KexnqCGyNOtie2bwisFSUBiM5-0w,12
60
- pytme-0.1.6.dist-info/RECORD,,
56
+ pytme-0.1.8.dist-info/LICENSE,sha256=K1IUNSVAz8BXbpH5EA8y5FpaHdvFXnAF2zeK95Lr2bY,18467
57
+ pytme-0.1.8.dist-info/METADATA,sha256=zG0llsYOJsC3hU1UCPwepti-FJg1O8VPn1ovO-j4MNE,2121
58
+ pytme-0.1.8.dist-info/WHEEL,sha256=-A_a4qtPtE7THspi2apYwdQWhv5IW90gRqlNhh7cwR4,110
59
+ pytme-0.1.8.dist-info/entry_points.txt,sha256=ff3LQL3FCWfCYOwFiP9zatm7laUbnwCkuPELkQVyUO4,241
60
+ pytme-0.1.8.dist-info/top_level.txt,sha256=J8FUkazOb2fZ0n_KexnqCGyNOtie2bwisFSUBiM5-0w,12
61
+ pytme-0.1.8.dist-info/RECORD,,
@@ -88,7 +88,7 @@ def main():
88
88
  shape2=template_box,
89
89
  matching_method=args.score,
90
90
  ncores=args.ncores,
91
- analyzer_method="MaxScoreOverRotations"
91
+ analyzer_method="MaxScoreOverRotations",
92
92
  )
93
93
  print(result)
94
94
 
scripts/match_template.py CHANGED
@@ -252,7 +252,7 @@ def parse_args():
252
252
  type=check_positive,
253
253
  default=40.0,
254
254
  help="Angular sampling rate for template matching. "
255
- "A lower number yields more rotations.",
255
+ "A lower number yields more rotations. Values >= 180 sample only the identity.",
256
256
  )
257
257
  parser.add_argument(
258
258
  "-p",
@@ -380,8 +380,8 @@ def parse_args():
380
380
  type=float,
381
381
  required=False,
382
382
  default=None,
383
- help="Step size between tilts, e.g. '5'. When set a more accurate"
384
- " wedge mask will be computed.",
383
+ help="Step size between tilts, e.g. '5'. When set the wedge mask"
384
+ " reflects the individual tilts, otherwise a continuous mask is used.",
385
385
  )
386
386
  parser.add_argument(
387
387
  "--wedge_axes",
@@ -488,14 +488,16 @@ def main():
488
488
  if target_mask:
489
489
  args.target_mask = generate_tempfile_name(suffix=".mrc")
490
490
  target_mask.to_file(args.target_mask)
491
- print_block(
492
- name="Target Mask",
493
- data={
494
- "Initial Shape": initial_shape,
495
- "Sampling Rate": tuple(np.round(target_mask.sampling_rate, 2)),
496
- "Final Shape": target_mask.shape,
497
- },
498
- )
491
+
492
+ if target_mask:
493
+ print_block(
494
+ name="Target Mask",
495
+ data={
496
+ "Initial Shape": initial_shape,
497
+ "Sampling Rate": tuple(np.round(target_mask.sampling_rate, 2)),
498
+ "Final Shape": target_mask.shape,
499
+ },
500
+ )
499
501
 
500
502
  initial_shape = template.shape
501
503
  _ = crop_data(data=template, data_mask=template_mask, cutoff=args.cutoff_template)
@@ -537,15 +539,14 @@ def main():
537
539
  opening_axis, tilt_axis = [int(x) for x in args.wedge_axes.split(",")]
538
540
 
539
541
  if args.tilt_step is not None:
540
- tilt_angles = np.arange(
541
- -tilt_start, tilt_stop + args.tilt_step, args.tilt_step
542
- )
543
- angles = np.zeros((template.data.ndim, tilt_angles.size))
544
- angles[tilt_axis, :] = tilt_angles
545
- template_filter["wedge_mask"] = {
546
- "tilt_angles": angles,
542
+ template_filter["step_wedge_mask"] = {
543
+ "start_tilt": tilt_start,
544
+ "stop_tilt": tilt_stop,
545
+ "tilt_step": args.tilt_step,
547
546
  "sigma": args.wedge_smooth,
548
- "opening_axes": opening_axis,
547
+ "opening_axis": opening_axis,
548
+ "tilt_axis": tilt_axis,
549
+ "omit_negative_frequencies": True,
549
550
  }
550
551
  else:
551
552
  template_filter["continuous_wedge_mask"] = {
@@ -555,6 +556,7 @@ def main():
555
556
  "opening_axis": opening_axis,
556
557
  "infinite_plane": True,
557
558
  "sigma": args.wedge_smooth,
559
+ "omit_negative_frequencies": True,
558
560
  }
559
561
 
560
562
  if template_mask is None:
@@ -577,8 +579,9 @@ def main():
577
579
  template_mask = template_mask.rigid_transform(
578
580
  rotation_matrix=np.eye(template_mask.data.ndim),
579
581
  translation=-translation,
582
+ order=1,
580
583
  )
581
-
584
+ template_mask.origin = template.origin.copy()
582
585
  print_block(
583
586
  name="Template Mask",
584
587
  data={
@@ -590,7 +593,9 @@ def main():
590
593
  print("\n" + "-" * 80)
591
594
 
592
595
  if args.scramble_phases:
593
- template.data = scramble_phases(template.data, noise_proportion=1.0)
596
+ template.data = scramble_phases(
597
+ template.data, noise_proportion=1.0, normalize_power=True
598
+ )
594
599
 
595
600
  available_memory = backend.get_available_memory()
596
601
  if args.use_gpu:
@@ -668,7 +673,7 @@ def main():
668
673
  exit(-1)
669
674
 
670
675
  analyzer_args = {
671
- "score_threshold": 0.0,
676
+ "score_threshold": 0,
672
677
  "number_of_peaks": 1000,
673
678
  "convolution_mode": "valid",
674
679
  "use_memmap": args.use_memmap,