Skip to content

Commit

Permalink
use regex for HCS label parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
ieivanov committed Oct 5, 2024
1 parent d5b8fac commit eb5ee14
Showing 1 changed file with 33 additions and 43 deletions.
76 changes: 33 additions & 43 deletions iohub/mm_fov.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import re
from pathlib import Path

from xarray import DataArray
Expand Down Expand Up @@ -109,58 +110,47 @@ def stage_positions(self, value):
@property
def hcs_position_labels(self):
"""Parse plate position labels generated by the HCS position generator,
e.g. 'A1-Site_0' or '1-Pos000_000', and split into row, column, and
FOV names.
e.g. 'A1-Site_0', '1-Pos000_000', or 'Pos-9-000_000', and split into
row, column, and FOV names.
Returns
-------
list[tuple[str, str, str]]
FOV name paths, e.g. ('A', '1', '0') or ('0', '1', '000000')
FOV name paths, e.g. ('A', '1', '0'), ('0', '1', '000000'), or
('0', '9', '000000').
"""
if not self.stage_positions:
raise ValueError("Stage position metadata not available.")
try:
# Look for "'A1-Site_0', 'H12-Site_1', ... " format
labels = [
pos["Label"].split("-Site_") for pos in self.stage_positions
]
return [(well[0], well[1:], fov) for well, fov in labels]
except Exception:
try:
# Look for "'1-Pos000_000', '2-Pos000_001', ... "
# and split into ('1', '000_000'), ...
labels = [
pos["Label"].split("-Pos") for pos in self.stage_positions
]

# remove underscore from FOV name, i.e. '000_000'
# collect all wells in row '0' so output is
# ('0', '1', '000000')
return [
("0", col, fov.replace("_", "")) for col, fov in labels
]
except Exception:
try:
# Look for "'Pos-1-000_000', 'Pos-2-000_001', ... "
# and split into ('1', '000_000'), ...
# New format following
# https://github.com/micro-manager/micro-manager/pull/1897
labels = [
pos["Label"].split("Pos-")[1].split("-")
for pos in self.stage_positions
]
return [
("0", col, fov.replace("_", "")) for col, fov in labels
]

except Exception:
labels = [pos.get("Label") for pos in self.stage_positions]
raise ValueError(
"HCS position labels are in the format of "
"'A1-Site_0', 'H12-Site_1', or '1-Pos000_000', "
f"or 'Pos-1-000_000'. Got labels {labels}"

# See https://chatgpt.com/share/e/67009155-d960-8008-bd64-aa3117b142b6
pattern = re.compile(
r"([A-Za-z])?(\d+)-(?:Site_(\d+)|Pos(?:-)?(\d+)[-_](\d+))"
)
labels = [pos.get("Label") for pos in self.stage_positions]
row_col_fov = []
for label in labels:
if label:
match = re.match(pattern, label)
if match:
row = match.group(1) if match.group(1) else "0"
col = match.group(2)
fov = (
match.group(3)
if match.group(3)
else f"{match.group(4)}{match.group(5)}"
)

row_col_fov.append((row, col, fov))

if not row_col_fov:
raise ValueError(
"HCS position labels are in the format of "
"'A1-Site_0', 'H12-Site_1', or '1-Pos000_000', "
f"or 'Pos-1-000_000'. Got labels {labels}"
)

return row_col_fov

@property
def zyx_scale(self) -> tuple[float, float, float]:
"""ZXY pixel size in micrometers."""
Expand Down

0 comments on commit eb5ee14

Please sign in to comment.