orfdata 0.4.0__tar.gz → 0.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. {orfdata-0.4.0 → orfdata-0.6.0}/MANIFEST.in +1 -1
  2. {orfdata-0.4.0/orfdata.egg-info → orfdata-0.6.0}/PKG-INFO +8 -4
  3. {orfdata-0.4.0 → orfdata-0.6.0}/README.md +7 -3
  4. {orfdata-0.4.0 → orfdata-0.6.0}/docs/measurements.md +17 -3
  5. {orfdata-0.4.0 → orfdata-0.6.0}/docs/pairing.md +15 -2
  6. orfdata-0.6.0/docs/pfizer-protein.md +71 -0
  7. {orfdata-0.4.0 → orfdata-0.6.0}/docs/reference.md +2 -3
  8. orfdata-0.6.0/docs/source-references.md +90 -0
  9. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/__init__.py +13 -1
  10. orfdata-0.6.0/orfdata/data/datasets.json +388 -0
  11. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/dataset.py +116 -26
  12. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/dataset_cli.py +41 -6
  13. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/datasets.py +10 -0
  14. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/measurements.py +47 -1
  15. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/pairing.py +41 -8
  16. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/reference.py +32 -7
  17. orfdata-0.6.0/orfdata/reference_mapping.py +150 -0
  18. orfdata-0.6.0/orfdata/sources/__init__.py +10 -0
  19. orfdata-0.6.0/orfdata/sources/pfizer.py +213 -0
  20. orfdata-0.6.0/orfdata/version.py +1 -0
  21. {orfdata-0.4.0 → orfdata-0.6.0/orfdata.egg-info}/PKG-INFO +8 -4
  22. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata.egg-info/SOURCES.txt +22 -0
  23. orfdata-0.6.0/tests/data/pfizer/NOTICE.md +14 -0
  24. orfdata-0.6.0/tests/data/pfizer/dog/expected.json +192 -0
  25. orfdata-0.6.0/tests/data/pfizer/dog/manifest.json +117 -0
  26. orfdata-0.6.0/tests/data/pfizer/dog/protein.tsv +6 -0
  27. orfdata-0.6.0/tests/data/pfizer/dog/search.fasta +6 -0
  28. orfdata-0.6.0/tests/data/pfizer/human/expected.json +190 -0
  29. orfdata-0.6.0/tests/data/pfizer/human/manifest.json +115 -0
  30. orfdata-0.6.0/tests/data/pfizer/human/protein.tsv +6 -0
  31. orfdata-0.6.0/tests/data/pfizer/human/search.fasta +6 -0
  32. orfdata-0.6.0/tests/data/pfizer/mouse/expected.json +193 -0
  33. orfdata-0.6.0/tests/data/pfizer/mouse/manifest.json +118 -0
  34. orfdata-0.6.0/tests/data/pfizer/mouse/protein.tsv +6 -0
  35. orfdata-0.6.0/tests/data/pfizer/mouse/search.fasta +6 -0
  36. orfdata-0.6.0/tests/data/references/context-keys-v0.4.json +62 -0
  37. orfdata-0.6.0/tests/test_cross_reference_pairing.py +160 -0
  38. {orfdata-0.4.0 → orfdata-0.6.0}/tests/test_measurements.py +1 -1
  39. orfdata-0.6.0/tests/test_pfizer.py +199 -0
  40. orfdata-0.6.0/tests/test_reference_mapping.py +225 -0
  41. orfdata-0.4.0/orfdata/data/datasets.json +0 -1
  42. orfdata-0.4.0/orfdata/version.py +0 -1
  43. {orfdata-0.4.0 → orfdata-0.6.0}/LICENSE +0 -0
  44. {orfdata-0.4.0 → orfdata-0.6.0}/deploy.sh +0 -0
  45. {orfdata-0.4.0 → orfdata-0.6.0}/docs/design.md +0 -0
  46. {orfdata-0.4.0 → orfdata-0.6.0}/docs/species.md +0 -0
  47. {orfdata-0.4.0 → orfdata-0.6.0}/lint.sh +0 -0
  48. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/build.py +0 -0
  49. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/catalog.py +0 -0
  50. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/cli.py +0 -0
  51. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/data/orf-evidence/AUTHOR-LICENSE.txt +0 -0
  52. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/data/orf-evidence/NOTICE.txt +0 -0
  53. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/data/orf-evidence/catalog.json.gz +0 -0
  54. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/data/orf-evidence/manifest.json +0 -0
  55. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/data/uorf-evidence/AUTHOR-LICENSE.txt +0 -0
  56. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/data/uorf-evidence/NOTICE.txt +0 -0
  57. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/data/uorf-evidence/catalog.json.gz +0 -0
  58. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/data/uorf-evidence/manifest.json +0 -0
  59. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/initiation_context.py +0 -0
  60. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/model.py +0 -0
  61. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata/sequence.py +0 -0
  62. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata.egg-info/dependency_links.txt +0 -0
  63. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata.egg-info/entry_points.txt +0 -0
  64. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata.egg-info/requires.txt +0 -0
  65. {orfdata-0.4.0 → orfdata-0.6.0}/orfdata.egg-info/top_level.txt +0 -0
  66. {orfdata-0.4.0 → orfdata-0.6.0}/pyproject.toml +0 -0
  67. {orfdata-0.4.0 → orfdata-0.6.0}/setup.cfg +0 -0
  68. {orfdata-0.4.0 → orfdata-0.6.0}/test.sh +0 -0
  69. {orfdata-0.4.0 → orfdata-0.6.0}/tests/conftest.py +0 -0
  70. {orfdata-0.4.0 → orfdata-0.6.0}/tests/data/references/README.md +0 -0
  71. {orfdata-0.4.0 → orfdata-0.6.0}/tests/data/references/canis_lupus_familiaris.json +0 -0
  72. {orfdata-0.4.0 → orfdata-0.6.0}/tests/data/references/homo_sapiens.json +0 -0
  73. {orfdata-0.4.0 → orfdata-0.6.0}/tests/data/references/mus_musculus.json +0 -0
  74. {orfdata-0.4.0 → orfdata-0.6.0}/tests/data/references/saccharomyces_cerevisiae.json +0 -0
  75. {orfdata-0.4.0 → orfdata-0.6.0}/tests/test_initiation_context.py +0 -0
  76. {orfdata-0.4.0 → orfdata-0.6.0}/tests/test_pairing.py +0 -0
  77. {orfdata-0.4.0 → orfdata-0.6.0}/tests/test_reference_context.py +0 -0
  78. {orfdata-0.4.0 → orfdata-0.6.0}/tests/test_reference_orf.py +0 -0
  79. {orfdata-0.4.0 → orfdata-0.6.0}/tests/test_uorf_catalog.py +0 -0
