pytme 0.2.0b0__tar.gz → 0.2.1__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 (73) hide show
  1. {pytme-0.2.0b0 → pytme-0.2.1}/MANIFEST.in +1 -2
  2. {pytme-0.2.0b0 → pytme-0.2.1}/PKG-INFO +2 -2
  3. {pytme-0.2.0b0 → pytme-0.2.1}/pyproject.toml +2 -2
  4. {pytme-0.2.0b0 → pytme-0.2.1}/pytme.egg-info/SOURCES.txt +8 -1
  5. pytme-0.2.1/scripts/extract_candidates.py +250 -0
  6. pytme-0.2.0b0/scripts/match_template_filters.py → pytme-0.2.1/scripts/match_template.py +449 -168
  7. pytme-0.2.0b0/scripts/match_template.py → pytme-0.2.1/scripts/match_template_filters.py +482 -141
  8. {pytme-0.2.0b0 → pytme-0.2.1}/scripts/postprocess.py +107 -49
  9. {pytme-0.2.0b0 → pytme-0.2.1}/scripts/preprocessor_gui.py +4 -1
  10. pytme-0.2.1/scripts/refine_matches.py +422 -0
  11. pytme-0.2.1/tme/__version__.py +1 -0
  12. {pytme-0.2.0b0 → pytme-0.2.1}/tme/analyzer.py +278 -148
  13. {pytme-0.2.0b0 → pytme-0.2.1}/tme/backends/__init__.py +1 -0
  14. {pytme-0.2.0b0 → pytme-0.2.1}/tme/backends/cupy_backend.py +20 -13
  15. pytme-0.2.1/tme/backends/jax_backend.py +218 -0
  16. {pytme-0.2.0b0 → pytme-0.2.1}/tme/backends/matching_backend.py +25 -10
  17. {pytme-0.2.0b0 → pytme-0.2.1}/tme/backends/mlx_backend.py +13 -9
  18. {pytme-0.2.0b0 → pytme-0.2.1}/tme/backends/npfftw_backend.py +22 -12
  19. {pytme-0.2.0b0 → pytme-0.2.1}/tme/backends/pytorch_backend.py +20 -9
  20. {pytme-0.2.0b0 → pytme-0.2.1}/tme/density.py +85 -64
  21. {pytme-0.2.0b0 → pytme-0.2.1}/tme/matching_data.py +86 -60
  22. {pytme-0.2.0b0 → pytme-0.2.1}/tme/matching_exhaustive.py +245 -166
  23. {pytme-0.2.0b0 → pytme-0.2.1}/tme/matching_optimization.py +137 -69
  24. {pytme-0.2.0b0 → pytme-0.2.1}/tme/matching_utils.py +1 -1
  25. {pytme-0.2.0b0 → pytme-0.2.1}/tme/orientations.py +175 -55
  26. pytme-0.2.1/tme/preprocessing/__init__.py +2 -0
  27. pytme-0.2.1/tme/preprocessing/_utils.py +188 -0
  28. pytme-0.2.1/tme/preprocessing/composable_filter.py +31 -0
  29. pytme-0.2.1/tme/preprocessing/compose.py +51 -0
  30. pytme-0.2.1/tme/preprocessing/frequency_filters.py +378 -0
  31. pytme-0.2.1/tme/preprocessing/tilt_series.py +1017 -0
  32. {pytme-0.2.0b0 → pytme-0.2.1}/tme/preprocessor.py +17 -7
  33. {pytme-0.2.0b0 → pytme-0.2.1}/tme/structure.py +4 -1
  34. pytme-0.2.0b0/scripts/extract_candidates.py +0 -218
  35. pytme-0.2.0b0/scripts/refine_matches.py +0 -218
  36. pytme-0.2.0b0/tme/__version__.py +0 -1
  37. {pytme-0.2.0b0 → pytme-0.2.1}/LICENSE +0 -0
  38. {pytme-0.2.0b0 → pytme-0.2.1}/README.md +0 -0
  39. {pytme-0.2.0b0 → pytme-0.2.1}/scripts/__init__.py +0 -0
  40. {pytme-0.2.0b0 → pytme-0.2.1}/scripts/estimate_ram_usage.py +0 -0
  41. {pytme-0.2.0b0 → pytme-0.2.1}/scripts/preprocess.py +0 -0
  42. {pytme-0.2.0b0 → pytme-0.2.1}/setup.cfg +0 -0
  43. {pytme-0.2.0b0 → pytme-0.2.1}/setup.py +0 -0
  44. {pytme-0.2.0b0 → pytme-0.2.1}/src/extensions.cpp +0 -0
  45. {pytme-0.2.0b0 → pytme-0.2.1}/tme/__init__.py +0 -0
  46. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/__init__.py +0 -0
  47. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48n309.npy +0 -0
  48. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48n527.npy +0 -0
  49. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48n9.npy +0 -0
  50. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48u1.npy +0 -0
  51. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48u1153.npy +0 -0
  52. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48u1201.npy +0 -0
  53. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48u1641.npy +0 -0
  54. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48u181.npy +0 -0
  55. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48u2219.npy +0 -0
  56. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48u27.npy +0 -0
  57. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48u2947.npy +0 -0
  58. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48u3733.npy +0 -0
  59. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48u4749.npy +0 -0
  60. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48u5879.npy +0 -0
  61. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48u7111.npy +0 -0
  62. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48u815.npy +0 -0
  63. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48u83.npy +0 -0
  64. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c48u8649.npy +0 -0
  65. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c600v.npy +0 -0
  66. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/c600vc.npy +0 -0
  67. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/metadata.yaml +0 -0
  68. {pytme-0.2.0b0 → pytme-0.2.1}/tme/data/quat_to_numpy.py +0 -0
  69. {pytme-0.2.0b0 → pytme-0.2.1}/tme/helpers.py +0 -0
  70. {pytme-0.2.0b0 → pytme-0.2.1}/tme/matching_constrained.py +0 -0
  71. {pytme-0.2.0b0 → pytme-0.2.1}/tme/matching_memory.py +0 -0
  72. {pytme-0.2.0b0 → pytme-0.2.1}/tme/parser.py +0 -0
  73. {pytme-0.2.0b0 → pytme-0.2.1}/tme/types.py +0 -0
