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,247 @@
|
|
|
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
|
+
import time
|
|
9
|
+
|
|
10
|
+
import mrcfile
|
|
11
|
+
import pandas as pd
|
|
12
|
+
|
|
13
|
+
from pycistem.database import datetime_to_msdos, get_movie_info_from_db
|
|
14
|
+
from pycistem.programs import cistem_program
|
|
15
|
+
from pycistem.programs._cistem_constants import socket_job_result, socket_send_next_job
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class UnblurParameters:
|
|
20
|
+
input_filename: str
|
|
21
|
+
output_filename: str = "unblurred.mrc"
|
|
22
|
+
pixel_size: float = 1.0
|
|
23
|
+
minimum_shift_in_angstroms: float = 2.00
|
|
24
|
+
maximum_shift_in_angstroms: float = 40.0
|
|
25
|
+
should_dose_filter: bool = True
|
|
26
|
+
should_restore_power: bool = True
|
|
27
|
+
termination_threshold_in_angstroms: float = 1.0
|
|
28
|
+
max_iterations: int = 10
|
|
29
|
+
bfactor_in_angstroms: float = 1500
|
|
30
|
+
should_mask_central_cross: bool = True
|
|
31
|
+
horizontal_mask_size: int = 1
|
|
32
|
+
vertical_mask_size: int = 1
|
|
33
|
+
acceleration_voltage: float = 300.0
|
|
34
|
+
exposure_per_frame: float = 0.0
|
|
35
|
+
pre_exposure_amount: float = 0.0
|
|
36
|
+
movie_is_gain_corrected: bool = False
|
|
37
|
+
gain_filename: str = "gain.mrc"
|
|
38
|
+
movie_is_dark_corrected: bool = True
|
|
39
|
+
dark_filename: str = "dark.mrc"
|
|
40
|
+
output_binning_factor: float = 2.0
|
|
41
|
+
correct_mag_distortion: bool = False
|
|
42
|
+
mag_distortion_angle: float = 0.0
|
|
43
|
+
mag_distortion_major_scale: float = 1.0
|
|
44
|
+
mag_distortion_minor_scale: float = 1.0
|
|
45
|
+
write_out_amplitude_spectrum: bool = True
|
|
46
|
+
amplitude_spectrum_filename: str = "amplitude_spectrum.mrc"
|
|
47
|
+
write_out_small_sum_image: bool = True
|
|
48
|
+
small_sum_image_filename: str = "scaled_sum.mrc"
|
|
49
|
+
first_frame: int = 1
|
|
50
|
+
last_frame: int = 0
|
|
51
|
+
number_of_frames_for_running_average: int = 1
|
|
52
|
+
max_threads: int = 1
|
|
53
|
+
save_aligned_frames: bool = False
|
|
54
|
+
aligned_frames_filename: str = "aligned_frames.mrc"
|
|
55
|
+
output_shift_text_file: str = "shifts.txt"
|
|
56
|
+
eer_frames_per_image: int = 0
|
|
57
|
+
eer_super_res_factor: int = 1
|
|
58
|
+
align_on_cropped_area: bool = False
|
|
59
|
+
cropped_area_center_x : int = 0
|
|
60
|
+
cropped_area_center_y : int = 0
|
|
61
|
+
cropped_area_size_x : int = -1
|
|
62
|
+
cropped_area_size_y : int = -1
|
|
63
|
+
replace_dark_areas_with_gaussian_noise: bool = False
|
|
64
|
+
threshold_for_gaussian_noise: float = 0.1
|
|
65
|
+
measure_mean_and_variance_for_gaussian_noise : bool = False
|
|
66
|
+
mean_for_gaussian_noise : float = 0.0
|
|
67
|
+
variance_for_gaussian_noise : float = 0.0
|
|
68
|
+
|
|
69
|
+
def parameters_from_database(database, decolace=False, **kwargs):
|
|
70
|
+
movie_info = get_movie_info_from_db(database)
|
|
71
|
+
ProjectDirectory = Path(database).parent
|
|
72
|
+
par = [UnblurParameters(
|
|
73
|
+
input_filename = movie["FILENAME"],
|
|
74
|
+
output_filename= (ProjectDirectory / "Assets" / "Images" / f"{Path(movie['FILENAME']).stem}_{movie['MOVIE_ASSET_ID']}_auto_{i}.mrc").as_posix(),
|
|
75
|
+
pixel_size = movie["PIXEL_SIZE"],
|
|
76
|
+
gain_filename=movie["GAIN_FILENAME"],
|
|
77
|
+
output_binning_factor=movie["OUTPUT_BINNING_FACTOR"],
|
|
78
|
+
exposure_per_frame=movie["DOSE_PER_FRAME"],
|
|
79
|
+
amplitude_spectrum_filename=(ProjectDirectory / "Assets" / "Images" / "Spectra" / f"{Path(movie['FILENAME']).stem}_{movie['MOVIE_ASSET_ID']}_auto.mrc").as_posix(),
|
|
80
|
+
small_sum_image_filename=(ProjectDirectory / "Assets" / "Images" / "Scaled" / f"{Path(movie['FILENAME']).stem}_{movie['MOVIE_ASSET_ID']}_auto.mrc").as_posix(),
|
|
81
|
+
align_on_cropped_area=decolace,
|
|
82
|
+
replace_dark_areas_with_gaussian_noise=decolace
|
|
83
|
+
) for i,movie in movie_info.iterrows()]
|
|
84
|
+
return(par)
|
|
85
|
+
|
|
86
|
+
def write_results_to_database(database, parameters, results, change_image_assets=True):
|
|
87
|
+
conn = sqlite3.connect(database)
|
|
88
|
+
cur = conn.cursor()
|
|
89
|
+
results = sorted(results, key=lambda x: x["parameter_index"])
|
|
90
|
+
MOVIE_ALIGNMENT_LIST = []
|
|
91
|
+
|
|
92
|
+
max_alignment_id= cur.execute("SELECT MAX(ALIGNMENT_ID) FROM MOVIE_ALIGNMENT_LIST").fetchone()[0]
|
|
93
|
+
if max_alignment_id is None:
|
|
94
|
+
max_alignment_id = 0
|
|
95
|
+
alignment_job_id= cur.execute("SELECT MAX(ALIGNMENT_JOB_ID) FROM MOVIE_ALIGNMENT_LIST").fetchone()[0]
|
|
96
|
+
if alignment_job_id is None:
|
|
97
|
+
alignment_job_id = 1
|
|
98
|
+
else:
|
|
99
|
+
alignment_job_id += 1
|
|
100
|
+
|
|
101
|
+
max_image_asset_id= cur.execute("SELECT MAX(IMAGE_ASSET_ID) FROM IMAGE_ASSETS").fetchone()[0]
|
|
102
|
+
if max_image_asset_id is None:
|
|
103
|
+
max_image_asset_id = 0
|
|
104
|
+
for result in results:
|
|
105
|
+
movie_info = cur.execute("SELECT X_SIZE, Y_SIZE, MOVIE_ASSET_ID, NAME, PROTEIN_IS_WHITE, SPHERICAL_ABERRATION FROM MOVIE_ASSETS WHERE FILENAME = ?", (parameters[result["parameter_index"]].input_filename,)).fetchone()
|
|
106
|
+
mrc = mrcfile.open(parameters[result["parameter_index"]].output_filename)
|
|
107
|
+
xsize = mrc.header.nx
|
|
108
|
+
ysize = mrc.header.ny
|
|
109
|
+
if result["orig_x"] > 0:
|
|
110
|
+
x_bin_factor = movie_info[0] / result["orig_x"]
|
|
111
|
+
y_bin_factor = movie_info[1] / result["orig_y"]
|
|
112
|
+
else:
|
|
113
|
+
x_bin_factor = movie_info[0] / xsize
|
|
114
|
+
y_bin_factor = movie_info[1] / ysize
|
|
115
|
+
average_bin_factor = (x_bin_factor + y_bin_factor) / 2.0
|
|
116
|
+
actual_pixel_size = parameters[result["parameter_index"]].pixel_size * average_bin_factor
|
|
117
|
+
MOVIE_ALIGNMENT_LIST.append({
|
|
118
|
+
"ALIGNMENT_ID" : max_alignment_id + 1,
|
|
119
|
+
"DATETIME_OF_RUN" : datetime_to_msdos(datetime.datetime.now()),
|
|
120
|
+
"ALIGNMENT_JOB_ID": alignment_job_id,
|
|
121
|
+
"MOVIE_ASSET_ID": movie_info[2],
|
|
122
|
+
"OUTPUT_FILE": parameters[result["parameter_index"]].output_filename,
|
|
123
|
+
"VOLTAGE": parameters[result["parameter_index"]].acceleration_voltage,
|
|
124
|
+
"PIXEL_SIZE": actual_pixel_size,
|
|
125
|
+
"EXPOSURE_PER_FRAME": parameters[result["parameter_index"]].exposure_per_frame,
|
|
126
|
+
"PRE_EXPOSURE_AMOUNT": parameters[result["parameter_index"]].pre_exposure_amount,
|
|
127
|
+
"MIN_SHIFT": parameters[result["parameter_index"]].minimum_shift_in_angstroms,
|
|
128
|
+
"MAX_SHIFT": parameters[result["parameter_index"]].maximum_shift_in_angstroms,
|
|
129
|
+
"SHOULD_DOSE_FILTER": parameters[result["parameter_index"]].should_dose_filter,
|
|
130
|
+
"SHOULD_RESTORE_POWER": parameters[result["parameter_index"]].should_restore_power,
|
|
131
|
+
"TERMINATION_THRESHOLD": parameters[result["parameter_index"]].termination_threshold_in_angstroms,
|
|
132
|
+
"MAX_ITERATIONS": parameters[result["parameter_index"]].max_iterations ,
|
|
133
|
+
"BFACTOR": parameters[result["parameter_index"]].bfactor_in_angstroms,
|
|
134
|
+
"SHOULD_MASK_CENTRAL_CROSS": parameters[result["parameter_index"]].should_mask_central_cross,
|
|
135
|
+
"HORIZONTAL_MASK": parameters[result["parameter_index"]].horizontal_mask_size,
|
|
136
|
+
"VERTICAL_MASK": parameters[result["parameter_index"]].vertical_mask_size,
|
|
137
|
+
"SHOULD_INCLUDE_ALL_FRAMES_IN_SUM": True,
|
|
138
|
+
"FIRST_FRAME_TO_SUM": parameters[result["parameter_index"]].first_frame,
|
|
139
|
+
"LAST_FRAME_TO_SUM": parameters[result["parameter_index"]].last_frame,
|
|
140
|
+
"ORIGINAL_X_SIZE": result["orig_x"],
|
|
141
|
+
"ORIGINAL_Y_SIZE": result["orig_y"],
|
|
142
|
+
"CROP_CENTER_X": result["crop_x"],
|
|
143
|
+
"CROP_CENTER_Y": result["crop_y"],
|
|
144
|
+
})
|
|
145
|
+
# Check if there is existing image asset
|
|
146
|
+
|
|
147
|
+
#existing_image_asset = cur.execute("SELECT IMAGE_ASSET_ID FROM IMAGE_ASSETS WHERE PARENT_MOVIE_ID = ?",(movie_info[2],)).fetchone()
|
|
148
|
+
#if existing_image_asset is None:
|
|
149
|
+
max_image_asset_id += 1
|
|
150
|
+
image_asset_id = max_image_asset_id
|
|
151
|
+
#else:
|
|
152
|
+
# image_asset_id = existing_image_asset[0]
|
|
153
|
+
|
|
154
|
+
if change_image_assets:
|
|
155
|
+
cur.execute("REPLACE INTO IMAGE_ASSETS (IMAGE_ASSET_ID, NAME, FILENAME, POSITION_IN_STACK, PARENT_MOVIE_ID, ALIGNMENT_ID, CTF_ESTIMATION_ID, X_SIZE, Y_SIZE, PIXEL_SIZE, VOLTAGE, SPHERICAL_ABERRATION, PROTEIN_IS_WHITE, ORIGINAL_X_SIZE, ORIGINAL_Y_SIZE, CROP_CENTER_X, CROP_CENTER_Y) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
|
|
156
|
+
(image_asset_id, movie_info[3], parameters[result["parameter_index"]].output_filename, 1,movie_info[2],max_alignment_id+1, -1, int(xsize), int(ysize), actual_pixel_size, parameters[result["parameter_index"]].acceleration_voltage, movie_info[5], movie_info[4],result["orig_x"],result["orig_y"],result["crop_x"],result["crop_y"]))
|
|
157
|
+
MOVIE_ALIGNMENT_PARAMETERS = {
|
|
158
|
+
"FRAME_NUMBER": range(1,len(result["x_shifts"])+1),
|
|
159
|
+
"X_SHIFT": result["x_shifts"],
|
|
160
|
+
"Y_SHIFT": result["y_shifts"],
|
|
161
|
+
}
|
|
162
|
+
conn.commit()
|
|
163
|
+
MOVIE_ALIGNMENT_PARAMETERS = pd.DataFrame(MOVIE_ALIGNMENT_PARAMETERS)
|
|
164
|
+
MOVIE_ALIGNMENT_PARAMETERS.to_sql(f"MOVIE_ALIGNMENT_PARAMETERS_{max_alignment_id+1}", conn, if_exists="fail", index=False)
|
|
165
|
+
max_alignment_id += 1
|
|
166
|
+
MOVIE_ALIGNMENT_LIST = pd.DataFrame(MOVIE_ALIGNMENT_LIST)
|
|
167
|
+
MOVIE_ALIGNMENT_LIST.to_sql("MOVIE_ALIGNMENT_LIST", conn, if_exists="append", index=False)
|
|
168
|
+
conn.close()
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
async def handle_results(reader, writer, logger):
|
|
175
|
+
#logger.info("Handling results")
|
|
176
|
+
await reader.read(4)
|
|
177
|
+
length = await reader.read(4)
|
|
178
|
+
number_of_bytes = int.from_bytes(length, byteorder="little")
|
|
179
|
+
results = await reader.read(number_of_bytes*4)
|
|
180
|
+
return(results)
|
|
181
|
+
|
|
182
|
+
signal_handlers = {
|
|
183
|
+
socket_send_next_job : handle_results
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
def run(parameters: Union[UnblurParameters,list[UnblurParameters]],**kwargs):
|
|
187
|
+
|
|
188
|
+
if not isinstance(parameters, list):
|
|
189
|
+
parameters = [parameters]
|
|
190
|
+
|
|
191
|
+
byte_results = asyncio.run(cistem_program.run("unblur", parameters, signal_handlers=signal_handlers,**kwargs))
|
|
192
|
+
result_shifts = []
|
|
193
|
+
|
|
194
|
+
for parameter_index,byte_result in byte_results:
|
|
195
|
+
number_of_images = int(((len(byte_result) /4 ) - 4 ) /2)
|
|
196
|
+
x_shifts = []
|
|
197
|
+
for offset in range(number_of_images):
|
|
198
|
+
x_shifts.append(struct.unpack_from("<f",byte_result,offset=offset*4)[0])
|
|
199
|
+
y_shifts = []
|
|
200
|
+
for offset in range(number_of_images):
|
|
201
|
+
y_shifts.append(struct.unpack_from("<f",byte_result,offset=offset*4+number_of_images*4)[0])
|
|
202
|
+
orig_x = int(struct.unpack_from("<f",byte_result,offset=2*4*number_of_images)[0])
|
|
203
|
+
orig_y = int(struct.unpack_from("<f",byte_result,offset=2*4*number_of_images+4)[0])
|
|
204
|
+
crop_x = int(struct.unpack_from("<f",byte_result,offset=2*4*number_of_images+8)[0])
|
|
205
|
+
crop_y = int(struct.unpack_from("<f",byte_result,offset=2*4*number_of_images+12)[0])
|
|
206
|
+
result_shifts.append({
|
|
207
|
+
"parameter_index": parameter_index,
|
|
208
|
+
"x_shifts": x_shifts,
|
|
209
|
+
"y_shifts": y_shifts,
|
|
210
|
+
"orig_x": orig_x,
|
|
211
|
+
"orig_y": orig_y,
|
|
212
|
+
"crop_x": crop_x,
|
|
213
|
+
"crop_y": crop_y
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
return(result_shifts)
|
|
217
|
+
|
|
218
|
+
async def run_async(parameters: Union[UnblurParameters,list[UnblurParameters]],**kwargs):
|
|
219
|
+
|
|
220
|
+
if not isinstance(parameters, list):
|
|
221
|
+
parameters = [parameters]
|
|
222
|
+
byte_results = await cistem_program.run("unblur", parameters, signal_handlers=signal_handlers,**kwargs)
|
|
223
|
+
result_shifts = []
|
|
224
|
+
|
|
225
|
+
for parameter_index,byte_result in byte_results:
|
|
226
|
+
number_of_images = int(((len(byte_result) /4 ) - 4 ) /2)
|
|
227
|
+
x_shifts = []
|
|
228
|
+
for offset in range(number_of_images):
|
|
229
|
+
x_shifts.append(struct.unpack_from("<f",byte_result,offset=offset*4)[0])
|
|
230
|
+
y_shifts = []
|
|
231
|
+
for offset in range(number_of_images):
|
|
232
|
+
y_shifts.append(struct.unpack_from("<f",byte_result,offset=offset*4+number_of_images*4)[0])
|
|
233
|
+
orig_x = int(struct.unpack_from("<f",byte_result,offset=2*4*number_of_images)[0])
|
|
234
|
+
orig_y = int(struct.unpack_from("<f",byte_result,offset=2*4*number_of_images+4)[0])
|
|
235
|
+
crop_x = int(struct.unpack_from("<f",byte_result,offset=2*4*number_of_images+8)[0])
|
|
236
|
+
crop_y = int(struct.unpack_from("<f",byte_result,offset=2*4*number_of_images+12)[0])
|
|
237
|
+
result_shifts.append({
|
|
238
|
+
"parameter_index": parameter_index,
|
|
239
|
+
"x_shifts": x_shifts,
|
|
240
|
+
"y_shifts": y_shifts,
|
|
241
|
+
"orig_x": orig_x,
|
|
242
|
+
"orig_y": orig_y,
|
|
243
|
+
"crop_x": crop_x,
|
|
244
|
+
"crop_y": crop_y
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
return(result_shifts)
|
|
@@ -0,0 +1,204 @@
|
|
|
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_movie_info_from_db
|
|
13
|
+
from pycistem.programs import cistem_program
|
|
14
|
+
from pycistem.programs._cistem_constants import socket_job_result, socket_send_next_job
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class UnblurPatchParameters:
|
|
19
|
+
input_filename: str
|
|
20
|
+
output_filename: str = "unblurred.mrc"
|
|
21
|
+
pixel_size: float = 1.0
|
|
22
|
+
minimum_shift_in_angstroms: float = 2.00
|
|
23
|
+
maximum_shift_in_angstroms: float = 40.0
|
|
24
|
+
should_dose_filter: bool = True
|
|
25
|
+
should_restore_power: bool = True
|
|
26
|
+
termination_threshold_in_angstroms: float = 1.0
|
|
27
|
+
max_iterations: int = 10
|
|
28
|
+
bfactor_in_angstroms: float = 1500
|
|
29
|
+
should_mask_central_cross: bool = True
|
|
30
|
+
horizontal_mask_size: int = 1
|
|
31
|
+
vertical_mask_size: int = 1
|
|
32
|
+
acceleration_voltage: float = 300.0
|
|
33
|
+
exposure_per_frame: float = 0.0
|
|
34
|
+
pre_exposure_amount: float = 0.0
|
|
35
|
+
movie_is_gain_corrected: bool = False
|
|
36
|
+
gain_filename: str = "gain.mrc"
|
|
37
|
+
movie_is_dark_corrected: bool = True
|
|
38
|
+
dark_filename: str = "dark.mrc"
|
|
39
|
+
output_binning_factor: float = 2.0
|
|
40
|
+
correct_mag_distortion: bool = False
|
|
41
|
+
mag_distortion_angle: float = 0.0
|
|
42
|
+
mag_distortion_major_scale: float = 1.0
|
|
43
|
+
mag_distortion_minor_scale: float = 1.0
|
|
44
|
+
write_out_amplitude_spectrum: bool = True
|
|
45
|
+
amplitude_spectrum_filename: str = "amplitude_spectrum.mrc"
|
|
46
|
+
write_out_small_sum_image: bool = True
|
|
47
|
+
small_sum_image_filename: str = "scaled_sum.mrc"
|
|
48
|
+
first_frame: int = 1
|
|
49
|
+
last_frame: int = 0
|
|
50
|
+
number_of_frames_for_running_average: int = 1
|
|
51
|
+
max_threads: int = 1
|
|
52
|
+
save_aligned_frames: bool = False
|
|
53
|
+
eer_frames_per_image: int = 0
|
|
54
|
+
eer_super_res_factor: int = 1
|
|
55
|
+
outputpath: str = "/tmp"
|
|
56
|
+
patchcorrection: bool = False
|
|
57
|
+
override_patchnum: bool = False
|
|
58
|
+
patch_num_x: int = 6
|
|
59
|
+
patch_num_y: int = 4
|
|
60
|
+
distortion_model: int = 3
|
|
61
|
+
|
|
62
|
+
def parameters_from_database(database, decolace=False, **kwargs):
|
|
63
|
+
movie_info = get_movie_info_from_db(database)
|
|
64
|
+
ProjectDirectory = Path(database).parent
|
|
65
|
+
par = [UnblurPatchParameters(
|
|
66
|
+
input_filename = movie["FILENAME"],
|
|
67
|
+
output_filename= (ProjectDirectory / "Assets" / "Images" / f"{Path(movie['FILENAME']).stem}_{movie['MOVIE_ASSET_ID']}_auto.mrc").as_posix(),
|
|
68
|
+
pixel_size = movie["PIXEL_SIZE"],
|
|
69
|
+
gain_filename=movie["GAIN_FILENAME"],
|
|
70
|
+
output_binning_factor=movie["OUTPUT_BINNING_FACTOR"],
|
|
71
|
+
exposure_per_frame=movie["DOSE_PER_FRAME"],
|
|
72
|
+
amplitude_spectrum_filename=(ProjectDirectory / "Assets" / "Images" / "Spectra" / f"{Path(movie['FILENAME']).stem}_{movie['MOVIE_ASSET_ID']}_auto.mrc").as_posix(),
|
|
73
|
+
small_sum_image_filename=(ProjectDirectory / "Assets" / "Images" / "Scaled" / f"{Path(movie['FILENAME']).stem}_{movie['MOVIE_ASSET_ID']}_auto.mrc").as_posix(),
|
|
74
|
+
) for i,movie in movie_info.iterrows()]
|
|
75
|
+
return(par)
|
|
76
|
+
|
|
77
|
+
def write_results_to_database(database, parameters, results,change_image_assets):
|
|
78
|
+
conn = sqlite3.connect(database)
|
|
79
|
+
cur = conn.cursor()
|
|
80
|
+
results = sorted(results, key=lambda x: x["parameter_index"])
|
|
81
|
+
MOVIE_ALIGNMENT_LIST = []
|
|
82
|
+
|
|
83
|
+
max_alignment_id= cur.execute("SELECT MAX(ALIGNMENT_ID) FROM MOVIE_ALIGNMENT_LIST").fetchone()[0]
|
|
84
|
+
if max_alignment_id is None:
|
|
85
|
+
max_alignment_id = 0
|
|
86
|
+
alignment_job_id= cur.execute("SELECT MAX(ALIGNMENT_JOB_ID) FROM MOVIE_ALIGNMENT_LIST").fetchone()[0]
|
|
87
|
+
if alignment_job_id is None:
|
|
88
|
+
alignment_job_id = 1
|
|
89
|
+
else:
|
|
90
|
+
alignment_job_id += 1
|
|
91
|
+
|
|
92
|
+
max_image_asset_id= cur.execute("SELECT MAX(IMAGE_ASSET_ID) FROM IMAGE_ASSETS").fetchone()[0]
|
|
93
|
+
if max_image_asset_id is None:
|
|
94
|
+
max_image_asset_id = 0
|
|
95
|
+
for result in results:
|
|
96
|
+
movie_info = cur.execute("SELECT X_SIZE, Y_SIZE, MOVIE_ASSET_ID, NAME, PROTEIN_IS_WHITE, SPHERICAL_ABERRATION FROM MOVIE_ASSETS WHERE FILENAME = ?", (parameters[result["parameter_index"]].input_filename,)).fetchone()
|
|
97
|
+
x_bin_factor = movie_info[0] / result["orig_x"]
|
|
98
|
+
y_bin_factor = movie_info[1] / result["orig_y"]
|
|
99
|
+
average_bin_factor = (x_bin_factor + y_bin_factor) / 2.0
|
|
100
|
+
actual_pixel_size = parameters[result["parameter_index"]].pixel_size * average_bin_factor
|
|
101
|
+
MOVIE_ALIGNMENT_LIST.append({
|
|
102
|
+
"ALIGNMENT_ID" : max_alignment_id + 1,
|
|
103
|
+
"DATETIME_OF_RUN" : datetime_to_msdos(datetime.datetime.now()),
|
|
104
|
+
"ALIGNMENT_JOB_ID": alignment_job_id,
|
|
105
|
+
"MOVIE_ASSET_ID": movie_info[2],
|
|
106
|
+
"OUTPUT_FILE": parameters[result["parameter_index"]].output_filename,
|
|
107
|
+
"VOLTAGE": parameters[result["parameter_index"]].acceleration_voltage,
|
|
108
|
+
"PIXEL_SIZE": actual_pixel_size,
|
|
109
|
+
"EXPOSURE_PER_FRAME": parameters[result["parameter_index"]].exposure_per_frame,
|
|
110
|
+
"PRE_EXPOSURE_AMOUNT": parameters[result["parameter_index"]].pre_exposure_amount,
|
|
111
|
+
"MIN_SHIFT": parameters[result["parameter_index"]].minimum_shift_in_angstroms,
|
|
112
|
+
"MAX_SHIFT": parameters[result["parameter_index"]].maximum_shift_in_angstroms,
|
|
113
|
+
"SHOULD_DOSE_FILTER": parameters[result["parameter_index"]].should_dose_filter,
|
|
114
|
+
"SHOULD_RESTORE_POWER": parameters[result["parameter_index"]].should_restore_power,
|
|
115
|
+
"TERMINATION_THRESHOLD": parameters[result["parameter_index"]].termination_threshold_in_angstroms,
|
|
116
|
+
"MAX_ITERATIONS": parameters[result["parameter_index"]].max_iterations ,
|
|
117
|
+
"BFACTOR": parameters[result["parameter_index"]].bfactor_in_angstroms,
|
|
118
|
+
"SHOULD_MASK_CENTRAL_CROSS": parameters[result["parameter_index"]].should_mask_central_cross,
|
|
119
|
+
"HORIZONTAL_MASK": parameters[result["parameter_index"]].horizontal_mask_size,
|
|
120
|
+
"VERTICAL_MASK": parameters[result["parameter_index"]].vertical_mask_size,
|
|
121
|
+
"SHOULD_INCLUDE_ALL_FRAMES_IN_SUM": True,
|
|
122
|
+
"FIRST_FRAME_TO_SUM": parameters[result["parameter_index"]].first_frame,
|
|
123
|
+
"LAST_FRAME_TO_SUM": parameters[result["parameter_index"]].last_frame,
|
|
124
|
+
"ORIGINAL_X_SIZE": result["orig_x"],
|
|
125
|
+
"ORIGINAL_Y_SIZE": result["orig_y"],
|
|
126
|
+
"CROP_CENTER_X": result["crop_x"],
|
|
127
|
+
"CROP_CENTER_Y": result["crop_y"],
|
|
128
|
+
})
|
|
129
|
+
# Check if there is existing image asset
|
|
130
|
+
|
|
131
|
+
existing_image_asset = cur.execute("SELECT IMAGE_ASSET_ID FROM IMAGE_ASSETS WHERE PARENT_MOVIE_ID = ?",(movie_info[2],)).fetchone()
|
|
132
|
+
if existing_image_asset is None:
|
|
133
|
+
max_image_asset_id += 1
|
|
134
|
+
image_asset_id = max_image_asset_id
|
|
135
|
+
else:
|
|
136
|
+
image_asset_id = existing_image_asset[0]
|
|
137
|
+
|
|
138
|
+
mrc = mrcfile.open(parameters[result["parameter_index"]].output_filename)
|
|
139
|
+
xsize = mrc.header.nx
|
|
140
|
+
ysize = mrc.header.ny
|
|
141
|
+
cur.execute("REPLACE INTO IMAGE_ASSETS (IMAGE_ASSET_ID, NAME, FILENAME, POSITION_IN_STACK, PARENT_MOVIE_ID, ALIGNMENT_ID, CTF_ESTIMATION_ID, X_SIZE, Y_SIZE, PIXEL_SIZE, VOLTAGE, SPHERICAL_ABERRATION, PROTEIN_IS_WHITE, ORIGINAL_X_SIZE, ORIGINAL_Y_SIZE, CROP_CENTER_X, CROP_CENTER_Y) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
|
|
142
|
+
(image_asset_id, movie_info[3], parameters[result["parameter_index"]].output_filename, 1,movie_info[2],max_alignment_id+1, -1, int(xsize), int(ysize), actual_pixel_size, parameters[result["parameter_index"]].acceleration_voltage, movie_info[5], movie_info[4],result["orig_x"],result["orig_y"],result["crop_x"],result["crop_y"]))
|
|
143
|
+
MOVIE_ALIGNMENT_PARAMETERS = {
|
|
144
|
+
"FRAME_NUMBER": range(1,len(result["x_shifts"])+1),
|
|
145
|
+
"X_SHIFT": result["x_shifts"],
|
|
146
|
+
"Y_SHIFT": result["y_shifts"],
|
|
147
|
+
}
|
|
148
|
+
conn.commit()
|
|
149
|
+
MOVIE_ALIGNMENT_PARAMETERS = pd.DataFrame(MOVIE_ALIGNMENT_PARAMETERS)
|
|
150
|
+
MOVIE_ALIGNMENT_PARAMETERS.to_sql(f"MOVIE_ALIGNMENT_PARAMETERS_{max_alignment_id+1}", conn, if_exists="fail", index=False)
|
|
151
|
+
max_alignment_id += 1
|
|
152
|
+
MOVIE_ALIGNMENT_LIST = pd.DataFrame(MOVIE_ALIGNMENT_LIST)
|
|
153
|
+
MOVIE_ALIGNMENT_LIST.to_sql("MOVIE_ALIGNMENT_LIST", conn, if_exists="append", index=False)
|
|
154
|
+
conn.close()
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
async def handle_results(reader, writer, logger):
|
|
161
|
+
#logger.info("Handling results")
|
|
162
|
+
await reader.read(4)
|
|
163
|
+
length = await reader.read(4)
|
|
164
|
+
number_of_bytes = int.from_bytes(length, byteorder="little")
|
|
165
|
+
results = await reader.read(number_of_bytes*4)
|
|
166
|
+
print(struct.unpack_from("<"+''.join(["f" for a in range(number_of_bytes)]),results))
|
|
167
|
+
return(results)
|
|
168
|
+
|
|
169
|
+
signal_handlers = {
|
|
170
|
+
socket_send_next_job : handle_results
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
def run(parameters: Union[UnblurPatchParameters,list[UnblurPatchParameters]], unblur_command: str="unblur", **kwargs):
|
|
174
|
+
|
|
175
|
+
if not isinstance(parameters, list):
|
|
176
|
+
parameters = [parameters]
|
|
177
|
+
|
|
178
|
+
byte_results = asyncio.run(cistem_program.run(unblur_command, parameters, signal_handlers=signal_handlers,**kwargs))
|
|
179
|
+
result_shifts = []
|
|
180
|
+
|
|
181
|
+
for parameter_index,byte_result in byte_results:
|
|
182
|
+
number_of_images = int(((len(byte_result) /4 ) - 4 ) /2)
|
|
183
|
+
x_shifts = []
|
|
184
|
+
for offset in range(number_of_images):
|
|
185
|
+
x_shifts.append(struct.unpack_from("<f",byte_result,offset=offset*4)[0])
|
|
186
|
+
y_shifts = []
|
|
187
|
+
for offset in range(number_of_images):
|
|
188
|
+
y_shifts.append(struct.unpack_from("<f",byte_result,offset=offset*4+number_of_images*4)[0])
|
|
189
|
+
orig_x = int(struct.unpack_from("<f",byte_result,offset=2*4*number_of_images)[0])
|
|
190
|
+
orig_y = int(struct.unpack_from("<f",byte_result,offset=2*4*number_of_images+4)[0])
|
|
191
|
+
crop_x = int(struct.unpack_from("<f",byte_result,offset=2*4*number_of_images+8)[0])
|
|
192
|
+
crop_y = int(struct.unpack_from("<f",byte_result,offset=2*4*number_of_images+12)[0])
|
|
193
|
+
result_shifts.append({
|
|
194
|
+
"parameter_index": parameter_index,
|
|
195
|
+
"x_shifts": x_shifts,
|
|
196
|
+
"y_shifts": y_shifts,
|
|
197
|
+
"orig_x": orig_x,
|
|
198
|
+
"orig_y": orig_y,
|
|
199
|
+
"crop_x": crop_x,
|
|
200
|
+
"crop_y": crop_y
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
return(result_shifts)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .extract_particles import extract_particles
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
def extract_particles(starfile_filename: Path, stack_filename: Path, box_size: int = 256):
|
|
4
|
+
"""Extract particles from a star file and save them as individual images.
|
|
5
|
+
|
|
6
|
+
Args:
|
|
7
|
+
starfile_filename (str): The filename of the star file.
|
|
8
|
+
box_size (int, optional): The size of the extracted particles. Defaults to 256.
|
|
9
|
+
"""
|
|
10
|
+
import starfile
|
|
11
|
+
import mrcfile
|
|
12
|
+
import numpy as np
|
|
13
|
+
from itertools import groupby
|
|
14
|
+
particle_info = starfile.read(starfile_filename)
|
|
15
|
+
mrc = mrcfile.new_mmap(stack_filename, (len(particle_info), box_size, box_size), mrc_mode=2, overwrite=True)
|
|
16
|
+
# Iterate over groupby cisTEMOriginalImageFilename
|
|
17
|
+
|
|
18
|
+
for micrograph_filename, subparticles in groupby(particle_info.itertuples(), lambda x: x.cisTEMOriginalImageFilename):
|
|
19
|
+
micrograph = mrcfile.open(micrograph_filename)
|
|
20
|
+
if micrograph.data.ndim == 3:
|
|
21
|
+
micrograph_data = micrograph.data[0].copy()
|
|
22
|
+
else:
|
|
23
|
+
micrograph_data = micrograph.data.copy()
|
|
24
|
+
for particle in subparticles:
|
|
25
|
+
x = round(particle.cisTEMOriginalXPosition/particle.cisTEMPixelSize)
|
|
26
|
+
y = round(particle.cisTEMOriginalYPosition/particle.cisTEMPixelSize)
|
|
27
|
+
particle_image = micrograph_data.take(range(y-box_size//2, y+box_size//2), mode='clip', axis=0).take(range(x-box_size//2, x+box_size//2), mode='clip', axis=1)
|
|
28
|
+
if particle_image.shape != (box_size, box_size):
|
|
29
|
+
raise ValueError(f"Particle at {x},{y} from micrograph {micrograph_filename} {micrograph_data.shape} is out of bounds {particle_image.shape}.")
|
|
30
|
+
|
|
31
|
+
particle_image -= particle_image.mean()
|
|
32
|
+
particle_image /= particle_image.std()
|
|
33
|
+
mrc.data[particle.cisTEMPositionInStack-1] = particle_image
|
|
34
|
+
yield
|
|
35
|
+
mrc.close()
|
|
36
|
+
return
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from typing import Union
|
|
3
|
+
import sqlite3
|
|
4
|
+
import typer
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing_extensions import Annotated
|
|
7
|
+
import starfile
|
|
8
|
+
|
|
9
|
+
app = typer.Typer()
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.command()
|
|
13
|
+
def plot(database: Annotated[Path, typer.Argument(...,help="The database file to use")],
|
|
14
|
+
refinement_id: Annotated[int, typer.Argument(...,help="The refinement to use")],
|
|
15
|
+
class_id: Annotated[int, typer.Argument(...,help="The class to cus")],
|
|
16
|
+
input_star_file: Annotated[Path, typer.Argument(...,help="The starfile to use")],
|
|
17
|
+
output_star_file: Annotated[Path, typer.Argument(...,help="The starfile to write to")],
|
|
18
|
+
):
|
|
19
|
+
db = sqlite3.connect(database)
|
|
20
|
+
refinements = []
|
|
21
|
+
refinment_info = pd.read_sql_query(f"SELECT * FROM REFINEMENT_LIST WHERE REFINEMENT_ID = {refinement_id}", db).iloc[0]
|
|
22
|
+
refinment_result = pd.read_sql_query(f"SELECT * FROM REFINEMENT_RESULT_{refinement_id}_{class_id}", db)
|
|
23
|
+
refinment_package_info = pd.read_sql_query(f"SELECT * FROM REFINEMENT_PACKAGE_CONTAINED_PARTICLES_{refinment_info['REFINEMENT_PACKAGE_ASSET_ID']}", db)
|
|
24
|
+
|
|
25
|
+
starfile_info = starfile.read(input_star_file)
|
|
26
|
+
|
|
27
|
+
original_ids = refinment_package_info["ORIGINAL_PARTICLE_POSITION_ASSET_ID"].to_list()
|
|
28
|
+
subset_starfile_info = starfile_info.iloc[original_ids].copy()
|
|
29
|
+
subset_starfile_info["cisTEMOccupancy"] = refinment_result["OCCUPANCY"].to_list()
|
|
30
|
+
subset_starfile_info["cisTEMScore"] = refinment_result["SCORE"].to_list()
|
|
31
|
+
starfile.write(subset_starfile_info, output_star_file)
|
|
32
|
+
|
|
33
|
+
if __name__ == "__main__":
|
|
34
|
+
app()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from typing import Union
|
|
3
|
+
import sqlite3
|
|
4
|
+
import typer
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing_extensions import Annotated
|
|
7
|
+
import matplotlib.pyplot as plt
|
|
8
|
+
|
|
9
|
+
app = typer.Typer()
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.command()
|
|
13
|
+
def plot(database: Annotated[Path, typer.Argument(...,help="The database file to use")],
|
|
14
|
+
start_refinement: Annotated[int, typer.Argument(...,help="The refinement to start from")]):
|
|
15
|
+
db = sqlite3.connect(database)
|
|
16
|
+
refinment_info = pd.read_sql_query(f"SELECT * FROM REFINEMENT_LIST WHERE REFINEMENT_ID = {start_refinement}", db)
|
|
17
|
+
class_info = pd.read_sql_query(f"SELECT * FROM REFINEMENT_DETAILS_{refinment_info['REFINEMENT_ID'].values[0]}", db)
|
|
18
|
+
class_info.sort_values(by="AVERAGE_OCCUPANCY", inplace=True)
|
|
19
|
+
# print as a table the CLASS_NUMBER and AVERAGE_OCCUPANCY
|
|
20
|
+
print(class_info[['CLASS_NUMBER', 'AVERAGE_OCCUPANCY']])
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
app()
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from typing import Union
|
|
3
|
+
import sqlite3
|
|
4
|
+
import typer
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing_extensions import Annotated
|
|
7
|
+
import matplotlib.pyplot as plt
|
|
8
|
+
|
|
9
|
+
app = typer.Typer()
|
|
10
|
+
|
|
11
|
+
def return_class_occupancies(row, db):
|
|
12
|
+
class_info = pd.read_sql_query(f"SELECT * FROM REFINEMENT_DETAILS_{row['REFINEMENT_ID']}", db)
|
|
13
|
+
return [row['REFINEMENT_ID']] + class_info['AVERAGE_OCCUPANCY'].to_list()
|
|
14
|
+
|
|
15
|
+
def return_num_part_with_occ_higher_than(row, db, min_occ):
|
|
16
|
+
class_info = pd.read_sql_query(f"SELECT * FROM REFINEMENT_DETAILS_{row['REFINEMENT_ID']}", db)
|
|
17
|
+
result = [row['REFINEMENT_ID']]
|
|
18
|
+
for class_id in class_info['CLASS_NUMBER']:
|
|
19
|
+
particle_info = pd.read_sql_query(f"SELECT OCCUPANCY FROM REFINEMENT_RESULT_{row['REFINEMENT_ID']}_{class_id}", db)
|
|
20
|
+
result.append(len(particle_info[particle_info['OCCUPANCY'] > min_occ]))
|
|
21
|
+
print(result)
|
|
22
|
+
return result
|
|
23
|
+
|
|
24
|
+
@app.command()
|
|
25
|
+
def plot(database: Annotated[Path, typer.Argument(...,help="The database file to use")],
|
|
26
|
+
start_refinement: Annotated[int, typer.Argument(...,help="The refinement to start from")]):
|
|
27
|
+
db = sqlite3.connect(database)
|
|
28
|
+
refinements = []
|
|
29
|
+
refinment_info = pd.read_sql_query(f"SELECT * FROM REFINEMENT_LIST WHERE REFINEMENT_ID = {start_refinement}", db)
|
|
30
|
+
while len(refinment_info) == 1:
|
|
31
|
+
reference_refinement_id = refinment_info["REFINEMENT_ID"].values[0]
|
|
32
|
+
refinements.append(refinment_info)
|
|
33
|
+
refinment_info = pd.read_sql_query(f"SELECT * FROM REFINEMENT_LIST WHERE STARTING_REFINEMENT_ID = {reference_refinement_id}", db)
|
|
34
|
+
refinements = pd.concat(refinements)
|
|
35
|
+
av_occs = refinements.apply(return_class_occupancies, axis=1, result_type='expand', args=(db,))
|
|
36
|
+
av_occs.plot(x=0)
|
|
37
|
+
plt.savefig("average_occupancies.png")
|
|
38
|
+
plt.figure()
|
|
39
|
+
occ_0_5 = refinements.apply(return_num_part_with_occ_higher_than, axis=1, result_type='expand', args=(db, 50))
|
|
40
|
+
occ_0_5.plot(x=0)
|
|
41
|
+
plt.savefig("occupancies_0_5.png")
|
|
42
|
+
plt.figure()
|
|
43
|
+
occ_0_9 = refinements.apply(return_num_part_with_occ_higher_than, axis=1, result_type='expand', args=(db, 90))
|
|
44
|
+
occ_0_9.plot(x=0)
|
|
45
|
+
plt.savefig("occupancies_0_9.png")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
if __name__ == "__main__":
|
|
51
|
+
app()
|