pytme 0.3b0__cp311-cp311-macosx_15_0_arm64.whl → 0.3b0.post1__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 (55) hide show
  1. {pytme-0.3b0.data → pytme-0.3b0.post1.data}/scripts/estimate_memory_usage.py +1 -5
  2. {pytme-0.3b0.data → pytme-0.3b0.post1.data}/scripts/match_template.py +163 -201
  3. {pytme-0.3b0.data → pytme-0.3b0.post1.data}/scripts/postprocess.py +48 -39
  4. {pytme-0.3b0.data → pytme-0.3b0.post1.data}/scripts/preprocess.py +10 -23
  5. {pytme-0.3b0.data → pytme-0.3b0.post1.data}/scripts/preprocessor_gui.py +3 -4
  6. pytme-0.3b0.post1.data/scripts/pytme_runner.py +769 -0
  7. {pytme-0.3b0.dist-info → pytme-0.3b0.post1.dist-info}/METADATA +14 -14
  8. {pytme-0.3b0.dist-info → pytme-0.3b0.post1.dist-info}/RECORD +54 -50
  9. {pytme-0.3b0.dist-info → pytme-0.3b0.post1.dist-info}/entry_points.txt +1 -0
  10. pytme-0.3b0.post1.dist-info/licenses/LICENSE +339 -0
  11. scripts/estimate_memory_usage.py +1 -5
  12. scripts/eval.py +93 -0
  13. scripts/match_template.py +163 -201
  14. scripts/match_template_filters.py +1200 -0
  15. scripts/postprocess.py +48 -39
  16. scripts/preprocess.py +10 -23
  17. scripts/preprocessor_gui.py +3 -4
  18. scripts/pytme_runner.py +769 -0
  19. scripts/refine_matches.py +0 -1
  20. tests/preprocessing/test_frequency_filters.py +19 -10
  21. tests/test_analyzer.py +122 -122
  22. tests/test_backends.py +1 -0
  23. tests/test_matching_cli.py +30 -30
  24. tests/test_matching_data.py +5 -5
  25. tests/test_matching_utils.py +1 -1
  26. tme/__version__.py +1 -1
  27. tme/analyzer/__init__.py +1 -1
  28. tme/analyzer/_utils.py +1 -4
  29. tme/analyzer/aggregation.py +15 -6
  30. tme/analyzer/base.py +25 -36
  31. tme/analyzer/peaks.py +39 -113
  32. tme/analyzer/proxy.py +1 -0
  33. tme/backends/_jax_utils.py +16 -15
  34. tme/backends/cupy_backend.py +9 -13
  35. tme/backends/jax_backend.py +19 -16
  36. tme/backends/npfftw_backend.py +27 -25
  37. tme/backends/pytorch_backend.py +4 -0
  38. tme/density.py +5 -4
  39. tme/filters/__init__.py +2 -2
  40. tme/filters/_utils.py +32 -7
  41. tme/filters/bandpass.py +225 -186
  42. tme/filters/ctf.py +117 -67
  43. tme/filters/reconstruction.py +38 -9
  44. tme/filters/wedge.py +88 -105
  45. tme/filters/whitening.py +1 -6
  46. tme/matching_data.py +24 -36
  47. tme/matching_exhaustive.py +14 -11
  48. tme/matching_scores.py +21 -12
  49. tme/matching_utils.py +13 -6
  50. tme/orientations.py +13 -3
  51. tme/parser.py +109 -29
  52. tme/preprocessor.py +2 -2
  53. pytme-0.3b0.dist-info/licenses/LICENSE +0 -153
  54. {pytme-0.3b0.dist-info → pytme-0.3b0.post1.dist-info}/WHEEL +0 -0
  55. {pytme-0.3b0.dist-info → pytme-0.3b0.post1.dist-info}/top_level.txt +0 -0
@@ -9,7 +9,7 @@ import argparse
9
9
  from sys import exit
10
10
  from os import getcwd
11
11
  from typing import Tuple, List
12
- from os.path import join, splitext
12
+ from os.path import join, splitext, basename
13
13
 
14
14
  import numpy as np
15
15
  from numpy.typing import NDArray
@@ -50,15 +50,15 @@ def parse_args():
50
50
  additional_group = parser.add_argument_group("Additional Parameters")
