pytme 0.1.6__tar.gz → 0.1.8__tar.gz
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.6 → pytme-0.1.8}/PKG-INFO +10 -8
- {pytme-0.1.6 → pytme-0.1.8}/README.md +9 -7
- {pytme-0.1.6 → pytme-0.1.8}/pyproject.toml +1 -1
- {pytme-0.1.6 → pytme-0.1.8}/pytme.egg-info/SOURCES.txt +1 -0
- {pytme-0.1.6 → pytme-0.1.8}/scripts/estimate_ram_usage.py +1 -1
- {pytme-0.1.6 → pytme-0.1.8}/scripts/match_template.py +27 -22
- {pytme-0.1.6 → pytme-0.1.8}/scripts/postprocess.py +83 -32
- {pytme-0.1.6 → pytme-0.1.8}/scripts/preprocessor_gui.py +110 -40
- pytme-0.1.8/tme/__version__.py +1 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/analyzer.py +13 -8
- {pytme-0.1.6 → pytme-0.1.8}/tme/backends/__init__.py +1 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/backends/cupy_backend.py +5 -1
- {pytme-0.1.6 → pytme-0.1.8}/tme/backends/matching_backend.py +3 -1
- pytme-0.1.8/tme/backends/mlx_backend.py +269 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/backends/npfftw_backend.py +6 -11
- {pytme-0.1.6 → pytme-0.1.8}/tme/backends/pytorch_backend.py +5 -5
- {pytme-0.1.6 → pytme-0.1.8}/tme/density.py +44 -31
- {pytme-0.1.6 → pytme-0.1.8}/tme/matching_data.py +278 -31
- {pytme-0.1.6 → pytme-0.1.8}/tme/matching_exhaustive.py +73 -41
- {pytme-0.1.6 → pytme-0.1.8}/tme/matching_utils.py +54 -24
- {pytme-0.1.6 → pytme-0.1.8}/tme/parser.py +2 -2
- {pytme-0.1.6 → pytme-0.1.8}/tme/preprocessor.py +128 -15
- {pytme-0.1.6 → pytme-0.1.8}/tme/types.py +1 -0
- pytme-0.1.6/tme/__version__.py +0 -1
- {pytme-0.1.6 → pytme-0.1.8}/LICENSE +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/MANIFEST.in +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/scripts/__init__.py +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/scripts/preprocess.py +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/setup.cfg +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/setup.py +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/src/extensions.cpp +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/__init__.py +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/__init__.py +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48n309.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48n527.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48n9.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48u1.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48u1153.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48u1201.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48u1641.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48u181.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48u2219.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48u27.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48u2947.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48u3733.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48u4749.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48u5879.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48u7111.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48u815.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48u83.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c48u8649.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c600v.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/c600vc.npy +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/metadata.yaml +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/data/quat_to_numpy.py +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/helpers.py +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/matching_memory.py +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/matching_optimization.py +0 -0
- {pytme-0.1.6 → pytme-0.1.8}/tme/structure.py +0 -0
@@ -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
|
```
|
@@ -6,7 +6,7 @@ A software for template matching on electron microscopy data.
|
|
6
6
|
|
7
7
|
### Installation
|
8
8
|
|
9
|
-
There are three ways to get
|
9
|
+
There are three ways to get pyTME up and running:
|
10
10
|
|
11
11
|
1. **Install from Source:**
|
12
12
|
```bash
|
@@ -19,7 +19,7 @@ pip install pytme
|
|
19
19
|
```
|
20
20
|
|
21
21
|
3. **Docker Container:**
|
22
|
-
Build and use the
|
22
|
+
Build and use the pyTME container from Docker. This assumes a linux/amd64 platform.
|
23
23
|
```bash
|
24
24
|
docker build \
|
25
25
|
-t pytme \
|
@@ -33,12 +33,14 @@ docker build \
|
|
33
33
|
|
34
34
|
### Publication
|
35
35
|
|
36
|
-
The pyTME publication is available on [
|
36
|
+
The pyTME publication is available on [SoftwareX](https://www.sciencedirect.com/science/article/pii/S2352711024000074).
|
37
37
|
|
38
38
|
```
|
39
|
-
@article{
|
40
|
-
author = {Valentin J.
|
41
|
-
journal = {
|
39
|
+
@article{Maurer:2024aa,
|
40
|
+
author = {Maurer, Valentin J. and Siggel, Marc and Kosinski, Jan},
|
41
|
+
journal = {SoftwareX},
|
42
|
+
pages = {101636},
|
42
43
|
title = {PyTME (Python Template Matching Engine): A fast, flexible, and multi-purpose template matching library for cryogenic electron microscopy data},
|
43
|
-
|
44
|
+
volume = {25},
|
45
|
+
year = {2024}}
|
44
46
|
```
|
@@ -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
|
384
|
-
"
|
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
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
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
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
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
|
-
"
|
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(
|
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
|
676
|
+
"score_threshold": 0,
|
672
677
|
"number_of_peaks": 1000,
|
673
678
|
"convolution_mode": "valid",
|
674
679
|
"use_memmap": args.use_memmap,
|
@@ -5,6 +5,8 @@
|
|
5
5
|
|
6
6
|
Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
|
7
7
|
"""
|
8
|
+
from os import getcwd
|
9
|
+
from os.path import join
|
8
10
|
import argparse
|
9
11
|
from sys import exit
|
10
12
|
from typing import List, Tuple
|
@@ -13,6 +15,7 @@ from dataclasses import dataclass
|
|
13
15
|
|
14
16
|
import numpy as np
|
15
17
|
from scipy.spatial.transform import Rotation
|
18
|
+
from numpy.typing import NDArray
|
16
19
|
|
17
20
|
from tme import Density, Structure
|
18
21
|
from tme.analyzer import (
|
@@ -26,6 +29,7 @@ from tme.matching_utils import (
|
|
26
29
|
load_pickle,
|
27
30
|
euler_to_rotationmatrix,
|
28
31
|
euler_from_rotationmatrix,
|
32
|
+
centered_mask,
|
29
33
|
)
|
30
34
|
|
31
35
|
PEAK_CALLERS = {
|
@@ -52,16 +56,33 @@ def parse_args():
|
|
52
56
|
help="Prefix for the output file name. Extension depends on output_format.",
|
53
57
|
)
|
54
58
|
parser.add_argument(
|
55
|
-
"--number_of_peaks",
|
59
|
+
"--number_of_peaks",
|
60
|
+
type=int,
|
61
|
+
default=1000,
|
62
|
+
help="Number of peaks to consider. Note, this is the number of called peaks "
|
63
|
+
", subject to min_distance and min_boundary_distance filtering. Therefore, the "
|
64
|
+
"returned number of peaks will be at most equal to number_of_peaks. "
|
65
|
+
"Ignored when --orientations is provided.",
|
56
66
|
)
|
57
67
|
parser.add_argument(
|
58
|
-
"--min_distance",
|
68
|
+
"--min_distance",
|
69
|
+
type=int,
|
70
|
+
default=5,
|
71
|
+
help="Minimum distance between peaks. Ignored when --orientations is provided.",
|
59
72
|
)
|
60
73
|
parser.add_argument(
|
61
74
|
"--min_boundary_distance",
|
62
75
|
type=int,
|
63
76
|
default=0,
|
64
|
-
help="Minimum distance from target boundaries."
|
77
|
+
help="Minimum distance from target boundaries. Ignored when --orientations "
|
78
|
+
"is provided.",
|
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.",
|
65
86
|
)
|
66
87
|
parser.add_argument(
|
67
88
|
"--wedge_mask",
|
@@ -73,7 +94,8 @@ def parse_args():
|
|
73
94
|
"--peak_caller",
|
74
95
|
choices=list(PEAK_CALLERS.keys()),
|
75
96
|
default="PeakCallerScipy",
|
76
|
-
help="Peak caller to use for analysis. Ignored if input_file contains peaks
|
97
|
+
help="Peak caller to use for analysis. Ignored if input_file contains peaks or when "
|
98
|
+
"--orientations is provided.",
|
77
99
|
)
|
78
100
|
parser.add_argument(
|
79
101
|
"--orientations",
|
@@ -205,8 +227,12 @@ class Orientations:
|
|
205
227
|
return None
|
206
228
|
|
207
229
|
def _to_relion_star(
|
208
|
-
self,
|
209
|
-
|
230
|
+
self,
|
231
|
+
filename: str,
|
232
|
+
name_prefix: str = None,
|
233
|
+
ctf_image: str = None,
|
234
|
+
sampling_rate: float = 1.0,
|
235
|
+
subtomogram_size: int = 0,
|
210
236
|
) -> None:
|
211
237
|
"""
|
212
238
|
Save orientations in RELION's STAR file format.
|
@@ -249,12 +275,11 @@ class Orientations:
|
|
249
275
|
"300.000000",
|
250
276
|
str(int(subtomogram_size)),
|
251
277
|
"3",
|
252
|
-
str(float(sampling_rate))
|
278
|
+
str(float(sampling_rate)),
|
253
279
|
]
|
254
280
|
optics_header = "\n".join(optics_header)
|
255
281
|
optics_data = "\t".join(optics_data)
|
256
282
|
|
257
|
-
|
258
283
|
header = [
|
259
284
|
"data_particles",
|
260
285
|
"",
|
@@ -283,13 +308,14 @@ class Orientations:
|
|
283
308
|
_ = ofile.write("\n# version 30001\n")
|
284
309
|
_ = ofile.write(f"{header}\n")
|
285
310
|
|
311
|
+
# pyTME uses a zyx data layout
|
286
312
|
for index, (translation, rotation, score, detail) in enumerate(self):
|
287
313
|
rotation = Rotation.from_euler("zyx", rotation, degrees=True)
|
288
|
-
rotation = rotation.as_euler(seq="
|
314
|
+
rotation = rotation.as_euler(seq="xyx", degrees=True)
|
289
315
|
|
290
316
|
translation_string = "\t".join([str(x) for x in translation][::-1])
|
291
|
-
angle_string = "\t".join([str(x) for x in rotation
|
292
|
-
name = f"{name_prefix}{index}.mrc"
|
317
|
+
angle_string = "\t".join([str(x) for x in rotation])
|
318
|
+
name = f"{name_prefix}_{index}.mrc"
|
293
319
|
_ = ofile.write(
|
294
320
|
f"{translation_string}\t{name}\t{angle_string}\t1{ctf_image}\n"
|
295
321
|
)
|
@@ -386,11 +412,25 @@ class Orientations:
|
|
386
412
|
return translation, rotation, score, detail
|
387
413
|
|
388
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
|
+
|
389
428
|
def main():
|
390
429
|
args = parse_args()
|
391
430
|
data = load_pickle(args.input_file)
|
392
431
|
|
393
432
|
meta = data[-1]
|
433
|
+
target_origin, _, sampling_rate, cli_args = meta
|
394
434
|
|
395
435
|
if args.orientations is not None:
|
396
436
|
orientations = Orientations.from_file(
|
@@ -402,13 +442,29 @@ def main():
|
|
402
442
|
# Output is MaxScoreOverRotations
|
403
443
|
if data[0].ndim == data[2].ndim:
|
404
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
|
+
|
405
456
|
peak_caller = PEAK_CALLERS[args.peak_caller](
|
406
457
|
number_of_peaks=args.number_of_peaks,
|
407
458
|
min_distance=args.min_distance,
|
408
459
|
min_boundary_distance=args.min_boundary_distance,
|
409
460
|
)
|
410
461
|
peak_caller(scores, rotation_matrix=np.eye(3))
|
411
|
-
candidates = peak_caller.merge(
|
462
|
+
candidates = peak_caller.merge(
|
463
|
+
candidates=[tuple(peak_caller)],
|
464
|
+
number_of_peaks=args.number_of_peaks,
|
465
|
+
min_distance=args.min_distance,
|
466
|
+
min_boundary_distance=args.min_boundary_distance,
|
467
|
+
)
|
412
468
|
if len(candidates) == 0:
|
413
469
|
exit(
|
414
470
|
"Found no peaks. Try reducing min_distance or min_boundary_distance."
|
@@ -436,18 +492,11 @@ def main():
|
|
436
492
|
orientations.to_file(filename=f"{args.output_prefix}.tsv", file_format="text")
|
437
493
|
exit(0)
|
438
494
|
|
439
|
-
target_origin, _, sampling_rate, cli_args = meta
|
440
|
-
|
441
|
-
template_is_density, index = True, 0
|
442
495
|
_, template_extension = splitext(cli_args.template)
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
except ValueError:
|
448
|
-
template_is_density = False
|
449
|
-
template = Structure.from_file(cli_args.template)
|
450
|
-
center_of_mass = template.center_of_mass()[::-1]
|
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
|
451
500
|
|
452
501
|
if args.output_format == "relion":
|
453
502
|
new_shape = np.add(template.shape, np.mod(template.shape, 2))
|
@@ -457,10 +506,6 @@ def main():
|
|
457
506
|
|
458
507
|
if args.output_format in ("extraction", "relion"):
|
459
508
|
target = Density.from_file(cli_args.target)
|
460
|
-
if isinstance(template, Structure):
|
461
|
-
template = Density.from_structure(
|
462
|
-
template, sampling_rate=target.sampling_rate
|
463
|
-
)
|
464
509
|
|
465
510
|
if not np.all(np.divide(target.shape, template.shape) > 2):
|
466
511
|
print(
|
@@ -489,14 +534,15 @@ def main():
|
|
489
534
|
)
|
490
535
|
|
491
536
|
orientations = orientations[keep_peaks]
|
537
|
+
working_directory = getcwd()
|
492
538
|
if args.output_format == "relion":
|
493
539
|
orientations.to_file(
|
494
540
|
filename=f"{args.output_prefix}.star",
|
495
541
|
file_format="relion",
|
496
|
-
name_prefix=args.output_prefix,
|
542
|
+
name_prefix=join(working_directory, args.output_prefix),
|
497
543
|
ctf_image=args.wedge_mask,
|
498
|
-
sampling_rate
|
499
|
-
subtomogram_size
|
544
|
+
sampling_rate=target.sampling_rate.max(),
|
545
|
+
subtomogram_size=template.shape[0],
|
500
546
|
)
|
501
547
|
|
502
548
|
peaks = peaks[keep_peaks,]
|
@@ -543,7 +589,9 @@ def main():
|
|
543
589
|
origin=candidate_starts[index] * sampling_rate,
|
544
590
|
)
|
545
591
|
# out_density.data = out_density.data * template_mask.data
|
546
|
-
out_density.to_file(
|
592
|
+
out_density.to_file(
|
593
|
+
join(working_directory, f"{args.output_prefix}_{index}.mrc")
|
594
|
+
)
|
547
595
|
|
548
596
|
exit(0)
|
549
597
|
|
@@ -566,7 +614,10 @@ def main():
|
|
566
614
|
translation=translation[::-1],
|
567
615
|
rotation_matrix=rotation_matrix[::-1, ::-1],
|
568
616
|
)
|
569
|
-
|
617
|
+
# template_extension should contain the extension '.'
|
618
|
+
transformed_template.to_file(
|
619
|
+
f"{args.output_prefix}_{index}{template_extension}"
|
620
|
+
)
|
570
621
|
index += 1
|
571
622
|
|
572
623
|
|