orfdata 0.2.0__tar.gz → 0.4.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 (56) hide show
  1. {orfdata-0.2.0/orfdata.egg-info → orfdata-0.4.0}/PKG-INFO +9 -2
  2. {orfdata-0.2.0 → orfdata-0.4.0}/README.md +3 -1
  3. orfdata-0.4.0/docs/measurements.md +134 -0
  4. orfdata-0.4.0/docs/pairing.md +84 -0
  5. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/__init__.py +26 -0
  6. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/cli.py +8 -1
  7. orfdata-0.4.0/orfdata/data/datasets.json +1 -0
  8. orfdata-0.4.0/orfdata/dataset.py +395 -0
  9. orfdata-0.4.0/orfdata/dataset_cli.py +96 -0
  10. orfdata-0.4.0/orfdata/datasets.py +172 -0
  11. orfdata-0.4.0/orfdata/measurements.py +365 -0
  12. orfdata-0.4.0/orfdata/pairing.py +329 -0
  13. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/reference.py +25 -0
  14. orfdata-0.4.0/orfdata/version.py +1 -0
  15. {orfdata-0.2.0 → orfdata-0.4.0/orfdata.egg-info}/PKG-INFO +9 -2
  16. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata.egg-info/SOURCES.txt +11 -0
  17. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata.egg-info/requires.txt +7 -0
  18. {orfdata-0.2.0 → orfdata-0.4.0}/pyproject.toml +4 -2
  19. orfdata-0.4.0/tests/conftest.py +45 -0
  20. orfdata-0.4.0/tests/test_measurements.py +325 -0
  21. orfdata-0.4.0/tests/test_pairing.py +269 -0
  22. orfdata-0.2.0/orfdata/version.py +0 -1
  23. {orfdata-0.2.0 → orfdata-0.4.0}/LICENSE +0 -0
  24. {orfdata-0.2.0 → orfdata-0.4.0}/MANIFEST.in +0 -0
  25. {orfdata-0.2.0 → orfdata-0.4.0}/deploy.sh +0 -0
  26. {orfdata-0.2.0 → orfdata-0.4.0}/docs/design.md +0 -0
  27. {orfdata-0.2.0 → orfdata-0.4.0}/docs/reference.md +0 -0
  28. {orfdata-0.2.0 → orfdata-0.4.0}/docs/species.md +0 -0
  29. {orfdata-0.2.0 → orfdata-0.4.0}/lint.sh +0 -0
  30. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/build.py +0 -0
  31. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/catalog.py +0 -0
  32. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/data/orf-evidence/AUTHOR-LICENSE.txt +0 -0
  33. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/data/orf-evidence/NOTICE.txt +0 -0
  34. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/data/orf-evidence/catalog.json.gz +0 -0
  35. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/data/orf-evidence/manifest.json +0 -0
  36. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/data/uorf-evidence/AUTHOR-LICENSE.txt +0 -0
  37. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/data/uorf-evidence/NOTICE.txt +0 -0
  38. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/data/uorf-evidence/catalog.json.gz +0 -0
  39. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/data/uorf-evidence/manifest.json +0 -0
  40. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/initiation_context.py +0 -0
  41. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/model.py +0 -0
  42. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata/sequence.py +0 -0
  43. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata.egg-info/dependency_links.txt +0 -0
  44. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata.egg-info/entry_points.txt +0 -0
  45. {orfdata-0.2.0 → orfdata-0.4.0}/orfdata.egg-info/top_level.txt +0 -0
  46. {orfdata-0.2.0 → orfdata-0.4.0}/setup.cfg +0 -0
  47. {orfdata-0.2.0 → orfdata-0.4.0}/test.sh +0 -0
  48. {orfdata-0.2.0 → orfdata-0.4.0}/tests/data/references/README.md +0 -0
  49. {orfdata-0.2.0 → orfdata-0.4.0}/tests/data/references/canis_lupus_familiaris.json +0 -0
  50. {orfdata-0.2.0 → orfdata-0.4.0}/tests/data/references/homo_sapiens.json +0 -0
  51. {orfdata-0.2.0 → orfdata-0.4.0}/tests/data/references/mus_musculus.json +0 -0
  52. {orfdata-0.2.0 → orfdata-0.4.0}/tests/data/references/saccharomyces_cerevisiae.json +0 -0
  53. {orfdata-0.2.0 → orfdata-0.4.0}/tests/test_initiation_context.py +0 -0
  54. {orfdata-0.2.0 → orfdata-0.4.0}/tests/test_reference_context.py +0 -0
  55. {orfdata-0.2.0 → orfdata-0.4.0}/tests/test_reference_orf.py +0 -0
  56. {orfdata-0.2.0 → orfdata-0.4.0}/tests/test_uorf_catalog.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orfdata
