Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/murfey/util/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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


"""
Expand Down
2 changes: 1 addition & 1 deletion src/murfey/workflows/fib/register_milling_progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
9 changes: 8 additions & 1 deletion src/murfey/workflows/fib/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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}"
Expand Down
78 changes: 67 additions & 11 deletions tests/workflows/fib/test_fib_shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -182,6 +211,8 @@ def create_image_metadata(
def test_parse_metadata(
mocker: MockerFixture,
test_params: tuple[
str,
str | int,
str,
str,
str,
Expand All @@ -207,8 +238,10 @@ def test_parse_metadata(
):
# Unpack test params
(
workflow_name,
tag_key,
image_name,
lamella_folder,
project_name,
voltage,
shift_x,
Expand All @@ -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
Expand All @@ -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,
Expand All @@ -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
Expand All @@ -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)
2 changes: 1 addition & 1 deletion tests/workflows/fib/test_register_milling_progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down