@@ -60,7 +60,6 @@ global-exclude .DS_Store
60
60
  global-exclude .gitconfig
61
61
  global-exclude *.pickle
62
62
  prune tme/temp
63
- prune tme/preprocessing
64
63
  global-exclude doc/compileApiReference.sh
65
64
  prune public
66
65
  global-exclude tme/matching_backend.py
@@ -70,4 +69,4 @@ global-exclude tme/scoring.py
70
69
  global-exclude tme/package.py
71
70
  global-exclude tme/transforms.py
72
71
  global-exclude tme/tests/test_packaging.py
73
- global-exclude scripts/match_template_devel.py
72
+ global-exclude scripts/match_template_devel.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pytme
3
- Version: 0.2.0b0
3
+ Version: 0.2.1
4
4
  Summary: Python Template Matching Engine
5
5
  Author: Valentin Maurer
6
6
  Author-email: Valentin Maurer <valentin.maurer@embl-hamburg.de>
@@ -22,7 +22,7 @@ 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]
25
+ Requires-Dist: tifffile
26
26
  Requires-Dist: h5py
27
27
 
28
28
  # Python Template Matching Engine (PyTME)
@@ -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.2.0b"
10
+ version="0.2.1"
11
11
  description="Python Template Matching Engine"
12
12
  readme="README.md"
13
13
  requires-python = ">=3.11"
@@ -23,7 +23,7 @@ dependencies=[
23
23
  "scipy>=1.9.1",
24
24
  "pybind11",
25
25
  "psutil",
26
- "tifffile[all]",
26
+ "tifffile",
27
27
  "h5py"
28
28
  ]
29
29
  license = {text = "Proprietary"}
@@ -31,6 +31,7 @@ tme/structure.py
31
31
  tme/types.py
32
32
  tme/backends/__init__.py
33
33
  tme/backends/cupy_backend.py
34
+ tme/backends/jax_backend.py
34
35
  tme/backends/matching_backend.py
35
36
  tme/backends/mlx_backend.py
36
37
  tme/backends/npfftw_backend.py
@@ -57,4 +58,10 @@ tme/data/c48u8649.npy
57
58
  tme/data/c600v.npy
58
59
  tme/data/c600vc.npy
59
60
  tme/data/metadata.yaml