3
- Version: 0.2.0
3
+ Version: 0.4.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
@@ -11,6 +11,10 @@ Provides-Extra: pyensembl
11
11
  Requires-Dist: pyensembl>=2.27.2; extra == "pyensembl"
12
12
  Provides-Extra: build-data
13
13
  Requires-Dist: openpyxl>=3.1; extra == "build-data"
14
+ Provides-Extra: data
15
+ Requires-Dist: datacache<2,>=1.25.1; extra == "data"
16
+ Provides-Extra: columnar
17
+ Requires-Dist: pyarrow>=14; extra == "columnar"
14
18
  Provides-Extra: dev
15
19
  Requires-Dist: pytest; extra == "dev"
16
20
  Requires-Dist: ruff; extra == "dev"
@@ -18,6 +22,7 @@ Requires-Dist: build; extra == "dev"
18
22
  Requires-Dist: twine; extra == "dev"
19
23
  Requires-Dist: openpyxl>=3.1; extra == "dev"
20
24
  Requires-Dist: pyensembl>=2.27.2; extra == "dev"
25
+ Requires-Dist: datacache<2,>=1.25.1; extra == "dev"
21
26
  Dynamic: license-file
22
27
 
23
28
  # orfdata
@@ -95,5 +100,7 @@ bind real human, mouse, dog and yeast reference slices; those fixtures are not
95
100
  new experimental ORF catalogues. [Species and reference identity](docs/species.md).
96
101
 
97
102
  Install with `pip install orfdata[pyensembl]`. See the