51
51
 
52
52
  input_group.add_argument(
53
- "--input_file",
54
- "--input_files",
53
+ "--input-file",
54
+ "--input-files",
55
55
  required=True,
56
56
  nargs="+",
57
57
  help="Path to one or multiple runs of match_template.py.",
58
58
  )
59
59
  input_group.add_argument(
60
- "--background_file",
61
- "--background_files",
60
+ "--background-file",
61
+ "--background-files",
62
62
  required=False,
63
63
  nargs="+",
64
64
  default=[],
@@ -66,7 +66,7 @@ def parse_args():
66
66
  "For instance from --scramble_phases or a different template.",
67
67
  )
68
68
  input_group.add_argument(
69
- "--target_mask",
69
+ "--target-mask",
70
70
  required=False,
71
71
  type=str,
72
72
  help="Path to an optional mask applied to template matching scores.",
@@ -81,12 +81,14 @@ def parse_args():
81
81
  )
82
82
 
83
83
  output_group.add_argument(
84
- "--output_prefix",
85
- required=True,
86
- help="Output filename, extension will be added based on output_format.",
84
+ "--output-prefix",
85
+ required=False,
86
+ default=None,
87
+ help="Output prefix. Defaults to basename of first input. Extension is "
88
+ "added with respect to chosen output format.",
87
89
  )
