pytme 0.1.9__tar.gz → 0.2.0b0__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.
Files changed (66) hide show
  1. {pytme-0.1.9 → pytme-0.2.0b0}/MANIFEST.in +2 -0
  2. {pytme-0.1.9 → pytme-0.2.0b0}/PKG-INFO +3 -1
  3. {pytme-0.1.9 → pytme-0.2.0b0}/pyproject.toml +3 -1
  4. {pytme-0.1.9 → pytme-0.2.0b0}/pytme.egg-info/SOURCES.txt +5 -0
  5. pytme-0.2.0b0/scripts/extract_candidates.py +218 -0
  6. {pytme-0.1.9 → pytme-0.2.0b0}/scripts/match_template.py +148 -126
  7. pytme-0.2.0b0/scripts/match_template_filters.py +852 -0
  8. pytme-0.2.0b0/scripts/postprocess.py +570 -0
  9. {pytme-0.1.9 → pytme-0.2.0b0}/scripts/preprocessor_gui.py +244 -60
  10. pytme-0.2.0b0/scripts/refine_matches.py +218 -0
  11. {pytme-0.1.9 → pytme-0.2.0b0}/src/extensions.cpp +3 -3
  12. {pytme-0.1.9 → pytme-0.2.0b0}/tme/__init__.py +2 -1
  13. pytme-0.2.0b0/tme/__version__.py +1 -0
  14. {pytme-0.1.9 → pytme-0.2.0b0}/tme/analyzer.py +545 -78
  15. {pytme-0.1.9 → pytme-0.2.0b0}/tme/backends/cupy_backend.py +80 -15
  16. {pytme-0.1.9 → pytme-0.2.0b0}/tme/backends/npfftw_backend.py +33 -2
  17. {pytme-0.1.9 → pytme-0.2.0b0}/tme/backends/pytorch_backend.py +15 -7
  18. {pytme-0.1.9 → pytme-0.2.0b0}/tme/density.py +156 -63
  19. pytme-0.2.0b0/tme/matching_constrained.py +195 -0
  20. {pytme-0.1.9 → pytme-0.2.0b0}/tme/matching_data.py +74 -33
  21. {pytme-0.1.9 → pytme-0.2.0b0}/tme/matching_exhaustive.py +351 -208
  22. {pytme-0.1.9 → pytme-0.2.0b0}/tme/matching_memory.py +1 -0
  23. pytme-0.2.0b0/tme/matching_optimization.py +1200 -0
  24. {pytme-0.1.9 → pytme-0.2.0b0}/tme/matching_utils.py +152 -8
  25. pytme-0.2.0b0/tme/orientations.py +561 -0
  26. {pytme-0.1.9 → pytme-0.2.0b0}/tme/preprocessor.py +21 -18
  27. {pytme-0.1.9 → pytme-0.2.0b0}/tme/structure.py +2 -37
  28. pytme-0.1.9/scripts/postprocess.py +0 -625
  29. pytme-0.1.9/tme/__version__.py +0 -1
  30. pytme-0.1.9/tme/matching_optimization.py +0 -1123
  31. {pytme-0.1.9 → pytme-0.2.0b0}/LICENSE +0 -0
  32. {pytme-0.1.9 → pytme-0.2.0b0}/README.md +0 -0
  33. {pytme-0.1.9 → pytme-0.2.0b0}/scripts/__init__.py +0 -0
  34. {pytme-0.1.9 → pytme-0.2.0b0}/scripts/estimate_ram_usage.py +0 -0
  35. {pytme-0.1.9 → pytme-0.2.0b0}/scripts/preprocess.py +0 -0
  36. {pytme-0.1.9 → pytme-0.2.0b0}/setup.cfg +0 -0
  37. {pytme-0.1.9 → pytme-0.2.0b0}/setup.py +0 -0
  38. {pytme-0.1.9 → pytme-0.2.0b0}/tme/backends/__init__.py +0 -0
  39. {pytme-0.1.9 → pytme-0.2.0b0}/tme/backends/matching_backend.py +0 -0
  40. {pytme-0.1.9 → pytme-0.2.0b0}/tme/backends/mlx_backend.py +0 -0
  41. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/__init__.py +0 -0
  42. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48n309.npy +0 -0
  43. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48n527.npy +0 -0
  44. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48n9.npy +0 -0
  45. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48u1.npy +0 -0
  46. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48u1153.npy +0 -0
  47. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48u1201.npy +0 -0
  48. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48u1641.npy +0 -0
  49. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48u181.npy +0 -0
  50. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48u2219.npy +0 -0
  51. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48u27.npy +0 -0
  52. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48u2947.npy +0 -0
  53. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48u3733.npy +0 -0
  54. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48u4749.npy +0 -0
  55. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48u5879.npy +0 -0
  56. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48u7111.npy +0 -0
  57. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48u815.npy +0 -0
  58. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48u83.npy +0 -0
  59. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c48u8649.npy +0 -0
  60. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c600v.npy +0 -0
  61. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/c600vc.npy +0 -0
  62. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/metadata.yaml +0 -0
  63. {pytme-0.1.9 → pytme-0.2.0b0}/tme/data/quat_to_numpy.py +0 -0
  64. {pytme-0.1.9 → pytme-0.2.0b0}/tme/helpers.py +0 -0
  65. {pytme-0.1.9 → pytme-0.2.0b0}/tme/parser.py +0 -0
  66. {pytme-0.1.9 → pytme-0.2.0b0}/tme/types.py +0 -0
