smftools.informatics.ragged_store#
Read-relative molecule storage and reference-grid materialization.
Ragged records keep per-base arrays in query coordinates. CIGAR placement is performed only when a dense reference-grid slice is requested, avoiding the mandatory padded matrices produced by the legacy load path.
Functions
|
Convert a pysam-like aligned segment to one read-relative record. |
|
Return |
|
Return the number of query bases consumed by cigar. |
|
Return the number of reference positions consumed by cigar. |
|
Yield |
|
Scatter selected read-relative records onto a dense reference grid. |
|
Memory-bounded |
|
Parse a SAM CIGAR string and reject malformed or unsupported input. |
|
Read ragged parquet shard(s), optionally retaining selected read IDs. |
|
Summarize an ordered deamination-vote track for PCR-chimera detection. |
|
Validate and normalize a ragged molecule DataFrame. |
|
Validate and write one shard of read-relative molecule records. |
- smftools.informatics.ragged_store.parse_cigar(cigar)#
Parse a SAM CIGAR string and reject malformed or unsupported input.
- smftools.informatics.ragged_store.cigar_query_length(cigar)#
Return the number of query bases consumed by cigar.
- Return type:
- smftools.informatics.ragged_store.cigar_reference_length(cigar)#
Return the number of reference positions consumed by cigar.
- Return type:
- smftools.informatics.ragged_store.cigar_max_indel_runs(cigar)#
Return
(max_insertion_run, max_deletion_run)for a CIGAR string.Each value is the length of the single longest internal insertion (
I) or deletion (D) operation. Insertions and deletions in a SAM CIGAR are always internal to the aligned span (read ends are represented as soft/hard clips), so no edge trimming is required. Returns(0, 0)for an unmapped/absent CIGAR ("*"or empty) rather than raising.
- smftools.informatics.ragged_store.strand_switch_metrics(signs)#
Summarize an ordered deamination-vote track for PCR-chimera detection.
signsis a reference-ordered list of per-position strand votes,+1for a C->T (top-consistent) event and-1for a G->A (bottom-consistent) event. A pure molecule is all one sign; a PCR chimera is a run of one sign followed by a run of the other.Returns
(segment_purity, switch_index)where: :rtype:tuple[float,int]segment_purityis the best two-segment purity over all split points, i.e.(max(#+, #-) left + max(#+, #-) right) / n. It is ~1.0 for both a pure molecule and a clean chimera, and lower for a randomly interspersed (noisy) read. With fewer than two votes it is 1.0 (trivially consistent).switch_indexis the indexk(split before positionk) of the best split whose left/right majorities have opposite sign, or-1if no split separates opposite majorities. Callers mapkto a reference coordinate.
- smftools.informatics.ragged_store.iter_cigar_aligned_pairs(cigar, reference_start)#
Yield
(query_position, reference_position)for aligned CIGAR bases.
- smftools.informatics.ragged_store.validate_ragged_frame(frame)#
Validate and normalize a ragged molecule DataFrame.
Returns a copy so callers never have their input DataFrame mutated.
- Return type:
DataFrame
- smftools.informatics.ragged_store.write_ragged_parquet(frame, path)#
Validate and write one shard of read-relative molecule records.
- Return type:
- smftools.informatics.ragged_store.read_ragged_parquet(paths, *, read_ids=None)#
Read ragged parquet shard(s), optionally retaining selected read IDs.
read_ids, when given, is pushed down as a pyarrow filter (pd.read_parquet(..., filters=[(read_id, "in", ...)])) rather than reading the whole shard into pandas and filtering afterward -- only the selected rows' ragged arrays are ever materialized, which is most of the remaining memory floor after streaming materialization (see dev/pipeline_scaling_audit.md, and_narrow_ragged_valuesabove for the other half).- Return type:
DataFrame
- smftools.informatics.ragged_store.alignment_to_ragged_record(read, reference_sequence, *, reference=None, reference_strand=None)#
Convert a pysam-like aligned segment to one read-relative record.
- smftools.informatics.ragged_store.materialize_ragged(frame, *, obs, reference_lengths, layers=None, uns=None, start=None, end=None)#
Scatter selected read-relative records onto a dense reference grid.
Whole-frame entry point: the caller already holds every selected read's ragged arrays in
frame.materialize_ragged_streamingis the memory-bounded variant for large selections (it never holds more than one shard's ragged frame plus the dense output at once); both share_scatter_read_rowso they cannot diverge.- Return type:
AnnData
- smftools.informatics.ragged_store.materialize_ragged_streaming(chunks, *, obs, reference_lengths, layers=None, uns=None, start=None, end=None)#
Memory-bounded
materialize_raggedthat consumes ragged frames in chunks.obs(one row per selected read, in output order) fixes the dense output shape/order and, via itsReference_strandcolumn, the reference lengths -- so the dense grids are preallocated once, up front, fromobsalone. Each chunk (e.g. one parquet shard filtered to the selection) is then scattered into those grids and freed before the next arrives; peak memory is therefore ~one chunk's ragged frame + the dense output, independent of the total selection size. This is the fix for a real ~27x memory balloon: reading a whole selection's ragged arrays into one pandas frame before compacting to dense (int64/float64 list-columns are ~25-50x their dense footprint) drove a nominally-0.5GB preprocess task to 16-44GB peak (see dev/pipeline_scaling_audit.md). Reads in a chunk that are not inobsare ignored (a shard holds many barcodes' reads); a chunk with no matching reads contributes nothing.- Return type:
AnnData