orfdata 0.37.0__tar.gz → 0.38.2__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.
- {orfdata-0.37.0/orfdata.egg-info → orfdata-0.38.2}/PKG-INFO +1 -1
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/proteome.md +9 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/species.md +9 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/catalog.py +40 -10
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/proteome.py +5 -2
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/sources/openprot.py +12 -5
- orfdata-0.38.2/orfdata/version.py +1 -0
- {orfdata-0.37.0 → orfdata-0.38.2/orfdata.egg-info}/PKG-INFO +1 -1
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata.egg-info/SOURCES.txt +1 -0
- orfdata-0.38.2/tests/test_dog_ncorf_search.py +62 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_genetic_codes.py +54 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_merge_catalogs.py +58 -0
- orfdata-0.37.0/orfdata/version.py +0 -1
- {orfdata-0.37.0 → orfdata-0.38.2}/LICENSE +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/MANIFEST.in +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/README.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/deploy.sh +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/catalogs.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/copy-yeast.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/coverage.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/dog-peptides.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/downloads.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/downstream.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/examples.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/human-tissue.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/index.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/ingolia-yeast.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/measurements.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/pairing.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/pfizer-protein.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/pfizer-rna.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/reference.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/search-references.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/source-references.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/storage.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/stylesheets/docs.css +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs/viral.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/docs.sh +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/lint.sh +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/mkdocs.yml +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/__init__.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/_pinned_genome.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/_structure.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/build.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/catalog_cli.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/catalog_manifest.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/catalogs.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/cli.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/cli_output.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/catalogs.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/chains.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/datasets.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/genomes.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/ires/rfam-15.1-human-ires.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/orf-evidence/AUTHOR-LICENSE.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/orf-evidence/NOTICE.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/orf-evidence/catalog.json.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/orf-evidence/manifest.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/uorf-evidence/AUTHOR-LICENSE.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/uorf-evidence/NOTICE.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/uorf-evidence/catalog.json.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/uorf-evidence/manifest.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/viral/NOTICE.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/viral/gdc-grch38-d1-vd1-coverage.tsv +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/viral/gdc-grch38-d1-vd1-genbank.tsv +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/viral/gdc-grch38-d1-vd1-pave.tsv +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/viral/hpv16-refseq-CDS.json.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/data/viral/subsets.yaml +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/dataset.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/dataset_cli.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/datasets.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/download_cli.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/downloads.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/evidence.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/evidence_summary.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/fasta.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/genbank.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/genomes.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/genomes_cli.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/gtf.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/initiation_context.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/install.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/liftover.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/liftover_cli.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/measurements.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/model.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/net.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/pairing.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/proteome_cli.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/record_sources.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/reference.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/reference_ledger.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/reference_mapping.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/reference_table.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/refseq.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/rna.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/search_reference.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/sequence.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/sources/__init__.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/sources/copy.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/sources/ingolia.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/sources/kaabinejadian.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/sources/ncorf_mammals.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/sources/peptideatlas.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/sources/pfizer.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/sources/pfizer_rna.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/sources/riborf.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/sources/wang.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/viral.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/viral_annotation.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/viral_cli.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/viral_coverage.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/viral_panel.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/viral_registry.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata/viral_subsets.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata.egg-info/dependency_links.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata.egg-info/entry_points.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata.egg-info/requires.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/orfdata.egg-info/top_level.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/pyproject.toml +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/setup.cfg +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/test.sh +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/conftest.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/aggregate_evidence.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/GSM1905474.soft +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/GSM1905474_KL9_fpkm.txt.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/GSM1905476.soft +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/GSM1905476_KL10_fpkm.txt.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/GSM1905478.soft +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/GSM1905478_KL11_fpkm.txt.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/GSM1905479.soft +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/GSM1905479_KL12_fpkm.txt.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/NOTICE.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/expected.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/geo-series.soft +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/manifest.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/methods.pdf +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/paper.xml +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/pmc-metadata.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/qconcat.fasta +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/copy/workbook.xlsx +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346111.metadata.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346111.quant.txt.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346114.metadata.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346114.quant.txt.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346115.metadata.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346115.quant.txt.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346116.metadata.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346116.quant.txt.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346117.metadata.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346117.quant.txt.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346118.metadata.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346118.quant.txt.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346120.metadata.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346120.quant.txt.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346122.metadata.txt +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/GSM346122.quant.txt.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/NOTICE.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/expected.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/manifest.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ingolia/readMe.txt.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/kaabinejadian/README.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/kaabinejadian/Results.zip +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/kaabinejadian/manifest-v1.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/kaabinejadian/manifest.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/kaabinejadian/sdrf.tsv +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ncorf_mammals/README.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ncorf_mammals/S3.xlsx +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ncorf_mammals/ensembl107.cdna.fa.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ncorf_mammals/ensembl107.gtf.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ncorf_mammals/human-ensembl107.gtf.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ncorf_mammals/human.bed +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ncorf_mammals/human.pep.fa +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ncorf_mammals/mouse.bed +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/ncorf_mammals/mouse.pep.fa +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/openprot/README.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/openprot/ensembl106.cdna.fa.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/openprot/ensembl106.gtf.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/openprot/mouse-openprot-2_2-altprots+isoforms-min_2_pep-GRCm39.106.bed.zip +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/openprot/mouse-openprot-2_2-altprots+isoforms-min_2_pep-GRCm39.106.fasta.zip +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/openprot/mouse-openprot-2_2-altprots+isoforms-min_2_pep-GRCm39.106.tsv.zip +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/peptideatlas/README.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/peptideatlas/atlas_build.tsv.zip +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/peptideatlas/ensembl.pep.fa.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/peptideatlas/manifest.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer/NOTICE.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer/dog/expected.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer/dog/manifest.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer/dog/protein.tsv +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer/dog/search.fasta +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer/human/expected.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer/human/manifest.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer/human/protein.tsv +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer/human/search.fasta +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer/mouse/expected.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer/mouse/manifest.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer/mouse/protein.tsv +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer/mouse/search.fasta +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer_rna/GSE325522_family.soft.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer_rna/GSE325523_family.soft.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer_rna/GSE325525_family.soft.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer_rna/NOTICE.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer_rna/counts.csv.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer_rna/dog-annotation.gtf.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer_rna/dog-expected.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer_rna/dog-manifest.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer_rna/mouse-annotation.gtf.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer_rna/mouse-expected.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer_rna/mouse-manifest.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/pfizer_rna/samples.xlsx +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/references/README.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/references/canis_lupus_familiaris.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/references/context-keys-v0.4.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/references/ensembl115.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/references/homo_sapiens.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/references/mitochondrial.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/references/mus_musculus.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/references/saccharomyces_cerevisiae.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/references/uniprot_literature.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/regions/NOTICE.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/regions/ingolia.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/README.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/SD3.xlsx +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/ensembl107.cdna.fa.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/ensembl107.gtf.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/ensembl107.ncrna.fa.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/human-ensembl105.cdna.fa.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/human-ensembl105.gtf.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/human-ensembl105.ncrna.fa.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/worm-ensembl105.cdna.fa.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/worm-ensembl105.gtf.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/worm-ensembl105.ncrna.fa.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/yeast-ensembl115.cdna.fa.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/yeast-ensembl115.dna.fa.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/yeast-ensembl115.gtf.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/zebrafish-ensembl115.cdna.fa.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/zebrafish-ensembl115.gtf.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/riborf/zebrafish-ensembl115.ncrna.fa.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/search_reference/NOTICE.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/search_reference/dog.fasta +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/search_reference/ensembl83-expected.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/search_reference/ensembl83-human.fasta.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/search_reference/expected.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/storage/README.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/storage/generate.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/storage/v1.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/storage/v1.sqlite +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/storage/v2.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/storage/v2.sqlite +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/storage/v3.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/storage/v3.sqlite +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/storage/v4.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/storage/v4.sqlite +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/viral/GRCh83.d1.vd1_virus_decoy.txt.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/viral/NC_001526.4.gb.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/viral/genbank/HBV__X04615.1.gb.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/viral/genbank/HPV16__K02718.1.gb.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/viral/genbank/HPV35__X74477.1.gb.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/viral/genbank/HPV51__M62877.1.gb.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/viral/genbank/HPV56__X74483.1.gb.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/wang/NOTICE.md +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/wang/annotation.gtf.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/wang/copies.zip +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/wang/expected.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/wang/manifest.json +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/wang/protein.zip +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/wang/rna.zip +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/data/wang/search.fasta.gz +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_catalog_registry.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_copy.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_cross_reference_pairing.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_dog_peptides.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_downloads.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_ensembl_search_reference.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_evidence_rules.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_evidence_summary.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_genbank.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_genbank_equivalence.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_genomes.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_ingolia.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_initiation_context.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_liftover.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_local_build_queries.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_measurements.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_more_species.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_ncorf_mammals.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_openprot.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_orf_cases.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_orf_gtf.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_paired_selectors.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_pairing.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_pfizer.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_pfizer_rna.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_protein_set.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_proteome.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_proteome_external.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_proteome_fasta_tokens.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_proteome_producer_graph.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_reference_context.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_reference_ledger.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_reference_mapping.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_reference_orf.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_reference_table.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_refseq.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_region_targets.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_riborf.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_search_reference.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_selectors.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_storage.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_uorf_catalog.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_viral.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_viral_bundle.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_viral_cli.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_viral_collections.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_viral_completeness.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_viral_coverage.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_viral_initiation.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_viral_origin_join.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_viral_sources.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_viral_subsets.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tests/test_wang.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tools/__init__.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tools/build_gdc_viral_coverage.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tools/build_hpv16_cds.py +0 -0
- {orfdata-0.37.0 → orfdata-0.38.2}/tools/build_reference_ledger.py +0 -0
|
@@ -281,6 +281,15 @@ other.
|
|
|
281
281
|
`source:id`. `catalog.get` and `ExtraORFs.for_orf` accept any of them.
|
|
282
282
|
- **ID collisions.** When two sources use one ID for different ORFs, both
|
|
283
283
|
become `source:id`, and the bare ID raises rather than picking one.
|
|
284
|
+
Direct `ORFCatalog(records, metadata)` construction follows the same rule,
|
|
285
|
+
retaining each native record in `members` without merging its evidence.
|
|
286
|
+
IDs must still be unique within a source. If a source or native ID contains
|
|
287
|
+
punctuation that would collide with a generated ID, generated components
|
|
288
|
+
are percent-escaped; native IDs remain available through the source records.
|
|
289
|
+
Use `catalog.get("native-id", source="study")` or
|
|
290
|
+
`orfs.for_orf("native-id", source="study")` for explicit source selection.
|
|
291
|
+
A combined string such as `study:native-id` raises if it also identifies
|
|
292
|
+
another native record; explicit source selection resolves that ambiguity.
|
|
284
293
|
- **Evidence.** Each source's evidence is kept, and evidence rules see the union:
|
|
285
294
|
a peptide counts once per sequence. A Ribo-seq study two catalogues label
|
|
286
295
|
differently counts once when their `ribosome_study_pmids` metadata give it
|
|
@@ -71,3 +71,12 @@ must declare table 2, and a yeast one table 3. See
|
|
|
71
71
|
products, such as Varcode and Isovar, must translate them with that code.
|
|
72
72
|
For example, OpenProt's IP_306399 on human MT-ND4 begins ATA and ends AGG. It
|
|
73
73
|
binds under table 2; table 1 would read those codons as isoleucine and arginine.
|
|
74
|
+
|
|
75
|
+
OpenProt import manifests can declare `processing.translation_tables` by exact
|
|
76
|
+
native transcript ID, for example `{"ENST00000361381.2": 2}` for the qualified
|
|
77
|
+
human IP_306399 row. The declaration belongs to the pinned source/reference
|
|
78
|
+
manifest and is retained in catalogue provenance. Mitochondrial rows require
|
|
79
|
+
such a declaration; unsupported codes and IDs absent from the input fail.
|
|
80
|
+
The importer retains the native coordinate conversion and aggregate MS/TE
|
|
81
|
+
counts. Binding still checks the exact transcript sequence and protein.
|
|
82
|
+
This does not publish a complete human or yeast OpenProt catalogue (#18).
|
|
@@ -15,6 +15,7 @@ from dataclasses import asdict, dataclass, replace
|
|
|
15
15
|
from importlib.resources import files
|
|
16
16
|
from pathlib import Path
|
|
17
17
|
from typing import NamedTuple, Optional
|
|
18
|
+
from urllib.parse import quote
|
|
18
19
|
|
|
19
20
|
from .evidence import EVIDENCE_METHODS as EVIDENCE_METHODS # Re-exported for existing imports.
|
|
20
21
|
from .evidence import MS_METHODS, evidence_rule, stored_method
|
|
@@ -402,25 +403,52 @@ class ORFRecord:
|
|
|
402
403
|
}
|
|
403
404
|
|
|
404
405
|
|
|
406
|
+
def _qualify_colliding_ids(records):
|
|
407
|
+
"""Give colliding source records unique catalogue IDs, retaining their native records."""
|
|
408
|
+
records = tuple(records)
|
|
409
|
+
keys = [(r.source, r.orf_id) for r in records]
|
|
410
|
+
if len(set(keys)) != len(keys):
|
|
411
|
+
raise ValueError("Duplicate ORF identifiers within one source")
|
|
412
|
+
names = [r.orf_id for r in records]
|
|
413
|
+
qualified = set()
|
|
414
|
+
while True:
|
|
415
|
+
counts = Counter(names)
|
|
416
|
+
collisions = {i for i, name in enumerate(names) if counts[name] > 1}
|
|
417
|
+
if not collisions:
|
|
418
|
+
break
|
|
419
|
+
# Qualify all participants, including a native ID that equals another
|
|
420
|
+
# record's generated ID. Escaping makes source/ID boundaries unambiguous.
|
|
421
|
+
qualified.update(collisions)
|
|
422
|
+
names = [f"{quote(r.source, safe='')}:{quote(r.orf_id, safe='')}" if i in qualified
|
|
423
|
+
else r.orf_id for i, r in enumerate(records)]
|
|
424
|
+
return tuple(r if name == r.orf_id else replace(
|
|
425
|
+
r, orf_id=name, members=r.members or (r,), lifted_from=None, liftover=None)
|
|
426
|
+
for r, name in zip(records, names))
|
|
427
|
+
|
|
428
|
+
|
|
405
429
|
class ORFCatalog:
|
|
406
430
|
"""Offline ORF records for one explicitly identified species and assembly."""
|
|
407
431
|
|
|
408
432
|
def __init__(self, records, metadata):
|
|
409
|
-
self.records =
|
|
433
|
+
self.records = _qualify_colliding_ids(records)
|
|
410
434
|
self._metadata = deepcopy(metadata)
|
|
411
435
|
self.genome_build = metadata["genome_build"]
|
|
412
436
|
self.taxon_id = metadata["taxon_id"]
|
|
413
437
|
self.species = metadata["species"]
|
|
414
438
|
self._by_id = {r.orf_id: r for r in self.records}
|
|
415
|
-
if len(self._by_id) != len(self.records):
|
|
416
|
-
raise ValueError("Duplicate ORF identifiers")
|
|
417
439
|
self._aliases = {}
|
|
440
|
+
self._by_source_id = {}
|
|
418
441
|
for r in self.records:
|
|
419
442
|
names = {f"{m.source}:{m.orf_id}" for m in r.members or (r,)} | {m.orf_id for m in r.members}
|
|
420
443
|
# A source accession split by coding path, "IP_1@ENST...", still answers to "IP_1".
|
|
421
444
|
names |= {m.orf_id.split("@")[0] for m in r.members or (r,) if "@" in m.orf_id}
|
|
422
445
|
for alias in names - {r.orf_id}:
|
|
423
446
|
self._aliases.setdefault(alias, []).append(r)
|
|
447
|
+
for member in r.members or (r,):
|
|
448
|
+
for name in {member.orf_id, member.orf_id.split("@")[0]}:
|
|
449
|
+
matches = self._by_source_id.setdefault((member.source, name), [])
|
|
450
|
+
if not any(match is r for match in matches):
|
|
451
|
+
matches.append(r)
|
|
424
452
|
for r in self.records:
|
|
425
453
|
if r.genome_build != self.genome_build or r.strand not in ("+", "-"):
|
|
426
454
|
raise ValueError(f"Invalid assembly or strand for {r.orf_id}")
|
|
@@ -503,14 +531,17 @@ class ORFCatalog:
|
|
|
503
531
|
"""Return a copy of dataset version, sources, scope and provenance."""
|
|
504
532
|
return deepcopy(self._metadata)
|
|
505
533
|
|
|
506
|
-
def get(self, orf_id):
|
|
534
|
+
def get(self, orf_id, *, source=None):
|
|
507
535
|
"""Return the ORF with this ID, bare or as ``source:id``; unknown IDs raise KeyError.
|
|
508
536
|
|
|
509
537
|
In a merged catalogue every source's ID finds its ORF. A bare ID that
|
|
510
538
|
two sources use for different ORFs raises rather than choosing one.
|
|
539
|
+
``source`` selects a native ID explicitly, including when a source or
|
|
540
|
+
native ID contains a colon and the combined string is ambiguous.
|
|
511
541
|
"""
|
|
512
|
-
|
|
513
|
-
|
|
542
|
+
matches = (self._by_source_id.get((source, orf_id), ()) if source is not None else
|
|
543
|
+
([self._by_id[orf_id]] if orf_id in self._by_id else []) + list(self._aliases.get(orf_id, ())))
|
|
544
|
+
found = list({id(record): record for record in matches}.values())
|
|
514
545
|
if len(found) > 1:
|
|
515
546
|
raise ValueError(f"{orf_id} names several ORFs: {', '.join(r.orf_id for r in found)}")
|
|
516
547
|
if not found:
|
|
@@ -780,21 +811,20 @@ def merge_catalogs(catalogs):
|
|
|
780
811
|
groups.append(group)
|
|
781
812
|
group[0].add(origin[id(record)])
|
|
782
813
|
group[1].append(record)
|
|
783
|
-
uses = Counter(orf_id for _, members in groups for orf_id in {m.orf_id for m in members})
|
|
784
814
|
records = []
|
|
785
815
|
for _, members in groups:
|
|
786
816
|
primary = members[0]
|
|
787
|
-
|
|
788
|
-
if len(members) == 1 and orf_id == primary.orf_id:
|
|
817
|
+
if len(members) == 1:
|
|
789
818
|
records.append(primary)
|
|
790
819
|
continue
|
|
791
820
|
pinned = {None if m.reference_context is None else m.reference_context.key for m in members}
|
|
792
821
|
records.append(replace(
|
|
793
822
|
# The merged ORF is no one source's lift; each member keeps its own lift provenance.
|
|
794
|
-
primary,
|
|
823
|
+
primary, members=tuple(members), lifted_from=None, liftover=None,
|
|
795
824
|
initiation_context=_shared_context(primary, members),
|
|
796
825
|
# Sources pinned to different annotations of one assembly leave the ORF unpinned.
|
|
797
826
|
reference_context=primary.reference_context if len(pinned) == 1 else None, **_union(members, study)))
|
|
827
|
+
records = _qualify_colliding_ids(records)
|
|
798
828
|
paths = {}
|
|
799
829
|
for record in records:
|
|
800
830
|
paths.setdefault(_path_key(record), set()).add((_merge_key(record), record.orf_id))
|
|
@@ -779,17 +779,20 @@ class ExtraORFs:
|
|
|
779
779
|
found.append(orf)
|
|
780
780
|
return tuple(found)
|
|
781
781
|
|
|
782
|
-
def for_orf(self, orf_id):
|
|
782
|
+
def for_orf(self, orf_id, *, source=None):
|
|
783
783
|
"""Every transcript placement of one ORF, the source's own transcript first.
|
|
784
784
|
|
|
785
785
|
After merging catalogues, any source's ID finds the ORF, bare or as
|
|
786
786
|
``source:id``; a bare ID two sources use for different ORFs raises.
|
|
787
|
+
Pass ``source`` to select the native ID in one source explicitly.
|
|
787
788
|
"""
|
|
788
789
|
if self.catalog is not None:
|
|
789
790
|
try:
|
|
790
|
-
orf_id = self.catalog.get(orf_id).orf_id
|
|
791
|
+
orf_id = self.catalog.get(orf_id, source=source).orf_id
|
|
791
792
|
except KeyError:
|
|
792
793
|
return ()
|
|
794
|
+
elif source is not None:
|
|
795
|
+
raise ValueError("Source-qualified lookup requires the source catalogue")
|
|
793
796
|
return tuple(sorted((o for o in self.orfs if o.orf_id == orf_id),
|
|
794
797
|
key=lambda o: (not o.on_source_transcript, _versioned(o.transcript))))
|
|
795
798
|
|
|
@@ -31,6 +31,7 @@ from ..catalog import ORFCatalog, ORFEvidence, ORFRecord
|
|
|
31
31
|
from ..evidence_summary import EvidenceSummary
|
|
32
32
|
from ..model import ORFModel
|
|
33
33
|
from ..reference import ScopedTarget
|
|
34
|
+
from ..sequence import genetic_code
|
|
34
35
|
|
|
35
36
|
MS_DEFINITION = "Sum of study-specific unique-peptide counts; not global peptide uniqueness."
|
|
36
37
|
TE_DEFINITION = "Count of studies reporting one or more significant translation detections."
|
|
@@ -83,6 +84,9 @@ def _summary(reference, accession, protein, method, metric, value, definition, u
|
|
|
83
84
|
def import_orfs(inputs, output, manifest):
|
|
84
85
|
"""Write the catalogue ``manifest`` describes from its OpenProt TSV, BED and FASTA archives."""
|
|
85
86
|
processing = manifest.processing
|
|
87
|
+
translation_tables = processing.get("translation_tables", {})
|
|
88
|
+
for code in translation_tables.values():
|
|
89
|
+
genetic_code(code) # Unsupported source declarations must never fall back.
|
|
86
90
|
members = processing["members"]
|
|
87
91
|
rows = list(csv.DictReader(io.StringIO(_member(inputs["tsv"], members["tsv"])), delimiter="\t"))
|
|
88
92
|
bed = [line.split("\t") for line in _member(inputs["bed"], members["bed"]).splitlines() if line.strip()]
|
|
@@ -92,13 +96,16 @@ def import_orfs(inputs, output, manifest):
|
|
|
92
96
|
tsv = next(s for s in manifest.sources if s.asset_id == "tsv")
|
|
93
97
|
if len(bed) != len(rows):
|
|
94
98
|
raise ValueError("OpenProt TSV and BED row counts disagree")
|
|
99
|
+
unknown = set(translation_tables) - {row["transcript accession"] for row in rows}
|
|
100
|
+
if unknown:
|
|
101
|
+
raise ValueError("OpenProt translation tables name absent source transcripts: %s" % sorted(unknown))
|
|
95
102
|
|
|
96
103
|
paths, unresolved, scores = defaultdict(dict), [], {}
|
|
97
104
|
for line, (row, region) in enumerate(zip(rows, bed), start=2):
|
|
98
105
|
accession, transcript = row["protein accession"], row["transcript accession"]
|
|
99
|
-
if row["chr"] in ("MT", "M")
|
|
106
|
+
if row["chr"] in ("MT", "M") and transcript not in translation_tables:
|
|
100
107
|
raise ValueError(f"OpenProt TSV line {line} ({accession}) is mitochondrial; the importer handles "
|
|
101
|
-
"
|
|
108
|
+
"it only with an explicit source-transcript translation table")
|
|
102
109
|
length = int(row["protein length (a.a.)"])
|
|
103
110
|
blocks = _blocks(region)
|
|
104
111
|
protein = proteins.get(accession)
|
|
@@ -116,7 +123,7 @@ def import_orfs(inputs, output, manifest):
|
|
|
116
123
|
if not transcript.startswith(processing["transcript_prefix"]):
|
|
117
124
|
unresolved.append(dict(protein=accession, transcript=transcript, reason=processing["unresolved_reason"]))
|
|
118
125
|
continue
|
|
119
|
-
key = (row["chr"], region[5], blocks)
|
|
126
|
+
key = (row["chr"], region[5], blocks, translation_tables.get(transcript, 1))
|
|
120
127
|
found = paths[accession].setdefault(key, dict(protein=protein, genes={}, types=set()))
|
|
121
128
|
found["genes"][transcript] = row["gene symbol"].split(".")[0] # Overlapping genes can share a path.
|
|
122
129
|
found["types"].add(row["protein type"])
|
|
@@ -124,7 +131,7 @@ def import_orfs(inputs, output, manifest):
|
|
|
124
131
|
records = []
|
|
125
132
|
for accession, found in sorted(paths.items()):
|
|
126
133
|
ms, te = scores[accession]
|
|
127
|
-
for (contig, strand, blocks), path in sorted(found.items(), key=lambda item: min(item[1]["genes"])):
|
|
134
|
+
for (contig, strand, blocks, table), path in sorted(found.items(), key=lambda item: min(item[1]["genes"])):
|
|
128
135
|
transcript = min(path["genes"])
|
|
129
136
|
if len(path["types"]) != 1:
|
|
130
137
|
raise ValueError(f"OpenProt gives {accession} several protein types")
|
|
@@ -132,7 +139,7 @@ def import_orfs(inputs, output, manifest):
|
|
|
132
139
|
model = ORFModel(accession if len(found) == 1 else f"{accession}@{transcript}", transcript,
|
|
133
140
|
path["genes"][transcript], "", contig, strand, blocks, protein, path["types"].pop(),
|
|
134
141
|
record_reference.genome_build, record_reference.taxon_id, record_reference.species,
|
|
135
|
-
source="openprot", reference_context=record_reference)
|
|
142
|
+
source="openprot", reference_context=record_reference, translation_table=table)
|
|
136
143
|
summaries = tuple(_summary(summary_reference, accession, protein, *values, tsv.url, tsv.sha256) for values in (
|
|
137
144
|
("ms", "MS score", ms, MS_DEFINITION), ("ribosome", "TE Translation Event score", te, TE_DEFINITION)))
|
|
138
145
|
records.append(ORFRecord.from_model(model, ORFEvidence(summaries=summaries)))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.38.2"
|
|
@@ -118,6 +118,7 @@ tests/conftest.py
|
|
|
118
118
|
tests/test_catalog_registry.py
|
|
119
119
|
tests/test_copy.py
|
|
120
120
|
tests/test_cross_reference_pairing.py
|
|
121
|
+
tests/test_dog_ncorf_search.py
|
|
121
122
|
tests/test_dog_peptides.py
|
|
122
123
|
tests/test_downloads.py
|
|
123
124
|
tests/test_ensembl_search_reference.py
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import importlib.util
|
|
2
|
+
import os
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
SCRIPTS = Path(__file__).parents[1] / "scripts" / "experimental" / "dog-ncorf-search"
|
|
11
|
+
pytestmark = pytest.mark.skipif(not SCRIPTS.is_dir(), reason="experimental scripts are not in the sdist")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _load(name):
|
|
15
|
+
spec = importlib.util.spec_from_file_location(name, SCRIPTS / f"{name}.py")
|
|
16
|
+
module = importlib.util.module_from_spec(spec)
|
|
17
|
+
spec.loader.exec_module(module)
|
|
18
|
+
return module
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_dog_search_qvalues_include_complete_score_ties():
|
|
22
|
+
qvalues = _load("fdr").qvalues
|
|
23
|
+
scores = np.array([10.0, 9.0, 9.0, 8.0])
|
|
24
|
+
decoys = np.array([False, False, True, True])
|
|
25
|
+
expected = np.array([0.0, 0.5, 0.5, 1.0])
|
|
26
|
+
np.testing.assert_allclose(qvalues(scores, decoys), expected)
|
|
27
|
+
np.testing.assert_allclose(qvalues(scores[[0, 2, 1, 3]], decoys[[0, 2, 1, 3]]), expected)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_dog_search_normalizes_non_blosum_residues():
|
|
31
|
+
normalize = _load("homology").blosum62_sequence
|
|
32
|
+
assert normalize("ACUOJX*") == "ACCKXX*"
|
|
33
|
+
with pytest.raises(ValueError, match="unsupported"):
|
|
34
|
+
normalize("AC-")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_dog_search_driver_fails_when_a_run_has_a_failure_marker(tmp_path):
|
|
38
|
+
work = tmp_path / "search"
|
|
39
|
+
(work / "db").mkdir(parents=True)
|
|
40
|
+
(work / "work").mkdir()
|
|
41
|
+
(work / "db" / "dog_db.fasta").write_text(">CANON000000\nPEPTIDE\n")
|
|
42
|
+
(work / "runs.tsv").write_text(
|
|
43
|
+
"failed\tfixture\thttps://example.invalid/archive.zip\tfailed.mzML\t1\t1\n")
|
|
44
|
+
(work / "work" / "failed.fetch_failed").write_text("intentional test marker\n")
|
|
45
|
+
|
|
46
|
+
sage = tmp_path / "sage"
|
|
47
|
+
sage.write_text("#!/bin/sh\n[ \"${1:-}\" = --version ] && echo 'sage test'\n")
|
|
48
|
+
sage.chmod(0o755)
|
|
49
|
+
python = tmp_path / "python"
|
|
50
|
+
python.write_text(
|
|
51
|
+
f"#!/bin/sh\n"
|
|
52
|
+
"case \"$*\" in\n"
|
|
53
|
+
" *'import pandas, pyarrow, inflate64'*) exit 0;;\n"
|
|
54
|
+
"esac\n"
|
|
55
|
+
f"exec {sys.executable} \"$@\"\n")
|
|
56
|
+
python.chmod(0o755)
|
|
57
|
+
env = dict(os.environ, SAGE=str(sage), PYTHON=str(python), MIN_FREE_GB="0")
|
|
58
|
+
result = subprocess.run(
|
|
59
|
+
["bash", str(SCRIPTS / "driver.sh"), str(work)], env=env,
|
|
60
|
+
capture_output=True, text=True, check=False)
|
|
61
|
+
assert result.returncode == 1
|
|
62
|
+
assert "INCOMPLETE searched=0 failed=1" in result.stdout
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"""Declared NCBI genetic codes bind native mitochondrial ORFs and fail closed otherwise."""
|
|
2
2
|
|
|
3
|
+
import csv
|
|
4
|
+
import io
|
|
3
5
|
import json
|
|
6
|
+
import zipfile
|
|
4
7
|
from dataclasses import replace
|
|
5
8
|
from pathlib import Path
|
|
6
9
|
|
|
@@ -122,3 +125,54 @@ def test_codon_annotation_uses_the_declared_code(table, expected):
|
|
|
122
125
|
assert codon["alternate_codon"] == "ATG" and codon["alternate_codon_translation"] == "M"
|
|
123
126
|
with pytest.raises(ValueError, match="translation table"):
|
|
124
127
|
replace(orf, translation_table=4).annotate_initiation_snv(103, "C", "A", genome_build="R64-1-1")
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@pytest.mark.parametrize("native", FIXTURES[:1], ids=[FIXTURES[0]["name"]], indirect=True)
|
|
131
|
+
def test_native_openprot_import_accepts_only_a_declared_supported_code(native, tmp_path):
|
|
132
|
+
"""Replay the pinned native row; archive wrappers/BED serialization are fixture-only."""
|
|
133
|
+
from orfdata import CatalogRegistry, load_catalog
|
|
134
|
+
from orfdata.sources.openprot import import_orfs
|
|
135
|
+
|
|
136
|
+
example, original, transcript = native
|
|
137
|
+
row = example["native"]
|
|
138
|
+
tsv = io.StringIO()
|
|
139
|
+
writer = csv.DictWriter(tsv, fieldnames=list(row), delimiter="\t", lineterminator="\n")
|
|
140
|
+
writer.writeheader()
|
|
141
|
+
writer.writerow(row)
|
|
142
|
+
a, b = original.coding_blocks[0]
|
|
143
|
+
bed = f"chrMT\t{a - 1}\t{b}\t{original.orf_id}\t0\t+\t{a - 1}\t{b}\t0\t1\t{b - a + 1}\t0\n"
|
|
144
|
+
contents = dict(tsv=tsv.getvalue(), bed=bed,
|
|
145
|
+
fasta=example["native_fasta_header"] + "\n" + original.protein_sequence + "\n")
|
|
146
|
+
inputs = {}
|
|
147
|
+
for kind, text in contents.items():
|
|
148
|
+
path = tmp_path / f"fixture.{kind}.zip"
|
|
149
|
+
with zipfile.ZipFile(path, "w") as archive:
|
|
150
|
+
archive.writestr(f"fixture.{kind}", text)
|
|
151
|
+
inputs[kind] = path
|
|
152
|
+
base = CatalogRegistry().info("openprot-mouse")
|
|
153
|
+
summary = example["summaries"][0]
|
|
154
|
+
manifest = replace(base, catalog_id="openprot-human-fixture",
|
|
155
|
+
references=(original.reference_context,
|
|
156
|
+
ReferenceContext(**summary["target"]["reference"])),
|
|
157
|
+
sources=tuple(replace(s, url=summary["source_url"], sha256=summary["source_sha256"])
|
|
158
|
+
if s.asset_id == "tsv" else s for s in base.sources),
|
|
159
|
+
processing=dict(base.processing, transcript_prefix="ENST",
|
|
160
|
+
members={kind: f"fixture.{kind}" for kind in contents},
|
|
161
|
+
translation_tables={original.transcript_id: 2}),
|
|
162
|
+
coverage=dict(records=1, source_rows=1, resolved_rows=1, unresolved_rows=0,
|
|
163
|
+
accessions=1, resolved_accessions=1))
|
|
164
|
+
output = tmp_path / "catalog.json.gz"
|
|
165
|
+
import_orfs(inputs, output, manifest)
|
|
166
|
+
imported = load_catalog(output).get(original.orf_id)
|
|
167
|
+
assert imported.translation_table == 2
|
|
168
|
+
assert imported.coding_blocks == original.coding_blocks
|
|
169
|
+
assert imported.bind(transcript).protein_sequence == original.protein_sequence
|
|
170
|
+
assert {s.metric: s.value for s in imported.summaries} == {
|
|
171
|
+
"MS score": 2, "TE Translation Event score": 0}
|
|
172
|
+
assert imported.summaries[0].source_sha256 == summary["source_sha256"]
|
|
173
|
+
for declarations, error in [({}, "is mitochondrial"),
|
|
174
|
+
({original.transcript_id: 4}, "translation table"),
|
|
175
|
+
({"missing-transcript": 2}, "absent source transcripts")]:
|
|
176
|
+
with pytest.raises(ValueError, match=error):
|
|
177
|
+
import_orfs(inputs, output, replace(manifest, processing=dict(
|
|
178
|
+
manifest.processing, translation_tables=declarations)))
|
|
@@ -62,6 +62,64 @@ def test_one_id_for_different_orfs_is_qualified_and_never_guessed():
|
|
|
62
62
|
merged.get("missing")
|
|
63
63
|
|
|
64
64
|
|
|
65
|
+
def test_direct_catalogue_preserves_colliding_source_records_and_lookup(tmp_path):
|
|
66
|
+
first = replace(orf("shared", ribosome_studies=("study-a",)), source="a")
|
|
67
|
+
second = replace(orf("shared", ribosome_studies=("study-b",)), source="b")
|
|
68
|
+
catalog = ORFCatalog([first, second], metadata("combined-v1", "combined"))
|
|
69
|
+
assert [r.orf_id for r in catalog.records] == ["a:shared", "b:shared"]
|
|
70
|
+
for original in (first, second):
|
|
71
|
+
record = catalog.get("shared", source=original.source)
|
|
72
|
+
assert record.members == (original,)
|
|
73
|
+
assert catalog.get(f"{original.source}:shared") is record
|
|
74
|
+
assert record.ribosome_studies == original.ribosome_studies
|
|
75
|
+
with pytest.raises(ValueError, match="shared names several ORFs"):
|
|
76
|
+
catalog.get("shared")
|
|
77
|
+
with pytest.raises(KeyError):
|
|
78
|
+
catalog.get("shared", source="absent")
|
|
79
|
+
path = tmp_path / "collisions.json.gz"
|
|
80
|
+
catalog.save(path)
|
|
81
|
+
loaded = load_catalog(path)
|
|
82
|
+
assert loaded.to_dict() == catalog.to_dict()
|
|
83
|
+
assert loaded.get("shared", source="a").members == (first,)
|
|
84
|
+
with pytest.raises(ValueError, match="names several ORFs"):
|
|
85
|
+
loaded.get("shared")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_source_qualified_ids_cannot_overwrite_native_ids_or_delimiter_collisions():
|
|
89
|
+
records = [replace(orf(identifier), source=source) for source, identifier in (
|
|
90
|
+
("a", "x"), ("b", "x"), ("a", "a:x"), ("a:b", "c"), ("a", "b:c"))]
|
|
91
|
+
catalog = ORFCatalog(records, metadata("combined-v1", "combined"))
|
|
92
|
+
assert len({r.orf_id for r in catalog.records}) == len(records)
|
|
93
|
+
for original in records:
|
|
94
|
+
resolved = catalog.get(original.orf_id, source=original.source)
|
|
95
|
+
assert original in (resolved.members or (resolved,))
|
|
96
|
+
for ambiguous in ("x", "a:x", "a:b:c"):
|
|
97
|
+
with pytest.raises(ValueError, match="names several ORFs"):
|
|
98
|
+
catalog.get(ambiguous)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@pytest.mark.parametrize("changed", [False, True])
|
|
102
|
+
def test_duplicate_ids_within_one_source_still_raise(changed):
|
|
103
|
+
original = orf("same")
|
|
104
|
+
other = replace(original, protein_sequence="MKPA") if changed else original
|
|
105
|
+
with pytest.raises(ValueError, match="Duplicate ORF identifiers"):
|
|
106
|
+
ORFCatalog([original, other], metadata("fixture-v1", "synthetic"))
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def test_direct_collisions_keep_distinct_placements_and_proteome_records(genome): # noqa: F811
|
|
110
|
+
records = [replace(orf("shared"), source="a"),
|
|
111
|
+
replace(orf("shared", blocks=((218, 226),), protein="MK"), source="b")]
|
|
112
|
+
catalog = ORFCatalog(records, metadata("combined-v1", "combined"))
|
|
113
|
+
found = extra_orfs(genome, catalog=catalog)
|
|
114
|
+
assert {o.protein_sequence for o in found.for_orf("shared", source="a")} == {"MKPG"}
|
|
115
|
+
assert {o.protein_sequence for o in found.for_orf("shared", source="b")} == {"MK"}
|
|
116
|
+
with pytest.raises(ValueError, match="names several ORFs"):
|
|
117
|
+
found.for_orf("shared")
|
|
118
|
+
proteins = Proteome.from_genome(genome).with_extra_orfs(None, catalog=catalog)
|
|
119
|
+
assert {(p.accession, p.sequence) for p in proteins if p.kind == "extra_orf"} == {
|
|
120
|
+
("a:shared", "MKPG"), ("b:shared", "MK")}
|
|
121
|
+
|
|
122
|
+
|
|
65
123
|
def test_incompatible_catalogues_are_not_merged():
|
|
66
124
|
first = make_catalog()
|
|
67
125
|
assert merge_catalogs([first]) is first
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.37.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|