pytme 0.1.7__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.
- {pytme-0.1.7.data → pytme-0.1.8.data}/scripts/match_template.py +12 -10
- {pytme-0.1.7.data → pytme-0.1.8.data}/scripts/postprocess.py +38 -12
- {pytme-0.1.7.data → pytme-0.1.8.data}/scripts/preprocessor_gui.py +74 -52
- {pytme-0.1.7.dist-info → pytme-0.1.8.dist-info}/METADATA +10 -8
- {pytme-0.1.7.dist-info → pytme-0.1.8.dist-info}/RECORD +21 -21
- scripts/match_template.py +12 -10
- scripts/postprocess.py +38 -12
- scripts/preprocessor_gui.py +74 -52
- tme/__version__.py +1 -1
- tme/backends/npfftw_backend.py +0 -7
- tme/density.py +17 -8
- tme/matching_data.py +55 -24
- tme/matching_exhaustive.py +67 -19
- tme/matching_utils.py +39 -13
- tme/preprocessor.py +113 -5
- {pytme-0.1.7.data → pytme-0.1.8.data}/scripts/estimate_ram_usage.py +0 -0
- {pytme-0.1.7.data → pytme-0.1.8.data}/scripts/preprocess.py +0 -0
- {pytme-0.1.7.dist-info → pytme-0.1.8.dist-info}/LICENSE +0 -0
- {pytme-0.1.7.dist-info → pytme-0.1.8.dist-info}/WHEEL +0 -0
- {pytme-0.1.7.dist-info → pytme-0.1.8.dist-info}/entry_points.txt +0 -0
- {pytme-0.1.7.dist-info → pytme-0.1.8.dist-info}/top_level.txt +0 -0
@@ -539,15 +539,14 @@ def main():
|
|
539
539
|
opening_axis, tilt_axis = [int(x) for x in args.wedge_axes.split(",")]
|
540
540
|
|
541
541
|
if args.tilt_step is not None:
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
angles[tilt_axis, :] = tilt_angles
|
547
|
-
template_filter["wedge_mask"] = {
|
548
|
-
"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,
|
549
546
|
"sigma": args.wedge_smooth,
|
550
|
-
"
|
547
|
+
"opening_axis": opening_axis,
|
548
|
+
"tilt_axis": tilt_axis,
|
549
|
+
"omit_negative_frequencies": True,
|
551
550
|
}
|
552
551
|
else:
|
553
552
|
template_filter["continuous_wedge_mask"] = {
|
@@ -557,6 +556,7 @@ def main():
|
|
557
556
|
"opening_axis": opening_axis,
|
558
557
|
"infinite_plane": True,
|
559
558
|
"sigma": args.wedge_smooth,
|
559
|
+
"omit_negative_frequencies": True,
|
560
560
|
}
|
561
561
|
|
562
562
|
if template_mask is None:
|
@@ -593,7 +593,9 @@ def main():
|
|
593
593
|
print("\n" + "-" * 80)
|
594
594
|
|
595
595
|
if args.scramble_phases:
|
596
|
-
template.data = scramble_phases(
|
596
|
+
template.data = scramble_phases(
|
597
|
+
template.data, noise_proportion=1.0, normalize_power=True
|
598
|
+
)
|
597
599
|
|
598
600
|
available_memory = backend.get_available_memory()
|
599
601
|
if args.use_gpu:
|
@@ -671,7 +673,7 @@ def main():
|
|
671
673
|
exit(-1)
|
672
674
|
|
673
675
|
analyzer_args = {
|
674
|
-
"score_threshold": 0
|
676
|
+
"score_threshold": 0,
|
675
677
|
"number_of_peaks": 1000,
|
676
678
|
"convolution_mode": "valid",
|
677
679
|
"use_memmap": args.use_memmap,
|
@@ -15,6 +15,7 @@ from dataclasses import dataclass
|
|
15
15
|
|
16
16
|
import numpy as np
|
17
17
|
from scipy.spatial.transform import Rotation
|
18
|
+
from numpy.typing import NDArray
|
18
19
|
|
19
20
|
from tme import Density, Structure
|
20
21
|
from tme.analyzer import (
|
@@ -28,6 +29,7 @@ from tme.matching_utils import (
|
|
28
29
|
load_pickle,
|
29
30
|
euler_to_rotationmatrix,
|
30
31
|
euler_from_rotationmatrix,
|
32
|
+
centered_mask,
|
31
33
|
)
|
32
34
|
|
33
35
|
PEAK_CALLERS = {
|
@@ -75,6 +77,13 @@ def parse_args():
|
|
75
77
|
help="Minimum distance from target boundaries. Ignored when --orientations "
|
76
78
|
"is provided.",
|
77
79
|
)
|
80
|
+
parser.add_argument(
|
81
|
+
"--mask_edges",
|
82
|
+
action="store_true",
|
83
|
+
default=False,
|
84
|
+
help="Whether to mask edges of the input score array according to the template shape."
|
85
|
+
"Uses twice the value of --min_boundary_distance if boht are provided.",
|
86
|
+
)
|
78
87
|
parser.add_argument(
|
79
88
|
"--wedge_mask",
|
80
89
|
type=str,
|
@@ -403,11 +412,25 @@ class Orientations:
|
|
403
412
|
return translation, rotation, score, detail
|
404
413
|
|
405
414
|
|
415
|
+
def load_template(filepath: str, sampling_rate: NDArray) -> "Density":
|
416
|
+
try:
|
417
|
+
template = Density.from_file(filepath)
|
418
|
+
template, _ = template.centered(0)
|
419
|
+
center_of_mass = template.center_of_mass(template.data)
|
420
|
+
except ValueError:
|
421
|
+
template = Structure.from_file(filepath)
|
422
|
+
center_of_mass = template.center_of_mass()[::-1]
|
423
|
+
template = Density.from_structure(template, sampling_rate=sampling_rate)
|
424
|
+
|
425
|
+
return template, center_of_mass
|
426
|
+
|
427
|
+
|
406
428
|
def main():
|
407
429
|
args = parse_args()
|
408
430
|
data = load_pickle(args.input_file)
|
409
431
|
|
410
432
|
meta = data[-1]
|
433
|
+
target_origin, _, sampling_rate, cli_args = meta
|
411
434
|
|
412
435
|
if args.orientations is not None:
|
413
436
|
orientations = Orientations.from_file(
|
@@ -419,6 +442,17 @@ def main():
|
|
419
442
|
# Output is MaxScoreOverRotations
|
420
443
|
if data[0].ndim == data[2].ndim:
|
421
444
|
scores, offset, rotation_array, rotation_mapping, meta = data
|
445
|
+
if args.mask_edges:
|
446
|
+
template, center_of_mass = load_template(
|
447
|
+
cli_args.template, sampling_rate=sampling_rate
|
448
|
+
)
|
449
|
+
if not cli_args.no_centering:
|
450
|
+
template, *_ = template.centered(0)
|
451
|
+
mask_size = template.shape
|
452
|
+
if args.min_boundary_distance > 0:
|
453
|
+
mask_size = 2 * args.min_boundary_distance
|
454
|
+
scores = centered_mask(scores, np.subtract(scores.shape, mask_size) + 1)
|
455
|
+
|
422
456
|
peak_caller = PEAK_CALLERS[args.peak_caller](
|
423
457
|
number_of_peaks=args.number_of_peaks,
|
424
458
|
min_distance=args.min_distance,
|
@@ -458,19 +492,11 @@ def main():
|
|
458
492
|
orientations.to_file(filename=f"{args.output_prefix}.tsv", file_format="text")
|
459
493
|
exit(0)
|
460
494
|
|
461
|
-
target_origin, _, sampling_rate, cli_args = meta
|
462
|
-
|
463
|
-
template_is_density, index = True, 0
|
464
495
|
_, template_extension = splitext(cli_args.template)
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
except ValueError:
|
470
|
-
template_is_density = False
|
471
|
-
template = Structure.from_file(cli_args.template)
|
472
|
-
center_of_mass = template.center_of_mass()[::-1]
|
473
|
-
template = Density.from_structure(template, sampling_rate=sampling_rate)
|
496
|
+
template, center_of_mass = load_template(
|
497
|
+
filepath=cli_args.template, sampling_rate=sampling_rate
|
498
|
+
)
|
499
|
+
template_is_density, index = isinstance(template, Density), 0
|
474
500
|
|
475
501
|
if args.output_format == "relion":
|
476
502
|
new_shape = np.add(template.shape, np.mod(template.shape, 2))
|
@@ -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,22 +94,30 @@ 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(
|
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
|
+
|
113
121
|
cutoff_frequency = np.max(2 * sampling_rate / cutoff_angstrom)
|
114
122
|
|
115
123
|
min_freq, max_freq = 0, cutoff_frequency
|
@@ -123,34 +131,39 @@ def resolution_sphere(template: NDArray, cutoff_angstrom: float, highpass : bool
|
|
123
131
|
omit_negative_frequencies=False,
|
124
132
|
)
|
125
133
|
|
126
|
-
mask = np.fft.ifftshift(mask)
|
127
134
|
template_ft = np.fft.fftn(template)
|
128
|
-
np.multiply(template_ft, mask, out
|
129
|
-
|
135
|
+
np.multiply(template_ft, mask, out=template_ft)
|
130
136
|
return np.fft.ifftn(template_ft).real
|
131
137
|
|
132
138
|
|
133
|
-
def resolution_gaussian(
|
134
|
-
|
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
|
+
|
135
148
|
grid = preprocessor.fftfreqn(
|
136
|
-
shape
|
149
|
+
shape=template.shape, sampling_rate=sampling_rate / sampling_rate.max()
|
137
150
|
)
|
138
151
|
|
139
152
|
sigma_fourier = np.divide(
|
140
|
-
np.max(2 * sampling_rate / cutoff_angstrom),
|
141
|
-
np.sqrt(2 * np.log(2))
|
153
|
+
np.max(2 * sampling_rate / cutoff_angstrom), np.sqrt(2 * np.log(2))
|
142
154
|
)
|
143
155
|
|
144
|
-
mask = np.exp(-grid
|
156
|
+
mask = np.exp(-(grid**2) / (2 * sigma_fourier**2))
|
145
157
|
if highpass:
|
146
158
|
mask = 1 - mask
|
147
159
|
|
148
160
|
mask = np.fft.ifftshift(mask)
|
149
|
-
template_ft = np.fft.fftn(template)
|
150
|
-
np.multiply(template_ft, mask, out = template_ft)
|
151
161
|
|
162
|
+
template_ft = np.fft.fftn(template)
|
163
|
+
np.multiply(template_ft, mask, out=template_ft)
|
152
164
|
return np.fft.ifftn(template_ft).real
|
153
165
|
|
166
|
+
|
154
167
|
def wedge(
|
155
168
|
template: NDArray,
|
156
169
|
tilt_start: float,
|
@@ -162,7 +175,7 @@ def wedge(
|
|
162
175
|
omit_negative_frequencies: bool = True,
|
163
176
|
extrude_plane: bool = True,
|
164
177
|
infinite_plane: bool = True,
|
165
|
-
):
|
178
|
+
) -> NDArray:
|
166
179
|
template_ft = np.fft.rfftn(template)
|
167
180
|
|
168
181
|
if tilt_step <= 0:
|
@@ -181,15 +194,14 @@ def wedge(
|
|
181
194
|
template = np.real(np.fft.irfftn(template_ft))
|
182
195
|
return template
|
183
196
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
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,
|
190
203
|
shape=template.shape,
|
191
204
|
sigma=gaussian_sigma,
|
192
|
-
opening_axes=opening_axis,
|
193
205
|
omit_negative_frequencies=omit_negative_frequencies,
|
194
206
|
)
|
195
207
|
np.multiply(template_ft, wedge_mask, out=template_ft)
|
@@ -197,7 +209,7 @@ def wedge(
|
|
197
209
|
return template
|
198
210
|
|
199
211
|
|
200
|
-
def compute_power_spectrum(template: NDArray):
|
212
|
+
def compute_power_spectrum(template: NDArray) -> NDArray:
|
201
213
|
return np.fft.fftshift(np.log(np.abs(np.fft.fftn(template))))
|
202
214
|
|
203
215
|
|
@@ -262,8 +274,8 @@ WRAPPED_FUNCTIONS = {
|
|
262
274
|
"mean_filter": mean,
|
263
275
|
"wedge_filter": wedge,
|
264
276
|
"power_spectrum": compute_power_spectrum,
|
265
|
-
"resolution_gaussian"
|
266
|
-
"resolution_sphere"
|
277
|
+
"resolution_gaussian": resolution_gaussian,
|
278
|
+
"resolution_sphere": resolution_sphere,
|
267
279
|
}
|
268
280
|
|
269
281
|
EXCLUDED_FUNCTIONS = [
|
@@ -405,7 +417,7 @@ class FilterWidget(widgets.Container):
|
|
405
417
|
|
406
418
|
def sphere_mask(
|
407
419
|
template: NDArray, center_x: float, center_y: float, center_z: float, radius: float
|
408
|
-
):
|
420
|
+
) -> NDArray:
|
409
421
|
return create_mask(
|
410
422
|
mask_type="ellipse",
|
411
423
|
shape=template.shape,
|
@@ -422,7 +434,7 @@ def ellipsod_mask(
|
|
422
434
|
radius_x: float,
|
423
435
|
radius_y: float,
|
424
436
|
radius_z: float,
|
425
|
-
):
|
437
|
+
) -> NDArray:
|
426
438
|
return create_mask(
|
427
439
|
mask_type="ellipse",
|
428
440
|
shape=template.shape,
|
@@ -439,7 +451,7 @@ def box_mask(
|
|
439
451
|
height_x: int,
|
440
452
|
height_y: int,
|
441
453
|
height_z: int,
|
442
|
-
):
|
454
|
+
) -> NDArray:
|
443
455
|
return create_mask(
|
444
456
|
mask_type="box",
|
445
457
|
shape=template.shape,
|
@@ -457,7 +469,7 @@ def tube_mask(
|
|
457
469
|
inner_radius: float,
|
458
470
|
outer_radius: float,
|
459
471
|
height: int,
|
460
|
-
):
|
472
|
+
) -> NDArray:
|
461
473
|
return create_mask(
|
462
474
|
mask_type="tube",
|
463
475
|
shape=template.shape,
|
@@ -480,7 +492,7 @@ def wedge_mask(
|
|
480
492
|
omit_negative_frequencies: bool = False,
|
481
493
|
extrude_plane: bool = True,
|
482
494
|
infinite_plane: bool = True,
|
483
|
-
):
|
495
|
+
) -> NDArray:
|
484
496
|
if tilt_step <= 0:
|
485
497
|
wedge_mask = preprocessor.continuous_wedge_mask(
|
486
498
|
start_tilt=tilt_start,
|
@@ -496,25 +508,24 @@ def wedge_mask(
|
|
496
508
|
wedge_mask = np.fft.fftshift(wedge_mask)
|
497
509
|
return wedge_mask
|
498
510
|
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
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,
|
506
517
|
shape=template.shape,
|
507
518
|
sigma=gaussian_sigma,
|
508
|
-
opening_axes=opening_axis,
|
509
519
|
omit_negative_frequencies=omit_negative_frequencies,
|
510
520
|
)
|
521
|
+
|
511
522
|
wedge_mask = np.fft.fftshift(wedge_mask)
|
512
523
|
return wedge_mask
|
513
524
|
|
514
525
|
|
515
526
|
def threshold_mask(
|
516
527
|
template: NDArray, standard_deviation: float = 5.0, invert: bool = False
|
517
|
-
):
|
528
|
+
) -> NDArray:
|
518
529
|
template_mean = template.mean()
|
519
530
|
template_deviation = standard_deviation * template.std()
|
520
531
|
upper = template_mean + template_deviation
|
@@ -526,6 +537,15 @@ def threshold_mask(
|
|
526
537
|
return mask
|
527
538
|
|
528
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
|
+
|
529
549
|
class MaskWidget(widgets.Container):
|
530
550
|
def __init__(self, viewer):
|
531
551
|
super().__init__(layout="vertical")
|
@@ -543,6 +563,7 @@ class MaskWidget(widgets.Container):
|
|
543
563
|
"Box": box_mask,
|
544
564
|
"Wedge": wedge_mask,
|
545
565
|
"Threshold": threshold_mask,
|
566
|
+
"Lowpass": lowpass_mask,
|
546
567
|
}
|
547
568
|
|
548
569
|
self.method_dropdown = widgets.ComboBox(
|
@@ -606,6 +627,7 @@ class MaskWidget(widgets.Container):
|
|
606
627
|
arr=active_layer.data,
|
607
628
|
rotation_matrix=rotation_matrix,
|
608
629
|
use_geometric_center=False,
|
630
|
+
order=1,
|
609
631
|
)
|
610
632
|
eps = np.finfo(rotated_data.dtype).eps
|
611
633
|
rotated_data[rotated_data < eps] = 0
|
@@ -636,10 +658,10 @@ class MaskWidget(widgets.Container):
|
|
636
658
|
dict(zip(["height_x", "height_y", "height_z"], coordinates_heights))
|
637
659
|
)
|
638
660
|
|
639
|
-
defaults["radius"] = np.
|
661
|
+
defaults["radius"] = np.max(coordinate_radius)
|
640
662
|
defaults["inner_radius"] = np.min(coordinate_radius)
|
641
663
|
defaults["outer_radius"] = np.max(coordinate_radius)
|
642
|
-
defaults["height"] =
|
664
|
+
defaults["height"] = np.max(coordinates_heights)
|
643
665
|
|
644
666
|
for widget in self.action_widgets:
|
645
667
|
if widget.name in defaults:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pytme
|
3
|
-
Version: 0.1.
|
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
|
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
|
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 [
|
61
|
+
The pyTME publication is available on [SoftwareX](https://www.sciencedirect.com/science/article/pii/S2352711024000074).
|
62
62
|
|
63
63
|
```
|
64
|
-
@article{
|
65
|
-
author = {Valentin J.
|
66
|
-
journal = {
|
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
|
-
|
69
|
+
volume = {25},
|
70
|
+
year = {2024}}
|
69
71
|
```
|
@@ -1,34 +1,34 @@
|
|
1
|
-
pytme-0.1.
|
2
|
-
pytme-0.1.
|
3
|
-
pytme-0.1.
|
4
|
-
pytme-0.1.
|
5
|
-
pytme-0.1.
|
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
7
|
scripts/estimate_ram_usage.py,sha256=rN7haobnHg3YcgGJIp81FNiCzy8-saJGeEurQlmQmNQ,2768
|
8
|
-
scripts/match_template.py,sha256=
|
9
|
-
scripts/postprocess.py,sha256=
|
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=
|
11
|
+
scripts/preprocessor_gui.py,sha256=E0F6quZnu32yZsBle38KDel5naHpC3Aci0uMCyo8DzY,29001
|
12
12
|
tme/__init__.py,sha256=NiPnYfrwb8e04ETubqwd3yzCGBliLBXRvCylD-T59jY,212
|
13
|
-
tme/__version__.py,sha256=
|
13
|
+
tme/__version__.py,sha256=C69ADlbQREQlR15trneyA2sk8x0-oH4rDAX5fsv19_U,22
|
14
14
|
tme/analyzer.py,sha256=Yh1o4kpjlRSq6ki5KiRsipF3tBwtSrL3KYfEm87NNOc,39188
|
15
|
-
tme/density.py,sha256=
|
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=
|
19
|
-
tme/matching_exhaustive.py,sha256=
|
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
|
22
|
+
tme/matching_utils.py,sha256=-cs3Nq8d9snaZ0mlgkSqdEc0c9A1TkX1sz93YY7TE_k,37227
|
23
23
|
tme/parser.py,sha256=tA9ABeV95cZn8lJCukVUaocQ9RguR6ZZzQsMXf_-ud0,13887
|
24
|
-
tme/preprocessor.py,sha256=
|
24
|
+
tme/preprocessor.py,sha256=UkWKBR9Z7FU-xUZ0ER_4c6lgLW9-MGmm-YN5Cs2mWD0,50631
|
25
25
|
tme/structure.py,sha256=AKGZML8bnsqZOpAOQADU1XDXZ-ITPhr3Dc0udQUMP6E,54134
|
26
26
|
tme/types.py,sha256=2Tyh_xnMLxIWYb3aJDAUb6GWpaL6gcYMUm2YNbJlAPI,295
|
27
27
|
tme/backends/__init__.py,sha256=xB2GBUFRskppvEs6S74VH0Pi-nXnIvu9_QFhESlcl3Y,4366
|
28
28
|
tme/backends/cupy_backend.py,sha256=CRwGqtycawTIfSfEDWpCQh4mcG03wad9mEODqzy75yQ,10648
|
29
29
|
tme/backends/matching_backend.py,sha256=E3cMXnMEazYJUr9RP5Q5rMEAf3vbkiOwzWrx5amt_nI,29311
|
30
30
|
tme/backends/mlx_backend.py,sha256=MrwICZpUiAcpZXON70r4SH-KsWxfhq1PdHUe80WbT-k,8467
|
31
|
-
tme/backends/npfftw_backend.py,sha256=
|
31
|
+
tme/backends/npfftw_backend.py,sha256=VsoKwMmusUxW81b2YSa6KO0_pfUw-51fdv9O6BkN0cQ,26200
|
32
32
|
tme/backends/pytorch_backend.py,sha256=lKv_7q0gDrCfbwHR38tfj5ixpD1lfCpqpfqS1KnOqdU,17978
|
33
33
|
tme/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
34
34
|
tme/data/c48n309.npy,sha256=NwH64mOEbm3tStq5c98o81fY1vMOoq4nvXDAh7Z7iZg,296768
|
@@ -53,9 +53,9 @@ tme/data/c600v.npy,sha256=JqSu3ALoL1A9iguehc0YGUMFPsh2fprHHp76VXeFXIw,2528
|
|
53
53
|
tme/data/c600vc.npy,sha256=Yht-GFXDSjjGvsjFBvyxxEZAI-ODADPd5gEgFNZQVTA,14528
|
54
54
|
tme/data/metadata.yaml,sha256=fAgX-mEzB0QMHTEtYDG4cSMbJhYxBbDJH3sdvJvL7a8,750
|
55
55
|
tme/data/quat_to_numpy.py,sha256=-gkDZb10fKBxwfYrSLCUWvMB76TzZWELCeKsYProwws,1333
|
56
|
-
pytme-0.1.
|
57
|
-
pytme-0.1.
|
58
|
-
pytme-0.1.
|
59
|
-
pytme-0.1.
|
60
|
-
pytme-0.1.
|
61
|
-
pytme-0.1.
|
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,,
|
scripts/match_template.py
CHANGED
@@ -539,15 +539,14 @@ def main():
|
|
539
539
|
opening_axis, tilt_axis = [int(x) for x in args.wedge_axes.split(",")]
|
540
540
|
|
541
541
|
if args.tilt_step is not None:
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
angles[tilt_axis, :] = tilt_angles
|
547
|
-
template_filter["wedge_mask"] = {
|
548
|
-
"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,
|
549
546
|
"sigma": args.wedge_smooth,
|
550
|
-
"
|
547
|
+
"opening_axis": opening_axis,
|
548
|
+
"tilt_axis": tilt_axis,
|
549
|
+
"omit_negative_frequencies": True,
|
551
550
|
}
|
552
551
|
else:
|
553
552
|
template_filter["continuous_wedge_mask"] = {
|
@@ -557,6 +556,7 @@ def main():
|
|
557
556
|
"opening_axis": opening_axis,
|
558
557
|
"infinite_plane": True,
|
559
558
|
"sigma": args.wedge_smooth,
|
559
|
+
"omit_negative_frequencies": True,
|
560
560
|
}
|
561
561
|
|
562
562
|
if template_mask is None:
|
@@ -593,7 +593,9 @@ def main():
|
|
593
593
|
print("\n" + "-" * 80)
|
594
594
|
|
595
595
|
if args.scramble_phases:
|
596
|
-
template.data = scramble_phases(
|
596
|
+
template.data = scramble_phases(
|
597
|
+
template.data, noise_proportion=1.0, normalize_power=True
|
598
|
+
)
|
597
599
|
|
598
600
|
available_memory = backend.get_available_memory()
|
599
601
|
if args.use_gpu:
|
@@ -671,7 +673,7 @@ def main():
|
|
671
673
|
exit(-1)
|
672
674
|
|
673
675
|
analyzer_args = {
|
674
|
-
"score_threshold": 0
|
676
|
+
"score_threshold": 0,
|
675
677
|
"number_of_peaks": 1000,
|
676
678
|
"convolution_mode": "valid",
|
677
679
|
"use_memmap": args.use_memmap,
|