diff --git a/src/murfey/util/models.py b/src/murfey/util/models.py index f7ad71905..9070bea3a 100644 --- a/src/murfey/util/models.py +++ b/src/murfey/util/models.py @@ -248,6 +248,7 @@ class FIBImageMetadata(BaseModel): visit_name: str file: Path thumbnail_path: Path | None = None + lamella_number: int | None = None # Acceleration voltage (V) voltage: float # Beam shifts (m) @@ -309,7 +310,10 @@ def site_name(self) -> str: Create a site name for the current image based on the project name and its slot number. """ - return f"{self.project_name}--slot_{self.slot_number}" + site_name = f"{self.project_name}/grid_{self.slot_number}" + if self.lamella_number is not None: + site_name += f"/lamella_{self.lamella_number}" + return site_name """ diff --git a/src/murfey/workflows/fib/register_milling_progress.py b/src/murfey/workflows/fib/register_milling_progress.py index b958cc6b9..c3c4b1673 100644 --- a/src/murfey/workflows/fib/register_milling_progress.py +++ b/src/murfey/workflows/fib/register_milling_progress.py @@ -43,7 +43,7 @@ def _ensure_prerequisites( """ # Construct the DataCollectionGroup and GridSquare lookup tags - dcg_tag = f"{project_name}--slot_{slot_number}" + dcg_tag = f"{project_name}/grid_{slot_number}" # Determine variables to register data collection group and atlas with proposal_code = "".join(char for char in visit_name.split("-")[0] if char.isalpha()) diff --git a/src/murfey/workflows/fib/shared.py b/src/murfey/workflows/fib/shared.py index 444721c14..a0ee133ff 100644 --- a/src/murfey/workflows/fib/shared.py +++ b/src/murfey/workflows/fib/shared.py @@ -11,7 +11,7 @@ import PIL.Image from murfey.util.db import ImagingSite -from murfey.util.fib import get_slot_number +from murfey.util.fib import get_slot_number, number_from_name from murfey.util.models import FIBImageMetadata @@ -101,6 +101,13 @@ def parse_image_metadata( ), # Convert to degrees rotation_offset=rotation_offset, ) + # Determine the lamella number + try: + parts = file.parts + site_idx = parts.index("Sites") + 1 + extracted["lamella_number"] = number_from_name(parts[site_idx]) + except ValueError: + extracted["lamella_number"] = None case _: raise NotImplementedError( f"Unsupported metadata format {metadata_format!r}" diff --git a/tests/workflows/fib/test_fib_shared.py b/tests/workflows/fib/test_fib_shared.py index 67369af18..4e6a21743 100644 --- a/tests/workflows/fib/test_fib_shared.py +++ b/tests/workflows/fib/test_fib_shared.py @@ -5,6 +5,7 @@ import pytest from pytest_mock import MockerFixture +from murfey.util.fib import number_from_name from murfey.util.models import FIBImageMetadata from murfey.workflows.fib.shared import parse_image_metadata from tests.conftest import ExampleVisit @@ -134,8 +135,10 @@ def create_image_metadata( "test_params", ( ( + "autotem", "Metadata", # Tag key "2026-04-15-21-50-14_drift_corrected_image_Finer Milling - Electron Image.png", + "Lamella", # Lamella folder "some_project", 2000, # Voltage 0, # Beam shift X @@ -156,8 +159,34 @@ def create_image_metadata( 1e-6, # Y ), ( + "autotem", "Metadata", # Tag key "2026-04-16-02-39-40_drift_corrected_image_Polishing 2 - Electron Image.png", + "Lamella (23)", # Lamella folder + "another_project", + 2000, # Voltage + 0, # Beam shift X + 0, # Y + 0.003072, # Field of view X + 0.002048, # Y + -0.003, # Stage X + 0.0003, # Y + 0.01, # Z + 1.833, # Rotation + -75, # Rotation offset + 0, # Alpha tilt + 0, # Beta tilt + 2, # Expected slot number + 3072, # Image size X + 2048, # Y + 1e-6, # Pixel size X + 1e-6, # Y + ), + ( + "maps", + 34683, # Tag key + "Electron Snapshot.tiff", + "", # Lamella folder "another_project", 2000, # Voltage 0, # Beam shift X @@ -182,6 +211,8 @@ def create_image_metadata( def test_parse_metadata( mocker: MockerFixture, test_params: tuple[ + str, + str | int, str, str, str, @@ -207,8 +238,10 @@ def test_parse_metadata( ): # Unpack test params ( + workflow_name, tag_key, image_name, + lamella_folder, project_name, voltage, shift_x, @@ -229,13 +262,25 @@ def test_parse_metadata( pixel_size_y, ) = test_params file = ( - visit_dir - / "autotem" - / project_name - / "Sites" - / "Lamella" - / "LamellaEvaluationImages" - / image_name + ( + visit_dir + / "autotem" + / project_name + / "Sites" + / lamella_folder + / "LamellaEvaluationImages" + / image_name + ) + if workflow_name == "autotem" + else ( + visit_dir + / "maps" + / project_name + / "LayersData" + / "Layer" + / "Electron Snapshot" + / image_name + ) ) # Mock the results of opening an image file @@ -256,9 +301,15 @@ def test_parse_metadata( pixel_size_x, pixel_size_y, ) - tags = dict.fromkeys(["Metadata", "MetadataAsINI"], 0) - tags[tag_key] = xml_string - mock_image = MagicMock(text=tags) + tags: dict[str | int, str | int] + if workflow_name == "autotem": + tags = dict.fromkeys(["Metadata", "MetadataAsINI"], 0) + tags[tag_key] = xml_string + mock_image = MagicMock(text=tags) + else: + tags = dict.fromkeys([34682, 34683], 0) + tags[tag_key] = xml_string + mock_image = MagicMock(tag_v2=tags) mocker.patch( "murfey.workflows.fib.shared.PIL.Image.open", return_value=mock_image, @@ -273,6 +324,8 @@ def test_parse_metadata( assert parsed.visit_name == visit_name assert parsed.file == file + lamella_number = number_from_name(lamella_folder) if lamella_folder else None + assert parsed.lamella_number == lamella_number assert parsed.voltage == voltage assert parsed.shift_x == shift_x assert parsed.shift_y == shift_y @@ -289,5 +342,8 @@ def test_parse_metadata( assert parsed.pixel_size_x == pixel_size_x assert parsed.pixel_size_y == pixel_size_y assert parsed.slot_number == expected_slot_number - assert parsed.site_name == f"{project_name}--slot_{expected_slot_number}" + expected_site_name = f"{project_name}/grid_{expected_slot_number}" + if workflow_name == "autotem": + expected_site_name += f"/lamella_{lamella_number}" + assert parsed.site_name == expected_site_name assert parsed.pixel_size == 0.5 * (pixel_size_x + pixel_size_y) diff --git a/tests/workflows/fib/test_register_milling_progress.py b/tests/workflows/fib/test_register_milling_progress.py index fd7a82c2b..aad13cd35 100644 --- a/tests/workflows/fib/test_register_milling_progress.py +++ b/tests/workflows/fib/test_register_milling_progress.py @@ -414,7 +414,7 @@ def test_run_with_db( sm_select(MurfeyDB.DataCollectionGroup) .where(MurfeyDB.DataCollectionGroup.session_id == session_id) .where( - MurfeyDB.DataCollectionGroup.tag == f"{site_info['project_name']}--slot_1" + MurfeyDB.DataCollectionGroup.tag == f"{site_info['project_name']}/grid_1" ) ).one_or_none() assert dcg_murfey is not None