@@ -1,3 +1,3 @@
1
1
  include lint.sh test.sh deploy.sh
2
2
  recursive-include docs *.md
3
- recursive-include tests *.py *.json *.md
3
+ recursive-include tests *.py *.json *.md *.tsv *.fasta
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orfdata
3
- Version: 0.4.0
3
+ Version: 0.6.0
4
4
  Summary: Reference open reading frames and experimental translation evidence on annotated transcripts
5
5
  Author: OpenVax
6
6
  License-Expression: Apache-2.0
@@ -95,12 +95,16 @@ RNA products. Reference evidence stays separate from evidence for a variant or
95
95
  fusion. See the [API and integration guide](docs/reference.md).
96
96
 
97
97
  The catalogue API supports other species, with explicit species and assembly
98
- checks. **Bundled experimental evidence is currently human-only**. Offline tests
98
+ checks. **The bundled experimental ORF catalogue is currently human-only**. Offline tests
99
99
  bind real human, mouse, dog and yeast reference slices; those fixtures are not
100
100
  new experimental ORF catalogues. [Species and reference identity](docs/species.md).
101
101
 
102
102
  Install with `pip install orfdata[pyensembl]`. See the
103
103
  [measurement API](docs/measurements.md) for native units, explicit samples and
104
- assays, and DataCache-managed downloads, and the
104
+ assays, and DataCache-managed downloads. Downloadable
105
+ [human, mouse and dog protein abundance](docs/pfizer-protein.md) uses the same
106
+ species-scoped API. These canonical-search protein groups do not establish
107
+ noncanonical ORF abundance. The
105
108
  [quantitative, multispecies data roadmap](https://github.com/openvax/orfdata/issues/3)
106
- for upcoming RNA abundance, ribosome occupancy and protein data releases.
109
+ tracks RNA abundance, ribosome occupancy, yeast absolute quantification and
110
+ additional protein data releases.
@@ -68,12 +68,16 @@ RNA products. Reference evidence stays separate from evidence for a variant or
68
68
  fusion. See the [API and integration guide](docs/reference.md).
69
69
 
70
70
  The catalogue API supports other species, with explicit species and assembly
71
- checks. **Bundled experimental evidence is currently human-only**. Offline tests
71
+ checks. **The bundled experimental ORF catalogue is currently human-only**. Offline tests
72
72
  bind real human, mouse, dog and yeast reference slices; those fixtures are not
73
73
  new experimental ORF catalogues. [Species and reference identity](docs/species.md).
74
74
 
75
75
  Install with `pip install orfdata[pyensembl]`. See the
76
76
  [measurement API](docs/measurements.md) for native units, explicit samples and
77
- assays, and DataCache-managed downloads, and the
77
+ assays, and DataCache-managed downloads. Downloadable
78
+ [human, mouse and dog protein abundance](docs/pfizer-protein.md) uses the same
79
+ species-scoped API. These canonical-search protein groups do not establish
80
+ noncanonical ORF abundance. The
78
81
  [quantitative, multispecies data roadmap](https://github.com/openvax/orfdata/issues/3)
79
- for upcoming RNA abundance, ribosome occupancy and protein data releases.
82
+ tracks RNA abundance, ribosome occupancy, yeast absolute quantification and
83
+ additional protein data releases.
@@ -6,8 +6,9 @@ proteins, protein groups and peptides. A measurement stays at the resolution
6
6
  the experiment supports. Parent-gene RNA abundance is useful context for an ORF;
7
7
  it is not a separate measurement of each ORF in that gene.
8
8
 
9
- Install `orfdata[data]` to manage datasets. The initial 0.3 registry is empty;
10
- the [data roadmap](https://github.com/openvax/orfdata/issues/3) tracks source
9
+ Install `orfdata[data]` to manage datasets. The registry includes downloadable
10
+ [Pfizer/Oziolor human, mouse and dog protein summaries](pfizer-protein.md);
11
+ the [data roadmap](https://github.com/openvax/orfdata/issues/3) tracks further
11
12
  imports. The bundled human ORF evidence catalogue remains available offline.
12
13
  Its pooled PSM counts describe spectra, not sample-level protein abundance.
13
14
 
@@ -46,6 +47,10 @@ mapping table. The default PyEnsembl target uses its unversioned `id`; request
46
47
  mapping across annotation releases, gene isoforms, ORFs or species. A variant or
47
48
  fusion product does not inherit a native reference protein measurement.
48
49
 
50
+ For native sources with unreported genomic metadata, use explicit
51
+ [source references and mapping views](source-references.md) to retain the original
52
+ observation alongside its mapping to a PyEnsembl target.
53
+
49
54
  The CLI uses the same operations:
50
55
 
51
56
  ```sh
@@ -96,7 +101,10 @@ An importer calls `QuantitativeDataset.create(path, manifest, samples=...,
96
101
  assays=..., measurements=..., mappings=...)`. These inputs may be generators;
97
102
  measurements are written incrementally. Every observation names a source asset
98
103
  or earlier input measurements. Derived inputs precede outputs in the same
99
- reference context. Duplicate IDs, broken foreign keys, wrong dataset releases
104
+ dataset release. `input_measurements` names IDs within the output reference;
105
+ `input_references` instead uses `MeasurementReference` records with each input's
106
+ dataset, version, reference and ID. The two forms cannot be mixed. Cross-species
107
+ derived abundance is rejected. Duplicate IDs, broken foreign keys, wrong dataset releases
100
108
  and cross-reference links fail the import. Failed builds do not replace data.
101
109
 
102
110
  Use `build_dataset(manifest, builder, ...)` for a managed local import.
@@ -123,6 +131,12 @@ definitions = {
123
131
  ```
124
132
 
125
133
  CLI users can supply this JSON with `orfdata datasets --registry FILE ...`.
134
+
135
+ Rebuild supported releases from their pinned original inputs with
136
+ `registry.build(name, version, source_paths={"asset_id": "/local/file"})` or
137
+ `orfdata datasets build NAME --source-path ASSET=PATH`. Local overrides still
138
+ require the published hashes. Rebuilds use a separate import cache and preserve
139
+ installed releases. Unsupported source importers fail explicitly.
126
140
  `ORFDATA_CACHE`, then `OPENVAX_DATA_CACHE`, then the platform's OpenVax cache
127
141
  select the root. ORFdata owns its `orfdata/` child. Release cache identities
128
142
  include manifest/reference and content hashes. SQLite partitions every table
@@ -25,6 +25,13 @@ only explicitly concurrent assays are returned; opt into `longitudinal` or
25
25
  TMT channels and bridges remain in the assays and do not become biological
26
26
  sample counts.
27
27
 
28
+ RNA annotation and protein search references can differ. `AssayPair.reference`
29
+ is the left assay's context; `right_reference` explicitly identifies the right
30
+ assay's context and defaults to the left for older records. Both must belong to
31
+ the same species. A protein FASTA does not need an invented genomic assembly:
32
+ see [source references](source-references.md). Original targets and references
33
+ remain attached to both sides, even when their local IDs happen to match.
34
+
28
35
  The CLI streams the same table rows:
29
36
 
30
37
  ```sh
@@ -39,10 +46,13 @@ and cardinality. `same_target` compares one target across assays/samples.
39
46
  `parent_rna_context` links parent RNA to an ORF but keeps the RNA value attached
40
47
  to its original gene/transcript. `shared_group_member` records an ambiguous
41
48
  protein-group assignment; the group value stays a group value.
49
+ `gene_protein_group_context` links RNA to an ambiguous source protein group
50
+ without assigning that group's abundance to an individual protein or ORF.
42
51
 
43
52
  Importers pass `AssayPair` and `TargetRelation` iterators as `pairings=` and
44
53
  `relations=` to `QuantitativeDataset.create`. IDs belong to the dataset release
45
- and reference context. Invalid assay references, contradictory known donor
54
+ and left reference context. The right assay/target keeps its own context.
55
+ Invalid assay references, contradictory known donor
46
56
  identities and conflicting one-to-one assignments fail the import. Original
47
57
  storage-version-1 datasets remain readable and have no declared relationships.
48
58
 
@@ -67,7 +77,10 @@ assays. Missing, censored or nonpositive denominators produce an unresolved
67
77
  `not_measured` result with its reason, never infinity or a measured zero. RPF/RNA
68
78
  ratios are source-defined translation-efficiency measures, not measured flux.
69
79
  All derived values retain their input IDs, pairing, target attribution and
70
- normalization assumptions.
80
+ normalization assumptions. When input reference contexts differ, the ratio
81
+ stores `MeasurementReference` records in `input_references`, rather than
82
+ unqualified local IDs. This preserves source identity across annotation and
83
+ search-FASTA releases.
71
84
 
72
85
  ## Across species
73
86
 
@@ -0,0 +1,71 @@
1
+ # Human, mouse and dog protein abundance
2
+
3
+ The [Oziolor et al. atlas](https://doi.org/10.1038/s41597-026-07512-9) provides
4
+ parallel TMT protein measurements. ORFdata keeps each species in a separate
5
+ dataset, using the same samples, assays, measurements and query API.
6
+
7
+ | Dataset | Reported protein groups | Source channels | Source rows |
8
+ |---|---:|---:|---:|
9
+ | `pfizer-atlas-human-protein` | 10,352 | 37 | 325,702 |
10
+ | `pfizer-atlas-mouse-protein` | 12,124 | 63 | 615,991 |
11
+ | `pfizer-atlas-dog-protein` | 9,929 | 38 | 313,263 |
12
+
13
+ Release `2026-10-12.1` contains the complete March 23, 2026 summary tables from
14
+ MassIVE MSV000099729, MSV000099754 and MSV000099744, respectively. Each source
15
+ row contributes two observations: native `iBAQ` and `rIBAQ`. Neither is calibrated
16
+ copies per cell. These are pooled tissue samples; rodent condition labels also
17
+ include sex. Channels and technical runs do not count as independent donors.
18
+
19
+ ```sh
20
+ pip install 'orfdata[data]'
21
+ orfdata datasets list --species dog
22
+ orfdata datasets download pfizer-atlas-dog-protein
23
+ orfdata datasets query pfizer-atlas-dog-protein --quantity protein_abundance
24
+ ```
25
+
26
+ ```python
27
+ from orfdata import DatasetRegistry, ScopedTarget
28
+
29
+ registry = DatasetRegistry()
30
+ dataset = registry.open("pfizer-atlas-dog-protein") # After explicit download.
31
+ reference, = dataset.manifest.references
32
+ group = ScopedTarget(reference, "protein_group", "A0A0A0MPB0", "MSV000099744:ProteinGroup")
33
+ for value in dataset.measurements(target=group):
34
+ print(value.sample_id, value.unit, value.value, value.status)
35
+ ```
36
+
37
+ Every target retains its species and the checksum of the deposited UniProt
38
+ search FASTA. The original genomic assembly and UniProt release are unknown.
39
+ They stay unknown; a future annotation mapping must be explicit and validated.
40
+ Group representatives can be inspected through `reference_mappings()`, but their
41
+ lookup does not establish all group members. Opting into unresolved mapped
42
+ views keeps the original group measurement visible, without assigning its value
43
+ to an individual protein. No RNA pairings are inferred in this release.
44
+
45
+ Source `NA` values remain missing and numeric zeros remain measured zeros.
46
+ Absent group/channel combinations have no observation. For dog, 64,039 combinations
47
+ are absent and eight reported rows contain `NA`, reproducing the existing
48
+ 64,047 missing iBAQ matrix cells. Each value retains its source line, column,
49
+ original numeric text, representative, normalization sum and native `Abundance`
50
+ field. Nonfinite transformed strings such as `-Inf` are kept as provenance only.
51
+
52
+ These searches used UniProt sequences without spliced isoforms. Coverage does
53
+ not establish that an unreported ncORF was searched or absent, nor does bulk
54
+ tissue MS establish MHC presentation. The article and deposit disagree on the
55
+ instrument name; that discrepancy remains explicit in assay metadata.
56
+
57
+ Downloads are 87.3 MB (human), 154.8 MB (mouse) and 84.4 MB (dog). Installed
58
+ SQLite files occupy 1.46 GB, 2.72 GB and 1.40 GB, respectively. Queries stream
59
+ observations; they do not load the entire file or a dense matrix into memory.
60
+
61
+ Source tables are CC0 according to the MassIVE deposits; UniProt search records
62
+ retain UniProt Consortium attribution and CC-BY-4.0 terms. Both sources have
63
+ pinned hashes and sizes. The data artifact is separate from the Python package.
64
+ Discovery and installed queries work offline. `download` verifies and installs
65
+ the compressed artifact; it does not fetch the large vendor search database.
66
+
67
+ To reproduce a source import, use `registry.build(name, source_paths=...)`,
68
+ `orfdata datasets build NAME`, or `orfdata.sources.pfizer.build_protein("dog")`.
69
+ The source overrides are `protein.tsv` and `search.fasta`; DataCache verifies
70
+ their original checksums before running the importer. Source slices with actual
71
+ positive, zero and missing values test the same importer for all three species.
@@ -75,9 +75,8 @@ reconstructed RNA products and preserves each candidate's RNA support. For
75
75
  example, the native TPST1 peptide KIILSKISV is absent from the Sid TPST1–CRCP
76
76
  alternatives, so its MS evidence does not support those altered products.
77
77
 
78
- The reference integration is available in Varcode 10.12.0; the Isovar 1.50.0
79
- integration is in review. The stricter reference-context contract is coordinated
80
- with Varcode 10.13.0 and Isovar 1.51.0.
78
+ The reference integration, including strict reference-context validation, is
79
+ available in Varcode 10.13.0 and Isovar 1.51.0.
81
80
 
82
81
  ## Data and limits
83
82
 
@@ -0,0 +1,90 @@
1
+ # Source references and PyEnsembl mappings
2
+
3
+ A proteomics experiment may search a known protein FASTA without naming a
4
+ genomic assembly. An older RNA study may report its annotation provider but
5
+ omit the release. ORFdata keeps these source identities and their unknown fields.
6
+
7
+ ```python
8
+ from orfdata import ReferenceContext
9
+
10
+ source = ReferenceContext(
11
+ taxon_id=9615, species="dog", genome_build=None,
12
+ annotation_name="uniprot", annotation_version=None,
13
+ sequence_sha256=searched_fasta_sha256,
14
+ )
15
+ ```
16
+
17
+ Unknown assembly/provider fields require a pinned `sequence_sha256` or
18
+ `source_sha256`. The former identifies a sequence set; the latter can pin an
19
+ input table when its reference release is unreported. These source contexts
20
+ cannot bind a genomic transcript. A `ReferenceORF` still requires a complete
21
+ genomic model validated against its actual PyEnsembl transcript. Existing
22
+ complete-reference keys are unchanged.
23
+
24
+ ## Query through an explicit mapping
25
+
26
+ `ReferenceMapping` connects a native `ScopedTarget` to all candidate targets in
27
+ one destination reference. It records the dataset/version, mapping method,
28
+ validation, source provenance, status and unresolved/unmapped reason. Importers
29
+ must perform the stated checks against the pinned inputs. Unique identifier
30
+ resolution is separate from sequence validation.
31
+
32
+ ```python
33
+ from orfdata import ScopedTarget
34
+
35
+ target = ScopedTarget.from_pyensembl(gene, kind="gene", namespace="ensembl:110")
36
+ for view in dataset.mapped_measurements(target):
37
+ print(view.measurement.value, view.measurement.unit)
38
+ print(view.measurement.target, view.requested_target)
39
+ print(view.mapping.method, view.mapping.validation)
40
+ ```
41
+
42
+ The view contains the **original observation**, including its source reference,
43
+ target, sample, assay, unit and provenance. Nothing is relabeled or copied onto
44
+ the requested target. Direct `dataset.measurements(target=...)` still returns
45
+ only observations native to that exact target/reference.
46
+
47
+ By default, mapped queries return uniquely resolved assignments. Use
48
+ `mapping_statuses=["ambiguous", "unresolved"]` to inspect other candidates, and
49
+ `require_sequence=True` to require recorded exact sequence validation. A group
50
+ value returned for a candidate member has `attribution="group_membership_context"`;
51
+ it does not independently quantify that protein. Parent gene/transcript RNA
52
+ cannot map directly onto an ORF. Use a separate parent-context relationship.
53
+
54
+ The CLI exposes the same query:
55
+
56
+ ```sh
57
+ orfdata datasets query DATASET --mapped --reference ref:SHA256 \
58
+ --kind protein --namespace ensembl:110 --target PROTEIN_ID --require-sequence
59
+ ```
60
+
61
+ ## Importer contract
62
+
63
+ Pass `reference_mappings=` to `QuantitativeDataset.create`. Declare source and
64
+ destination contexts in the manifest. Each source/destination-reference pair
65
+ has one mapping containing all candidates, preventing competing unique claims.
66
+ Unmapped records remain visible through `dataset.reference_mappings()`.
67
+
68
+ The status is `unique`, `ambiguous`, `unmapped` or `unresolved`. A single reported
69
+ protein representative with incomplete group membership is unresolved; its
70
+ measurement cannot become a uniquely measured member. Identifier-based mappings
71
+ must say what was checked and leave sequence validation absent when unavailable.
72
+ For an exact sequence search, record:
73
+
74
+ ```python
75
+ validation = {"sequence": {
76
+ "source_sha256": source_protein_sequence_sha256,
77
+ "target_sha256": matching_protein_sequence_sha256,
78
+ "all_candidates_checked": True,
79
+ }}
80
+ ```
81
+
82
+ These are hashes of the compared sequences, distinct from the whole searched
83
+ FASTA's hash in the reference context. Both hashes must agree to count as an
84
+ exact match. ORF assignments additionally require their own `frame` and
85
+ `position` evidence. Known reference-strain differences need explicit
86
+ `strain_relationship` evidence. Cross-species mappings use the separate
87
+ [orthology API](pairing.md#across-species).
88
+
89
+ Storage version 3 preserves these mappings. Earlier versions remain readable
90
+ and report no declared reference mappings; no mapping is inferred on load.
@@ -15,7 +15,15 @@ from .catalog import (
15
15
  from .dataset import QuantitativeDataset
16
16
  from .datasets import DatasetRegistry, build_dataset
17
17
  from .initiation_context import KOZAK_PREFERENCES, InitiationContext, annotate_initiation_context
18
- from .measurements import Assay, DatasetManifest, Measurement, Sample, SourceAsset, TargetMapping
18
+ from .measurements import (
19
+ Assay,
20
+ DatasetManifest,
21
+ Measurement,
22
+ MeasurementReference,
23
+ Sample,
24
+ SourceAsset,
25
+ TargetMapping,
26
+ )
19
27
  from .model import ORFModel, ReferenceORF
20
28
  from .pairing import (
21
29
  AssayPair,
@@ -26,6 +34,7 @@ from .pairing import (
26
34
  compare_orthologs,
27
35
  )
28
36
  from .reference import ReferenceContext, ScopedTarget
37
+ from .reference_mapping import MappedMeasurement, ReferenceMapping
29
38
  from .version import __version__
30
39
 
31
40
  __all__ = [
@@ -47,6 +56,7 @@ __all__ = [
47
56
  "Sample",
48
57
  "Assay",
49
58
  "Measurement",
59
+ "MeasurementReference",
50
60
  "TargetMapping",
51
61
  "AssayPair",
52
62
  "TargetRelation",
@@ -54,6 +64,8 @@ __all__ = [
54
64
  "OrthologyMapping",
55
65
  "OrthologyComparison",
56
66
  "compare_orthologs",
67
+ "ReferenceMapping",
68
+ "MappedMeasurement",
57
69
  "load_catalog",
58
70
  "UORFCatalog",
59
71
  "UORFRecord",