88
90
  output_group.add_argument(
89
- "--output_format",
91
+ "--output-format",
90
92
  choices=[
91
93
  "orientations",
92
94
  "relion4",
@@ -108,44 +110,44 @@ def parse_args():
108
110
  )
109
111
 
110
112
  peak_group.add_argument(
111
- "--peak_caller",
113
+ "--peak-caller",
112
114
  choices=list(PEAK_CALLERS.keys()),
113
115
  default="PeakCallerScipy",
114
116
  help="Peak caller for local maxima identification.",
115
117
  )
116
118
  peak_group.add_argument(
117
- "--minimum_score",
119
+ "--min-score",
118
120
  type=float,
119
121
  default=0.0,
120
122
  help="Minimum score from which peaks will be considered.",
121
123
  )
122
124
  peak_group.add_argument(
123
- "--maximum_score",
125
+ "--max-score",
124
126
  type=float,
125
127
  default=None,
126
128
  help="Maximum score until which peaks will be considered.",
127
129
  )
128
130
  peak_group.add_argument(
129
- "--min_distance",
131
+ "--min-distance",
130
132
  type=int,
131
133
  default=5,
132
134
  help="Minimum distance between peaks.",
133
135
  )
134
136
  peak_group.add_argument(
135
- "--min_boundary_distance",
137
+ "--min-boundary-distance",
136
138
  type=int,
137
139
  default=0,
138
140
  help="Minimum distance of peaks to target edges.",
139
141
  )
140
142
  peak_group.add_argument(
141
- "--mask_edges",
143
+ "--mask-edges",
142
144
  action="store_true",
143
145
  default=False,
144
146
  help="Whether candidates should not be identified from scores that were "
145
147
  "computed from padded densities. Superseded by min_boundary_distance.",
146
148
  )
147
149
  peak_group.add_argument(
148
- "--num_peaks",
150
+ "--num-peaks",
149
151
  type=int,
150
152
  default=1000,
151
153
  required=False,
@@ -153,7 +155,7 @@ def parse_args():
153
155
  "If minimum_score is provided all peaks scoring higher will be reported.",
154
156
  )
155
157
  peak_group.add_argument(
156
- "--peak_oversampling",
158
+ "--peak-oversampling",
157
159
  type=int,
158
160
  default=1,
159
161
  help="1 / factor equals voxel precision, e.g. 2 detects half voxel "
@@ -161,33 +163,33 @@ def parse_args():
161
163
  )
162
164
 
163
165
  additional_group.add_argument(
164
- "--extraction_box_size",
166
+ "--extraction-box-size",
165
167
  type=int,
166
168
  default=None,
167
169
  help="Box size of extracted subtomograms, defaults to the centered template.",
168
170
  )
169
171
  additional_group.add_argument(
170
- "--mask_subtomograms",
172
+ "--mask-subtomograms",
171
173
  action="store_true",
172
174
  default=False,
173
175
  help="Whether to mask subtomograms using the template mask. The mask will be "
174
176
  "rotated according to determined angles.",
175
177
  )
176
178
  additional_group.add_argument(
177
- "--invert_target_contrast",
179
+ "--invert-target-contrast",
178
180
  action="store_true",
179
181
  default=False,
180
182
  help="Whether to invert the target contrast.",
181
183
  )
182
184
  additional_group.add_argument(
183
- "--n_false_positives",
185
+ "--n-false-positives",
184
186
  type=int,
185
187
  default=None,
186
188
  required=False,
187
189
  help="Number of accepted false-positives picks to determine minimum score.",
188
190
  )
189
191
  additional_group.add_argument(
190
- "--local_optimization",
192
+ "--local-optimization",
191
193
  action="store_true",
192
194
  required=False,
193
195
  help="[Experimental] Perform local optimization of candidates. Useful when the "
@@ -196,6 +198,9 @@ def parse_args():
196
198
 
197
199
  args = parser.parse_args()
198
200
 
201
+ if args.output_prefix is None:
202
+ args.output_prefix = splitext(basename(args.input_file[0]))[0]
203
+
199
204
  if args.orientations is not None:
200
205
  args.orientations = Orientations.from_file(filename=args.orientations)
201
206
 
@@ -371,7 +376,7 @@ def normalize_input(foregrounds: Tuple[str], backgrounds: Tuple[str]) -> Tuple:
371
376
  scores_out = np.full(out_shape, fill_value=0, dtype=np.float32)
372
377
  scores_out[update] = data[0][update] - scores_norm[update]
373
378
  scores_out[update] = np.divide(scores_out[update], 1 - scores_norm[update])
374
- np.fmax(scores_out, 0, out=scores_out)
379
+ scores_out = np.fmax(scores_out, 0, out=scores_out)
375
380
  data[0] = scores_out
376
381
 
377
382
  fg, bg = simple_stats(data[0]), simple_stats(scores_norm)
@@ -421,6 +426,10 @@ def main():
421
426
 
422
427
  data, entities = normalize_input(args.input_file, args.background_file)
423
428
 
429
+ if args.output_format == "pickle":
430
+ write_pickle(data, f"{args.output_prefix}.pickle")
431
+ exit(0)
432
+
424
433
  if args.target_mask:
425
434
  target_mask = Density.from_file(args.target_mask, use_memmap=True).data
426
435
  if target_mask.shape != data[0].shape:
@@ -433,11 +442,15 @@ def main():
433
442
 
434
443
  target_origin, _, sampling_rate, cli_args = data[-1]
435
444
 
445
+ # Backwards compatibility with pre v0.3.0b
446
+ if hasattr(cli_args, "no_centering"):
447
+ cli_args.centering = not cli_args.no_centering
448
+
436
449
  _, template_extension = splitext(cli_args.template)
437
450
  ret = load_template(
438
451
  filepath=cli_args.template,
439
452
  sampling_rate=sampling_rate,
440
- centering=not cli_args.no_centering,
453
+ centering=cli_args.centering,
441
454
  )
442
455
  template, center_of_mass, translation, template_is_density = ret
443
456
 
@@ -461,10 +474,6 @@ def main():
461
474
  max_shape = np.max(template.shape)
462
475
  args.min_boundary_distance = np.ceil(np.divide(max_shape, 2))
463
476
 
464
- if args.output_format == "pickle":
465
- write_pickle(data, f"{args.output_prefix}.pickle")
466
- exit(0)
467
-
468
477
  orientations = args.orientations
469
478
  if orientations is None:
470
479
  translations, rotations, scores, details = [], [], [], []
@@ -496,7 +505,7 @@ def main():
496
505
  )
497
506
  print(f"Determined minimum score cutoff: {minimum_score}.")
498
507
  minimum_score = max(minimum_score, 0)
499
- args.minimum_score = minimum_score
508
+ args.min_score = minimum_score
500
509
 
501
510
  args.batch_dims = None
502
511
  if hasattr(cli_args, "target_batch"):
@@ -508,8 +517,8 @@ def main():
508
517
  "min_distance": args.min_distance,
509
518
  "min_boundary_distance": args.min_boundary_distance,
510
519
  "batch_dims": args.batch_dims,
511
- "minimum_score": args.minimum_score,
512
- "maximum_score": args.maximum_score,
520
+ "minimum_score": args.min_score,
521
+ "maximum_score": args.max_score,
513
522
  }
