spacr.ops_engine

Workflow inputs and outputs

OPS

Use sequencing-cycle images and phenotype alignment to decode barcodes per nucleus. Aggregate/join the decoded identities to compatible phenotype inputs before Regression; the OPS database is not a drop-in FASTQ count CSV.

Open: Mask → OPS.

Inputs and outputs below include conditional alternatives. The guidance and handoff notes say which route applies.

Inputs

  • Microscope images — Source image folder; original files, supported vendor files or imported TIFFs.

  • Aligned mosaic and coordinates — Align & Stitch destination: composed image and the tile-coordinate/layout records needed to interpret it.

Outputs

  • Optical barcode assignments — OPS destination measurements.db: per-well geometry, phenotype alignment, nuclei and barcode tables; optional per-cycle reads. Relevant tables, depending on the route: ops_geometry, ops_phenotype, ops_objects, ops_barcodes, ops_reads.

Before this module

  • Align & Stitch: Carry tile coordinates and original sequencing cycles into OPS; a flattened mosaic alone is insufficient.

After this module

  • Regression: Join/aggregate decoded objects to phenotype and guide inputs explicitly before Regression; this is not a direct CSV handoff.

API reference.

Module tutorial.

Run an optical pooled screen’s sequencing acquisition from tiles to tables.

One call takes each well from its tile files to the tables of measurements.db: ops_geometry, where each nuclear tile sits in the well frame; ops_phenotype, where each field of the high-magnification phenotype acquisition lands on that frame and which tile covers it; ops_objects, one row per nucleus, segmented on the composed nuclear map and numbered once for the well; ops_barcodes, one row per nucleus whose attributed reads agree; and, when asked for, ops_reads, one row per read per cycle behind those barcodes.

A file that cannot be read costs one cycle of the field it belongs to and is listed in the report; it does not cost the well.

Functions

run_ops(→ Dict[str, Any])

Stitch, place, segment and decode the wells of one sequencing acquisition.

run_spatial_map(→ Dict[str, Any])

Count every transcript or bin into the cells of the spatial fields.

run_spatial_masks(→ Dict[str, Any])

Segment a whole Xenium or Visium HD slide into Measure-ready fields.

Module Contents

spacr.ops_engine.run_ops(settings: Mapping[str, Any], *, wells: Sequence[str] | None = None, phases: Sequence[str] = _PHASES, library=None) → Dict[str, Any][source]

Stitch, place, segment and decode the wells of one sequencing acquisition.

Parameters:
  • settings –

    the OPS settings. Read here: genotype_source, the folder of sequencing tiles, searched recursively; phenotype_source, the folder of the high-magnification phenotype acquisition, which the phenotype phase places on the stitched well and which an empty value skips; dst_root, where measurements.db and the per-well reports go, the source folder when empty; plate, the source folder’s name when empty; ops_gpu; n_workers, how many fields decode at once; cellpose_model and cellpose_diameter; ops_library, a guide library CSV the library keyword overrides; and the five measured numbers ops_base_channels, ops_read_threshold, ops_raster_overlap, ops_window_overlap and ops_footprint, each of which falls back to the value this plate was validated at. ops_store_reads writes ops_reads.

    Either folder may be a parent of both halves, and each setting still reads its own: genotype_source indexes only names that carry a cycle and phenotype_source only names that do not, falling back to cycled names for a phenotype acquisition that carries them. Pointing both at 20200202_6W-LaC024A therefore runs the plate, rather than filing 1,281 phenotype fields and 333 sequencing ones as one acquisition – see _index_tiles().

  • wells – which wells to run; every well found when None.

  • phases – any of "stitch", "phenotype", "objects" and "decode", run in that order. A phase left out reads what it needs from the database, so a well can be stitched once and decoded again.

  • library – the guide barcodes, as a sequence or the path of a CSV with a prefix, barcode or sequence column. When given, each barcode is also mapped to its closest guide. Overrides the ops_library setting.

Returns:

{"db": path, "wells": {well: {phase: report}}}.

Raises:

ValueError – when the source holds no tiles this can name, an unknown phase or well is asked for, or a phase’s input is missing.

