|
15 | 15 |
|
16 | 16 |
|
17 | 17 | def run(message: dict[str, Any], murfey_db: SQLModelSession): |
18 | | - # Outer try-finally block to close Murfey DB with |
19 | | - try: |
20 | | - try: |
21 | | - # Parse and unpack incoming message |
22 | | - session_id = int(message["session_id"]) |
23 | | - gif_params = FIBGIFParameters(**message["gif_params"]) |
24 | | - except Exception: |
25 | | - logger.error("Error parsing contents of message", exc_info=True) |
26 | | - return {"success": False, "requeue": False} |
| 18 | + # Parse and unpack incoming message |
| 19 | + session_id = int(message["session_id"]) |
| 20 | + gif_params = FIBGIFParameters(**message["gif_params"]) |
27 | 21 |
|
28 | | - # Load machine config and session info |
29 | | - session_entry = murfey_db.exec( |
30 | | - select(MurfeyDB.Session).where(MurfeyDB.Session.id == session_id) |
31 | | - ).one() |
32 | | - instrument_name = session_entry.instrument_name |
33 | | - visit_name = session_entry.visit |
34 | | - machine_config = get_machine_config(instrument_name=instrument_name)[ |
35 | | - instrument_name |
36 | | - ] |
37 | | - rsync_basepath = machine_config.rsync_basepath or Path(".").resolve() |
| 22 | + # Load machine config and session info |
| 23 | + session_entry = murfey_db.exec( |
| 24 | + select(MurfeyDB.Session).where(MurfeyDB.Session.id == session_id) |
| 25 | + ).one() |
| 26 | + instrument_name = session_entry.instrument_name |
| 27 | + visit_name = session_entry.visit |
| 28 | + machine_config = get_machine_config(instrument_name=instrument_name)[ |
| 29 | + instrument_name |
| 30 | + ] |
| 31 | + rsync_basepath = machine_config.rsync_basepath or Path(".").resolve() |
38 | 32 |
|
39 | | - # Sanitise and verify that the output directory is relative to rsync basepath |
40 | | - output_file = sanitise_path(gif_params.output_file) |
41 | | - if not output_file.is_relative_to(rsync_basepath): |
42 | | - raise ValueError("Output file path is not permitted") |
| 33 | + # Sanitise and verify that the output directory is relative to rsync basepath |
| 34 | + output_file = sanitise_path(gif_params.output_file) |
| 35 | + if not output_file.is_relative_to(rsync_basepath): |
| 36 | + raise ValueError("Output file path is not permitted") |
43 | 37 |
|
44 | | - # Create folders in the visit directory and onwards and change permissions |
45 | | - visit_index = output_file.parts.index(visit_name) |
46 | | - for current_path in list(reversed(output_file.parents))[visit_index + 1 :]: |
47 | | - if not current_path.exists(): |
48 | | - current_path.mkdir(parents=True) |
49 | | - logger.debug(f"Created output directory {current_path}") |
50 | | - safe_chmod(current_path, mode=machine_config.mkdir_chmod) |
| 38 | + # Create folders in the visit directory and onwards and change permissions |
| 39 | + visit_index = output_file.parts.index(visit_name) |
| 40 | + for current_path in list(reversed(output_file.parents))[visit_index + 1 :]: |
| 41 | + if not current_path.exists(): |
| 42 | + current_path.mkdir(parents=True) |
| 43 | + logger.debug(f"Created output directory {current_path}") |
| 44 | + safe_chmod(current_path, mode=machine_config.mkdir_chmod) |
51 | 45 |
|
52 | | - # Load the images as PIL Image objects |
53 | | - converted: list[PIL.Image.Image] = [] |
54 | | - for f in gif_params.images: |
55 | | - with PIL.Image.open(f) as im: |
56 | | - im.thumbnail((512, 512)) |
57 | | - frame = np.array(im, dtype=np.float32) |
58 | | - # Normalise to 8-bit |
59 | | - vmin, vmax = np.percentile(frame, (0.5, 99.5)) |
60 | | - scale = 255 / ((vmax - vmin) or 1) |
61 | | - np.clip(frame, a_min=vmin, a_max=vmax, out=frame) |
62 | | - np.subtract(frame, vmin, out=frame) |
63 | | - np.multiply(frame, scale, out=frame) |
64 | | - # Convert back to PIL Image |
65 | | - converted.append( |
66 | | - PIL.Image.fromarray(frame.astype(np.uint8), mode="L").copy() |
67 | | - ) |
68 | | - del frame # Explicitly remove frame from memory |
69 | | - # Save stack as a GIF |
70 | | - if not converted: |
71 | | - raise ValueError("No images were provided or loaded") |
72 | | - converted[0].save( |
73 | | - output_file, |
74 | | - format="GIF", |
75 | | - append_images=converted[1:], |
76 | | - save_all=True, |
77 | | - duration=30, |
78 | | - loop=0, |
79 | | - ) |
80 | | - logger.info(f"Created GIF file {output_file}") |
81 | | - return {"success": True} |
82 | | - except Exception: |
83 | | - logger.error("Error creating FIB milling GIF", exc_info=True) |
84 | | - return {"success": False, "requeue": False} |
85 | | - finally: |
86 | | - murfey_db.close() |
| 46 | + # Load the images as PIL Image objects |
| 47 | + converted: list[PIL.Image.Image] = [] |
| 48 | + for f in gif_params.images: |
| 49 | + with PIL.Image.open(f) as im: |
| 50 | + im.thumbnail((512, 512)) |
| 51 | + frame = np.array(im, dtype=np.float32) |
| 52 | + # Normalise to 8-bit |
| 53 | + vmin, vmax = np.percentile(frame, (0.5, 99.5)) |
| 54 | + scale = 255 / ((vmax - vmin) or 1) |
| 55 | + np.clip(frame, a_min=vmin, a_max=vmax, out=frame) |
| 56 | + np.subtract(frame, vmin, out=frame) |
| 57 | + np.multiply(frame, scale, out=frame) |
| 58 | + # Convert back to PIL Image |
| 59 | + converted.append(PIL.Image.fromarray(frame.astype(np.uint8), mode="L").copy()) |
| 60 | + del frame # Explicitly remove frame from memory |
| 61 | + |
| 62 | + # Save stack as a GIF |
| 63 | + if not converted: |
| 64 | + raise ValueError("No images were provided or loaded") |
| 65 | + converted[0].save( |
| 66 | + output_file, |
| 67 | + format="GIF", |
| 68 | + append_images=converted[1:], |
| 69 | + save_all=True, |
| 70 | + duration=30, |
| 71 | + loop=0, |
| 72 | + ) |
| 73 | + logger.info(f"Created GIF file {output_file}") |
| 74 | + return {"success": True} |
0 commit comments