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

Result of one re-rooting pass: how many paths moved and how many did not.

Functions

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

Return the candidate root folders derived from root, nearest first.

reroot_column(frame, column, src_root)

Re-root one path column of frame in place; files on disk are not changed.

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]

Result of one re-rooting pass: how many paths moved and how many did not.

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.

__bool__() → bool[source]

Return whether at least one path was moved to a new root.

__int__() → int[source]

Return the number of paths moved to a new root.

describe() → str[source]

Return one line for a caller to print, or "" when nothing moved or failed.

property absent: bool[source]

True when no path in this column moved and at least one stayed unresolved.

property partial: bool[source]

True when some paths in this column moved and some stayed unresolved.

This separates a partial failure from a route whose files are not on this machine. A column where nothing moved usually belongs to such a route – a screen with PNG crops and no merged/ folder has 60,816 unplaceable path_name values and is healthy (see absent). A column where most paths resolved and a few did not is the partial failure that a caller should report.

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

Return the candidate root folders derived from root, 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 place; files on disk are not changed.

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.