spacr.ops_engine.run_spatial_map(settings: Mapping[str, Any]) → Dict[str, Any][source]

Count every transcript or bin into the cells of the spatial fields.

Reads the whole Xenium bundle (transcripts at spatial_min_qv) or one Visium HD bin size, puts every point in full-resolution pixels of the slide image (_st_slide_xy()), then in the frame of each field Spatial Mask Generation wrote (_st_field_frame()), and counts it into the object of each plane named in spatial_objects: Xenium transcripts by the pixel they fall in, Visium HD bins shared out by the fraction of the bin each object covers. Each object is owned by one field, so nothing is counted twice across the overlaps. The counts go to <object>_expression (and for Xenium <object>_expression_long, for Visium HD <object>_spot_coverage) in the fields’ measurements.db, keyed by prcfo like Measure’s tables. Infection calls, infected-versus-uninfected tests, the distance trend (to the nearest infected cell, over the uninfected ones), the region summary, the .h5ad export and an overlay of the field with the most cells go to spatial_transcriptomics beside the masks.

Parameters:

settings – the Spatial Map Barcodes settings (spacr.ops_settings.SPATIAL_MAP_DEFAULTS).

Returns:

the run report, also written as spatial_map_report.json.

Raises:

ValueError – when the masks folder holds no fields of this slide or a requested plane is not in the fields.

spacr.ops_engine.run_spatial_masks(settings: Mapping[str, Any], *, segment=None) → Dict[str, Any][source]

Segment a whole Xenium or Visium HD slide into Measure-ready fields.

The slide (or spatial_window of it) is cut into overlapping windows with spacr.ops_compose.windows_over(); each window’s tiles are read with _st_read_window(), its nuclei segmented and grown into cells, and the observations sewn and numbered across the seams with spacr.ops_objects.sew() and spacr.ops_objects.number(), the OPS window code. Every object is kept from one window that saw all of it, and every window that keeps an object is written as a field: stack/<stem>.npy, masks/cell_mask_stack and masks/nucleus_mask_stack, and merged/<stem>.npy (the channels, then the cell and nucleus masks) with the plane-layout file, the layout Mask Generation writes and Measure reads. The fields’ places on the slide go to the spatial_fields table and the objects to spatial_objects in measurements/measurements.db.

Parameters:
  • settings – the Spatial Mask Generation settings (spacr.ops_settings.SPATIAL_MASK_DEFAULTS).

  • segment – optional callable taking the stain image and returning its nucleus label image, in place of the configured segmenter.

Returns:

the run report, also written as spatial_mask_report.json.

Raises:

ValueError – when the source is not a folder or the overlap is not smaller than the window.

Nested helpers

_decode_field.load_slot(slot)

Read one original source with the shared deferred overload policy.

spacr/ops_engine.py:1385

_largest_component.find(site: int) → int

The representative of site’s component.

Parameters:

site – a site.

Returns:

its root.

spacr/ops_engine.py:432

_phenotype.seed_of(site: int) → Tuple[float, float]

Where a phenotype field’s centre is expected, before aligning it.

Parameters:

site – the phenotype site.

Returns:

the (y, x) seed in the well frame.

spacr/ops_engine.py:889

_phenotype.usable_under(window) → Dict[int, Tuple[float, float]]

The placed tiles that touch window and read.

Parameters:

window – the rectangle about to be composed.

Returns:

site -> (y, x) for compose_window().

Only tiles that touch the window are opened, not the whole well. Six anchors need about nine tiles each; testing readability over every placement instead would read all 333 of the reference well’s sequencing tiles, and tifffile reads the whole five-plane 1,480 px file for one plane of it – 22 MB each, about 7 GB over NFS per well, before compose_window re-reads the nine it needs. The overlap test is the same rounding compose_window uses, so a tile is offered here exactly when it would have been used there; a tile that will not read is dropped so the composer never sees a None.

spacr/ops_engine.py:910

_st_level_geometry.size(item)

(rows, columns) of one level of the series.

spacr/ops_engine.py:3604

_st_register_intensity.shrink(image)

Return the grayscale registration image and its reduction factor.

spacr/ops_engine.py:2504