pytme 0.2.0__cp311-cp311-macosx_14_0_arm64.whl → 0.2.1__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.
Files changed (40) hide show
  1. {pytme-0.2.0.data → pytme-0.2.1.data}/scripts/match_template.py +183 -69
  2. {pytme-0.2.0.data → pytme-0.2.1.data}/scripts/postprocess.py +107 -49
  3. {pytme-0.2.0.data → pytme-0.2.1.data}/scripts/preprocessor_gui.py +4 -1
  4. {pytme-0.2.0.dist-info → pytme-0.2.1.dist-info}/METADATA +1 -1
  5. pytme-0.2.1.dist-info/RECORD +73 -0
  6. scripts/extract_candidates.py +117 -85
  7. scripts/match_template.py +183 -69
  8. scripts/match_template_filters.py +193 -71
  9. scripts/postprocess.py +107 -49
  10. scripts/preprocessor_gui.py +4 -1
  11. scripts/refine_matches.py +364 -160
  12. tme/__version__.py +1 -1
  13. tme/analyzer.py +259 -117
  14. tme/backends/__init__.py +1 -0
  15. tme/backends/cupy_backend.py +20 -13
  16. tme/backends/jax_backend.py +218 -0
  17. tme/backends/matching_backend.py +25 -10
  18. tme/backends/mlx_backend.py +13 -9
  19. tme/backends/npfftw_backend.py +20 -8
  20. tme/backends/pytorch_backend.py +20 -9
  21. tme/density.py +79 -60
  22. tme/extensions.cpython-311-darwin.so +0 -0
  23. tme/matching_data.py +85 -61
  24. tme/matching_exhaustive.py +222 -129
  25. tme/matching_optimization.py +117 -76
  26. tme/orientations.py +175 -55
  27. tme/preprocessing/_utils.py +17 -5
  28. tme/preprocessing/composable_filter.py +2 -1
  29. tme/preprocessing/compose.py +1 -2
  30. tme/preprocessing/frequency_filters.py +97 -41
  31. tme/preprocessing/tilt_series.py +137 -87
  32. tme/preprocessor.py +3 -0
  33. tme/structure.py +4 -1
  34. pytme-0.2.0.dist-info/RECORD +0 -72
  35. {pytme-0.2.0.data → pytme-0.2.1.data}/scripts/estimate_ram_usage.py +0 -0
  36. {pytme-0.2.0.data → pytme-0.2.1.data}/scripts/preprocess.py +0 -0
  37. {pytme-0.2.0.dist-info → pytme-0.2.1.dist-info}/LICENSE +0 -0
  38. {pytme-0.2.0.dist-info → pytme-0.2.1.dist-info}/WHEEL +0 -0
  39. {pytme-0.2.0.dist-info → pytme-0.2.1.dist-info}/entry_points.txt +0 -0
  40. {pytme-0.2.0.dist-info → pytme-0.2.1.dist-info}/top_level.txt +0 -0
scripts/refine_matches.py CHANGED
@@ -1,52 +1,121 @@
1
1
  #!python3
2
- """ CLI to refine template matching candidates.
2
+ """ Iterative template matching parameter tuning.
3
3
 
4
- Copyright (c) 2023-2024 European Molecular Biology Laboratory
4
+ Copyright (c) 2024 European Molecular Biology Laboratory
5
5
 
6
6
  Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
