Skip to content

Commit

Permalink
fix: hacky fix for files with subloops (#193)
Browse files Browse the repository at this point in the history
* fix: small hack for strange file

* update comment

* style(pre-commit.ci): auto fixes [...]

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
tlambert03 and pre-commit-ci[bot] committed Feb 22, 2024
1 parent 8b2fd66 commit 9324428
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 3 deletions.
18 changes: 16 additions & 2 deletions src/nd2/_parse/_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def _parse_ne_time_loop(item: NETimeLoopPars) -> strct.NETimeLoop:


def load_experiment(
level: int, src: RawExperimentDict, dest: list[ExpLoop] | None = None
src: RawExperimentDict, level: int = 0, dest: list[ExpLoop] | None = None
) -> list[ExpLoop]:
"""Parse the "ImageMetadata[LV]!" section of an nd2 file."""
dest = dest or []
Expand All @@ -208,10 +208,24 @@ def load_experiment(
if prev.count < loop.count:
dest[-1] = loop

# FIXME:
# hack for file in https://github.com/tlambert03/nd2/issues/190
# there is a better fix, but this is a very rare case
loop_params = src.get("uLoopPars", {})
if "pSubLoops" in loop_params:
loop_params = cast("NETimeLoopPars", loop_params)
subloops = loop_params["pSubLoops"]
i0 = "i0000000000"
if i0 in subloops:
subnext = subloops[i0]["ppNextLevelEx"]
if i0 in subnext:
experiment = subnext[i0]["SLxExperiment"]
dest.extend(load_experiment(experiment))

next_level_src = src.get("ppNextLevelEx")
if next_level_src:
for item in next_level_src.values():
dest = load_experiment(level + 1, item, dest)
dest = load_experiment(item, level + 1, dest)

return dest

Expand Down
10 changes: 10 additions & 0 deletions src/nd2/_sdk_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@ class SpectLoopPars(TypedDict):
pPlanes: PicturePlanesDict
uiCount: NotRequired[int]

class SLxExperimentDict(TypedDict):
SLxExperiment: RawExperimentDict

class SubLoopDict(TypedDict):
uiNextLevelCount: int
# this is a dict of keys 'i0000000000', 'i0000000001', etc.
ppNextLevelEx: dict[str, SLxExperimentDict]

class NETimeLoopPars(TypedDict):
# keys are '_00' or 'i0000000000' ...
pPeriod: dict[str, PeriodDict]
Expand All @@ -167,6 +175,8 @@ class NETimeLoopPars(TypedDict):
uiPeriodCount: int
wsCommandAfterPeriod: str
wsCommandBeforePeriod: str
# this is a dict of keys 'i0000000000', 'i0000000001', etc.
pSubLoops: NotRequired[dict[str, SubLoopDict]]

LoopParsDict: TypeAlias = Union[
TimeLoopPars, XYPosLoopPars, ZStackLoopPars, SpectLoopPars, NETimeLoopPars
Expand Down
2 changes: 1 addition & 1 deletion src/nd2/readers/_modern/modern_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def experiment(self) -> list[structures.ExpLoop]:
exp = self._decode_chunk(k, strip_prefix=False)
exp = exp.get("SLxExperiment", exp) # for v3 only
self._raw_experiment = cast("RawExperimentDict", exp)
self._experiment = load_experiment(0, self._raw_experiment)
self._experiment = load_experiment(self._raw_experiment)
return self._experiment

def loop_indices(self) -> list[dict[str, int]]:
Expand Down

0 comments on commit 9324428

Please sign in to comment.