514
523
 
515
524
  peak_caller = PEAK_CALLERS[args.peak_caller](**peak_caller_kwargs)
@@ -518,7 +527,7 @@ def main():
518
527
  state,
519
528
  scores,
520
529
  rotation_matrix=np.eye(template.data.ndim),
521
- mask=template.data,
530
+ mask=template_mask.data,
522
531
  rotation_mapping=rotation_mapping,
523
532
  rotations=rotation_array,
524
533
  )
@@ -553,12 +562,12 @@ def main():
553
562
  details=details,
554
563
  )
555
564
 
556
- if args.minimum_score is not None and len(orientations.scores):
557
- keep = orientations.scores >= args.minimum_score
565
+ if args.min_score is not None and len(orientations.scores):
566
+ keep = orientations.scores >= args.min_score
558
567
  orientations = orientations[keep]
559
568
 
560
- if args.maximum_score is not None and len(orientations.scores):
561
- keep = orientations.scores <= args.maximum_score
569
+ if args.max_score is not None and len(orientations.scores):
570
+ keep = orientations.scores <= args.max_score
562
571
  orientations = orientations[keep]
563
572
 
564
573
  if args.peak_oversampling > 1:
@@ -623,7 +632,7 @@ def main():
623
632
  orientations.to_file(
624
633
  filename=f"{args.output_prefix}.{extension}",
625
634
  file_format=file_format,
626
- source_path=cli_args.target,
635
+ source_path=basename(cli_args.target),
627
636
  version=version,
628
637
  )
629
638
  exit(0)
@@ -708,7 +717,7 @@ def main():
708
717
  template, center, *_ = load_template(
709
718
  filepath=cli_args.template,
710
719
  sampling_rate=sampling_rate,
711
- centering=not cli_args.no_centering,
720
+ centering=cli_args.centering,
712
721
  )
713
722
 
714
723
  for index, (translation, angles, *_) in enumerate(orientations):
@@ -11,7 +11,7 @@ import numpy as np
11
11
  from tme import Density, Structure
12
12
  from tme.cli import print_entry
13
13
  from tme.backends import backend as be
14
- from tme.filters import BandPassFilter
14
+ from tme.filters import BandPassReconstructed
15
15
 
16
16
 
17
17
  def parse_args():
