spacr.spacrops
Module Contents
- class spacr.spacrops.spacrStitcher(detector: str = 'ORB', nfeatures: int = 6000, max_keypoints: int | None = 2000, downsample: float = 0.5, ransac_thresh_px: float = 3.0, allow_scale: bool = False, allow_rotation: bool = False, outline_source: str = 'otsu', canny: Tuple[int, int] = (40, 120), blur_sigma: float = 0.0, dilate_ksize: int = 0, line_thickness: int = 1, outline_alpha: float = 1.0, outdir: str = './sbs_out', save_qc: bool = True, save_stitched_default: bool = True, all_scores: bool = False, score_threshold: float | None = None, verbose: bool = False, feature_cache_mode: str = 'disk', feature_cache_dir: str | None = None, max_ram_features: int = 256, n_workers_features: int | None = None, pair_batch_size: int = 8000, stream_csv: bool = True, opencv_threads: int = 1, arr_axes: str = 'AUTO', mip: bool = False, z_index: int = 0, t_index: int = 0, squeeze_singleton: bool = True)[source]
Pairwise stitcher with downsampled scoring and whole-well mosaic assembly.
- Robustness features for very large datasets:
feature_cache_mode: “disk” (default) writes DS features to disk with an LRU RAM cap
pair_batch_size: limit number of concurrent pair futures
stream_csv: write pairwise rows immediately (low RAM)
opencv_threads: limit OpenCV internal threading to avoid oversubscription
Transform control
- allow_scale: if True → use RANSAC affine (rotation+scale+translation)
if False → enforce unit scale (see allow_rotation)
- allow_rotation: if True → rotation+translation
if False → translation-only
Mosaic
Uses topology-aware pruning + maximum spanning tree on pairwise scores to build a cohesive grid. Exports mosaic image and a mosaic.csv manifest.
Axis & Z handling
- arr_axesstr in {“AUTO”} or a string over {T,C,Z,Y,X} (e.g. “CZYX”, “CYX”, “ZYX”).
Determines how to interpret multi-dimensional TIFFs.
mip : bool. If True and Z exists, perform max-intensity projection over Z. z_index : int (if mip=False) choose Z slice index. t_index : int choose time index if T exists.
- set_meta_regex(pattern: str | re.Pattern)[source]
Replace the filename regex used to parse well, site, channel and magnification.
- prepare_features(paths: List[str], channel_index: int, num_workers: int | None = None)[source]
Precompute keypoints and descriptors for
pathsand cache them.In
diskmode every result is flushed to the on-disk feature store with only an LRU-sized subset kept in RAM; inrammode results are held in memory only.- Parameters:
paths – image files to feature.
channel_index – channel to read from multi-channel TIFFs.
num_workers – worker thread count; defaults to
self.n_workers_features.
- Returns:
None.
- stitch_pair(pathA: str, pathB: str, channel_index: int = 0, score_threshold: float | None = None, save_stitched: bool | None = None, force_no_qc: bool = False, qc_only_if_score_ge: float | None = None) Dict | None[source]
Estimate the B-to-A affine, score the overlap, and optionally write the stitched pair.
- Parameters:
pathA – reference image path.
pathB – image to align to
pathA.channel_index – channel used for feature matching. Default
0.score_threshold – minimum edge-ZNCC score required to save the stitched TIFF; falls back to
self.score_threshold.save_stitched – override for whether to write the stitched image; falls back to
self.save_stitched_default.force_no_qc – suppress QC overlay images regardless of settings.
qc_only_if_score_ge – emit QC overlays only when the pair score meets this cutoff.
- Returns:
dict of pair metrics and output paths, or
Nonewhen matching/RANSAC fails.
- run_folder(folder: str, csv_path: str, *, channel_index: int = 0, exts: Tuple[str, Ellipsis] = ('.tif', '.tiff'), recursive: bool = False, same_well_only: bool = True, max_site_gap: int = 3, n_workers: int = 8, stitch: bool = True, score_threshold: float | None = None, meta_regex: str | re.Pattern | None = None, mosaic: bool = False, mosaic_out: str | None = None, mosaic_min_score: float | None = None, mosaic_csv_out: str | None = None, mosaic_all_channels: bool = False, mosaic_channel_count: int | None = None, mosaic_channel_index_order: List[int] | None = None, qc_pairs_threshold: int = 1000, qc_only_above_threshold_when_many: bool = True) str[source]
Score every candidate pair in
folderand optionally build a whole-well mosaic.When the number of candidate pairs exceeds
qc_pairs_threshold, QC overlays are skipped in the first pass and reissued only for pairs whose score clears the auto-threshold in the second pass.- Parameters:
folder – directory of tiles to scan.
csv_path – destination CSV for pairwise metrics.
channel_index – channel used for feature scoring. Default
0.exts – accepted image extensions.
recursive – recurse into subfolders. Default
False.same_well_only – restrict pairings to the same parsed well. Default
True.max_site_gap – maximum site-index gap between candidate neighbours. Default
3.n_workers – worker threads for the scoring pass. Default
8.stitch – save stitched TIFFs for pairs above the score threshold.
score_threshold – minimum score required to save the stitched image.
meta_regex – override the filename regex before scanning.
mosaic – build a single-channel mosaic once pair scoring finishes.
mosaic_out – output TIFF path for the mosaic (single-channel mode).
mosaic_min_score – minimum edge score used when pruning mosaic edges.
mosaic_csv_out – output CSV path for the mosaic manifest.
mosaic_all_channels – build a CYX mosaic across all channels.
mosaic_channel_count – force this many channels for the multi-channel mosaic.
mosaic_channel_index_order – explicit channel order for the multi-channel mosaic.
qc_pairs_threshold – pair count above which QC plotting is gated.
qc_only_above_threshold_when_many – enable the second-pass, score-gated QC output.
- Returns:
path to the pairwise-metrics CSV.
- build_multichannel_mosaic_from_manifest(manifest_csv: str, out_tif: str, out_png: str | None = None, channel_indices: List[int] | None = None, blend: str = 'max', tmp_dir: str | None = None, preview_downsample: int = 8)[source]
Build a CYX BigTIFF mosaic from a ‘mosaic.csv’ manifest written by spacrStitcher.render_mosaic_from_csv(…).
- Expected CSV columns (per tile row):
path, H, W, M00, M01, M02, M10, M11, M12, canvas_x, canvas_y, best_pair_score
Notes
Uses the 2x3 affine in the manifest (already includes global offset).
If channel_indices is None, infers the channel count from the first valid tile.
blend=”max” takes per-pixel max across overlapping tiles; blend=”overwrite” writes the latest tile over earlier ones where coverage>0.
If tmp_dir is provided (or available from self.feature_cache_dir), the output workspace uses a disk memmap to reduce RAM.
- render_mosaic_from_csv(csv_path: str, out_tif: str, out_png: str | None = None, channel_index: int = 0, min_score: float | None = None, *, angle_tol_deg: float = 30.0, step_tol_frac: float = 0.25, rot_tol_deg: float = 5.0, scale_tol: float = 0.03, cap_one_per_dir: bool = True, out_csv: str | None = None) Tuple[str, str | None][source]
Assemble a mosaic image (and manifest) from a pairwise-metrics CSV.
Pass
out_tif=Nonetogether with anout_csvto run in manifest-only mode (transforms are computed and written but no image is rendered).- Parameters:
csv_path – input pairwise metrics CSV.
out_tif – mosaic TIFF output path (
Nonefor manifest-only).out_png – optional preview PNG output path.
channel_index – channel used for rendering. Default
0.min_score – minimum pair score kept for the mosaic (auto-detected when
None).angle_tol_deg – tolerance for classifying edges into R/L/U/D bins.
step_tol_frac – fractional tolerance around the estimated grid step.
rot_tol_deg – max allowed rotation when rotation is disabled.
scale_tol – max allowed scale deviation when scaling is disabled.
cap_one_per_dir – keep at most one edge per direction per tile.
out_csv – optional path to the per-tile manifest CSV.
- Returns:
tuple
(out_tif, out_png).
- mosaic_all_channels_from_csv(csv_path: str, out_tif: str | None, *, min_score: float | None = None, channel_count: int | None = None, channel_index_order: List[int] | None = None, angle_tol_deg: float = 30.0, step_tol_frac: float = 0.25, rot_tol_deg: float = 5.0, scale_tol: float = 0.03, cap_one_per_dir: bool = True, out_csv: str | None = None) str | None[source]
Assemble a multi-channel CYX mosaic by reusing pairwise transforms across channels.
Pass
out_tif=Nonewith anout_csvto run in manifest-only mode (compute transforms and canvas geometry, write manifest, skip rendering).- Parameters:
csv_path – input pairwise metrics CSV.
out_tif – mosaic TIFF output path (
Nonefor manifest-only).min_score – minimum pair score kept for the mosaic (auto-detected when
None).channel_count – force this many channels; auto-detected when
None.channel_index_order – explicit channel index ordering for the output.
angle_tol_deg – tolerance for classifying edges into R/L/U/D bins.
step_tol_frac – fractional tolerance around the estimated grid step.
rot_tol_deg – max allowed rotation when rotation is disabled.
scale_tol – max allowed scale deviation when scaling is disabled.
cap_one_per_dir – keep at most one edge per direction per tile.
out_csv – optional per-tile manifest CSV path.
- Returns:
path to the mosaic TIFF (or
Nonein manifest-only mode).
- class spacr.spacrops.StitchedMultiAligner(detector: str = 'ORB', nfeatures: int = 6000, max_keypoints: int | None = 2000, downsample: float = 0.5, ransac_thresh_px: float = 3.0, allow_scale: bool = False, allow_rotation: bool = False, outdir: str = './align_out', opencv_threads: int = 1, arr_axes: str = 'AUTO', mip: bool = False, z_index: int = 0, t_index: int = 0, squeeze_singleton: bool = True)[source]
Align an arbitrary number of stitched mosaics (multi-channel, arbitrary axes) to a common reference using the nuclei/ Hoechst channel. Saves a channel-concatenated aligned stack and a CSV manifest describing the mapping from input channels to output channels and the estimated transforms/scores.
Output image axes: CYX (channels stacked in the order inputs are provided).
- Parameters:
detector ({"ORB","SIFT"}) – Feature detector for keypoint matching.
nfeatures (int) – Feature budget for detector.
max_keypoints (Optional[int]) – Hard cap on kept keypoints after detection (by detector’s internal ranking).
downsample (float in (0,1]) – Downsample factor for feature/score pass.
ransac_thresh_px (float) – Reprojection threshold (pixels) for affine estimation (downsampled space).
allow_scale (bool) – If False, constrain to rotation+translation (or translation only if allow_rotation=False).
allow_rotation (bool) – If False, constrain to translation only.
outdir (str) – Output directory for images/csv.
opencv_threads (int) – Limit OpenCV internal threading (avoid oversubscription).
reading) (# Axis/Z/time handling (for TIFF)
arr_axes ("AUTO" or a string over {T,C,Z,Y,X})
mip (bool) – If True and Z exists, max-project Z.
z_index (int) – If mip=False, choose Z slice.
t_index (int) – Choose T index if T exists.
squeeze_singleton (bool) – Squeeze 1-length axes after slicing.
Notes
Alignment is done to the first image in paths (reference).
For each image, you can provide a per-image nuclei channel index via nuclei_channel_indices. If None, defaults to 0 for all.
- align(paths: List[str], nuclei_channel_indices: List[int] | None = None, out_tif: str | None = None, out_png_preview: str | None = None, csv_path: str | None = None) Tuple[str, str | None, str | None][source]
Align every stitched mosaic in
pathsto the first and save a CYX stack.Alignment uses the specified nuclei channel per image; the resulting stack concatenates all input channels in the order given.
- Parameters:
paths – stitched TIFFs to align;
paths[0]is the reference.nuclei_channel_indices – per-image nuclei channel indices; defaults to zeros.
out_tif – output aligned stack path; defaults to
<outdir>/aligned_allc.tif.out_png_preview – optional preview PNG path.
csv_path – manifest CSV path; defaults to
<outdir>/aligned_manifest.csv.
- Returns:
tuple
(out_tif, out_png_preview, csv_path).
- spacr.spacrops.stitch_cycle_wells(settings)[source]
Organize a plate of TIFFs into per-well folders and stitch each well.
Groups images by well from filename metadata, optionally moves or symlinks them into per-well folders, then runs
spacrStitcheron each well to produce pairwise CSVs and single- or multi-channel mosaics.- Parameters:
settings – dict of preprocess settings; see
get_preprocess_ops_settings()for supported keys.- Returns:
dict with keys
organized(move/symlink summary) andwells(per-well output paths).
- spacr.spacrops.get_preprocess_ops_settings(settings)[source]
Fill in defaults for the ops preprocessing / stitching / alignment pipeline.
- Parameters:
settings – user-supplied settings dict, updated in place with defaults.
- Returns:
the settings dict with all defaults populated.
- class spacr.spacrops.FOVAlignAndCropper(detector: str = 'ORB', nfeatures: int = 6000, max_keypoints: int | None = 2000, downsample: float = 0.5, ransac_thresh_px: float = 3.0, allow_scale: bool = False, allow_rotation: bool = False, outdir: str = './fov_out', opencv_threads: int = 1, arr_axes: str = 'AUTO', mip: bool = False, z_index: int = 0, t_index: int = 0, squeeze_singleton: bool = True, folder_image_scale: float = 1.0)[source]
Align individual FOVs to a stitched mosaic and export FOV-frame stacks.
For each FOV, saves a
.npywith shape(C_fov + C_mosaic, H_fov, W_fov)(native FOV channels stacked with the mosaic channels warped into the FOV frame) and a CSV row with the transform, score and mosaic bbox.Delegates feature/matching helpers to
StitchedMultiAligner.- Parameters:
detector – keypoint detector (
'ORB'or'SIFT'). Default'ORB'.nfeatures – feature budget for the detector.
max_keypoints – hard cap on kept keypoints after detection.
downsample – downsample factor for the feature/score pass.
ransac_thresh_px – RANSAC reprojection threshold (pixels, downsampled space).
allow_scale – allow scale in the estimated affine.
allow_rotation – allow rotation in the estimated affine.
outdir – output directory. Default
'./fov_out'.opencv_threads – OpenCV internal thread cap.
arr_axes – TIFF axis interpretation (
'AUTO'or string overTCZYX).mip – max-project Z when present.
z_index – Z slice to select if
mipis false.t_index – T slice to select if T is present.
squeeze_singleton – squeeze length-1 axes after slicing.
folder_image_scale – default FOV-to-mosaic pixel-scale factor used by
run().
- run(stitched_path: str, folder: str, *, stitched_nuclei_idx: int = 0, fov_nuclei_idx: int = 0, exts: Tuple[str, Ellipsis] = ('.tif', '.tiff'), recursive: bool = False, csv_path: str | None = None, npy_dir: str | None = None, folder_image_scale: float | None = None) str[source]
Align every FOV in
foldertostitched_pathand export FOV-frame stacks.Uses the nuclei channel for alignment and writes one
.npyper FOV containing the FOV channels plus mosaic channels warped into the FOV frame.- Parameters:
stitched_path – path to the reference stitched mosaic.
folder – directory of FOV TIFFs to align.
stitched_nuclei_idx – nuclei channel index in the mosaic. Default
0.fov_nuclei_idx – nuclei channel index in each FOV. Default
0.exts – accepted FOV extensions.
recursive – recurse into subfolders.
csv_path – output manifest CSV path; defaults to
<outdir>/fov_align_manifest.csv.npy_dir – output folder for the per-FOV
.npystacks; defaults to<outdir>/npy.folder_image_scale – FOV-to-mosaic pixel-scale factor; falls back to
self.folder_image_scale.
- Returns:
path to the manifest CSV.
- spacr.spacrops.align_image_to_stitch(stitch_dst_root: str, align_src: str, *, meta_regex: str = '(?P<mag>\\d+X)_c(?P<chan>\\d+)_?(?P<well>[A-H]\\d{1,2}).*?Site[-_](?P<site>\\d+)\\.(?:tif|tiff)$', well_group: str = 'well', channel_index: int = 0, relative_scale: float = 2.0, downsample: float = 0.5, nfeatures: int = 4000, ransac_thresh_px: float = 3.0, allow_scale: bool = False, allow_rotation: bool = False, qc_outlines: bool = False, recursive_align_src: bool = True, exts: tuple = ('.tif', '.tiff')) Dict[str, Dict[str, str]][source]
Align each well’s higher-mag FOVs to that well’s stitched mosaic.
For every well with a mosaic at
<stitch_dst_root>/<WELL>/_stitch/mosaic_allc.tif, groups images fromalign_srcby well and runsFOVAlignAndCropperto produce per-well crop manifests and.npycrops.- Parameters:
stitch_dst_root – root folder containing per-well stitched mosaics.
align_src – folder of higher-magnification images to align.
meta_regex – regex extracting well/site metadata from filenames.
well_group – named capture group holding the well identifier.
channel_index – nuclei channel index. Default
0.relative_scale – FOV-to-mosaic pixel-scale factor. Default
2.0.downsample – feature-pass downsample factor. Default
0.5.nfeatures – keypoint budget for the detector.
ransac_thresh_px – RANSAC reprojection threshold in pixels.
allow_scale – allow scale in the estimated affine.
allow_rotation – allow rotation in the estimated affine.
qc_outlines – emit QC outline overlays.
recursive_align_src – recurse when scanning
align_src.exts – accepted image extensions.
- Returns:
mapping
{well: {'mosaic': path, 'align_folder': path, 'manifest_csv': path}}.
- spacr.spacrops.ops_preprocess(settings)[source]
Run the full ops preprocessing pipeline: per-genotype stitching + phenotype alignment.
Iterates over one or more genotype folders, calls
stitch_cycle_wells()on each, then aligns the phenotype images to the resulting mosaics viaalign_image_to_stitch().- Parameters:
settings – dict of preprocessing settings; see
get_preprocess_ops_settings()for supported keys.- Returns:
dict with
stitch(per-genotype summaries),align(per-genotype align results) andnpy_out_root(npy output root path).