60
- tme/data/quat_to_numpy.py
61
+ tme/data/quat_to_numpy.py
62
+ tme/preprocessing/__init__.py
63
+ tme/preprocessing/_utils.py
64
+ tme/preprocessing/composable_filter.py
65
+ tme/preprocessing/compose.py
66
+ tme/preprocessing/frequency_filters.py
67
+ tme/preprocessing/tilt_series.py
@@ -0,0 +1,250 @@
1
+ #!python3
2
+ """ Prepare orientations stack for refinement.
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
+ load_pickle,
16
+ generate_tempfile_name,
17
+ rotation_aligning_vectors,
18
+ euler_from_rotationmatrix,
19
+ euler_to_rotationmatrix,
20
+ )
21
+
22
+
23
+ class ProgressBar:
24
+ """
25
+ ASCII progress bar.
26
+ """
27
+
28
+ def __init__(self, message : str, nchars : int, total : int):
29
+ self._size = nchars - len(message)
30
+ self._message = message
31
+ self._total = total
32
+
33
+ def update(self, cur):
34
+ x = int(cur * self._size / self._total)
35
+ print(
36
+ "%s[%s%s] %i/%i\r"
37
+ % (self._message, "#" * x, "." * (self._size - x), cur, self._total),
38
+ end=''
39
+ )
40
+
41
+
42
+ def parse_args():
43
+ parser = argparse.ArgumentParser(
44
+ description="Extract matching candidates for further refinement."
45
+ )
46
+
47
+ io_group = parser.add_argument_group("Input / Output")
48
+ io_group.add_argument(
49
+ "--input_file",
50
+ required=False,
51
+ type=str,
52
+ help="Path to the output of match_template.py.",
53
+ )
54
+ io_group.add_argument(
55
+ "--orientations",
56
+ required=True,
57
+ type=str,
58
+ help="Path to file generated by postprocess.py using output_format orientations.",
59
+ )
60
+ io_group.add_argument(
61
+ "--target",
62
+ required=False,
63
+ type=str,
64
+ help="Extract candidates from this target, can be at different sampling rate.",
65
+ )
66
+ io_group.add_argument(
67
+ "--template",
68
+ required=False,
69
+ type=str,
70
+ help="Extract candidates from this target, can be at different sampling rate.",
71
+ )
72
+ io_group.add_argument(
73
+ "-o",
74
+ "--output_file",
75
+ required=True,
76
+ type=str,
77
+ help="Path to output HDF5 file.",
78
+ )
79
+
80
+ alignment_group = parser.add_argument_group("Alignment")
81
+ alignment_group.add_argument(
82
+ "--align_orientations",
83
+ action="store_true",
84
+ required=False,
85
+ help="Whether to align extracted orientations based on their angles. Allows "
86
+ "for efficient subsequent sampling of cone angles.",
87
+ )
88
+ alignment_group.add_argument(
89
+ "--angles_are_vector",
90
+ action="store_true",
91
+ required=False,
92
+ help="Considers euler_z euler_y, euler_x as vector that will be rotated to align "
93
+ "with the z-axis (1,0,0). Only considered when --align_orientations is set."
94
+ )
95
+ alignment_group.add_argument(
96
+ "--interpolation_order",
97
+ dest="interpolation_order",
98
+ required=False,
99
+ type=int,
100
+ default=1,
101
+ help="Interpolation order for alignment, less than zero is no interpolation."
102
+ )
103
+
104
+ extraction_group = parser.add_argument_group("Extraction")
105
+ extraction_group.add_argument(
106
+ "--box_size",
107
+ required=False,
108
+ type=int,
109
+ help="Box size for extraction, defaults to two times the template.",
110
+ )
111
+ extraction_group.add_argument(
112
+ "--keep_out_of_box",
113
+ action="store_true",
114
+ required=False,
115
+ help="Whether to keep orientations that fall outside the box. If the "
116
+ "orientations are sensible, it is safe to pass this flag.",
117
+ )
118
+
119
+ args = parser.parse_args()
120
+
121
+ data_present = args.target is not None and args.template is not None
122
+ if args.input_file is None and not data_present:
123
+ raise ValueError(
124
+ "Either --input_file or --target and --template need to be specified."
125
+ )
126
+ elif args.input_file is not None and data_present:
127
+ raise ValueError(
128
+ "Please specific either --input_file or --target and --template."
129
+ )
130
+
131
+ return args
132
+
133
+
134
+ def main():
135
+ args = parse_args()
136
+ orientations = Orientations.from_file(args.orientations)
137
+
138
+ if args.input_file is not None:
139
+ data = load_pickle(args.input_file)
140
+ target_origin, _, sampling_rate, cli_args = data[-1]
141
+ args.target, args.template = cli_args.target, cli_args.template
142
+
143
+ target = Density.from_file(args.target, use_memmap=True)
144
+
145
+ try:
146
+ template = Density.from_file(args.template)
147
+ except Exception:
148
+ template = Density.from_structure(args.template, sampling_rate = target.sampling_rate)
149
+
150
+ box_size = args.box_size
151
+ if box_size is None:
152
+ box_size = np.multiply(template.shape, 2)
153
+ box_size = np.array(box_size)
154
+ box_size = np.repeat(box_size, template.data.ndim // box_size.size).astype(int)
155
+
156
+ extraction_shape = np.copy(box_size)
157
+ if args.align_orientations:
158
+ extraction_shape[:] = int(np.linalg.norm(box_size) + 1)
159
+
160
+ orientations, cand_slices, obs_slices = orientations.get_extraction_slices(
161
+ target_shape=target.shape,
162
+ extraction_shape=extraction_shape,
163
+ drop_out_of_box=not args.keep_out_of_box,
164
+ return_orientations=True,
165
+ )
166
+
167
+ if args.align_orientations:
168
+ orientations.rotations = orientations.rotations.astype(np.float32)
169
+ for index in range(orientations.rotations.shape[0]):
170
+ rotation_matrix = euler_to_rotationmatrix(orientations.rotations[index])
171
+ rotation_matrix = np.linalg.inv(rotation_matrix)
172
+ if args.angles_are_vector:
173
+ rotation_matrix = rotation_aligning_vectors(
174
+ orientations.rotations[index], target_vector=(1,0,0)
175
+ )
176
+ orientations.rotations[index] = euler_from_rotationmatrix(rotation_matrix)
177
+
178
+
179
+ filename = generate_tempfile_name()
180
+ output_dtype = target.data.dtype
181
+ if args.align_orientations is not None:
182
+ output_dtype = np.float32
183
+
184
+ target.data = target.data.astype(output_dtype)
185
+
186
+ dens = Density(
187
+ np.memmap(
188
+ filename,
189
+ mode="w+",
190
+ shape=(len(obs_slices), *box_size),
191
+ dtype=output_dtype,
192
+ ),
193
+ sampling_rate=(1, *target.sampling_rate),
194
+ origin=(0, *target.origin),
195
+ )
196
+ dens.data[:] = target.metadata["mean"]
197
+
198
+ print(target.data.shape)
199
+ # There appears to be an isseu with the stack creation. Trace this further
200
+ data_subset = np.zeros(extraction_shape, dtype = target.data.dtype)
201
+ pbar = ProgressBar(message = "Orientation ", nchars = 80, total = len(obs_slices))
202
+ for index, (obs_slice, cand_slice) in enumerate(zip(obs_slices, cand_slices)):
203
+ pbar.update(index + 1)
204
+
205
+ data_subset.fill(0)
206
+ data_subset[cand_slice] = target.data[obs_slice]
207
+ target_subset = Density(
208
+ data_subset,
209
+ sampling_rate=target.sampling_rate,
210
+ origin=target.origin,
211
+ )
212
+
213
+ if args.align_orientations:
214
+ rotation_matrix = euler_to_rotationmatrix(orientations.rotations[index])
215
+ target_subset = target_subset.rigid_transform(
216
+ rotation_matrix=rotation_matrix,
217
+ use_geometric_center=True,
218
+ order=args.interpolation_order,
219
+ )
220
+ target_subset.pad(box_size, center=True)
221
+
222
+ target_value = target.data[tuple(orientations.translations[index].astype(int))]
223
+ center = np.divide(target_subset.data.shape, 2).astype(int ) + np.mod(target_subset.shape, 2)
224
+ print(np.where(target_subset.data == target_value), center)
225
+ print(target_subset.data[tuple(center.astype(int))],
226
+ target_value,
227
+ target_subset.data[tuple(center.astype(int))] == target_value
228
+ )
229
+
230
+ dens.data[index] = target_subset.data
231
+ print("")
232
+
233
+ target_meta = {
234
+ k: v for k, v in target.metadata.items() if k in ("mean", "max", "min", "std")
235
+ }
236
+ dens.metadata.update(target_meta)
237
+ dens.metadata["batch_dimension"] = (0, )
238
+
239
+ dens.to_file(args.output_file)
240
+ orientations.to_file(
241
+ f"{splitext(args.output_file)[0]}_aligned.tsv",
242
+ file_format="text"
243
+ )
244
+ orientations.to_file(
245
+ f"{splitext(args.output_file)[0]}_aligned.star",
246
+ file_format="relion"
247
+ )
248
+
249
+ if __name__ == "__main__":
250
+ main()