spacr.portable_paths

Resolve recorded crop paths after a dataset is moved or remounted.

png_list.png_path is absolute when written. If the dataset later moves to another computer or mount point, the prefix changes while the directory structure below the screen remains the same:

<recorded root>/plate1/data/single_nucleus/single_pathogen/plate1_H19/...
<current  root>/plate1/data/single_nucleus/single_pathogen/plate1_H19/...

Resolution selects the deepest recorded suffix that exists below the current root. The root may be a database file, measurements folder, plate folder, or screen folder. Paths are changed only when the reconstructed file exists, and the database itself is never modified.

Classes

RerootReport

What one re-rooting pass did, INCLUDING what it could not do.

Functions

candidate_roots(→ Tuple[str, ...])

Every folder root could mean, nearest first.

reroot_column(frame, column, src_root)

Re-root one path column of frame IN THE FRAME, never on disk.

reroot_crop_path(→ Optional[str])

path as it exists under src_root, or path unchanged.

source_root_for_database(→ str)

The plate folder a measurements.db belongs to.

Module Contents

class spacr.portable_paths.RerootReport[source]

What one re-rooting pass did, INCLUDING what it could not do.

The last two fields are the reason this is a record and not a bare count. A path with no recognisable structure under the root is returned unchanged and otherwise fails later as a missing file with less context. The report counts unresolved paths and includes an example so callers can explain the problem where re-rooting was attempted.

Parameters:
  • column – DataFrame column inspected and, when at least one value moves, rewritten in place.

  • moved – number of nonblank path values replaced by existing paths discovered below a candidate root.

  • unresolved – number of nonblank string paths that remained missing after re-rooting; existing, blank, and non-string values do not count.

  • first_unresolved – first unresolved source path encountered, or an empty string when none remained.

  • root – first normalized candidate derived from src_root, used in report messages; it need not be the ancestor where a match was found.

describe() str[source]

One line for a caller to print, or “” when there is nothing to say.

property absent: bool[source]

Nothing in this column could be placed, and nothing already was.

property partial: bool[source]

Some of this column resolved and some did not.

THE DISTINCTION THAT DECIDES WHETHER TO SHOUT. A column where nothing resolved and nothing existed is a ROUTE THAT IS NOT ON THIS MACHINE – a screen with PNG crops and no merged/ folder has 60,816 unplaceable path_name values and is completely healthy. A column where most paths resolved and a few did not is the actionable partial-failure case.

spacr.portable_paths.candidate_roots(root: str | None) Tuple[str, ...][source]

Every folder root could mean, nearest first.

Parameters:

root – plate, screen, measurements folder, or database path to normalize into candidate roots; None yields no candidates.

Accepts the plate folder, the screen folder, the measurements/ folder, or the measurements.db file itself – callers hold different ones and should not each have to normalise.

spacr.portable_paths.reroot_column(frame, column: str, src_root: str | None)[source]

Re-root one path column of frame IN THE FRAME, never on disk.

Parameters:
  • frame – any DataFrame; a missing column is not an error, because the PNG route and the merged route carry different ones and a caller should be able to ask for both.

  • column – name of the path-bearing column to resolve and, when any paths move, replace in place.

  • src_root – anything candidate_roots() accepts.

Returns:

a RerootReport, which counts as its own moved in a boolean or integer context, so a caller that only wants the number still gets it.

Resolves the first dead path against the filesystem, then applies the prefix that worked to the rest – 60,816 rows cost one search plus one string replacement each, rather than 60,816 searches. Any row the prefix does not fix is still resolved on its own, so a frame holding crops from two different screens is not half-abandoned.

spacr.portable_paths.reroot_crop_path(path: str | None, src_root: str | None) str | None[source]

path as it exists under src_root, or path unchanged.

Parameters:
  • path – the recorded absolute path, or anything falsy.

  • src_root – the plate folder, the screen folder, the measurements folder, or the database file. All four resolve.

Returns:

a path that EXISTS when one could be built; otherwise the input untouched, so a caller’s error still names what was recorded.

spacr.portable_paths.source_root_for_database(db_path: str) str[source]

The plate folder a measurements.db belongs to.

Parameters:

db_path – path to the measurements database; an empty path yields an empty result.

<plate>/measurements/measurements.db -> <plate>, which is the folder that holds data/. Derived rather than passed so a reader gains portability without new plumbing through every caller; candidate_roots() then covers the cases where the layout differs.