pycistem 0.6.1__cp310-cp310-manylinux_2_28_x86_64.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.
- pycistem/__init__.py +9 -0
- pycistem/config.py +20 -0
- pycistem/core/__init__.py +1 -0
- pycistem/core/core.cpp +1070 -0
- pycistem/core/core.cpython-310-x86_64-linux-gnu.so +0 -0
- pycistem/core/database.cpp +408 -0
- pycistem/core/euler_search.cpp +72 -0
- pycistem/core/run_profiles.cpp +114 -0
- pycistem/database/__init__.py +301 -0
- pycistem/programs/__init__.py +10 -0
- pycistem/programs/_cistem_constants.py +23 -0
- pycistem/programs/apply_ctf.py +59 -0
- pycistem/programs/cistem_program.py +277 -0
- pycistem/programs/ctffind.py +254 -0
- pycistem/programs/estimate_beamtilt.py +60 -0
- pycistem/programs/match_template.py +325 -0
- pycistem/programs/reconstruct3d.py +79 -0
- pycistem/programs/refine_ctf.py +106 -0
- pycistem/programs/refine_template.py +157 -0
- pycistem/programs/refine_template_dev.py +35 -0
- pycistem/programs/refine_template_niko.py +124 -0
- pycistem/programs/resample.py +30 -0
- pycistem/programs/run_profile.py +17 -0
- pycistem/programs/unblur.py +247 -0
- pycistem/programs/unblur_patch.py +204 -0
- pycistem/utils/__init__.py +1 -0
- pycistem/utils/extract_particles.py +36 -0
- pycistem/utils/move_class_into_unbinned_particle_stack.py +34 -0
- pycistem/utils/order_by_class_occupancy.py +26 -0
- pycistem/utils/plot_class_occupancy.py +51 -0
- pycistem/utils/plot_classification_fsc_movie.py +90 -0
- pycistem/utils/plot_occupancy_by_condition.py +129 -0
- pycistem-0.6.1.dist-info/METADATA +258 -0
- pycistem-0.6.1.dist-info/RECORD +84 -0
- pycistem-0.6.1.dist-info/WHEEL +5 -0
- pycistem-0.6.1.dist-info/licenses/LICENSE +201 -0
- pycistem-0.6.1.dist-info/sboms/auditwheel.cdx.json +1 -0
- pycistem.libs/libXau-154567c4.so.6.0.0 +0 -0
- pycistem.libs/libXcomposite-9a78b2b5.so.1.0.0 +0 -0
- pycistem.libs/libXcursor-557eab0f.so.1.0.2 +0 -0
- pycistem.libs/libXdamage-45f20f14.so.1.1.0 +0 -0
- pycistem.libs/libXfixes-e3b7d94c.so.3.1.0 +0 -0
- pycistem.libs/libXi-9178a6bd.so.6.1.0 +0 -0
- pycistem.libs/libXinerama-6a3f4a3e.so.1.0.0 +0 -0
- pycistem.libs/libXrandr-9f75043e.so.2.2.0 +0 -0
- pycistem.libs/libatk-1-3e086f29.0.so.0.22810.1 +0 -0
- pycistem.libs/libblkid-a9167753.so.1.1.0 +0 -0
- pycistem.libs/libbz2-a1e77c99.so.1.0.6 +0 -0
- pycistem.libs/libcairo-dfbea965.so.2.11512.0 +0 -0
- pycistem.libs/libdatrie-584ecbbd.so.1.3.2 +0 -0
- pycistem.libs/libffi-3a37023a.so.6.0.2 +0 -0
- pycistem.libs/libfontconfig-dcb2ce6c.so.1.12.0 +0 -0
- pycistem.libs/libfreetype-2f3b32b6.so.6.16.1 +0 -0
- pycistem.libs/libfribidi-a2ddad26.so.0.4.0 +0 -0
- pycistem.libs/libgdk-x11-2-ae2f4865.0.so.0.2400.32 +0 -0
- pycistem.libs/libgdk_pixbuf-2-e875edac.0.so.0.3612.0 +0 -0
- pycistem.libs/libgio-2-54f4f0a9.0.so.0.5600.4 +0 -0
- pycistem.libs/libgmodule-2-a8eef785.0.so.0.5600.4 +0 -0
- pycistem.libs/libgmp-d944b113.so.10.3.2 +0 -0
- pycistem.libs/libgnutls-e5fc1c5f.so.30.28.2 +0 -0
- pycistem.libs/libgomp-e985bcbb.so.1.0.0 +0 -0
- pycistem.libs/libgraphite2-a2b39163.so.3.0.1 +0 -0
- pycistem.libs/libgtk-x11-2-76f42ab1.0.so.0.2400.32 +0 -0
- pycistem.libs/libharfbuzz-26b3d829.so.0.10705.0 +0 -0
- pycistem.libs/libhogweed-cd4c53be.so.4.5 +0 -0
- pycistem.libs/libidn2-2f4a5893.so.0.3.6 +0 -0
- pycistem.libs/libmount-ec61bd71.so.1.1.0 +0 -0
- pycistem.libs/libnettle-37944285.so.6.5 +0 -0
- pycistem.libs/libp11-kit-ac9dcd7e.so.0.3.0 +0 -0
- pycistem.libs/libpango-1-e80d1584.0.so.0.4200.3 +0 -0
- pycistem.libs/libpangocairo-1-e0e0fbcf.0.so.0.4200.3 +0 -0
- pycistem.libs/libpangoft2-1-1fa1613e.0.so.0.4200.3 +0 -0
- pycistem.libs/libpcre-0dd207b5.so.1.2.10 +0 -0
- pycistem.libs/libpcre2-8-516f4c9d.so.0.7.1 +0 -0
- pycistem.libs/libpixman-1-06469c37.so.0.38.4 +0 -0
- pycistem.libs/libpng16-748299c7.so.16.34.0 +0 -0
- pycistem.libs/libselinux-d0805dcb.so.1 +0 -0
- pycistem.libs/libtasn1-564de53e.so.6.5.5 +0 -0
- pycistem.libs/libthai-cd935638.so.0.3.0 +0 -0
- pycistem.libs/libunistring-05abdd40.so.2.1.0 +0 -0
- pycistem.libs/libuuid-95b83d40.so.1.3.0 +0 -0
- pycistem.libs/libxcb-5ddf6756.so.1.1.0 +0 -0
- pycistem.libs/libxcb-render-161c0eb5.so.0.0.0 +0 -0
- pycistem.libs/libxcb-shm-0be6dfbf.so.0.0.0 +0 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import datetime
|
|
3
|
+
import sqlite3
|
|
4
|
+
import struct
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import List, Union
|
|
8
|
+
|
|
9
|
+
import mrcfile
|
|
10
|
+
import pandas as pd
|
|
11
|
+
|
|
12
|
+
from pycistem.database import datetime_to_msdos, get_image_info_from_db
|
|
13
|
+
from pycistem.programs import cistem_program
|
|
14
|
+
from pycistem.programs._cistem_constants import socket_send_next_job
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class CtffindParameters:
|
|
19
|
+
input_filename : str
|
|
20
|
+
input_is_a_movie: bool = True
|
|
21
|
+
number_of_frames_to_average : int = 3
|
|
22
|
+
output_diagnostic_filename : str = "diagnostic.mrc"
|
|
23
|
+
pixel_size_of_input_image : float = 1.0
|
|
24
|
+
acceleration_voltage : float = 300.0
|
|
25
|
+
spherical_aberration : float = 2.7
|
|
26
|
+
amplitude_contrast: float = 0.07
|
|
27
|
+
box_size: int = 512
|
|
28
|
+
minimum_resolution: float = 30.0
|
|
29
|
+
maximum_resolution: float = 5.0
|
|
30
|
+
minimum_defocus: float = 3000.0
|
|
31
|
+
maximum_defocus: float = 30000.0
|
|
32
|
+
defocus_search_step: float = 100.0
|
|
33
|
+
slower_search: bool = False
|
|
34
|
+
astigmatism_tolerance: float = -100.0
|
|
35
|
+
find_additional_phase_shift: bool = False
|
|
36
|
+
minimum_additional_phase_shift: float = 0.0
|
|
37
|
+
maximum_additional_phase_shift: float = 0.0
|
|
38
|
+
additional_phase_shift_search_step: float = 0.0
|
|
39
|
+
astigmatism_is_known: bool = False
|
|
40
|
+
known_astigmatism: float = 0.0
|
|
41
|
+
known_astigmatism_angle: float = 0.0
|
|
42
|
+
resample_if_pixel_too_small: bool = True
|
|
43
|
+
movie_is_gain_corrected: bool = False
|
|
44
|
+
gain_filename: str = "gain.mrc"
|
|
45
|
+
movie_is_dark_corrected: bool = True
|
|
46
|
+
dark_filename: str = "dark.mrc"
|
|
47
|
+
correct_movie_mag_distortion: bool = False
|
|
48
|
+
movie_mag_distortion_angle: float = 0.0
|
|
49
|
+
movie_mag_distortion_major_scale: float = 1.0
|
|
50
|
+
movie_mag_distortion_minor_scale: float = 1.0
|
|
51
|
+
defocus_is_known: bool = False
|
|
52
|
+
known_defocus_1: float = 0.0
|
|
53
|
+
known_defocus_2: float = 0.0
|
|
54
|
+
known_phase_shift: float = 0.0
|
|
55
|
+
determine_tilt: bool = False
|
|
56
|
+
desired_number_of_threads: int = 1
|
|
57
|
+
eer_frames_per_image: int = 0
|
|
58
|
+
eer_super_res_factor: int = 1
|
|
59
|
+
filter_lowres_signal: bool = True
|
|
60
|
+
fit_nodes: bool = False
|
|
61
|
+
fit_nodes_1D_brute_force: bool = True
|
|
62
|
+
fit_nodes_2D_refine: bool = True
|
|
63
|
+
fit_nodes_low_resolution_limit: float = 30.0
|
|
64
|
+
fit_nodes_high_resolution_limit: float = 4.0
|
|
65
|
+
target_pixel_size_after_resampling: float = 1.4
|
|
66
|
+
fit_nodes_use_rounded_square: bool = False
|
|
67
|
+
fit_nodes_downweight_nodes: bool = False
|
|
68
|
+
|
|
69
|
+
def parameters_from_database(database, decolace=False, **kwargs):
|
|
70
|
+
image_info = get_image_info_from_db(database,get_ctf=False)
|
|
71
|
+
ProjectDirectory = Path(database).parent
|
|
72
|
+
par = [CtffindParameters(
|
|
73
|
+
input_filename = image["movie_filename"],
|
|
74
|
+
pixel_size_of_input_image = image["movie_pixel_size"],
|
|
75
|
+
gain_filename=image["GAIN_FILENAME"],
|
|
76
|
+
output_diagnostic_filename=(ProjectDirectory / "Assets" / "CTF" / f"{Path(image['FILENAME']).stem}_{image['MOVIE_ASSET_ID']}_auto.mrc").as_posix(),
|
|
77
|
+
fit_nodes=decolace
|
|
78
|
+
) for i,image in image_info.iterrows()]
|
|
79
|
+
return((par, image_info))
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def write_results_to_database(database, parameters: list[CtffindParameters], results, image_info):
|
|
83
|
+
conn = sqlite3.connect(database, isolation_level=None)
|
|
84
|
+
cur = conn.cursor()
|
|
85
|
+
results = sorted(results, key=lambda x: x["parameter_index"])
|
|
86
|
+
ESTIMATED_CTF_PARAMETERS_LIST = []
|
|
87
|
+
|
|
88
|
+
max_ctf_estimation_id= cur.execute("SELECT MAX(CTF_ESTIMATION_ID) FROM ESTIMATED_CTF_PARAMETERS").fetchone()[0]
|
|
89
|
+
if max_ctf_estimation_id is None:
|
|
90
|
+
max_ctf_estimation_id = 0
|
|
91
|
+
ctf_estimation_job_id= cur.execute("SELECT MAX(CTF_ESTIMATION_JOB_ID) FROM ESTIMATED_CTF_PARAMETERS").fetchone()[0]
|
|
92
|
+
if ctf_estimation_job_id is None:
|
|
93
|
+
ctf_estimation_job_id = 1
|
|
94
|
+
else:
|
|
95
|
+
ctf_estimation_job_id += 1
|
|
96
|
+
|
|
97
|
+
for result in results:
|
|
98
|
+
|
|
99
|
+
ESTIMATED_CTF_PARAMETERS_LIST.append({
|
|
100
|
+
"CTF_ESTIMATION_ID": max_ctf_estimation_id + 1,
|
|
101
|
+
"CTF_ESTIMATION_JOB_ID": ctf_estimation_job_id,
|
|
102
|
+
"DATETIME_OF_RUN": datetime_to_msdos(datetime.datetime.now()),
|
|
103
|
+
"IMAGE_ASSET_ID": image_info.loc[result["parameter_index"]]["IMAGE_ASSET_ID"],
|
|
104
|
+
"ESTIMATED_ON_MOVIE_FRAMES": True,
|
|
105
|
+
"VOLTAGE": parameters[result["parameter_index"]].acceleration_voltage,
|
|
106
|
+
"SPHERICAL_ABERRATION": parameters[result["parameter_index"]].spherical_aberration,
|
|
107
|
+
"PIXEL_SIZE": parameters[result["parameter_index"]].pixel_size_of_input_image,
|
|
108
|
+
"AMPLITUDE_CONTRAST": parameters[result["parameter_index"]].amplitude_contrast,
|
|
109
|
+
"BOX_SIZE": parameters[result["parameter_index"]].box_size,
|
|
110
|
+
"MIN_RESOLUTION": parameters[result["parameter_index"]].minimum_resolution,
|
|
111
|
+
"MAX_RESOLUTION": parameters[result["parameter_index"]].maximum_resolution,
|
|
112
|
+
"MIN_DEFOCUS": parameters[result["parameter_index"]].minimum_defocus,
|
|
113
|
+
"MAX_DEFOCUS": parameters[result["parameter_index"]].maximum_defocus,
|
|
114
|
+
"DEFOCUS_STEP": parameters[result["parameter_index"]].defocus_search_step,
|
|
115
|
+
"RESTRAIN_ASTIGMATISM": parameters[result["parameter_index"]].astigmatism_tolerance > 0,
|
|
116
|
+
"TOLERATED_ASTIGMATISM": parameters[result["parameter_index"]].astigmatism_tolerance,
|
|
117
|
+
"FIND_ADDITIONAL_PHASE_SHIFT": parameters[result["parameter_index"]].find_additional_phase_shift,
|
|
118
|
+
"MIN_PHASE_SHIFT": parameters[result["parameter_index"]].minimum_additional_phase_shift,
|
|
119
|
+
"MAX_PHASE_SHIFT": parameters[result["parameter_index"]].maximum_additional_phase_shift,
|
|
120
|
+
"PHASE_SHIFT_STEP": parameters[result["parameter_index"]].additional_phase_shift_search_step,
|
|
121
|
+
"DEFOCUS1": result["defocus1"],
|
|
122
|
+
"DEFOCUS2": result["defocus2"],
|
|
123
|
+
"DEFOCUS_ANGLE": result["astigmatism_angle"],
|
|
124
|
+
"ADDITIONAL_PHASE_SHIFT": result["phase_shift"],
|
|
125
|
+
"SCORE": result["score"],
|
|
126
|
+
"DETECTED_RING_RESOLUTION": result["fit_resolution"],
|
|
127
|
+
"DETECTED_ALIAS_RESOLUTION": result["aliasing_resolution"],
|
|
128
|
+
"OUTPUT_DIAGNOSTIC_FILE": parameters[result["parameter_index"]].output_diagnostic_filename,
|
|
129
|
+
"NUMBER_OF_FRAMES_AVERAGED": parameters[result["parameter_index"]].number_of_frames_to_average,
|
|
130
|
+
"LARGE_ASTIGMATISM_EXPECTED": parameters[result["parameter_index"]].slower_search,
|
|
131
|
+
"ICINESS": result["iciness"],
|
|
132
|
+
"TILT_ANGLE": result["tilt_angle"],
|
|
133
|
+
"TILT_AXIS": result["tilt_axis"],
|
|
134
|
+
"SAMPLE_THICKNESS": result["sample_thickness"],
|
|
135
|
+
"SAMPLE_THICKNESS_JSON": "",
|
|
136
|
+
"DETERMINE_TILT": parameters[result["parameter_index"]].determine_tilt,
|
|
137
|
+
"FIT_NODES": parameters[result["parameter_index"]].fit_nodes,
|
|
138
|
+
"FIT_NODES_1D": parameters[result["parameter_index"]].fit_nodes_1D_brute_force,
|
|
139
|
+
"FIT_NODES_2D": parameters[result["parameter_index"]].fit_nodes_2D_refine,
|
|
140
|
+
"FIT_NODES_LOW_LIMIT": parameters[result["parameter_index"]].fit_nodes_low_resolution_limit,
|
|
141
|
+
"FIT_NODES_HIGH_LIMIT": parameters[result["parameter_index"]].fit_nodes_high_resolution_limit,
|
|
142
|
+
"FIT_NODES_ROUNDED_SQUARE": parameters[result["parameter_index"]].fit_nodes_use_rounded_square,
|
|
143
|
+
"FIT_NODES_DOWNWEIGHT_NODES": parameters[result["parameter_index"]].fit_nodes_downweight_nodes,
|
|
144
|
+
"RESAMPLE_IF_NESCESSARY": parameters[result["parameter_index"]].resample_if_pixel_too_small,
|
|
145
|
+
"TARGET_PIXEL_SIZE": parameters[result["parameter_index"]].target_pixel_size_after_resampling
|
|
146
|
+
})
|
|
147
|
+
#print("UPDATE IMAGE_ASSETS SET CTF_ESTIMATION_ID = ? WHERE IMAGE_ASSET_ID = ?", (max_ctf_estimation_id + 1, image_info.loc[result["parameter_index"]]["IMAGE_ASSET_ID"]))
|
|
148
|
+
#cur.execute("UPDATE IMAGE_ASSETS SET CTF_ESTIMATION_ID = ? WHERE IMAGE_ASSET_ID = ?", (max_ctf_estimation_id + 1, image_info.loc[result["parameter_index"]]["IMAGE_ASSET_ID"]))
|
|
149
|
+
max_ctf_estimation_id += 1
|
|
150
|
+
|
|
151
|
+
ESTIMATED_CTF_PARAMETERS_LIST = pd.DataFrame(ESTIMATED_CTF_PARAMETERS_LIST)
|
|
152
|
+
ESTIMATED_CTF_PARAMETERS_LIST.to_sql("ESTIMATED_CTF_PARAMETERS", conn, if_exists="append", index=False)
|
|
153
|
+
|
|
154
|
+
cur = conn.cursor()
|
|
155
|
+
cur.executemany("UPDATE IMAGE_ASSETS SET CTF_ESTIMATION_ID = ? WHERE IMAGE_ASSET_ID = ?",[
|
|
156
|
+
(row["CTF_ESTIMATION_ID"], row["IMAGE_ASSET_ID"])
|
|
157
|
+
for i, row in ESTIMATED_CTF_PARAMETERS_LIST.iterrows()
|
|
158
|
+
])
|
|
159
|
+
conn.commit()
|
|
160
|
+
# Update CTF_ESTIMATION_ID in IMAGE_ASSETS table
|
|
161
|
+
|
|
162
|
+
conn.close()
|
|
163
|
+
|
|
164
|
+
async def handle_results(reader, writer, logger):
|
|
165
|
+
#logger.info("Handling results")
|
|
166
|
+
await reader.read(4)
|
|
167
|
+
length = await reader.readexactly(4)
|
|
168
|
+
print(f"CTFFIND results length {length}")
|
|
169
|
+
number_of_bytes = int.from_bytes(length, byteorder="little")
|
|
170
|
+
results = await reader.readexactly(number_of_bytes*4)
|
|
171
|
+
print(f"CTFFIND results {results}")
|
|
172
|
+
return(results)
|
|
173
|
+
|
|
174
|
+
signal_handlers = {
|
|
175
|
+
socket_send_next_job : handle_results
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
def run(parameters: Union[CtffindParameters,list[CtffindParameters]],**kwargs):
|
|
179
|
+
|
|
180
|
+
if not isinstance(parameters, list):
|
|
181
|
+
parameters = [parameters]
|
|
182
|
+
|
|
183
|
+
byte_results = asyncio.run(cistem_program.run("ctffind", parameters, signal_handlers=signal_handlers,**kwargs))
|
|
184
|
+
result_ctf = []
|
|
185
|
+
|
|
186
|
+
for parameter_index,byte_result in byte_results:
|
|
187
|
+
defocus1 = struct.unpack("<f",byte_result[0:4])[0]
|
|
188
|
+
defocus2 = struct.unpack("<f",byte_result[4:8])[0]
|
|
189
|
+
astigmatism_angle = struct.unpack("<f",byte_result[8:12])[0]
|
|
190
|
+
phase_shift = struct.unpack("<f",byte_result[12:16])[0]
|
|
191
|
+
score = struct.unpack("<f",byte_result[16:20])[0]
|
|
192
|
+
fit_resolution = struct.unpack("<f",byte_result[20:24])[0]
|
|
193
|
+
aliasing_resolution = struct.unpack("<f",byte_result[24:28])[0]
|
|
194
|
+
iciness = struct.unpack("<f",byte_result[28:32])[0]
|
|
195
|
+
tilt_angle = struct.unpack("<f",byte_result[32:36])[0]
|
|
196
|
+
tilt_axis = struct.unpack("<f",byte_result[36:40])[0]
|
|
197
|
+
sample_thickness = struct.unpack("<f",byte_result[40:44])[0]
|
|
198
|
+
|
|
199
|
+
result_ctf.append({
|
|
200
|
+
"parameter_index" : parameter_index,
|
|
201
|
+
"defocus1" : defocus1,
|
|
202
|
+
"defocus2" : defocus2,
|
|
203
|
+
"astigmatism_angle" : astigmatism_angle,
|
|
204
|
+
"phase_shift" : phase_shift,
|
|
205
|
+
"score" : score,
|
|
206
|
+
"fit_resolution" : fit_resolution,
|
|
207
|
+
"aliasing_resolution" : aliasing_resolution,
|
|
208
|
+
"iciness" : iciness,
|
|
209
|
+
"tilt_angle" : tilt_angle,
|
|
210
|
+
"tilt_axis" : tilt_axis,
|
|
211
|
+
"sample_thickness" : sample_thickness
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
return(result_ctf)
|
|
216
|
+
|
|
217
|
+
async def run_async(parameters: Union[CtffindParameters,list[CtffindParameters]],**kwargs):
|
|
218
|
+
|
|
219
|
+
if not isinstance(parameters, list):
|
|
220
|
+
parameters = [parameters]
|
|
221
|
+
|
|
222
|
+
byte_results = await cistem_program.run("ctffind", parameters, signal_handlers=signal_handlers,**kwargs)
|
|
223
|
+
result_ctf = []
|
|
224
|
+
|
|
225
|
+
for parameter_index,byte_result in byte_results:
|
|
226
|
+
defocus1 = struct.unpack("<f",byte_result[0:4])[0]
|
|
227
|
+
defocus2 = struct.unpack("<f",byte_result[4:8])[0]
|
|
228
|
+
astigmatism_angle = struct.unpack("<f",byte_result[8:12])[0]
|
|
229
|
+
phase_shift = struct.unpack("<f",byte_result[12:16])[0]
|
|
230
|
+
score = struct.unpack("<f",byte_result[16:20])[0]
|
|
231
|
+
fit_resolution = struct.unpack("<f",byte_result[20:24])[0]
|
|
232
|
+
aliasing_resolution = struct.unpack("<f",byte_result[24:28])[0]
|
|
233
|
+
iciness = struct.unpack("<f",byte_result[28:32])[0]
|
|
234
|
+
tilt_angle = struct.unpack("<f",byte_result[32:36])[0]
|
|
235
|
+
tilt_axis = struct.unpack("<f",byte_result[36:40])[0]
|
|
236
|
+
sample_thickness = struct.unpack("<f",byte_result[40:44])[0]
|
|
237
|
+
|
|
238
|
+
result_ctf.append({
|
|
239
|
+
"parameter_index" : parameter_index,
|
|
240
|
+
"defocus1" : defocus1,
|
|
241
|
+
"defocus2" : defocus2,
|
|
242
|
+
"astigmatism_angle" : astigmatism_angle,
|
|
243
|
+
"phase_shift" : phase_shift,
|
|
244
|
+
"score" : score,
|
|
245
|
+
"fit_resolution" : fit_resolution,
|
|
246
|
+
"aliasing_resolution" : aliasing_resolution,
|
|
247
|
+
"iciness" : iciness,
|
|
248
|
+
"tilt_angle" : tilt_angle,
|
|
249
|
+
"tilt_axis" : tilt_axis,
|
|
250
|
+
"sample_thickness" : sample_thickness
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
return(result_ctf)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import Union
|
|
4
|
+
import numpy as np
|
|
5
|
+
import struct
|
|
6
|
+
import mrcfile
|
|
7
|
+
from functools import partial
|
|
8
|
+
import pandas as pd
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
from pycistem.programs import cistem_program
|
|
12
|
+
from pycistem.programs._cistem_constants import socket_send_next_job, socket_job_result_queue
|
|
13
|
+
#from pycistem.core import Image
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class EstimateBeamtiltParameters:
|
|
17
|
+
input_phase_difference_image: str
|
|
18
|
+
pixel_size: float = 1.0
|
|
19
|
+
voltage_kV: float = 300.0
|
|
20
|
+
spherical_aberration_mm: float = 2.7
|
|
21
|
+
first_position_to_search: int = 0
|
|
22
|
+
last_position_to_search: int = 0
|
|
23
|
+
|
|
24
|
+
async def handle_results(reader, writer, logger):
|
|
25
|
+
#logger.info("Handling results")
|
|
26
|
+
await reader.read(4)
|
|
27
|
+
length = await reader.read(4)
|
|
28
|
+
number_of_bytes = int.from_bytes(length, byteorder="little")
|
|
29
|
+
results = await reader.read(number_of_bytes*4)
|
|
30
|
+
score = struct.unpack("<f",results[0:4])[0]
|
|
31
|
+
beam_tilt_x = struct.unpack("<f",results[4:8])[0]
|
|
32
|
+
beam_tilt_y = struct.unpack("<f",results[8:12])[0]
|
|
33
|
+
particle_shift_x = struct.unpack("<f",results[12:16])[0]
|
|
34
|
+
particle_shift_y = struct.unpack("<f",results[16:20])[0]
|
|
35
|
+
return(score,beam_tilt_x,beam_tilt_y,particle_shift_x,particle_shift_y)
|
|
36
|
+
|
|
37
|
+
async def handle_job_result_queue(reader, writer, logger):
|
|
38
|
+
|
|
39
|
+
length = await reader.readexactly(4)
|
|
40
|
+
number_of_bytes = int.from_bytes(length, byteorder="little")
|
|
41
|
+
results = await reader.readexactly(number_of_bytes)
|
|
42
|
+
return(results)
|
|
43
|
+
|
|
44
|
+
def run(parameters: Union[EstimateBeamtiltParameters,list[EstimateBeamtiltParameters]],**kwargs) -> pd.DataFrame:
|
|
45
|
+
|
|
46
|
+
if not isinstance(parameters, list):
|
|
47
|
+
parameters = [parameters]
|
|
48
|
+
signal_handlers = {
|
|
49
|
+
socket_send_next_job : handle_results,
|
|
50
|
+
socket_job_result_queue : handle_job_result_queue,
|
|
51
|
+
|
|
52
|
+
}
|
|
53
|
+
result = asyncio.run(cistem_program.run("estimate_beamtilt", parameters, signal_handlers=signal_handlers,**kwargs))
|
|
54
|
+
result = pd.DataFrame([a[1] for a in result],
|
|
55
|
+
index = [a[0] for a in result],
|
|
56
|
+
columns=["score","beam_tilt_x","beam_tilt_y","particle_shift_x","particle_shift_y"])
|
|
57
|
+
return(result)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import sqlite3
|
|
3
|
+
import struct
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from functools import partial
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import List, Tuple, Union, Optional
|
|
8
|
+
|
|
9
|
+
import mrcfile
|
|
10
|
+
import numpy as np
|
|
11
|
+
import pandas as pd
|
|
12
|
+
from skimage.feature import peak_local_max
|
|
13
|
+
import datetime
|
|
14
|
+
|
|
15
|
+
from pycistem.core import EulerSearch, ParameterMap
|
|
16
|
+
from pycistem.database import datetime_to_msdos, ensure_template_is_a_volume_asset, get_image_info_from_db, create_peak_lists, get_max_match_template_job_id
|
|
17
|
+
from pycistem.programs import cistem_program
|
|
18
|
+
from pycistem.programs._cistem_constants import socket_job_result_queue, socket_program_defined_result, socket_i_have_info
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class MatchTemplateParameters:
|
|
23
|
+
input_search_images_filename: str #0
|
|
24
|
+
input_reconstruction_filename: str #1
|
|
25
|
+
pixel_size: float = 1.0 #2
|
|
26
|
+
voltage_kV: float = 300.0 #3
|
|
27
|
+
spherical_aberration_mm: float = 2.7
|
|
28
|
+
amplitude_contrast: float = 0.07
|
|
29
|
+
defocus1: float = 10000.0
|
|
30
|
+
defocus2: float = 10000.0
|
|
31
|
+
defocus_angle: float = 0.0
|
|
32
|
+
low_resolution_limit: float = 30.0
|
|
33
|
+
high_resolution_limit_search: float = 3.0
|
|
34
|
+
angular_step: float = 3.0 #10
|
|
35
|
+
best_parameters_to_keep: int = 1
|
|
36
|
+
defocus_search_range: float = 1000.0
|
|
37
|
+
defocus_step: float = 200.0
|
|
38
|
+
pixel_size_search_range: float = 0.0
|
|
39
|
+
pixel_size_step: float = 0.0
|
|
40
|
+
padding: float = 1.0
|
|
41
|
+
ctf_refinement: bool = False
|
|
42
|
+
particle_radius_angstroms: float = 0.0
|
|
43
|
+
phase_shift: float = 0.0
|
|
44
|
+
mip_output_file: str = "/dev/null"
|
|
45
|
+
best_psi_output_file: str = "best_psi.mrc"
|
|
46
|
+
best_theta_output_file: str = "best_theta.mrc"
|
|
47
|
+
best_phi_output_file: str = "best_phi.mrc"
|
|
48
|
+
best_defocus_output_file: str = "best_defocus.mrc"
|
|
49
|
+
best_pixel_size_output_file: str = "best_pixel_size.mrc"
|
|
50
|
+
scaled_mip_output_file: str = "scaled_mip.mrc"
|
|
51
|
+
correlation_avg_output_file : str = "correlation_avg.mrc"
|
|
52
|
+
my_symmetry: str = "C1"
|
|
53
|
+
in_plane_angular_step: float = 2.0
|
|
54
|
+
output_histogram_file: str = "histogram.txt"
|
|
55
|
+
first_search_position: int = 0
|
|
56
|
+
last_search_position: int = 100
|
|
57
|
+
image_number_for_gui: int = 0
|
|
58
|
+
number_of_jobs_per_image_in_gui: int = 1
|
|
59
|
+
correlation_std_output_file: str = "correlation_std.mrc"
|
|
60
|
+
directory_for_results: str = "/dev/null"
|
|
61
|
+
result_output_filename: str = "/dev/null"
|
|
62
|
+
min_peak_radius: float = 10.0
|
|
63
|
+
use_gpu: bool = True
|
|
64
|
+
max_threads: int = 4
|
|
65
|
+
|
|
66
|
+
# TODO
|
|
67
|
+
# 1. Write correct threshold into db
|
|
68
|
+
# 2. Get correct border_exclude value
|
|
69
|
+
# 3. Maybe do projection?
|
|
70
|
+
async def handle_socket_i_have_info(reader, writer, logger):
|
|
71
|
+
data = await reader.readexactly(4)
|
|
72
|
+
length = int.from_bytes(data, byteorder="little")
|
|
73
|
+
data = await reader.readexactly(length)
|
|
74
|
+
print(f"Info: {data.decode('utf-8')}")
|
|
75
|
+
|
|
76
|
+
def get_np_arrays(bytes,o,i,x,y,numpix):
|
|
77
|
+
array = np.frombuffer(bytes,offset=o+i*numpix*4, count=numpix,dtype=np.float32).copy()
|
|
78
|
+
array = array.reshape((y,-1))
|
|
79
|
+
array = array[:,:x]
|
|
80
|
+
return array
|
|
81
|
+
|
|
82
|
+
def parameters_from_database(database, template_filename: str, match_template_job_id: Optional[int] = None,**kwargs) :
|
|
83
|
+
image_info = get_image_info_from_db(database,get_ctf=True)
|
|
84
|
+
if image_info is None:
|
|
85
|
+
return []
|
|
86
|
+
if match_template_job_id is None:
|
|
87
|
+
match_template_job_id = get_max_match_template_job_id(database) + 1
|
|
88
|
+
ProjectDirectory = Path(database).parent
|
|
89
|
+
par = [MatchTemplateParameters(
|
|
90
|
+
input_search_images_filename = image["FILENAME"],
|
|
91
|
+
input_reconstruction_filename = template_filename,
|
|
92
|
+
pixel_size = image["image_pixel_size"],
|
|
93
|
+
defocus1=image["DEFOCUS1"],
|
|
94
|
+
defocus2=image["DEFOCUS2"],
|
|
95
|
+
defocus_angle=image["DEFOCUS_ANGLE"],
|
|
96
|
+
scaled_mip_output_file=(ProjectDirectory / "Assets" / "TemplateMatching" / f"{Path(image['FILENAME']).stem}_auto_{match_template_job_id}_scaled_mip.mrc").as_posix(),
|
|
97
|
+
output_histogram_file=(ProjectDirectory / "Assets" / "TemplateMatching" / f"{Path(image['FILENAME']).stem}_auto_{match_template_job_id}_histogram.txt").as_posix(),
|
|
98
|
+
) for i,image in image_info.iterrows()]
|
|
99
|
+
image_info["MATCH_TEMPLATE_JOB_ID"] = match_template_job_id
|
|
100
|
+
image_info["PARAMETERS"] = par
|
|
101
|
+
image_info["DATABASE"] = database
|
|
102
|
+
image_info["THRESHOLD"] = 0.0
|
|
103
|
+
return(image_info)
|
|
104
|
+
|
|
105
|
+
def write_results_to_database(database, parameters: list[MatchTemplateParameters], results: list[tuple[int, pd.DataFrame]], image_info):
|
|
106
|
+
# Ensure Volume assets
|
|
107
|
+
template_vol_ids = {}
|
|
108
|
+
for par in parameters:
|
|
109
|
+
template_vol_ids[par.input_reconstruction_filename] = -1
|
|
110
|
+
for template in template_vol_ids.keys():
|
|
111
|
+
template_vol_ids[template] = ensure_template_is_a_volume_asset(database, template, parameters[0].pixel_size)
|
|
112
|
+
|
|
113
|
+
conn = sqlite3.connect(database, isolation_level=None)
|
|
114
|
+
cur = conn.cursor()
|
|
115
|
+
results = sorted(results, key=lambda x: x[0])
|
|
116
|
+
# Add results to TEMPLATE_MATCH_LIST
|
|
117
|
+
template_match_result_list = []
|
|
118
|
+
|
|
119
|
+
max_template_match_id = cur.execute("SELECT MAX(TEMPLATE_MATCH_ID) FROM TEMPLATE_MATCH_LIST").fetchone()[0]
|
|
120
|
+
if max_template_match_id is None:
|
|
121
|
+
max_template_match_id = 0
|
|
122
|
+
template_match_id = max_template_match_id + 1
|
|
123
|
+
#template_match_job_id = cur.execute("SELECT MAX(TEMPLATE_MATCH_JOB_ID) FROM TEMPLATE_MATCH_LIST").fetchone()[0]
|
|
124
|
+
#if template_match_job_id is None:
|
|
125
|
+
# template_match_job_id = 1
|
|
126
|
+
#else:
|
|
127
|
+
# template_match_job_id += 1
|
|
128
|
+
|
|
129
|
+
for result in results:
|
|
130
|
+
template_match_job_id = image_info.iloc[result[0]]["MATCH_TEMPLATE_JOB_ID"]
|
|
131
|
+
# CHeck if THRESHOLD column exists in image_info
|
|
132
|
+
if "THRESHOLD" in image_info.columns:
|
|
133
|
+
threshold = image_info.iloc[result[0]]["THRESHOLD"]
|
|
134
|
+
else:
|
|
135
|
+
threshold = 7.0
|
|
136
|
+
template_match_result_list.append({
|
|
137
|
+
"TEMPLATE_MATCH_ID": template_match_id,
|
|
138
|
+
"JOB_NAME": f"auto_{template_match_job_id}_{Path(parameters[result[0]].input_reconstruction_filename).stem}",
|
|
139
|
+
"DATETIME_OF_RUN": datetime_to_msdos(datetime.datetime.now()),
|
|
140
|
+
"TEMPLATE_MATCH_JOB_ID": template_match_job_id,
|
|
141
|
+
"JOB_TYPE_CODE": 0,
|
|
142
|
+
"INPUT_TEMPLATE_MATCH_ID": 0,
|
|
143
|
+
"IMAGE_ASSET_ID": image_info.iloc[result[0]]["IMAGE_ASSET_ID"],
|
|
144
|
+
"REFERENCE_VOLUME_ASSET_ID": template_vol_ids[parameters[result[0]].input_reconstruction_filename],
|
|
145
|
+
"IS_ACTIVE": 1,
|
|
146
|
+
"USED_SYMMETRY": parameters[result[0]].my_symmetry,
|
|
147
|
+
"USED_PIXEL_SIZE": parameters[result[0]].pixel_size,
|
|
148
|
+
"USED_VOLTAGE": parameters[result[0]].voltage_kV,
|
|
149
|
+
"USED_SPHERICAL_ABERRATION": parameters[result[0]].spherical_aberration_mm,
|
|
150
|
+
"USED_AMPLITUDE_CONTRAST": parameters[result[0]].amplitude_contrast,
|
|
151
|
+
"USED_DEFOCUS1": parameters[result[0]].defocus1,
|
|
152
|
+
"USED_DEFOCUS2": parameters[result[0]].defocus2,
|
|
153
|
+
"USED_DEFOCUS_ANGLE": parameters[result[0]].defocus_angle,
|
|
154
|
+
"USED_PHASE_SHIFT": parameters[result[0]].phase_shift,
|
|
155
|
+
"LOW_RESOLUTION_LIMIT": parameters[result[0]].low_resolution_limit,
|
|
156
|
+
"HIGH_RESOLUTION_LIMIT": parameters[result[0]].high_resolution_limit_search,
|
|
157
|
+
"OUT_OF_PLANE_ANGULAR_STEP": parameters[result[0]].angular_step,
|
|
158
|
+
"IN_PLANE_ANGULAR_STEP": parameters[result[0]].in_plane_angular_step,
|
|
159
|
+
"DEFOCUS_SEARCH_RANGE": parameters[result[0]].defocus_search_range,
|
|
160
|
+
"DEFOCUS_STEP": parameters[result[0]].defocus_step,
|
|
161
|
+
"PIXEL_SIZE_SEARCH_RANGE": parameters[result[0]].pixel_size_search_range,
|
|
162
|
+
"PIXEL_SIZE_STEP": parameters[result[0]].pixel_size_step,
|
|
163
|
+
"REFINEMENT_THRESHOLD": 0.0,
|
|
164
|
+
"USED_THRESHOLD": threshold,
|
|
165
|
+
"REF_BOX_SIZE_IN_ANGSTROMS": 0,
|
|
166
|
+
"MASK_RADIUS": 0.0,
|
|
167
|
+
"MIN_PEAK_RADIUS": parameters[result[0]].min_peak_radius,
|
|
168
|
+
"XY_CHANGE_THRESHOLD": 0.0,
|
|
169
|
+
"EXCLUDE_ABOVE_XY_THRESHOLD": False,
|
|
170
|
+
"MIP_OUTPUT_FILE": "/dev/null",
|
|
171
|
+
"SCALED_MIP_OUTPUT_FILE": parameters[result[0]].scaled_mip_output_file,
|
|
172
|
+
"AVG_OUTPUT_FILE": "/dev/null",
|
|
173
|
+
"STD_OUTPUT_FILE": "/dev/null",
|
|
174
|
+
"PSI_OUTPUT_FILE": "/dev/null",
|
|
175
|
+
"THETA_OUTPUT_FILE": "/dev/null",
|
|
176
|
+
"PHI_OUTPUT_FILE": "/dev/null",
|
|
177
|
+
"DEFOCUS_OUTPUT_FILE": "/dev/null",
|
|
178
|
+
"PIXEL_SIZE_OUTPUT_FILE": "/dev/null",
|
|
179
|
+
"HISTOGRAM_OUTPUT_FILE": parameters[result[0]].output_histogram_file,
|
|
180
|
+
"PROJECTION_RESULT_OUTPUT_FILE": parameters[result[0]].scaled_mip_output_file,
|
|
181
|
+
})
|
|
182
|
+
create_peak_lists(conn, template_match_id)
|
|
183
|
+
result[1].to_sql(f"TEMPLATE_MATCH_PEAK_LIST_{template_match_id}", conn, if_exists="append", index=False)
|
|
184
|
+
conn.commit()
|
|
185
|
+
result[1]['ORIGINAL_PEAK_NUMBER'] = 0
|
|
186
|
+
result[1]['NEW_PEAK_NUMBER'] = 0
|
|
187
|
+
print(result[1])
|
|
188
|
+
result[1].to_sql(f"TEMPLATE_MATCH_PEAK_CHANGE_LIST_{template_match_id}", conn, if_exists="append", index=False)
|
|
189
|
+
template_match_id += 1
|
|
190
|
+
template_match_result_list = pd.DataFrame(template_match_result_list)
|
|
191
|
+
template_match_result_list.to_sql("TEMPLATE_MATCH_LIST", conn, if_exists="append", index=False)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
conn.close()
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
async def handle_results(reader, writer, logger, parameters, write_directly_to_db, image_info):
|
|
198
|
+
logger.debug("Handling results")
|
|
199
|
+
size_of_array= await reader.readexactly(4)
|
|
200
|
+
result_number= await reader.readexactly(4)
|
|
201
|
+
number_of_expected_results= await reader.readexactly(4)
|
|
202
|
+
number_of_floats = int.from_bytes(size_of_array, byteorder="little")
|
|
203
|
+
result_number = int.from_bytes(result_number, byteorder="little")
|
|
204
|
+
number_of_expected_results = int.from_bytes(number_of_expected_results, byteorder="little")
|
|
205
|
+
results = await reader.readexactly(number_of_floats*4)
|
|
206
|
+
x_dim = int(struct.unpack("<f",results[0:4])[0])
|
|
207
|
+
y_dim = int(struct.unpack("<f",results[4:8])[0])
|
|
208
|
+
num_pixels = int(struct.unpack("<f",results[8:12])[0])
|
|
209
|
+
num_histogram_points = int(struct.unpack("<f",results[16:20])[0])
|
|
210
|
+
print(f"Got number of histogram points: {num_histogram_points}, but replacing with hardcoded 512")
|
|
211
|
+
num_histogram_points = 512
|
|
212
|
+
num_ccs = struct.unpack("<f",results[12:16])[0]
|
|
213
|
+
struct.unpack("<f",results[20:24])[0]
|
|
214
|
+
struct.unpack("<f",results[24:28])[0]
|
|
215
|
+
print(f"Result number: {result_number} Number of expected results: {number_of_expected_results} Number of pixels: {num_pixels} X dim: {x_dim} Y dim: {y_dim} Num histogram points: {num_histogram_points} Num ccs: {num_ccs} Num float {number_of_floats}")
|
|
216
|
+
mip = get_np_arrays(results,28,0,x_dim,y_dim,num_pixels)
|
|
217
|
+
psi = get_np_arrays(results,28,1,x_dim,y_dim,num_pixels)
|
|
218
|
+
theta = get_np_arrays(results,28,2,x_dim,y_dim,num_pixels)
|
|
219
|
+
phi = get_np_arrays(results,28,3,x_dim,y_dim,num_pixels)
|
|
220
|
+
defocus = get_np_arrays(results,28,4,x_dim,y_dim,num_pixels)
|
|
221
|
+
get_np_arrays(results,28,5,x_dim,y_dim,num_pixels)
|
|
222
|
+
sum = get_np_arrays(results,28,6,x_dim,y_dim,num_pixels)
|
|
223
|
+
|
|
224
|
+
sum = sum / num_ccs
|
|
225
|
+
sum_squares = get_np_arrays(results,28,7,x_dim,y_dim,num_pixels)
|
|
226
|
+
sum_squares = np.sqrt(sum_squares/num_ccs - sum**2)
|
|
227
|
+
scaled_mip = np.divide(mip - sum, sum_squares, out=np.zeros_like(mip), where=sum_squares!=0)
|
|
228
|
+
par = parameters[result_number]
|
|
229
|
+
histogram = np.frombuffer(results,offset=28+8*num_pixels*4, count=num_histogram_points,dtype=np.int64).copy()
|
|
230
|
+
survival_histogram = np.zeros(num_histogram_points, dtype=np.float32)
|
|
231
|
+
survival_histogram[-1] = histogram[-1]
|
|
232
|
+
for line_counter in range(num_histogram_points - 2, -1, -1):
|
|
233
|
+
survival_histogram[line_counter] = survival_histogram[line_counter + 1] + histogram[line_counter]
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
# Calculate expected threshold
|
|
237
|
+
from scipy.special import erfcinv,erfc
|
|
238
|
+
expected_threshold = np.sqrt(2.0) * erfcinv(2.0/(x_dim*y_dim*num_ccs)) * 1
|
|
239
|
+
|
|
240
|
+
histogram_min = -12.5
|
|
241
|
+
histogram_max = 22.5
|
|
242
|
+
histogram_step = (histogram_max - histogram_min) / num_histogram_points
|
|
243
|
+
temp_float = histogram_min + (histogram_step / 2.0)
|
|
244
|
+
|
|
245
|
+
expected_survival_histogram = np.zeros(num_histogram_points, dtype=np.float32)
|
|
246
|
+
for line_counter in range(num_histogram_points):
|
|
247
|
+
expected_survival_histogram[line_counter] = (erfc((temp_float + histogram_step * float(line_counter)) / np.sqrt(2.0)) / 2.0) * (x_dim*y_dim*num_ccs)
|
|
248
|
+
|
|
249
|
+
survival_histogram_float = survival_histogram * (expected_survival_histogram.sum() / survival_histogram.sum())
|
|
250
|
+
with open(par.output_histogram_file, 'w') as f:
|
|
251
|
+
f.write(f"# Expected threshold = {expected_threshold:.2f}\n")
|
|
252
|
+
f.write("# histogram, expected histogram, survival histogram, expected survival histogram\n")
|
|
253
|
+
for line_counter in range(num_histogram_points):
|
|
254
|
+
temp_double_array = [
|
|
255
|
+
temp_float + histogram_step * float(line_counter),
|
|
256
|
+
histogram[line_counter],
|
|
257
|
+
survival_histogram[line_counter],
|
|
258
|
+
expected_survival_histogram[line_counter]
|
|
259
|
+
]
|
|
260
|
+
f.write(" ".join(str(x) for x in temp_double_array) + "\n")
|
|
261
|
+
mrcfile.write(par.scaled_mip_output_file, scaled_mip.astype(np.float32), overwrite=True)
|
|
262
|
+
if par.mip_output_file != "/dev/null":
|
|
263
|
+
mrcfile.write(par.mip_output_file, mip.astype(np.float32), overwrite=True)
|
|
264
|
+
peak_coordinates = peak_local_max(scaled_mip, min_distance=int(par.min_peak_radius), exclude_border=50, threshold_abs=expected_threshold)
|
|
265
|
+
result = pd.DataFrame({
|
|
266
|
+
"X_POSITION": peak_coordinates[:,1] * par.pixel_size,
|
|
267
|
+
"Y_POSITION": peak_coordinates[:,0] * par.pixel_size,
|
|
268
|
+
"PSI": psi[tuple(peak_coordinates.T)],
|
|
269
|
+
"THETA": theta[tuple(peak_coordinates.T)],
|
|
270
|
+
"PHI": phi[tuple(peak_coordinates.T)],
|
|
271
|
+
"DEFOCUS": defocus[tuple(peak_coordinates.T)],
|
|
272
|
+
"PEAK_HEIGHT": scaled_mip[tuple(peak_coordinates.T)]
|
|
273
|
+
})
|
|
274
|
+
if(write_directly_to_db):
|
|
275
|
+
image_info["THRESHOLD"].iat[result_number] = expected_threshold
|
|
276
|
+
write_results_to_database(image_info.iloc[result_number]["DATABASE"], parameters, [(result_number, result)], image_info)
|
|
277
|
+
print("Wrote results to database")
|
|
278
|
+
print(f"{par.input_search_images_filename}: {len(result)} peaks found. Median {result['PEAK_HEIGHT'].median()} Max {result['PEAK_HEIGHT'].max()} Threshold {expected_threshold}")
|
|
279
|
+
return(result)
|
|
280
|
+
|
|
281
|
+
async def handle_job_result_queue(reader, writer, logger):
|
|
282
|
+
#logger.info("Handling results")
|
|
283
|
+
#await reader.read(4)
|
|
284
|
+
length = await reader.readexactly(4)
|
|
285
|
+
number_of_bytes = int.from_bytes(length, byteorder="little")
|
|
286
|
+
results = await reader.readexactly(number_of_bytes)
|
|
287
|
+
number_of_jobs = int.from_bytes(results[0:4], byteorder="little")
|
|
288
|
+
# print(f"Number of bytes: {number_of_bytes} Number of jobs: {number_of_jobs}")
|
|
289
|
+
#for i in range(number_of_jobs):
|
|
290
|
+
# job_number = int.from_bytes(results[4+i*4:8+i*4], byteorder="little")
|
|
291
|
+
# result_size = int.from_bytes(results[8+i*4:12+i*4], byteorder="little")
|
|
292
|
+
|
|
293
|
+
# logger.info(f"Job {job_number} finished with result {result_number}")
|
|
294
|
+
return(results)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def run(parameters: Union[MatchTemplateParameters,list[MatchTemplateParameters],pd.DataFrame],write_directly_to_db=False,image_info=None,**kwargs):
|
|
299
|
+
|
|
300
|
+
if isinstance(parameters, pd.DataFrame):
|
|
301
|
+
image_info = parameters
|
|
302
|
+
parameters = image_info["PARAMETERS"].tolist()
|
|
303
|
+
if not isinstance(parameters, list):
|
|
304
|
+
parameters = [parameters]
|
|
305
|
+
|
|
306
|
+
signal_handlers = {
|
|
307
|
+
socket_program_defined_result : partial(handle_results, parameters = parameters, write_directly_to_db=write_directly_to_db,image_info=image_info),
|
|
308
|
+
socket_job_result_queue : handle_job_result_queue,
|
|
309
|
+
socket_i_have_info: handle_socket_i_have_info,
|
|
310
|
+
}
|
|
311
|
+
for i, par in enumerate(parameters):
|
|
312
|
+
par.image_number_for_gui = i
|
|
313
|
+
global_euler_search = EulerSearch()
|
|
314
|
+
parameter_map = ParameterMap()
|
|
315
|
+
parameter_map.SetAllTrue( )
|
|
316
|
+
global_euler_search.InitGrid(par.my_symmetry,par.angular_step, 0.0, 0.0, 360.0, par.in_plane_angular_step, 0.0, 1.0 / 2.0, parameter_map, 10)
|
|
317
|
+
if par.my_symmetry.startswith("C") and global_euler_search.test_mirror:
|
|
318
|
+
global_euler_search.theta_max = 180.0
|
|
319
|
+
global_euler_search.CalculateGridSearchPositions(False)
|
|
320
|
+
par.first_search_position = 0
|
|
321
|
+
par.last_search_position = global_euler_search.number_of_search_positions - 1
|
|
322
|
+
|
|
323
|
+
results = asyncio.run(cistem_program.run("match_template_gpu", parameters, signal_handlers=signal_handlers,num_threads=parameters[0].max_threads,**kwargs))
|
|
324
|
+
|
|
325
|
+
return(results)
|