103
+ [measurement API](docs/measurements.md) for native units, explicit samples and
104
+ assays, and DataCache-managed downloads, and the
98
105
  [quantitative, multispecies data roadmap](https://github.com/openvax/orfdata/issues/3)
99
- for planned RNA abundance, ribosome occupancy and protein measurements.
106
+ for upcoming RNA abundance, ribosome occupancy and protein data releases.
@@ -73,5 +73,7 @@ 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
+ [measurement API](docs/measurements.md) for native units, explicit samples and
77
+ assays, and DataCache-managed downloads, and the
76
78
  [quantitative, multispecies data roadmap](https://github.com/openvax/orfdata/issues/3)
77
- for planned RNA abundance, ribosome occupancy and protein measurements.
79
+ for upcoming RNA abundance, ribosome occupancy and protein data releases.
@@ -0,0 +1,134 @@
1
+ # RNA, ribosome and protein measurements
2
+
3
+ ORFdata adds evidence to PyEnsembl's reference transcripts and proteins. Its
4
+ quantitative layer stores measurements of genes, transcripts, reference ORFs,
5
+ proteins, protein groups and peptides. A measurement stays at the resolution
6
+ the experiment supports. Parent-gene RNA abundance is useful context for an ORF;
7
+ it is not a separate measurement of each ORF in that gene.
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
11
+ imports. The bundled human ORF evidence catalogue remains available offline.
12
+ Its pooled PSM counts describe spectra, not sample-level protein abundance.
13
+
14
+ ## Discover, download and query
15
+
16
+ ```python
17
+ from orfdata import DatasetRegistry, ScopedTarget
18
+
19
+ registry = DatasetRegistry() # Metadata only; no download.
20
+ releases = registry.list(species="dog", assay="digest_ms")
21
+ ```
22
+
23
+ For a registered release, use `registry.info(name, version)` for its immutable
24
+ manifest, `registry.download(name, version)` to fetch it, and
25
+ `registry.open(name, version)` to read it offline. `inspect` reports missing,
26
+ available or invalid files without downloading or repairing them.
27
+ `download_metadata` returns the artifact's access terms and file hashes/sizes.
28
+ An invalid cache
29
+ requires an explicit `download(..., force=True)`; old reader paths survive.
30
+ Python download options such as timeout, retries and progress go to DataCache.
31
+
32
+ ```python
33
+ # dataset = registry.open(name, version)
34
+ # transcript is a PyEnsembl Transcript in the dataset's exact reference context.
35
+ target = ScopedTarget.from_pyensembl(
36
+ transcript, kind="transcript", namespace="ensembl:110"
37
+ )
38
+ for measurement in dataset.measurements(target=target):
39
+ print(measurement.value, measurement.unit, measurement.status)
40
+ ```
41
+
42
+ Use `ScopedTarget.from_orf(bound_reference_orf, namespace=source_release)` for a
43
+ validated reference ORF. Namespaces and identifiers must match the source's
44
+ mapping table. The default PyEnsembl target uses its unversioned `id`; request
45
+ `versioned=True` when the source uses versioned identifiers. There is no implicit
46
+ mapping across annotation releases, gene isoforms, ORFs or species. A variant or
47
+ fusion product does not inherit a native reference protein measurement.
48
+
49
+ The CLI uses the same operations:
50
+
51
+ ```sh
52
+ orfdata datasets list --species yeast
53
+ orfdata datasets info DATASET --version RELEASE
54
+ orfdata datasets download DATASET --version RELEASE
55
+ orfdata datasets inspect DATASET --version RELEASE
56
+ orfdata datasets query DATASET --version RELEASE --quantity protein_abundance
57
+ ```
58
+
59
+ Queries stream JSON lines. `--reference ref:SHA256` selects an exact context;
60
+ target queries also require `--target`, `--kind` and `--namespace`. Unqualified
61
+ sample/assay ID queries across multiple references are rejected. Existing
62
+ catalogue commands such as `orfdata --gene TPST1` retain their behavior.
63
+
64
+ ## What each value means
65
+
66
+ `Measurement` retains the dataset/version, reference-scoped target, sample and
67
+ assay IDs, value, native unit, linear/log scale and log base, uncertainty and its
68
+ definition, detection limit, status, origin and provenance. Measured zero,
69
+ below detection, not measured, not mapped and missing are distinct. Censored or
70
+ missing values use `None`; native sentinels can remain in provenance.
71
+
72
+ RNA counts/TPM/FPKM, ribosome occupancy, source-defined translation efficiency,
73
+ LFQ/iBAQ/TMT values, peptide intensity, PSM counts, copies per cell and turnover
74
+ remain distinct. No conversion is automatic. Derived/predicted values name a
75
+ method and retain source/input provenance. An estimate from calibration remains
76
+ an estimate; an intensity/TPM ratio does not acquire molecule-ratio units.
77
+
78
+ `Sample` records biological units, pools and source labels. `Assay` separately
79
+ records technical replicates, runs, fractions, TMT plex/channel/bridge,
80
+ normalization and calibration. A sample's strain/breed belongs in its attributes;
81
+ it need not be the strain used to assemble its reference genome. `TargetMapping`
82
+ retains all candidate assignments or an unmapped reason. A protein-group
83
+ representative does not become a uniquely measured protein. See
84
+ [pairing and orthology comparisons](pairing.md) for explicit experimental
85
+ relationships and derived RNA/protein ratios.
86
+
87
+ ## Importing a source
88
+
89
+ Define a `DatasetManifest` with exact reference contexts, raw source URLs,
90
+ SHA-256 hashes and byte sizes, citations, file-specific access/redistribution
91
+ terms, searched/measurable coverage, processing software/version/parameters and
92
+ row accounting. Unavailable metadata stay unknown. Article licensing does not
93
+ substitute for the data files' terms.
94
+
95
+ An importer calls `QuantitativeDataset.create(path, manifest, samples=...,
96
+ assays=..., measurements=..., mappings=...)`. These inputs may be generators;
97
+ measurements are written incrementally. Every observation names a source asset
98
+ or earlier input measurements. Derived inputs precede outputs in the same
99
+ reference context. Duplicate IDs, broken foreign keys, wrong dataset releases
100
+ and cross-reference links fail the import. Failed builds do not replace data.
101
+
102
+ Use `build_dataset(manifest, builder, ...)` for a managed local import.
103
+ `builder(source_paths, output_path)` reads the verified inputs and creates that
104
+ SQLite dataset. DataCache publishes it atomically with input/output checksums
105
+ and a processing receipt. `source_paths={asset_id: local_file}` supports manually
106
+ acquired sources. Importing locally does not grant redistribution rights.
107
+
108
+ A `DatasetRegistry(definitions, cache_root=...)` registers releases as:
109
+
110
+ ```python
111
+ definitions = {
112
+ name: {
113
+ "default_version": version,
114
+ "versions": {version: {
115
+ "manifest": manifest.to_dict(),
116
+ "distribution": {"access_terms": terms, "redistributable": False},
117
+ "assets": {"dataset.sqlite": {
118
+ "url": url, "sha256": sha256, "size": size, "decompress": False,
119
+ }},
120
+ }},
121
+ }
122
+ }
123
+ ```
124
+
125
+ CLI users can supply this JSON with `orfdata datasets --registry FILE ...`.
126
+ `ORFDATA_CACHE`, then `OPENVAX_DATA_CACHE`, then the platform's OpenVax cache
127
+ select the root. ORFdata owns its `orfdata/` child. Release cache identities
128
+ include manifest/reference and content hashes. SQLite partitions every table
129
+ by reference key, with composite foreign keys; human, mouse, dog, yeast and
130
+ arbitrary other taxa use the same schema. The core API needs neither pandas nor
131
+ PyArrow. Optional `orfdata[columnar]` enables `dataset.export_parquet(path)`;
132
+ query columns accompany full measurement JSON, preserving exact values and
133
+ provenance even when a floating-point analysis column cannot represent an
134
+ integer exactly.
@@ -0,0 +1,84 @@
1
+ # Comparing RNA, ribosome and protein abundance
2
+
3
+ Use declared experimental relationships to compare assays. A tissue label alone
4
+ does not make an RNA sample and a protein sample a matched pair.
5
+
6
+ ```python
7
+ for match in dataset.matched_measurements(allowed_bases=["same_material"]):
8
+ row = match.to_table_row()
9
+ print(row["rna_abundance"], row["protein_abundance"])
10
+ ```
11
+
12
+ Rows include named RNA, ribosome occupancy, translation-efficiency, protein,
13
+ peptide and spectrum-count columns, each containing original measurement
14
+ records with units, missingness and provenance. Missing columns are empty lists.
15
+ Multiple values remain multiple values; the API does not average them or create
16
+ a Cartesian product of technical replicates. Each row retains its assay pairing
17
+ and target relationship. A three-assay experiment can declare several pairwise
18
+ comparisons; sharing an RNA measurement does not create independent replicates.
19
+
20
+ Pairing bases are `same_material`, `adjacent_donor_tissue`,
21
+ `biological_replicate`, `independent_cultures`, `tissue_aggregate` and
22
+ `condition_aggregate`. The caller must choose the allowed bases. By default,
23
+ only explicitly concurrent assays are returned; opt into `longitudinal` or
24
+ `unknown` with `allowed_temporal`. Missing mates stay explicit. Technical runs,
25
+ TMT channels and bridges remain in the assays and do not become biological
26
+ sample counts.
27
+
28
+ The CLI streams the same table rows:
29
+
30
+ ```sh
31
+ orfdata datasets pairs DATASET --version RELEASE --basis same_material
32
+ ```
33
+
34
+ ## Which targets are being compared?
35
+
36
+ `TargetRelation` links exact, reference-scoped targets with mapping evidence
37
+ and cardinality. `same_target` compares one target across assays/samples.
38
+ `canonical_translation` links a gene/transcript to its annotated protein.
39
+ `parent_rna_context` links parent RNA to an ORF but keeps the RNA value attached
40
+ to its original gene/transcript. `shared_group_member` records an ambiguous
41
+ protein-group assignment; the group value stays a group value.
42
+
43
+ Importers pass `AssayPair` and `TargetRelation` iterators as `pairings=` and
44
+ `relations=` to `QuantitativeDataset.create`. IDs belong to the dataset release
45
+ and reference context. Invalid assay references, contradictory known donor
46
+ identities and conflicting one-to-one assignments fail the import. Original
47
+ storage-version-1 datasets remain readable and have no declared relationships.
48
+
49
+ ## Ratios are derived measurements
50
+
51
+ ```python
52
+ ratio = match.ratio(
53
+ selected_protein_measurement, selected_rna_measurement,
54
+ measurement_id="ratio-1", method="native protein/RNA ratio",
55
+ normalization={"protein": "source bridge normalization", "rna": "source TPM"},
56
+ )
57
+ ```
58
+
59
+ Select actual measurements from opposite sides of the match. Ratios require
60
+ one-to-one target attribution and linear inputs. Parent-RNA/ORF and shared-group
61
+ links cannot produce target-specific ratios. There is no implicit log conversion,
62
+ unit conversion, replicate averaging or uncertainty propagation.
63
+
64
+ An iBAQ/TPM ratio keeps `(iBAQ)/(TPM)` units. Copies-per-cell values also retain
65
+ their native composite units and the calibration recorded on their source
66
+ assays. Missing, censored or nonpositive denominators produce an unresolved
67
+ `not_measured` result with its reason, never infinity or a measured zero. RPF/RNA
68
+ ratios are source-defined translation-efficiency measures, not measured flux.
69
+ All derived values retain their input IDs, pairing, target attribution and
70
+ normalization assumptions.
71
+
72
+ ## Across species
73
+
74
+ `compare_orthologs(left_dataset, right_dataset, mappings)` is separate and
75
+ opt-in. Each `OrthologyMapping` pins its source file, release, both reference
76
+ contexts, cardinality, confidence definition and evidence. The default accepts
77
+ one-to-one canonical gene mappings; one-to-many relationships require explicit
78
+ permission through `allowed_cardinalities`.
79
+
80
+ The result contains each species' original observations. It neither merges
81
+ identities nor transfers abundance or protein-existence evidence. ORF comparisons
82
+ additionally require their own sequence, frame and positional evidence and
83
+ `allow_orfs=True`; a gene ortholog cannot establish an orthologous ncORF.
84
+ Human, mouse, dog, yeast and arbitrary other taxa use this same API.
@@ -12,8 +12,19 @@ from .catalog import (
12
12
  load_catalog,
13
13
  load_uorf_catalog,
14
14
  )
15
+ from .dataset import QuantitativeDataset
16
+ from .datasets import DatasetRegistry, build_dataset
15
17
  from .initiation_context import KOZAK_PREFERENCES, InitiationContext, annotate_initiation_context
18
+ from .measurements import Assay, DatasetManifest, Measurement, Sample, SourceAsset, TargetMapping
16
19
  from .model import ORFModel, ReferenceORF
20
+ from .pairing import (
21
+ AssayPair,
22
+ MatchedMeasurements,
23
+ OrthologyComparison,
24
+ OrthologyMapping,
25
+ TargetRelation,
26
+ compare_orthologs,
27
+ )
17
28
  from .reference import ReferenceContext, ScopedTarget
18
29
  from .version import __version__
19
30
 
@@ -28,6 +39,21 @@ __all__ = [
28
39
  "ReferenceORF",
29
40
  "ReferenceContext",
30
41
  "ScopedTarget",
42
+ "QuantitativeDataset",
43
+ "DatasetRegistry",
44
+ "build_dataset",
45
+ "DatasetManifest",
46
+ "SourceAsset",
47
+ "Sample",
48
+ "Assay",
49
+ "Measurement",
50
+ "TargetMapping",
51
+ "AssayPair",
52
+ "TargetRelation",
53
+ "MatchedMeasurements",
54
+ "OrthologyMapping",
55
+ "OrthologyComparison",
56
+ "compare_orthologs",
31
57
  "load_catalog",
32
58
  "UORFCatalog",
33
59
  "UORFRecord",
@@ -11,7 +11,14 @@ from .catalog import EVIDENCE_METHODS, UORFCatalog, load_catalog
11
11
 
12
12
  def run(argv=None, prog=None, *, catalog_loader=load_catalog):
13
13
  """Export reference records as JSON, TSV or FASTA."""
14
- parser = argparse.ArgumentParser(description=__doc__, prog=prog)
14
+ argv = list(sys.argv[1:] if argv is None else argv)
15
+ if argv and argv[0] == "datasets":
16
+ from .dataset_cli import run as dataset_run
17
+
18
+ return dataset_run(argv[1:], prog=(prog or "orfdata") + " datasets")
19
+ parser = argparse.ArgumentParser(
20
+ description=__doc__, prog=prog,
21
+ epilog="For quantitative data management, use 'orfdata datasets --help'.")
15
22
  parser.add_argument("--catalog", help="Use a compatible local JSON/JSON.gz catalogue")
16
23
  parser.add_argument("--gene", help="Exact gene symbol or Ensembl gene ID")
17
24
  parser.add_argument("--transcript", help="Exact source transcript ID (unversioned)")
@@ -0,0 +1 @@
1
+ {}