@@ -60,6 +60,7 @@ global-exclude .DS_Store
60
60
  global-exclude .gitconfig
61
61
  global-exclude *.pickle
62
62
  prune tme/temp
63
+ prune tme/preprocessing
63
64
  global-exclude doc/compileApiReference.sh
64
65
  prune public
65
66
  global-exclude tme/matching_backend.py
@@ -67,5 +68,6 @@ prune doc/_build
67
68
  prune doc/reference/api
68
69
  global-exclude tme/scoring.py
69
70
  global-exclude tme/package.py
71
+ global-exclude tme/transforms.py
70
72
  global-exclude tme/tests/test_packaging.py
71
73
  global-exclude scripts/match_template_devel.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pytme
3
- Version: 0.1.9
3
+ Version: 0.2.0b0
4
4
  Summary: Python Template Matching Engine
5
5
  Author: Valentin Maurer
6
6
  Author-email: Valentin Maurer <valentin.maurer@embl-hamburg.de>
@@ -22,6 +22,8 @@ Requires-Dist: scikit_learn>=1.2.1
22
22
  Requires-Dist: scipy>=1.9.1
23
23
  Requires-Dist: pybind11
24
24
  Requires-Dist: psutil
25
+ Requires-Dist: tifffile[all]
26
+ Requires-Dist: h5py
25
27
 
26
28
  # Python Template Matching Engine (PyTME)
27
29
 
@@ -7,7 +7,7 @@ name="pytme"
7
7
  authors = [
8
8
  { name = "Valentin Maurer", email = "valentin.maurer@embl-hamburg.de" },
9
9
  ]
10
- version="0.1.9"
10
+ version="0.2.0b"
11
11
  description="Python Template Matching Engine"
12
12
  readme="README.md"
13
13
  requires-python = ">=3.11"
@@ -23,6 +23,8 @@ dependencies=[
23
23
  "scipy>=1.9.1",
24
24
  "pybind11",
25
25
  "psutil",
26
+ "tifffile[all]",
27
+ "h5py"
26
28
  ]
27
29
  license = {text = "Proprietary"}
