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.
- {pytme-0.3b0.data → pytme-0.3b0.post1.data}/scripts/estimate_memory_usage.py +1 -5
- {pytme-0.3b0.data → pytme-0.3b0.post1.data}/scripts/match_template.py +163 -201
- {pytme-0.3b0.data → pytme-0.3b0.post1.data}/scripts/postprocess.py +48 -39
- {pytme-0.3b0.data → pytme-0.3b0.post1.data}/scripts/preprocess.py +10 -23
- {pytme-0.3b0.data → pytme-0.3b0.post1.data}/scripts/preprocessor_gui.py +3 -4
- pytme-0.3b0.post1.data/scripts/pytme_runner.py +769 -0
- {pytme-0.3b0.dist-info → pytme-0.3b0.post1.dist-info}/METADATA +14 -14
- {pytme-0.3b0.dist-info → pytme-0.3b0.post1.dist-info}/RECORD +54 -50
- {pytme-0.3b0.dist-info → pytme-0.3b0.post1.dist-info}/entry_points.txt +1 -0
- pytme-0.3b0.post1.dist-info/licenses/LICENSE +339 -0
- scripts/estimate_memory_usage.py +1 -5
- scripts/eval.py +93 -0
- scripts/match_template.py +163 -201
- scripts/match_template_filters.py +1200 -0
- scripts/postprocess.py +48 -39
- scripts/preprocess.py +10 -23
- scripts/preprocessor_gui.py +3 -4
- scripts/pytme_runner.py +769 -0
- scripts/refine_matches.py +0 -1
- tests/preprocessing/test_frequency_filters.py +19 -10
- tests/test_analyzer.py +122 -122
- tests/test_backends.py +1 -0
- tests/test_matching_cli.py +30 -30
- tests/test_matching_data.py +5 -5
- tests/test_matching_utils.py +1 -1
- tme/__version__.py +1 -1
- tme/analyzer/__init__.py +1 -1
- tme/analyzer/_utils.py +1 -4
- tme/analyzer/aggregation.py +15 -6
- tme/analyzer/base.py +25 -36
- tme/analyzer/peaks.py +39 -113
- tme/analyzer/proxy.py +1 -0
- tme/backends/_jax_utils.py +16 -15
- tme/backends/cupy_backend.py +9 -13
- tme/backends/jax_backend.py +19 -16
- tme/backends/npfftw_backend.py +27 -25
- tme/backends/pytorch_backend.py +4 -0
- tme/density.py +5 -4
- tme/filters/__init__.py +2 -2
- tme/filters/_utils.py +32 -7
- tme/filters/bandpass.py +225 -186
- tme/filters/ctf.py +117 -67
- tme/filters/reconstruction.py +38 -9
- tme/filters/wedge.py +88 -105
- tme/filters/whitening.py +1 -6
- tme/matching_data.py +24 -36
- tme/matching_exhaustive.py +14 -11
- tme/matching_scores.py +21 -12
- tme/matching_utils.py +13 -6
- tme/orientations.py +13 -3
- tme/parser.py +109 -29
- tme/preprocessor.py +2 -2
- pytme-0.3b0.dist-info/licenses/LICENSE +0 -153
- {pytme-0.3b0.dist-info → pytme-0.3b0.post1.dist-info}/WHEEL +0 -0
- {pytme-0.3b0.dist-info → pytme-0.3b0.post1.dist-info}/top_level.txt +0 -0
scripts/postprocess.py
CHANGED
@@ -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
|
-
"--
|
54
|
-
"--
|
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
|
-
"--
|
61
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
85
|
-
required=
|
86
|
-
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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=
|
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.
|
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.
|
512
|
-
"maximum_score": args.
|
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=
|
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.
|
557
|
-
keep = orientations.scores >= args.
|
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.
|
561
|
-
keep = orientations.scores <= args.
|
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=
|
720
|
+
centering=cli_args.centering,
|
712
721
|
)
|
713
722
|
|
714
723
|
for index, (translation, angles, *_) in enumerate(orientations):
|
scripts/preprocess.py
CHANGED
@@ -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
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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
|
-
"--
|
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 =
|
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)
|
scripts/preprocessor_gui.py
CHANGED
@@ -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
|
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 =
|
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=
|
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
|
|