Skip to content

Commit 29e8668

Browse files
committed
Add minimal logic needed to create, save, and register thumbnail images of the FIB atlases
1 parent c778394 commit 29e8668

1 file changed

Lines changed: 69 additions & 7 deletions

File tree

src/murfey/workflows/fib/register_atlas.py

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import os
23
import traceback
34
import xml.etree.ElementTree as ET
45
from functools import cached_property
@@ -12,6 +13,7 @@
1213
from sqlmodel import Session, select
1314

1415
import murfey.util.db as MurfeyDB
16+
from murfey.util.config import get_machine_config
1517
from murfey.util.fib import number_from_name
1618

1719
logger = logging.getLogger("murfey.workflows.fib.register_atlas")
@@ -25,6 +27,7 @@ class FIBAtlasMetadata(BaseModel):
2527

2628
visit_name: str
2729
file: Path
30+
thumbnail_path: Path | None = None
2831
# Acceleration voltage
2932
voltage: float
3033
# Beam shifts
@@ -79,16 +82,24 @@ def slot_number(self) -> int:
7982
# mypy doesn't support decorators on @property
8083
@computed_field # type: ignore
8184
@cached_property
82-
def site_name(self) -> str:
85+
def project_name(self) -> str:
8386
"""
84-
Create a site name for the current image based on the project name
85-
and its slot number. This assumes a specific folder structure of
86-
{visit_name}/maps/{project_name}
87+
Extract the project name from the file path. This assumes a specific
88+
folder structure of '{visit_name}/maps/{project_name}'.
8789
"""
8890
path_parts = self.file.parts
8991
visit_idx = path_parts.index(self.visit_name)
90-
project_name = path_parts[visit_idx + 2] # {visit}/maps/{project_name}
91-
return f"{project_name}--slot_{self.slot_number}"
92+
return path_parts[visit_idx + 2] # {visit}/maps/{project_name}
93+
94+
# mypy doesn't support decorators on @property
95+
@computed_field # type: ignore
96+
@cached_property
97+
def site_name(self) -> str:
98+
"""
99+
Create a site name for the current image based on the project name
100+
and its slot number.
101+
"""
102+
return f"{self.project_name}--slot_{self.slot_number}"
92103

93104

94105
def _parse_metadata(file: Path, visit_name: str):
@@ -146,6 +157,35 @@ def _parse_metadata(file: Path, visit_name: str):
146157
)
147158

148159

160+
def _make_thumbnail(file: Path, metadata: FIBAtlasMetadata, visit_name: str, mode: int):
161+
img = PIL.Image.open(file)
162+
img.thumbnail((512, 512))
163+
164+
# Find visit directory path
165+
visit_idx = file.parts.index(visit_name)
166+
visit_dir = list(reversed(file.parents))[visit_idx]
167+
168+
# Construct processed directory and set permissions
169+
processed_dir = visit_dir / "processed"
170+
processed_dir.mkdir(exist_ok=True)
171+
os.chmod(processed_dir, mode=mode)
172+
173+
# Construct path to thumbnail
174+
image_number = number_from_name(file.stem)
175+
save_path = (
176+
processed_dir
177+
/ metadata.project_name
178+
/ f"grid_{metadata.slot_number}"
179+
/ "atlas"
180+
/ f"atlas_{str(image_number).zfill(2)}.png"
181+
)
182+
save_path.parent.mkdir(parents=True, exist_ok=True)
183+
184+
# Save the thumbnail
185+
img.save(save_path)
186+
return save_path
187+
188+
149189
def _register_fib_imaging_site(
150190
session_id: int,
151191
metadata: FIBAtlasMetadata,
@@ -172,6 +212,13 @@ def _update_entry(
172212
imaging_site.image_pixels_y = metadata.pixels_y
173213
imaging_site.image_pixel_size = metadata.pixel_size
174214

215+
if metadata.thumbnail_path is not None:
216+
scale = 512 / (max(metadata.pixels_x, metadata.pixels_y) or 1)
217+
imaging_site.thumbnail_path = str(metadata.thumbnail_path)
218+
imaging_site.thumbnail_pixels_x = int(round(metadata.pixels_x * scale)) or 1
219+
imaging_site.thumbnail_pixels_y = int(round(metadata.pixels_y * scale)) or 1
220+
imaging_site.thumbnail_pixel_size = metadata.pixel_size / scale
221+
175222
return imaging_site
176223

177224
if (
@@ -202,7 +249,7 @@ def _update_entry(
202249
else:
203250
current_number = 0
204251
# Update if incoming one is newer
205-
if incoming_number > current_number:
252+
if incoming_number >= current_number:
206253
fib_imaging_site = _update_entry(fib_imaging_site, metadata)
207254

208255
murfey_db.add(fib_imaging_site)
@@ -323,6 +370,8 @@ def run(
323370
)
324371
).one()
325372
visit_name = murfey_session.visit
373+
instrument_name = murfey_session.instrument_name
374+
machine_config = get_machine_config(instrument_name)[instrument_name]
326375
except Exception:
327376
logger.error(
328377
"Exception encountered while querying Murfey database", exc_info=True
@@ -339,6 +388,19 @@ def run(
339388
)
340389
return {"success": False, "requeue": False}
341390

391+
try:
392+
# Make a thumbnail of the image and update metadata accordingly
393+
metadata.thumbnail_path = _make_thumbnail(
394+
file=metadata.file,
395+
metadata=metadata,
396+
visit_name=visit_name,
397+
mode=machine_config.mkdir_chmod,
398+
)
399+
except Exception:
400+
logger.warning(
401+
f"Error creating thumbnail of file {fib_info.atlas_file}", exc_info=True
402+
)
403+
342404
try:
343405
# Register imaging site in Murfey, or update existing one
344406
fib_imaging_site = _register_fib_imaging_site(

0 commit comments

Comments
 (0)