7
7
  """
8
8
  import argparse
9
- from time import time
9
+ import subprocess
10
+ from sys import exit
11
+ from shutil import copyfile
12
+ from typing import Tuple, List, Dict
10
13
 
11
14
  import numpy as np
12
- from numpy.typing import NDArray
13
-
14
- from tme.backends import backend
15
- from tme import Density, Structure
16
- from tme.matching_data import MatchingData
17
- from tme.analyzer import MaxScoreOverRotations, MaxScoreOverTranslations
18
- from tme.matching_utils import (
19
- load_pickle,
20
- get_rotation_matrices,
21
- compute_parallelization_schedule,
22
- )
23
- from tme.matching_exhaustive import scan_subsets, MATCHING_EXHAUSTIVE_REGISTER
24
-
25
- from postprocess import Orientations
26
- from match_template import load_and_validate_mask
15
+ from scipy import optimize
16
+
17
+ from tme import Orientations, Density
18
+ from tme.matching_utils import generate_tempfile_name, load_pickle
19
+ from tme.matching_exhaustive import MATCHING_EXHAUSTIVE_REGISTER
20
+
27
21
 
28
22
  def parse_args():
29
23
  parser = argparse.ArgumentParser(
30
- description="Refine Template Matching Orientations."
24
+ description="Refine template matching candidates using deep matching.",
31
25
  )
32
- parser.add_argument(
33
- "--input_file",
26
+ io_group = parser.add_argument_group("Input / Output")
27
+ io_group.add_argument(
28
+ "--orientations",
34
29
  required=True,
35
30
  type=str,
36
- help="Path to the output of match_template.py.",
31
+ help="Path to an orientations file in a supported format. See "
32
+ "https://kosinskilab.github.io/pyTME/reference/api/tme.orientations.Orientations.from_file.html"
33
+ " for available options."
37
34
  )
38
- parser.add_argument(
39
- "--orientations",
35
+ io_group.add_argument(
36
+ "--output_prefix",
40
37
  required=True,
41
38
  type=str,
42
- help="Path to orientations from postprocess.py.",
39
+ help="Path to write output to."
40
+ )
41
+ io_group.add_argument(
42
+ "--iterations",
43
+ required=False,
44
+ default=0,
45
+ type=int,
46
+ help="Number of refinement iterations to perform.",
47
+ )
48
+ io_group.add_argument(
49
+ "--verbose",
50
+ action="store_true",
51
+ default=False,
52
+ help="More verbose and more files written to disk.",
53
+ )
54
+ matching_group = parser.add_argument_group("Template Matching")
55
+ matching_group.add_argument(
56
+ "--input_file",
57
+ required=False,
58
+ type=str,
59
+ help="Path to the output of match_template.py.",
60
+ )
61
+ matching_group.add_argument(
62
+ "-m",
63
+ "--target",
64
+ dest="target",
65
+ type=str,
66
+ required=False,
67
+ help="Path to a target in CCP4/MRC, EM, H5 or another format supported by "
68
+ "tme.density.Density.from_file "
69
+ "https://kosinskilab.github.io/pyTME/reference/api/tme.density.Density.from_file.html",
43
70
  )
44
- parser.add_argument(
45
- "--output_file",
71
+ matching_group.add_argument(
72
+ "--target_mask",
73
+ dest="target_mask",
74
+ type=str,
75
+ required=False,
76
+ help="Path to a mask for the target in a supported format (see target).",
77
+ )
78
+ matching_group.add_argument(
79
+ "-i",
80
+ "--template",
81
+ dest="template",
82
+ type=str,
83
+ required=False,
84
+ help="Path to a template in PDB/MMCIF or other supported formats (see target).",
85
+ )
86
+ matching_group.add_argument(
87
+ "--template_mask",
88
+ dest="template_mask",
89
+ type=str,
90
+ required=False,
91
+ help="Path to a mask for the template in a supported format (see target).",
92
+ )
93
+ matching_group.add_argument(
94
+ "--invert_target_contrast",
95
+ dest="invert_target_contrast",
96
+ action="store_true",
97
+ default=False,
98
+ help="Invert the target's contrast and rescale linearly between zero and one. "
99
+ "This option is intended for targets where templates to-be-matched have "
100
+ "negative values, e.g. tomograms.",
101
+ )
102
+ matching_group.add_argument(
103
+ "--angular_sampling",
104
+ dest="angular_sampling",
46
105
  required=True,
47
- help="Path to the refined output orientations.",
106
+ default=None,
107
+ help="Angular sampling rate using optimized rotational sets."
108
+ "A lower number yields more rotations. Values >= 180 sample only the identity.",
109
+ )
110
+ matching_group.add_argument(
111
+ "-s",
112
+ dest="score",
113
+ type=str,
114
+ default="FLCSphericalMask",
115
+ choices=list(MATCHING_EXHAUSTIVE_REGISTER.keys()),
116
+ help="Template matching scoring function.",
48
117
  )
49
- parser.add_argument(
118
+ matching_group.add_argument(
50
119
  "-n",
51
120
  dest="cores",
52
121
  required=False,
@@ -54,165 +123,300 @@ def parse_args():
54
123
  default=4,
55
124
  help="Number of cores used for template matching.",
56
125
  )
126
+ matching_group.add_argument(
127
+ "--use_gpu",
128
+ dest="use_gpu",
129
+ action="store_true",
130
+ default=False,
131
+ help="Whether to perform computations on the GPU.",
132
+ )
133
+ matching_group.add_argument(
134
+ "--no_centering",
135
+ dest="no_centering",
136
+ action="store_true",
137
+ help="Assumes the template is already centered and omits centering.",
138
+ )
139
+ matching_group.add_argument(
140
+ "--no_edge_padding",
141
+ dest="no_edge_padding",
142
+ action="store_true",
143
+ default=False,
144
+ help="Whether to not pad the edges of the target. Can be set if the target"
145
+ " has a well defined bounding box, e.g. a masked reconstruction.",
146
+ )
147
+ matching_group.add_argument(
148
+ "--no_fourier_padding",
149
+ dest="no_fourier_padding",
150
+ action="store_true",
151
+ default=False,
152
+ help="Whether input arrays should not be zero-padded to full convolution shape "
153
+ "for numerical stability. When working with very large targets, e.g. tomograms, "
154
+ "it is safe to use this flag and benefit from the performance gain.",
155
+ )
156
+
157
+ peak_group = parser.add_argument_group("Peak Calling")
158
+ peak_group.add_argument(
159
+ "--number_of_peaks",
160
+ type=int,
161
+ default=100,
162
+ required=False,
163
+ help="Upper limit of peaks to call, subject to filtering parameters. Default 1000. "
164
+ "If minimum_score is provided all peaks scoring higher will be reported.",
165
+ )
166
+ extraction_group = parser.add_argument_group("Extraction")
167
+ extraction_group.add_argument(
168
+ "--keep_out_of_box",
169
+ action="store_true",
170
+ required=False,
171
+ help="Whether to keep orientations that fall outside the box. If the "
172
+ "orientations are sensible, it is safe to pass this flag.",
173
+ )
174
+
175
+ optimization_group = parser.add_argument_group("Optimization")
176
+ optimization_group.add_argument(
177
+ "--lowpass",
178
+ dest="lowpass",
179
+ action="store_true",
180
+ default=False,
181
+ help="Optimize template matching lowpass filter cutoff.",
182
+ )
183
+ optimization_group.add_argument(
184
+ "--highpass",
185
+ dest="highpass",
186
+ action="store_true",
187
+ default=False,
188
+ help="Optimize template matching highpass filter cutoff.",
189
+ )
57
190
 
58
191
  args = parser.parse_args()
59
192
 
193
+ data_present = args.target is not None and args.template is not None
194
+ if args.input_file is None and not data_present:
195
+ raise ValueError(
196
+ "Either --input_file or --target and --template need to be specified."
197
+ )
198
+ elif args.input_file is not None and data_present:
199
+ raise ValueError(
200
+ "Please specific either --input_file or --target and --template."
201
+ )
202
+
60
203
  return args
61
204
 
62
205
 
63
- def load_template(filepath: str, sampling_rate: NDArray) -> "Density":
64
- try:
65
- template = Density.from_file(filepath)
66
- except ValueError:
67
- template = Structure.from_file(filepath)
68
- template = Density.from_structure(template, sampling_rate=sampling_rate)
206
+ def argdict_to_command(input_args: Dict, executable: str) -> List:
207
+ ret = []
208
+ for key, value in input_args.items():
209
+ if value is None:
210
+ continue
211
+ elif isinstance(value, bool):
212
+ if value:
213
+ ret.append(key)
214
+ else:
215
+ ret.extend([key, value])
216
+
217
+ ret = [str(x) for x in ret]
218
+ ret.insert(0, executable)
219
+ return " ".join(ret)
220
+
221
+
222
+ def create_stacking_argdict(args) -> Dict:
223
+ arg_dict = {
224
+ "--input_file": args.input_file,
225
+ "--orientations": args.orientations,
226
+ "--output_file": args.candidate_stack_path,
227
+ "--keep_out_of_box": args.keep_out_of_box,
228
+ }
229
+ return arg_dict
230
+
231
+
232
+ def create_matching_argdict(args) -> Dict:
233
+ arg_dict = {
234
+ "--target": args.target,
235
+ "--template": args.template,
236
+ "--template_mask": args.template_mask,
237
+ "--target_mask": args.target_mask,
238
+ "-o": args.match_template_path,
239
+ "-a": args.angular_sampling,
240
+ "-s": args.score,
241
+ "--no_fourier_padding": True,
242
+ "--no_edge_padding": True,
243
+ "--no_centering": args.no_centering,
244
+ "-n": args.cores,
245
+ "--invert_target_contrast": args.invert_target_contrast,
246
+ "--use_gpu": args.use_gpu,
247
+ }
248
+ return arg_dict
249
+
250
+
251
+ def create_postprocessing_argdict(args) -> Dict:
252
+ arg_dict = {
253
+ "--input_file": args.match_template_path,
254
+ "--target_mask": args.target_mask,
255
+ "--output_prefix": args.new_orientations_path,
256
+ "--peak_caller": "PeakCallerMaximumFilter",
257
+ "--number_of_peaks": args.number_of_peaks,
258
+ "--output_format": "orientations",
259
+ "--mask_edges" : True,
260
+ }
261
+ return arg_dict
262
+
263
+ def update_orientations(old, new, args):
264
+ stack_shape = Density.from_file(
265
+ args.candidate_stack_path, use_memmap = True
266
+ ).shape
267
+
268
+ stack_center = np.add(
269
+ np.divide(stack_shape, 2).astype(int),
270
+ np.mod(stack_shape, 2)
271
+ )
69
272
 
70
- return template
273
+ print(old.translations[new.translations[:, 0].astype(int)])
274
+ print(new.translations[:, 1:], stack_center, stack_shape)
71
275
 
276
+ new.translations[:, 1:] = np.add(
277
+ old.translations[new.translations[:, 0].astype(int)],
278
+ np.subtract(new.translations, stack_center)[:, 1:]
279
+ )
280
+ print(new.translations)
281
+ # The effect of --align_orientations should be handled herer
282
+ return new
72
283
 
73
- def main():
74
- args = parse_args()
75
- meta = load_pickle(args.input_file)[-1]
76
- target_origin, _, sampling_rate, cli_args = meta
77
284
 
78
- orientations = Orientations.from_file(
79
- filename=args.orientations, file_format="text"
80
- )
81
285
 
82
- template = load_template(cli_args.template, sampling_rate)
83
- template_mask = load_and_validate_mask(
84
- mask_target=template, mask_path=cli_args.template_mask
85
- )
86
286
 
87
- if not cli_args.no_centering:
88
- template, translation = template.centered(0)
287
+ class DeepMatcher:
288
+ def __init__(self, args):
289
+ self.orientations = Orientations.from_file(args.orientations)
89
290
 
90
- if template_mask is None:
91
- template_mask = template.empty
92
- if not cli_args.no_centering:
93
- enclosing_box = template.minimum_enclosing_box(
94
- 0, use_geometric_center=False
95
- )
96
- template_mask.adjust_box(enclosing_box)
291
+ match_template_args = create_matching_argdict(args)
292
+ match_template_args["--target"] = args.candidate_stack_path
293
+ self.match_template_args = match_template_args
97
294
 
98
- template_mask.data[:] = 1
99
- translation = np.zeros_like(translation)
295
+ self.filter_parameters = {}
296
+ if args.lowpass:
297
+ self.filter_parameters["--lowpass"] = 0
298
+ if args.highpass:
299
+ self.filter_parameters["--highpass"] = 200
100
300
 
101
- template_mask.pad(template.shape, center=False)
102
- origin_translation = np.divide(
103
- np.subtract(template.origin, template_mask.origin), template.sampling_rate
104
- )
105
- translation = np.add(translation, origin_translation)
301
+ self.postprocess_args = create_postprocessing_argdict(args)
302
+ self.postprocess_args["--number_of_peaks"] = 1
106
303
 
107
- template_mask = template_mask.rigid_transform(
108
- rotation_matrix=np.eye(template_mask.data.ndim),
109
- translation=-translation,
110
- order=1,
111
- )
112
- template_mask.origin = template.origin.copy()
113
304
 
114
- target = Density.from_file(cli_args.target)
115
- peaks = orientations.translations.astype(int)
116
- half_shape = np.divide(template.shape, 2).astype(int)
117
- observation_starts = np.subtract(peaks, half_shape)
118
- observation_stops = np.add(peaks, half_shape) + np.mod(template.shape, 2).astype(
119
- int
120
- )
305
+ def get_initial_values(self) -> Tuple[float]:
306
+ ret = tuple(float(x) for x in self.filter_parameters.values())
307
+ return ret
121
308
 
122
- pruned_starts = np.maximum(observation_starts, 0)
123
- pruned_stops = np.minimum(observation_stops, target.shape)
309
+ def format_parameters(self, parameter_values: Tuple[float]) -> Dict:
310
+ ret = {}
311
+ for value, key in zip(parameter_values, ret.keys()):
312
+ ret[key] = value
313
+ if isinstance(self.filter_parameters[key], bool):
314
+ ret[key] = value > 0.5
315
+ return ret
124
316
 
125
- keep_peaks = (
126
- np.sum(
127
- np.multiply(
128
- observation_starts == pruned_starts, observation_stops == pruned_stops
129
- ),
130
- axis=1,
317
+ def __call__(self, x: Tuple[float]):
318
+ filter_parameters = self.format_parameters(x)
319
+ self.match_template_args.update(filter_parameters)
320
+ match_template = argdict_to_command(
321
+ self.match_template_args,
322
+ executable="python3 /Users/vmaurer/src/pytme/scripts/match_template_filters.py"
131
323
  )
132
- == observation_starts.shape[1]
133
- )
134
- observation_starts = observation_starts[keep_peaks]
135
- observation_stops = observation_stops[keep_peaks]
324
+ _ = subprocess.run(match_template, capture_output=True, shell = True)
136
325
 
137
- observation_slices = [
138
- tuple(slice(s, e) for s, e in zip(start_row, stop_row))
139
- for start_row, stop_row in zip(observation_starts, observation_stops)
140
- ]
326
+ # Assume we get a new peak for each input in the same order
327
+ postprocess = argdict_to_command(
328
+ self.postprocess_args,
329
+ executable="python3 /Users/vmaurer/src/pytme/scripts/postprocess.py"
330
+ )
331
+ _ = subprocess.run(postprocess, capture_output=True, shell = True)
141
332
 
142
- matching_data = MatchingData(target=target, template=template)
143
- matching_data.rotations = np.eye(template.data.ndim).reshape(1, 3, 3)
333
+ orientations_new = Orientations.from_file(
334
+ f"{self.postprocess_args['--output_prefix']}.tsv"
335
+ )
336
+ orientations_new = orientations_new[np.argsort(orientations_new.translations[:, 0])]
144
337
 
145
- target_pad = matching_data.target_padding(pad_target=True)
146
- out_shape = np.add(target_pad, template.shape).astype(int)
338
+ label, dist = self.orientations.details, orientations_new.scores
339
+ loss = np.add(
340
+ (1 - label) * np.square(dist),
341
+ label * np.square(np.fmax(.5 - dist, 0.0))
342
+ )
343
+ return np.sum(loss)
147
344
 
148
- observations = np.zeros((len(observation_slices), *out_shape))
149
345
 
150
346
 
151
- for idx, obs_slice in enumerate(observation_slices):
152
- subset = matching_data.subset_by_slice(
153
- target_slice=obs_slice,
154
- target_pad=target_pad,
155
- invert_target=cli_args.invert_target_contrast,
347
+ def main():
348
+ args = parse_args()
349
+
350
+ if args.input_file is not None:
351
+ data = load_pickle(args.input_file)
352
+ target_origin, _, sampling_rate, cli_args = data[-1]
353
+ args.target, args.template = cli_args.target, cli_args.template
354
+
355
+ args.candidate_stack_path = generate_tempfile_name(suffix = ".h5")
356
+ args.new_orientations_path = generate_tempfile_name()
357
+ args.match_template_path = generate_tempfile_name()
358
+
359
+ match_deep = DeepMatcher(args)
360
+ initial_values = match_deep.get_initial_values()
361
+
362
+ # Do a single pass over the data
363
+ if len(initial_values) == 0:
364
+ create_image_stack = create_stacking_argdict(args)
365
+ create_image_stack = argdict_to_command(
366
+ create_image_stack,
367
+ executable="python3 /Users/vmaurer/src/pytme/scripts/extract_candidates.py"
156
368
  )
157
- xd = template.copy()
158
- xd.pad(subset.target.shape, center = True)
159
- # observations[idx] = subset.target
160
- observations[idx] = xd.data
161
-
162
-
163
- matching_data = MatchingData(target=observations, template=template)
164
- matching_data._set_batch_dimension(target_dims=0, template_dims=None)
165
- matching_data.rotations = get_rotation_matrices(15)
166
- if template_mask is not None:
167
- matching_data.template_mask = template_mask.data
168
-
169
- template_box = np.ones(len(matching_data._output_template_shape), dtype=int)
170
- target_padding = np.zeros_like(matching_data._output_target_shape)
171
-
172
- scoring_method = "FLC"
173
- callback_class = MaxScoreOverRotations
174
- splits, schedule = compute_parallelization_schedule(
175
- shape1=matching_data._output_target_shape,
176
- shape2=template_box,
177
- shape1_padding=target_padding,
178
- max_cores=args.cores,
179
- max_ram=backend.get_available_memory(),
180
- split_only_outer=False,
181
- matching_method=scoring_method,
182
- analyzer_method=callback_class.__name__,
183
- backend=backend._backend_name,
184
- float_nbytes=backend.datatype_bytes(backend._default_dtype),
185
- complex_nbytes=backend.datatype_bytes(backend._complex_dtype),
186
- integer_nbytes=backend.datatype_bytes(backend._default_dtype_int),
187
- )
188
-
189
- matching_setup, matching_score = MATCHING_EXHAUSTIVE_REGISTER[scoring_method]
190
-
191
- start = time()
192
- candidates = scan_subsets(
193
- matching_data=matching_data,
194
- matching_score=matching_score,
195
- matching_setup=matching_setup,
196
- callback_class=callback_class,
197
- callback_class_args={
198
- # "score_space_shape" : (
199
- # matching_data.rotations.shape[0], observations.shape[0]
200
- # ),
201
- # "score_space_dtype" : backend._default_dtype,
202
- # "template_shape" : (matching_data.rotations.shape[0], *matching_data._template.shape)
203
- },
204
- target_splits=splits,
205
- job_schedule=schedule,
206
- pad_target_edges=False,
207
- pad_fourier=False,
208
- interpolation_order=cli_args.interpolation_order,
209
- )
210
- print(candidates[0].max())
211
- Density(candidates[0][0]).to_file("scores.mrc")
212
-
213
- runtime = time() - start
214
- print(f"\nRuntime real: {runtime:.3f}s user: {(runtime * args.cores):.3f}s.")
369
+ _ = subprocess.run(create_image_stack, capture_output=True, shell = True)
370
+ if args.verbose:
371
+ copyfile(args.candidate_stack_path, f"{args.output_prefix}_stack.h5")
372
+ _ = match_deep(x = ())
373
+ if args.verbose:
374
+ copyfile(args.match_template_path, f"{args.output_prefix}_stack.pickle")
375
+ orientations = Orientations.from_file(f"{args.new_orientations_path}.tsv")
376
+ orientations = update_orientations(
377
+ new = orientations,
378
+ old = Orientations.from_file(args.orientations),
379
+ args= args
380
+ )
381
+ orientations.to_file(f"{args.output_prefix}.tsv")
382
+ exit(0)
383
+
384
+ for current_iteration in range(args.iterations):
385
+ create_image_stack = create_stacking_argdict(args)
386
+ create_image_stack = argdict_to_command(
387
+ create_image_stack,
388
+ executable="python3 /Users/vmaurer/src/pytme/scripts/extract_candidates.py"
389
+ )
390
+ _ = subprocess.run(create_image_stack, capture_output=True, shell = True)
391
+
392
+ # Perhaps we need a different optimizer here to use sensible steps for each parameter
393
+ match_deep = DeepMatcher(args)
394
+ parameters = optimize.minimize(
395
+ x0=match_deep.get_initial_values(),
396
+ fun=match_deep,
397
+ options = {"maxiter" : 2}
398
+ )
399
+ parameter_dict = match_deep.format_parameters(parameters)
215
400
 
401
+ match_template = create_matching_argdict(args)
402
+ match_template.update(parameter_dict)
403
+ match_template = argdict_to_command(
404
+ match_template,
405
+ executable="python3 /Users/vmaurer/src/pytme/scripts/match_template_filters.py"
406
+ )
407
+ _ = subprocess.run(match_template, capture_output=True, shell = True)
408
+
409
+ # Some form of labelling is necessary for these matches
410
+ # 1. All of them are true positives
411
+ # 2. All of them are true positives up to a certain threshold
412
+ # 3. Kernel fitting
413
+ # 4. Perhaps also sensible to include a certain percentage of low scores as true negatives
414
+ postprocess = create_postprocessing_argdict(args)
415
+ postprocess = argdict_to_command(postprocess, executable="postprocess.py")
416
+ _ = subprocess.run(postprocess, capture_output=True, shell = True)
417
+ args.orientations = f"{args.new_orientations_path}.tsv"
418
+ orientations = Orientations.from_file(args.orientations)
419
+ orientations.to_file(f"{args.output_prefix}_{current_iteration}.tsv")
216
420
 
217
421
  if __name__ == "__main__":
218
422
  main()
tme/__version__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.2.0"
1
+ __version__ = "0.2.1"