Skip to content

Commit 41f533a

Browse files
committed
Added logic to register non-atlas CLEM image series as grid squares
1 parent d7b33f3 commit 41f533a

File tree

1 file changed

+197
-28
lines changed

1 file changed

+197
-28
lines changed

src/murfey/workflows/clem/register_preprocessing_results.py

Lines changed: 197 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import murfey.util.db as MurfeyDB
2222
from murfey.server import _transport_object
23+
from murfey.util.models import GridSquareParameters
2324
from murfey.util.processing_params import (
2425
default_clem_align_and_merge_parameters as processing_params,
2526
)
@@ -47,11 +48,13 @@ class CLEMPreprocessingResult(BaseModel):
4748
units: str
4849
pixel_size: float
4950
resolution: float
50-
extent: list[float]
51+
extent: list[float] # [x0, x1, y0, y1]
5152

5253

53-
def _register_results_in_murfey(
54-
session_id: int, result: CLEMPreprocessingResult, murfey_db: Session
54+
def _register_clem_image_series(
55+
session_id: int,
56+
result: CLEMPreprocessingResult,
57+
murfey_db: Session,
5558
):
5659
clem_img_series: MurfeyDB.CLEMImageSeries = get_db_entry(
5760
db=murfey_db,
@@ -76,9 +79,8 @@ def _register_results_in_murfey(
7679
clem_img_series.parent_lif = clem_lif_file
7780
clem_metadata.parent_lif = clem_lif_file
7881

79-
# Link and commit series and metadata tables first
82+
# Link and commit series and metadata tables
8083
clem_img_series.associated_metadata = clem_metadata
81-
clem_img_series.number_of_members = result.number_of_members
8284
murfey_db.add_all([clem_img_series, clem_metadata])
8385
murfey_db.commit()
8486

@@ -138,18 +140,28 @@ def _register_results_in_murfey(
138140
murfey_db.add_all(clem_tiff_files)
139141
murfey_db.commit()
140142

141-
# Add data type and image search string
143+
# Add metadata for this series
142144
clem_img_series.search_string = str(output_file.parent / "*tiff")
143145
clem_img_series.data_type = (
144146
"atlas" if "Overview_" in result.series_name else "grid_square"
145147
)
148+
clem_img_series.number_of_members = result.number_of_members
149+
clem_img_series.pixels_x = result.pixels_x
150+
clem_img_series.pixels_y = result.pixels_y
151+
clem_img_series.pixel_size = result.pixel_size
152+
clem_img_series.units = result.units
153+
clem_img_series.x0 = result.extent[0]
154+
clem_img_series.x1 = result.extent[1]
155+
clem_img_series.y0 = result.extent[2]
156+
clem_img_series.y1 = result.extent[3]
146157
murfey_db.add(clem_img_series)
147158
murfey_db.commit()
159+
murfey_db.close()
148160

149161
logger.info(f"CLEM preprocessing results registered for {result.series_name!r} ")
150162

151163

152-
def _register_results_in_ispyb(
164+
def _register_dcg_and_atlas(
153165
session_id: int,
154166
instrument_name: str,
155167
visit_name: str,
@@ -177,15 +189,14 @@ def _register_results_in_ispyb(
177189
atlas_name = ""
178190
atlas_pixel_size = 0.0
179191

180-
registration_result: dict[str, bool]
181192
if dcg_search := murfey_db.exec(
182193
select(MurfeyDB.DataCollectionGroup)
183194
.where(MurfeyDB.DataCollectionGroup.session_id == session_id)
184195
.where(MurfeyDB.DataCollectionGroup.tag == dcg_name)
185196
).all():
197+
dcg_entry = dcg_search[0]
186198
# Update atlas if registering atlas dataset
187199
# and data collection group already exists
188-
dcg_entry = dcg_search[0]
189200
if "Overview_" in result.series_name:
190201
atlas_message = {
191202
"session_id": session_id,
@@ -199,15 +210,12 @@ def _register_results_in_ispyb(
199210
group="murfey.workflows", name="atlas_update"
200211
):
201212
(workflow,) = entry_point_result
202-
registration_result = workflow.load()(
213+
_ = workflow.load()(
203214
message=atlas_message,
204215
murfey_db=murfey_db,
205216
)
206217
else:
207218
logger.warning("No workflow found for 'atlas_update'")
208-
registration_result = {"success": False, "requeue": False}
209-
else:
210-
registration_result = {"success": True}
211219
else:
212220
# Register data collection group and placeholder for the atlas
213221
dcg_message = {
@@ -228,23 +236,12 @@ def _register_results_in_ispyb(
228236
):
229237
(workflow,) = entry_point_result
230238
# Register grid square
231-
registration_result = workflow.load()(
239+
_ = workflow.load()(
232240
message=dcg_message,
233241
murfey_db=murfey_db,
234242
)
235243
else:
236244
logger.warning("No workflow found for 'data_collection_group'")
237-
registration_result = {"success": False, "requeue": False}
238-
if registration_result.get("success", False):
239-
logger.info(
240-
"Successfully registered data collection group for CLEM workflow "
241-
f"using{result.series_name!r}"
242-
)
243-
else:
244-
logger.warning(
245-
"Failed to register data collection group for CLEM workflow "
246-
f"using {result.series_name!r}"
247-
)
248245

249246
# Store data collection group id in CLEM image series table
250247
dcg_entry = murfey_db.exec(
@@ -263,6 +260,162 @@ def _register_results_in_ispyb(
263260
clem_img_series.dcg_name = dcg_entry.tag
264261
murfey_db.add(clem_img_series)
265262
murfey_db.commit()
263+
murfey_db.close()
264+
265+
266+
def _register_grid_square(
267+
session_id: int,
268+
result: CLEMPreprocessingResult,
269+
murfey_db: Session,
270+
):
271+
# Skip this step if no transport manager object is configured
272+
if _transport_object is None:
273+
logger.error("Unable to find transport manager")
274+
return
275+
# Load all entries for the current data collection group
276+
dcg_name = result.series_name.split("--")[0]
277+
if result.series_name.split("--")[1].isdigit():
278+
dcg_name += f"--{result.series_name.split('--')[1]}"
279+
280+
# Check if an atlas has been registered
281+
if atlas_search := murfey_db.exec(
282+
select(MurfeyDB.CLEMImageSeries)
283+
.where(MurfeyDB.CLEMImageSeries.session_id == session_id)
284+
.where(MurfeyDB.CLEMImageSeries.dcg_name == dcg_name)
285+
.where(MurfeyDB.CLEMImageSeries.data_type == "atlas")
286+
).all():
287+
atlas_entry = atlas_search[0]
288+
else:
289+
logger.info(
290+
f"No atlas has been registered for data collection group {dcg_name!r} yet"
291+
)
292+
return
293+
294+
# Check if there are CLEM entries to register
295+
if clem_img_series_to_register := murfey_db.exec(
296+
select(MurfeyDB.CLEMImageSeries)
297+
.where(MurfeyDB.CLEMImageSeries.session_id == session_id)
298+
.where(MurfeyDB.CLEMImageSeries.dcg_name == dcg_name)
299+
.where(MurfeyDB.CLEMImageSeries.data_type == "grid_square")
300+
):
301+
if (
302+
atlas_entry.x0 is not None
303+
and atlas_entry.x1 is not None
304+
and atlas_entry.y0 is not None
305+
and atlas_entry.y1 is not None
306+
and atlas_entry.pixels_x is not None
307+
and atlas_entry.pixels_y is not None
308+
):
309+
atlas_width_real = atlas_entry.x1 - atlas_entry.x0
310+
atlas_height_real = atlas_entry.y1 - atlas_entry.y0
311+
else:
312+
logger.warning("Atlas entry not populated with required values")
313+
return
314+
315+
for clem_img_series in clem_img_series_to_register:
316+
if (
317+
clem_img_series.x0 is not None
318+
and clem_img_series.x1 is not None
319+
and clem_img_series.y0 is not None
320+
and clem_img_series.y1 is not None
321+
):
322+
# Find pixel corresponding to image midpoint on atlas
323+
x_mid_real = (
324+
0.5 * (clem_img_series.x0 + clem_img_series.x1) - atlas_entry.x0
325+
)
326+
x_mid_px = int(x_mid_real / atlas_width_real * atlas_entry.pixels_x)
327+
y_mid_real = (
328+
0.5 * (clem_img_series.y0 + clem_img_series.y1) - atlas_entry.y0
329+
)
330+
y_mid_px = int(y_mid_real / atlas_height_real * atlas_entry.pixels_y)
331+
else:
332+
logger.warning(
333+
f"Image series {clem_img_series.series_name!r} not populated with required values"
334+
)
335+
continue
336+
337+
# Populate grid square Pydantic model
338+
grid_square_params = GridSquareParameters(
339+
tag=dcg_name,
340+
x_location=clem_img_series.x0,
341+
x_location_scaled=x_mid_px,
342+
y_location=clem_img_series.y0,
343+
y_location_scaled=y_mid_px,
344+
height=clem_img_series.pixels_x,
345+
width=clem_img_series.pixels_y,
346+
x_stage_position=clem_img_series.x0,
347+
y_stage_position=clem_img_series.y0,
348+
pixel_size=clem_img_series.pixel_size,
349+
image=clem_img_series.search_string,
350+
)
351+
# Register or update the grid square entry as required
352+
if grid_square_result := murfey_db.exec(
353+
select(MurfeyDB.GridSquare)
354+
.where(MurfeyDB.GridSquare.name == clem_img_series.id)
355+
.where(MurfeyDB.GridSquare.tag == grid_square_params.tag)
356+
.where(MurfeyDB.GridSquare.session_id == session_id)
357+
).all():
358+
# Update existing grid square entry on Murfey
359+
grid_square_entry = grid_square_result[0]
360+
grid_square_entry.x_location = grid_square_params.x_location
361+
grid_square_entry.y_location = grid_square_params.y_location
362+
grid_square_entry.x_stage_position = grid_square_params.x_stage_position
363+
grid_square_entry.y_stage_position = grid_square_params.y_stage_position
364+
grid_square_entry.readout_area_x = grid_square_params.readout_area_x
365+
grid_square_entry.readout_area_y = grid_square_params.readout_area_y
366+
grid_square_entry.thumbnail_size_x = grid_square_params.thumbnail_size_x
367+
grid_square_entry.thumbnail_size_y = grid_square_params.thumbnail_size_y
368+
grid_square_entry.pixel_size = grid_square_params.pixel_size
369+
grid_square_entry.image = grid_square_params.image
370+
371+
# Update existing entry on ISPyB
372+
_transport_object.do_update_grid_square(
373+
grid_square_id=grid_square_entry.id,
374+
grid_square_parameters=grid_square_params,
375+
)
376+
else:
377+
# Look up data collection group for current series
378+
dcg_entry = murfey_db.exec(
379+
select(MurfeyDB.DataCollectionGroup)
380+
.where(MurfeyDB.DataCollectionGroup.session_id == session_id)
381+
.where(MurfeyDB.DataCollectionGroup.tag == grid_square_params.tag)
382+
).one()
383+
# Register to ISPyB
384+
grid_square_ispyb_result = _transport_object.do_insert_grid_square(
385+
atlas_id=dcg_entry.atlas_id,
386+
grid_square_id=clem_img_series.id,
387+
grid_square_parameters=grid_square_params,
388+
)
389+
# Register to Murfey
390+
grid_square_entry = MurfeyDB.GridSquare(
391+
id=grid_square_ispyb_result.get("return_value", None),
392+
name=clem_img_series.id,
393+
session_id=session_id,
394+
tag=grid_square_params.tag,
395+
x_location=grid_square_params.x_location,
396+
y_location=grid_square_params.y_location,
397+
x_stage_position=grid_square_params.x_stage_position,
398+
y_stage_position=grid_square_params.y_stage_position,
399+
readout_area_x=grid_square_params.readout_area_x,
400+
readout_area_y=grid_square_params.readout_area_y,
401+
thumbnail_size_x=grid_square_params.thumbnail_size_x,
402+
thumbnail_size_y=grid_square_params.thumbnail_size_y,
403+
pixel_size=grid_square_params.pixel_size,
404+
image=grid_square_params.image,
405+
)
406+
murfey_db.add(grid_square_entry)
407+
murfey_db.commit()
408+
409+
# Add grid square ID to existing CLEM image series entry
410+
clem_img_series.grid_square_id = grid_square_entry.id
411+
murfey_db.add(clem_img_series)
412+
murfey_db.commit()
413+
else:
414+
logger.info(
415+
f"No grid squares to register for data collection group {dcg_name!r} yet"
416+
)
417+
murfey_db.close()
418+
return
266419

267420

268421
def run(message: dict, murfey_db: Session, demo: bool = False) -> dict[str, bool]:
@@ -304,7 +457,7 @@ def run(message: dict, murfey_db: Session, demo: bool = False) -> dict[str, bool
304457
return {"success": False, "requeue": False}
305458
try:
306459
# Register items in Murfey database
307-
_register_results_in_murfey(
460+
_register_clem_image_series(
308461
session_id=session_id,
309462
result=result,
310463
murfey_db=murfey_db,
@@ -317,21 +470,37 @@ def run(message: dict, murfey_db: Session, demo: bool = False) -> dict[str, bool
317470
)
318471
return {"success": False, "requeue": False}
319472
try:
320-
# Register items in ISPyB
321-
_register_results_in_ispyb(
473+
# Register data collection group and atlas in ISPyB
474+
_register_dcg_and_atlas(
322475
session_id=session_id,
323476
instrument_name=murfey_session.instrument_name,
324477
visit_name=murfey_session.visit,
325478
result=result,
326479
murfey_db=murfey_db,
327480
)
328481
except Exception:
482+
# Log error but allow workflow to proceed
329483
logger.error(
330484
"Exception encountered when registering data collection group for CLEM workflow "
331485
f"using {result.series_name!r}: \n"
332486
f"{traceback.format_exc()}"
333487
)
334488

489+
try:
490+
# Register dataset as grid square
491+
if "Overview_" not in result.series_name:
492+
_register_grid_square(
493+
session_id=session_id,
494+
result=result,
495+
murfey_db=murfey_db,
496+
)
497+
except Exception:
498+
# Log error but allow workflow to proceed
499+
logger.error(
500+
f"Exception encountered when registering grid square for {result.series_name}: \n"
501+
f"{traceback.format_exc()}"
502+
)
503+
335504
# Construct list of files to use for image alignment and merging steps
336505
image_combos_to_process = [
337506
list(result.output_files.values()) # Composite image of all channels

0 commit comments

Comments
 (0)