2020
2121import murfey .util .db as MurfeyDB
2222from murfey .server import _transport_object
23+ from murfey .util .models import GridSquareParameters
2324from 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
268421def 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