Skip to content

Quantitative storage

This page describes how measurement datasets are stored on disk, for maintainers and anyone reading a dataset.sqlite directly. Dataset users need only the query API. Generic dataset creation writes SQLite storage version 5, canine native-evidence builds write version 6, and versions 1–6 are all readable. The sections below follow the history of the layout.

ORFdata 0.8 writes compact SQLite storage version 4. Measurement, QuantitativeDataset, the registry and CLI keep the same public records and query semantics. Human, mouse, dog, yeast and arbitrary taxa retain separate reference-scoped identities.

References, targets and assays are stored once and addressed by internal integer keys. Measurements retain their values and metadata; repeated required fields are reconstructed from indexed columns and the dataset manifest. Fields equal to the fixed version-4 defaults are omitted from stored JSON and restored on read. Zeros, nulls, censoring, uncertainty, nested provenance and derived inputs retain their meaning. Foreign keys prevent cross-reference target/assay assignments. Internal integer keys never appear as public biological identifiers.

ORFdata 0.32 writes storage version 5, which also stores each target mapping's candidates as kind, identifier and namespace: they always share the mapping's reference, which its row already names. The dog DLA ligand dataset, with 62,492 mappings, is 255 MB, against 389 MB in the version 4 layout. Version 4 files remain readable, and a version 4 fixture written by the released ORFdata 0.30.0 tests that.

Published storage versions 1 to 6 remain readable. There is no automatic migration or replacement of downloaded artifacts. A new source rebuild can use a different storage layout and therefore a different file checksum while returning the same records. Registry downloads always verify the exact published artifact's hash; source builds retain their own DataCache receipts.

Large releases can distribute a tar.gz archive in ordered, checksummed parts. DatasetRegistry.download() installs these through DataCache's transactional archive support and still returns one dataset.sqlite. The registry pins every part, the assembled compressed archive, and the extracted SQLite bytes separately. Only that one regular file is permitted; extraction has an explicit size limit. The extracted hash and embedded dataset manifest are checked before publication and when an existing installation is reused. A failed refresh preserves readers of the previous installation. This requires DataCache 1.29.3 or later.

download_metadata() includes an archive definition for these releases. Local overrides use source_paths={"dataset.sqlite": [part0, part1, ...]} in the declared order. After installation, open() and inspect() remain offline and need neither the parts nor original build inputs. Checks use the registry's independent SQLite hash, so changing both cached bytes and a cache receipt cannot repin a release. verify_files=False skips content hashing but checks file type and size, and never reports cryptographic verification. Historical single-file releases retain their existing download paths.

A source asset may likewise declare metadata.archive, with its own hash and size describing the extracted file. Explicit source builds can acquire that component, or accept an ordered list of local part paths for its source override. A local extracted-file override still works. Opening a built dataset never acquires a component, and an already verified source build can be reused after the separate component cache has been removed.

The implementation streams observations and bounds its target cache to 131,072 entries. SQLite index statistics are populated during creation so a narrow target query can use the target index instead of scanning an entire reference. Raw SQL table layouts are internal; use the Python/CLI query and export APIs.

Native peptide vectors

Canine native-evidence builds use storage version 6 for the common measurement API. Numeric vectors preserve their declared type, exact numeric bytes, independent presence bits and null-vector state. Sample/assay axes and native source records are stored once. Queries expand the requested cells into ordinary Measurement objects, retaining missing values, source record IDs, native units and provenance. Target and assay indexes select vectors before expansion. Counts report logical observations rather than stored vectors. Mapped/paired queries and Parquet export use the same projection. Opening and querying a release never accesses the remote vendor file or requires the extraction dependencies.

The native evidence component declares its own encoding version. Version 2 stores scalar values in source-column order with a hexadecimal presence mask; column names are stored once per table. A present null remains distinct from an omitted field stored in the binary or numeric-vector tables. Readers reconstruct the same original dictionaries and also support version-1 JSON-object records. Malformed masks, missing fields and conflicting payloads are rejected. The common quantitative storage version remains 6.

Measured-only queries discard source-null vectors in SQL before expanding cells; non-null vectors still receive per-cell presence and finite-value checks. Missing queries and logical counts retain every null cell. On a 10,000-group spread across the completed native table, the same 30,831 measured records (identical full-field hash) took 30.2 seconds before this filter and 3.4 seconds after it. The query expanded 1,758 non-null vectors instead of 30,000 total vectors. This is a bounded query benchmark, not a full-dataset performance guarantee.

Version 6 declares its projection encoding and completion state explicitly. It does not contain an empty flat measurement view: SQL access to that old internal view fails. Generic dataset creation continues to write version 5, and versions 1–5 remain readable without migration.

The packaged canine importer also requires a final successful build receipt. It pins normalized evidence, compiled lineage, searched FASTA and the existing protein summary; validates the source selection and counts; builds membership and candidate indexes; and projects the native vectors. Common mappings() and relations() queries project the existing indexes into TargetMapping and TargetRelation records without storing another copy. Counts include those logical mappings and relations. Native-table inspection uses the source module's CanineEvidence(dataset.path) adapter. Its summary_group() query connects the baseline summary representative to native records and group links without duplicating the baseline abundance series or asserting unique protein detection.

A bounded comparison of 100 actual native peptide groups (source row IDs 50, 100, …, 5000) reproduced all 13,200 cells from their three 44-channel abundance vectors, field for field. Flat storage occupied 24,891,392 bytes; vector storage occupied 6,557,696 bytes including exact selected source evidence and shared sample/assay metadata. Peak benchmark process RSS was 127,729,664 bytes. This is a storage slice, not a completed canine dataset release or a guarantee of full-dataset size.

Actual-source benchmark

The first 100,000 rows of the native Pfizer/GEO RNA table contain four dog libraries and 30,941 genes, including measured zeros. Source gzip SHA-256: a22780f92ffd0a028e30fe3392d73d01f787eb5a62b2043e8d26940191cbac70. This is a storage benchmark slice, not a newly released experimental dataset.

Measurement Storage v3 Storage v4
Installed size 121.6 MB 38.6 MB
Gzip size 13.4 MB 7.5 MB
Build time 8.90 s 4.28 s
One-gene query (four results) 135 ms 1.5 ms
Peak build RSS 39.8 MB 52.1 MB

All 100,000 reconstructed observations were compared field for field. Timings are local measurements on Python 3.12, not cross-machine guarantees; the bounded target cache trades some memory for repeated-target lookup speed. Legacy tests also use actual databases written by ORFdata 0.3.0, 0.4.0 and 0.5.0.