@@ -24,7 +24,6 @@ def parse_args():
24
24
  io_group.add_argument(
25
25
  "-m",
26
26
  "--data",
27
- dest="data",
28
27
  type=str,
29
28
  required=True,
30
29
  help="Path to a file in PDB/MMCIF, CCP4/MRC, EM, H5 or a format supported by "
@@ -34,7 +33,6 @@ def parse_args():
34
33
  io_group.add_argument(
35
34
  "-o",
36
35
  "--output",
37
- dest="output",
38
36
  type=str,
39
37
  required=True,
40
38
  help="Path the output should be written to.",
@@ -42,22 +40,19 @@ def parse_args():
42
40
 
43
41
  box_group = parser.add_argument_group("Box")
44
42
  box_group.add_argument(
45
- "--box_size",
46
- dest="box_size",
43
+ "--box-size",
47
44
  type=int,
48
45
  required=False,
49
46
  help="Box size of the output. Defaults to twice the required box size.",
50
47
  )
51
48
  box_group.add_argument(
52
- "--sampling_rate",
53
- dest="sampling_rate",
49
+ "--sampling-rate",
54
50
  type=float,
55
51
  required=True,
56
52
  help="Sampling rate of the output file.",
57
53
  )
58
54
  box_group.add_argument(
59
- "--input_sampling_rate",
60
- dest="input_sampling_rate",
55
+ "--input-sampling-rate",
61
56
  type=float,
62
57
  required=False,
63
58
  help="Sampling rate of the input file. Defaults to header for volume "
@@ -66,15 +61,13 @@ def parse_args():
66
61
 
67
62
  modulation_group = parser.add_argument_group("Modulation")
68
63
  modulation_group.add_argument(
69
- "--invert_contrast",
70
- dest="invert_contrast",
64
+ "--invert-contrast",
71
65
  action="store_true",
72
66
  required=False,
73
67
  help="Inverts the template contrast.",
74
68
  )
75
69
  modulation_group.add_argument(
76
70
  "--lowpass",
77
- dest="lowpass",
78
71
  type=float,
79
72
  required=False,
80
73
  default=None,
@@ -82,14 +75,12 @@ def parse_args():
82
75
  "A value of 0 disables the filter.",
83
76
  )
84
77
  modulation_group.add_argument(
85
- "--no_centering",
86
- dest="no_centering",
78
+ "--no-centering",
87
79
  action="store_true",
88
80
  help="Assumes the template is already centered and omits centering.",
89
81
  )
90
82
  modulation_group.add_argument(
91
83
  "--backend",
92
- dest="backend",
93
84
  type=str,
94
85
  default=None,
95
86
  choices=be.available_backends(),
@@ -98,15 +89,13 @@ def parse_args():
98
89
 
99
90
  alignment_group = parser.add_argument_group("Modulation")
100
91
  alignment_group.add_argument(
101
- "--align_axis",
102
- dest="align_axis",
92
+ "--align-axis",
103
93
  type=int,
104
94
  required=False,
105
95
  help="Align template to given axis, e.g. 2 for z-axis.",
106
96
  )
107
97
  alignment_group.add_argument(
108
- "--align_eigenvector",
109
- dest="align_eigenvector",
98
+ "--align-eigenvector",
110
99
  type=int,
111
100
  required=False,
112
101
  default=0,
@@ -114,8 +103,7 @@ def parse_args():
114
103
  "with numerically largest eigenvalue.",
115
104
  )
116
105
  alignment_group.add_argument(
117
- "--flip_axis",
118
- dest="flip_axis",
106
+ "--flip-axis",
119
107
  action="store_true",
120
108
  required=False,
121
109
  help="Align the template to -axis instead of axis.",
@@ -185,12 +173,11 @@ def main():
185
173
  bpf_mask = 1
186
174
  lowpass = 2 * args.sampling_rate if args.lowpass is None else args.lowpass
187
175
  if args.lowpass != 0:
188
- bpf_mask = BandPassFilter(
176
+ bpf_mask = BandPassReconstructed(
189
177
  lowpass=lowpass,
190
178
  highpass=None,
191
179
  use_gaussian=True,
192
180
  return_real_fourier=True,
193
- shape_is_real_fourier=False,
194
181
  sampling_rate=data.sampling_rate,
195
182
  )(shape=data.shape)["data"]
196
183
  bpf_mask = be.to_backend_array(bpf_mask)
@@ -26,7 +26,7 @@ from tme.backends import backend
26
26
  from tme.rotations import align_vectors
27
27
  from tme import Preprocessor, Density, Orientations
28
28
  from tme.matching_utils import create_mask, load_pickle
29
- from tme.filters import BandPassFilter, CTFReconstructed
29
+ from tme.filters import BandPassReconstructed, CTFReconstructed
30
30
 
31
31
  preprocessor = Preprocessor()
32
32
  SLIDER_MIN, SLIDER_MAX = 0, 25
@@ -43,17 +43,16 @@ def bandpass_filter(
43
43
  hard_edges: bool = False,
44
44
  sampling_rate=None,
45
45
  ) -> NDArray:
46
- bpf = BandPassFilter(
46
+ bpf = BandPassReconstructed(
47
47
  lowpass=lowpass_angstrom,
48
48
  highpass=highpass_angstrom,
49
49
  sampling_rate=np.max(sampling_rate),
50
50
  use_gaussian=not hard_edges,
51
- shape_is_real_fourier=True,
52
51
  return_real_fourier=True,
53
52
  )
54
53
  template_ft = np.fft.rfftn(template, s=template.shape)
55
54
 
56
- mask = bpf(shape=template_ft.shape)["data"]
55
+ mask = bpf(shape=template.shape)["data"]
57
56
  np.multiply(template_ft, mask, out=template_ft)
58
57
  return np.fft.irfftn(template_ft, s=template.shape).real
59
58