28
30
  classifiers = [
@@ -5,21 +5,26 @@ pyproject.toml
5
5
  setup.py
6
6
  scripts/__init__.py
7
7
  scripts/estimate_ram_usage.py
8
+ scripts/extract_candidates.py
8
9
  scripts/match_template.py
10
+ scripts/match_template_filters.py
9
11
  scripts/postprocess.py
10
12
  scripts/preprocess.py
11
13
  scripts/preprocessor_gui.py
14
+ scripts/refine_matches.py
12
15
  src/extensions.cpp
13
16
  tme/__init__.py
14
17
  tme/__version__.py
15
18
  tme/analyzer.py
16
19
  tme/density.py
17
20
  tme/helpers.py
21
+ tme/matching_constrained.py
18
22
  tme/matching_data.py
19
23
  tme/matching_exhaustive.py
20
24
  tme/matching_memory.py
21
25
  tme/matching_optimization.py
22
26
  tme/matching_utils.py
27
+ tme/orientations.py
23
28
  tme/parser.py
24
29
  tme/preprocessor.py
25
30
  tme/structure.py
@@ -0,0 +1,218 @@
1
+ #!python3
2
+ """ CLI to simplify analysing the output of match_template.py.
3
+
4
+ Copyright (c) 2023 European Molecular Biology Laboratory
5
+
6
+ Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
7
+ """
8
+ import argparse
9
+ from os.path import splitext
10
+
11
+ import numpy as np
12
+
13
+ from tme import Density, Orientations
14
+ from tme.matching_utils import (
15
+ create_mask,
16
+ generate_tempfile_name,
17
+ rotation_aligning_vectors,
18
+ euler_from_rotationmatrix,
19
+ )
20
+
21
+
22
+ def parse_args():
23
+ parser = argparse.ArgumentParser(
24
+ description="Extract matching candidates for further refinement."
25
+ )
26
+
27
+ io_group = parser.add_argument_group("Input / Output")
28
+ io_group.add_argument(
29
+ "--input_file",
30
+ required=False,
31
+ type=str,
32
+ help="Path to the output of match_template.py.",
33
+ )
34
+ io_group.add_argument(
35
+ "--orientations",
36
+ required=True,
37
+ type=str,
38
+ help="Path to file generated by postprocess.py using output_format orientations.",
39
+ )
40
+ io_group.add_argument(
41
+ "--target",
42
+ required=False,
43
+ type=str,
44
+ help="Extract candidates from this target, can be at different sampling rate.",
45
+ )
46
+ io_group.add_argument(
47
+ "--template",
48
+ required=False,
49
+ type=str,
50
+ help="Extract candidates from this target, can be at different sampling rate.",
51
+ )
52
+ io_group.add_argument(
53
+ "-o",
54
+ "--output_file",
55
+ required=False,
56
+ type=str,
57
+ help="Path to output HDF5 file.",
58
+ )
59
+
60
+ extraction_group = parser.add_argument_group("Extraction")
61
+ extraction_group.add_argument(
62
+ "--box_size",
63
+ required=False,
64
+ type=int,
65
+ help="Box size for extraction, defaults to two times the template box.",
66
+ )
67
+ extraction_group.add_argument(
68
+ "--alignment_vector",
69
+ required=False,
70
+ type=str,
71
+ help="Vector to align extracted coordinate to e.g. '1,0,0'. If provided, euler_z"
72
+ "euler_y and euler_x are assumed to be a vector that will be rotated to match "
73
+ "alignment_vector.",
74
+ )
75
+ extraction_group.add_argument(
76
+ "--interpolation_order",
77
+ dest="interpolation_order",
78
+ required=False,
79
+ type=int,
80
+ default=1,
81
+ help="Spline interpolation used for template rotations. If less than zero "
82
+ "no interpolation is performed.",
83
+ )
84
+ extraction_group.add_argument(
85
+ "--translation_uncertainty",
86
+ dest="translation_uncertainty",
87
+ required=False,
88
+ type=int,
89
+ default=None,
90
+ help="Creates a cented spherical target mask with given radius in voxel.",
91
+ )
92
+ extraction_group.add_argument(
93
+ "--mask_path",
94
+ dest="mask_path",
95
+ required=False,
96
+ type=str,
97
+ default="target_mask.h5",
98
+ help="Path to write spherical mask to, defaults to target_mask.h5.",
99
+ )
100
+ args = parser.parse_args()
101
+
102
+ if args.alignment_vector is not None:
103
+ args.alignment_vector = [float(x) for x in args.alignment_vector.split(",")]
104
+ if len(args.alignment_vector) != 3:
105
+ raise ValueError("Only three-dimensional vectors are supported")
106
+
107
+ return args
108
+
109
+
110
+ def main():
111
+ args = parse_args()
112
+ orientations = Orientations.from_file(args.orientations)
113
+
114
+ target = Density.from_file(args.target, use_memmap=True)
115
+ template = Density.from_file(args.template)
116
+
117
+ box_size = template.shape
118
+ if args.box_size is not None:
119
+ args.box_size = args.box_size // 2
120
+ box_size = np.full(template.data.ndim, fill_value=args.box_size, dtype=int)
121
+
122
+ subtomo_shape = np.multiply(box_size, 2).astype(int)
123
+ extraction_scaling = 3 if args.alignment_vector is not None else 2
124
+ extraction_shape = np.multiply(box_size, extraction_scaling).astype(int)
125
+ orientations, cand_slices, obs_slices = orientations.get_extraction_slices(
126
+ target_shape=target.shape,
127
+ extraction_shape=extraction_shape,
128
+ drop_out_of_box=True,
129
+ return_orientations=True,
130
+ )
131
+
132
+ filename = generate_tempfile_name()
133
+ output_dtype = target.data.dtype
134
+ if args.alignment_vector is not None:
135
+ output_dtype = np.float32
136
+
137
+ if args.translation_uncertainty is not None:
138
+ dens = Density(
139
+ np.memmap(
140
+ args.mask_path,
141
+ mode="w+",
142
+ shape=(len(obs_slices), *subtomo_shape),
143
+ dtype=output_dtype,
144
+ ),
145
+ sampling_rate=(1, *target.sampling_rate),
146
+ origin=(0, *target.origin),
147
+ )
148
+ dens.data[:] = 0
149
+ mask = create_mask(
150
+ mask_type="ellipse",
151
+ center=template.shape,
152
+ radius=args.translation_uncertainty,
153
+ shape=subtomo_shape,
154
+ )
155
+ dens.data[:] = mask
156
+ dens.to_file(args.mask_path)
157
+
158
+ target.data = target.data.astype(output_dtype)
159
+
160
+ dens = Density(
161
+ np.memmap(
162
+ filename,
163
+ mode="w+",
164
+ shape=(len(obs_slices), *subtomo_shape),
165
+ dtype=output_dtype,
166
+ ),
167
+ sampling_rate=(1, *target.sampling_rate),
168
+ origin=(0, *target.origin),
169
+ )
170
+ dens.data[:] = target.metadata["mean"]
171
+
172
+ target_meta = {
173
+ k: v for k, v in target.metadata.items() if k in ("mean", "max", "min", "std")
174
+ }
175
+
176
+ total_slices = len(obs_slices)
177
+ magnitude = len(str(total_slices))
178
+ for index, obs_slice in enumerate(obs_slices):
179
+ print(f"Processing {index:{magnitude}} / {total_slices:{magnitude}}", end="\r")
180
+
181
+ target_subset = Density(
182
+ target.data[obs_slice],
183
+ sampling_rate=target.sampling_rate,
184
+ origin=target.origin,
185
+ )
186
+
187
+ rotation_matrix = np.eye(target_subset.data.ndim)
188
+ if args.alignment_vector is not None:
189
+ normal = orientations.rotations[index]
190
+ # To visualize only normals were picked we would need to do the opposite
191
+ # However, this allows us to align everything to the template axis
192
+ rotation_matrix = rotation_aligning_vectors(
193
+ normal, target_vector=args.alignment_vector
194
+ )
195
+
196
+ target_subset = target_subset.rigid_transform(
197
+ rotation_matrix=rotation_matrix,
198
+ use_geometric_center=True,
199
+ order=args.interpolation_order,
200
+ )
201
+ target_subset.pad(subtomo_shape, center=True)
202
+ dens.data[index] = target_subset.data
203
+ orientations.rotations[index] = euler_from_rotationmatrix(rotation_matrix)
204
+
205
+ dens.metadata.update(target_meta)
206
+ dens.to_file(args.output_file)
207
+ orientations.to_file(
208
+ f"{splitext(args.output_file)}_aligned.tsv",
209
+ file_format="text"
210
+ )
211
+ orientations.to_file(
212
+ f"{splitext(args.output_file)}_aligned.star",
213
+ file_format="relion"
214
+ )
215
+
216
+
217
+ if __name__ == "__main__":
218
+ main()