hca-schema-validator 0.2.0__py3-none-any.whl
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.
- hca_schema_validator/__init__.py +11 -0
- hca_schema_validator/_vendored/__init__.py +18 -0
- hca_schema_validator/_vendored/cellxgene_schema/LICENSE +20 -0
- hca_schema_validator/_vendored/cellxgene_schema/__init__.py +1 -0
- hca_schema_validator/_vendored/cellxgene_schema/atac_seq.py +675 -0
- hca_schema_validator/_vendored/cellxgene_schema/cli.py +206 -0
- hca_schema_validator/_vendored/cellxgene_schema/env.py +9 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode.py +163 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/.gitignore +3 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/drosophila_melanogaster_diff.txt +42 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/gene_info.md +29 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/gene_info.yml +51 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_caenorhabditis_elegans.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_callithrix_jacchus.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_danio_rerio.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_drosophila_melanogaster.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_ercc.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_gorilla_gorilla.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_homo_sapiens.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_macaca_fascicularis.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_macaca_mulatta.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_microcebus_murinus.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_mus_musculus.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_oryctolagus_cuniculus.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_pan_troglodytes.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_rattus_norvegicus.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_sars_cov_2.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_sus_scrofa.csv.gz +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/homo_sapiens_diff.txt +1237 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/mus_musculus_diff.txt +549 -0
- hca_schema_validator/_vendored/cellxgene_schema/gencode_files/rattus_norvegicus_diff.txt +7306 -0
- hca_schema_validator/_vendored/cellxgene_schema/map_species.py +40 -0
- hca_schema_validator/_vendored/cellxgene_schema/matrix_utils.py +134 -0
- hca_schema_validator/_vendored/cellxgene_schema/migrate.py +145 -0
- hca_schema_validator/_vendored/cellxgene_schema/migrate_files/automigrate_terms.json +2 -0
- hca_schema_validator/_vendored/cellxgene_schema/migrate_files/donor_updates.json +2 -0
- hca_schema_validator/_vendored/cellxgene_schema/migrate_files/non_csr_list.txt +54 -0
- hca_schema_validator/_vendored/cellxgene_schema/migrate_files/private_non_csr.json +1 -0
- hca_schema_validator/_vendored/cellxgene_schema/migrate_files/title_donor_updates.json +2 -0
- hca_schema_validator/_vendored/cellxgene_schema/ontology_files/.gitignore +1 -0
- hca_schema_validator/_vendored/cellxgene_schema/ontology_parser.py +3 -0
- hca_schema_validator/_vendored/cellxgene_schema/remove_labels.py +74 -0
- hca_schema_validator/_vendored/cellxgene_schema/schema.py +21 -0
- hca_schema_validator/_vendored/cellxgene_schema/schema_definitions/schema_definition.yaml +841 -0
- hca_schema_validator/_vendored/cellxgene_schema/utils.py +242 -0
- hca_schema_validator/_vendored/cellxgene_schema/validate.py +2389 -0
- hca_schema_validator/_vendored/cellxgene_schema/validation_internals/__init__.py +0 -0
- hca_schema_validator/_vendored/cellxgene_schema/validation_internals/check_duplicates.py +87 -0
- hca_schema_validator/_vendored/cellxgene_schema/write_labels.py +403 -0
- hca_schema_validator/schema_definitions/hca_schema_definition.yaml +839 -0
- hca_schema_validator/validator.py +47 -0
- hca_schema_validator-0.2.0.dist-info/METADATA +116 -0
- hca_schema_validator-0.2.0.dist-info/RECORD +55 -0
- hca_schema_validator-0.2.0.dist-info/WHEEL +4 -0
- hca_schema_validator-0.2.0.dist-info/licenses/NOTICE +15 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger("cellxgene_schema")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.group(
|
|
10
|
+
name="schema",
|
|
11
|
+
subcommand_metavar="COMMAND <args>",
|
|
12
|
+
short_help="Apply and validate the cellxgene data integration schema to an h5ad file.",
|
|
13
|
+
context_settings=dict(max_content_width=85, help_option_names=["-h", "--help"]),
|
|
14
|
+
)
|
|
15
|
+
@click.option("-v", "--verbose", help="When present will set logging level to debug", is_flag=True)
|
|
16
|
+
def schema_cli(verbose):
|
|
17
|
+
logging.basicConfig(level=logging.ERROR)
|
|
18
|
+
logger.setLevel(logging.DEBUG if verbose else logging.INFO)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@schema_cli.command(
|
|
22
|
+
name="validate",
|
|
23
|
+
short_help="Check that an h5ad follows the cellxgene data integration schema.",
|
|
24
|
+
help="Check that an h5ad follows the cellxgene data integration schema. If validation fails this command will "
|
|
25
|
+
"return an exit status of 1 otherwise 0. When the '--add-labels <FILE>' tag is present, the command will add "
|
|
26
|
+
"ontology/gene labels based on IDs and write them to a new h5ad.",
|
|
27
|
+
)
|
|
28
|
+
@click.argument("h5ad_file", nargs=1, type=click.Path(exists=True, dir_okay=False))
|
|
29
|
+
@click.option(
|
|
30
|
+
"-a",
|
|
31
|
+
"--add-labels",
|
|
32
|
+
"add_labels_file",
|
|
33
|
+
help="When present it will add labels to genes and ontologies based on IDs",
|
|
34
|
+
required=False,
|
|
35
|
+
default=None,
|
|
36
|
+
type=click.Path(exists=False, dir_okay=False, writable=True),
|
|
37
|
+
)
|
|
38
|
+
@click.option("-i", "--ignore-labels", help="Ignore ontology labels when validating", is_flag=True)
|
|
39
|
+
def schema_validate(h5ad_file, add_labels_file, ignore_labels):
|
|
40
|
+
# Imports are very slow so we defer loading until Click arg validation has passed
|
|
41
|
+
logger.info("Loading dependencies")
|
|
42
|
+
try:
|
|
43
|
+
import anndata # noqa: F401
|
|
44
|
+
except ImportError:
|
|
45
|
+
raise click.ClickException("[cellxgene] cellxgene-schema requires anndata") from None
|
|
46
|
+
|
|
47
|
+
logger.info("Loading validator modules")
|
|
48
|
+
from .validate import validate
|
|
49
|
+
|
|
50
|
+
is_valid, _, _ = validate(h5ad_file, add_labels_file, ignore_labels=ignore_labels)
|
|
51
|
+
if is_valid:
|
|
52
|
+
sys.exit(0)
|
|
53
|
+
else:
|
|
54
|
+
sys.exit(1)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@schema_cli.command(
|
|
58
|
+
name="add-labels",
|
|
59
|
+
short_help="Create a copy of an h5ad with portal-added labels",
|
|
60
|
+
help="Create a copy of an h5ad with portal-added labels. The labels are added based on the IDs in the "
|
|
61
|
+
"provided file.",
|
|
62
|
+
)
|
|
63
|
+
@click.argument("input_file", nargs=1, type=click.Path(exists=True, dir_okay=False))
|
|
64
|
+
@click.argument("output_file", nargs=1, type=click.Path(exists=False, dir_okay=False))
|
|
65
|
+
def add_labels(input_file, output_file):
|
|
66
|
+
from utils import read_h5ad
|
|
67
|
+
|
|
68
|
+
from .write_labels import AnnDataLabelAppender
|
|
69
|
+
|
|
70
|
+
logger.info(f"Loading h5ad from {input_file}")
|
|
71
|
+
adata = read_h5ad(input_file)
|
|
72
|
+
anndata_label_adder = AnnDataLabelAppender(adata)
|
|
73
|
+
logger.info("Adding labels")
|
|
74
|
+
if anndata_label_adder.write_labels(output_file):
|
|
75
|
+
sys.exit(0)
|
|
76
|
+
else:
|
|
77
|
+
sys.exit(1)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _check_anndata_requires_fragment(h5ad_file):
|
|
81
|
+
from .atac_seq import check_anndata_requires_fragment, report_errors
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
fragment_required = check_anndata_requires_fragment(h5ad_file)
|
|
85
|
+
if fragment_required:
|
|
86
|
+
logger.info("Anndata requires an ATAC fragment file.")
|
|
87
|
+
else:
|
|
88
|
+
logger.info("Anndata does not require an ATAC fragment file.")
|
|
89
|
+
except Exception as e:
|
|
90
|
+
report_errors("Anndata does not support ATAC fragment files for the followings reasons:", [str(e)])
|
|
91
|
+
sys.exit(1)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@schema_cli.command(
|
|
95
|
+
name="process-fragment",
|
|
96
|
+
short_help="Check that an ATAC SEQ fragment follows the cellxgene data integration schema.",
|
|
97
|
+
help="Check that an ATAC SEQ fragment follows the cellxgene data integration schema. If validation fails this "
|
|
98
|
+
"command will return an exit status of 1 otherwise 0. When the '--generate-index' tag is present, "
|
|
99
|
+
"the command will generate a tabix compatible version of the fragment and tabix index. The generated "
|
|
100
|
+
"fragment will have the file suffix .bgz and the index will have the file suffix .bgz.tbi.",
|
|
101
|
+
)
|
|
102
|
+
@click.argument("h5ad_file", nargs=1, type=click.Path(exists=True, dir_okay=False))
|
|
103
|
+
@click.argument("fragment_file", nargs=1, type=click.Path(exists=True, dir_okay=False))
|
|
104
|
+
@click.option("-i", "--generate-index", help="Generate index for fragment", is_flag=True)
|
|
105
|
+
@click.option("-o", "--output-file", help="Output file for the processed fragment.", type=click.Path(exists=False))
|
|
106
|
+
def fragment_validate(h5ad_file, fragment_file, generate_index, output_file):
|
|
107
|
+
from .atac_seq import process_fragment
|
|
108
|
+
|
|
109
|
+
_check_anndata_requires_fragment(h5ad_file)
|
|
110
|
+
|
|
111
|
+
if not process_fragment(fragment_file, h5ad_file, generate_index=generate_index, output_file=output_file):
|
|
112
|
+
sys.exit(1)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
# add a cli command to deduplicate an ATAC fragment file
|
|
116
|
+
@schema_cli.command(
|
|
117
|
+
name="deduplicate-fragment",
|
|
118
|
+
short_help="Deduplicate an ATAC SEQ fragment file.",
|
|
119
|
+
help="Deduplicate an ATAC SEQ fragment file. If deduplication fails this command will return an exit status of 1 "
|
|
120
|
+
"otherwise 0. The deduplicated fragment will have the file suffix .dedup.bgz and the index will have the file "
|
|
121
|
+
"suffix .dedup.bgz.tbi.",
|
|
122
|
+
)
|
|
123
|
+
@click.argument("fragment_file", nargs=1, type=click.Path(exists=True, dir_okay=False))
|
|
124
|
+
@click.option("-o", "--output-file", help="Output file for the deduplicated fragment.", type=click.Path(exists=False))
|
|
125
|
+
@click.option("-m", "--memory", help="Memory limit as a percentage of total memory.", type=int, default=80)
|
|
126
|
+
def deduplicate_fragment(fragment_file, output_file, memory):
|
|
127
|
+
from .atac_seq import deduplicate_fragment_rows
|
|
128
|
+
|
|
129
|
+
try:
|
|
130
|
+
deduplicate_fragment_rows(fragment_file, output_file_name=output_file, sort_memory_percent=memory)
|
|
131
|
+
except Exception as e:
|
|
132
|
+
logger.error(f"Failed to deduplicate fragment file: {e}")
|
|
133
|
+
sys.exit(1)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@schema_cli.command(
|
|
137
|
+
name="check-anndata-requires-fragment",
|
|
138
|
+
short_help="Check if that the anndata provided supports an Atac seq fragment file.",
|
|
139
|
+
help="Check that an ATAC SEQ anndata.obs['assay_ontology_term_id'] is all paired or unpaired assays. "
|
|
140
|
+
"This determines if a fragment file is required, optional, or forbiden. "
|
|
141
|
+
"If the anndata does not support a fragment, an error message will be printed and exit status will be 1.",
|
|
142
|
+
)
|
|
143
|
+
@click.argument("h5ad_file", nargs=1, type=click.Path(exists=True, dir_okay=False))
|
|
144
|
+
def check_anndata_requires_fragment(h5ad_file):
|
|
145
|
+
_check_anndata_requires_fragment(h5ad_file)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@schema_cli.command(
|
|
149
|
+
name="remove-labels",
|
|
150
|
+
short_help="Create a copy of an h5ad without portal-added labels",
|
|
151
|
+
help="Create a copy of an h5ad without portal-added labels.",
|
|
152
|
+
)
|
|
153
|
+
@click.argument("input_file", nargs=1, type=click.Path(exists=True, dir_okay=False))
|
|
154
|
+
@click.argument("output_file", nargs=1, type=click.Path(exists=False, dir_okay=False))
|
|
155
|
+
def remove_labels(input_file, output_file):
|
|
156
|
+
from .remove_labels import AnnDataLabelRemover
|
|
157
|
+
|
|
158
|
+
logger.info("Loading dependencies")
|
|
159
|
+
try:
|
|
160
|
+
import anndata # noqa: F401
|
|
161
|
+
except ImportError:
|
|
162
|
+
raise click.ClickException("[cellxgene] cellxgene-schema requires anndata") from None
|
|
163
|
+
|
|
164
|
+
logger.info(f"Loading h5ad from {input_file}")
|
|
165
|
+
adata = anndata.read_h5ad(input_file)
|
|
166
|
+
anndata_label_remover = AnnDataLabelRemover(adata)
|
|
167
|
+
if not anndata_label_remover.schema_def:
|
|
168
|
+
return
|
|
169
|
+
logger.info("Removing labels")
|
|
170
|
+
anndata_label_remover.remove_labels()
|
|
171
|
+
logger.info(f"Labels have been removed. Writing to {output_file}")
|
|
172
|
+
anndata_label_remover.adata.write(output_file, compression="gzip")
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
@schema_cli.command(
|
|
176
|
+
name="migrate",
|
|
177
|
+
short_help="Convert an h5ad to the latest schema version.",
|
|
178
|
+
help="Convert an h5ad from the previous to latest minor schema version. No validation will be "
|
|
179
|
+
"performed on either the input or the output file.",
|
|
180
|
+
)
|
|
181
|
+
@click.argument("input_file", nargs=1, type=click.Path(exists=True, dir_okay=False))
|
|
182
|
+
@click.argument("output_file", nargs=1, type=click.Path(exists=False, dir_okay=False))
|
|
183
|
+
@click.option("--collection_id", default=None, type=str, help="Collection ID, if migrating already published dataset")
|
|
184
|
+
@click.option("--dataset_id", default=None, type=str, help="Dataset ID, if migrating already published dataset")
|
|
185
|
+
def migrate(input_file, output_file, collection_id, dataset_id):
|
|
186
|
+
from .migrate import migrate
|
|
187
|
+
|
|
188
|
+
migrate(input_file, output_file, collection_id, dataset_id)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
@schema_cli.command(
|
|
192
|
+
name="map-species",
|
|
193
|
+
short_help="Annotate non-human, non-mouse anndata with CL and UBERON equivalent terms",
|
|
194
|
+
help="Annotate non-human, non-mouse anndata with CL and UBERON equivalent terms, based on values in"
|
|
195
|
+
"organism-specific columns (e.g. organism_cell_type_ontology_term_id and organism_tissue_ontology_term_id)",
|
|
196
|
+
)
|
|
197
|
+
@click.argument("input_file", nargs=1, type=click.Path(exists=True, dir_okay=False))
|
|
198
|
+
@click.argument("output_file", nargs=1, type=click.Path(exists=False, dir_okay=False))
|
|
199
|
+
def map_species(input_file, output_file):
|
|
200
|
+
from .map_species import map_species
|
|
201
|
+
|
|
202
|
+
map_species(input_file, output_file)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
if __name__ == "__main__":
|
|
206
|
+
schema_cli()
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
PACKAGE_ROOT = os.path.dirname(os.path.realpath(__file__))
|
|
4
|
+
GENCODE_DIR = os.path.join(PACKAGE_ROOT, "gencode_files")
|
|
5
|
+
GENE_INFO_YAML = os.path.join(GENCODE_DIR, "gene_info.yml")
|
|
6
|
+
SCHEMA_DEFINITIONS_DIR = os.path.join(PACKAGE_ROOT, "schema_definitions")
|
|
7
|
+
SCHEMA_DEFINITION_FILE = os.path.join(SCHEMA_DEFINITIONS_DIR, "schema_definition.yaml")
|
|
8
|
+
SCHEMA_REFERENCE_BASE_URL = "https://github.com/chanzuckerberg/single-cell-curation/blob/main/schema"
|
|
9
|
+
SCHEMA_REFERENCE_FILE_NAME = "schema.md"
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import enum
|
|
2
|
+
import gzip
|
|
3
|
+
import os
|
|
4
|
+
from typing import Union
|
|
5
|
+
|
|
6
|
+
from . import env
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SupportedOrganisms(enum.Enum):
|
|
10
|
+
# Note that this is different from the valid organisms in `organism_ontology_term_id`
|
|
11
|
+
HOMO_SAPIENS = "NCBITaxon:9606"
|
|
12
|
+
MUS_MUSCULUS = "NCBITaxon:10090"
|
|
13
|
+
SARS_COV_2 = "NCBITaxon:2697049"
|
|
14
|
+
ERCC = "NCBITaxon:32630"
|
|
15
|
+
DROSOPHILA_MELANOGASTER = "NCBITaxon:7227"
|
|
16
|
+
DANIO_RERIO = "NCBITaxon:7955"
|
|
17
|
+
CAENORHABDITIS_ELEGANS = "NCBITaxon:6239"
|
|
18
|
+
MACACA_FASCICULARIS = "NCBITaxon:9541"
|
|
19
|
+
ORYCTOLAGUS_CUNICULUS = "NCBITaxon:9986"
|
|
20
|
+
CALLITHRIX_JACCHUS = "NCBITaxon:9483"
|
|
21
|
+
GORILLA_GORILLA = "NCBITaxon:9595"
|
|
22
|
+
MACACA_MULATTA = "NCBITaxon:9544"
|
|
23
|
+
PAN_TROGLODYTES = "NCBITaxon:9598"
|
|
24
|
+
SUS_SCROFA = "NCBITaxon:9823"
|
|
25
|
+
MICROCEBUS_MURINUS = "NCBITaxon:30608"
|
|
26
|
+
RATTUS_NORVEGICUS = "NCBITaxon:10116"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
EXEMPT_ORGANISMS = ["NCBITaxon:2697049", "NCBITaxon:32630"]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_organism_from_feature_id(
|
|
33
|
+
feature_id: str,
|
|
34
|
+
) -> Union[SupportedOrganisms, None]:
|
|
35
|
+
"""
|
|
36
|
+
Determines organism based on which gene file the feature id was in
|
|
37
|
+
|
|
38
|
+
:param str feature_id: the feature id
|
|
39
|
+
|
|
40
|
+
:rtype Union[ontology.SypportedOrganisms, None]
|
|
41
|
+
:return: the organism the feature id is from
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
for organism in SupportedOrganisms:
|
|
45
|
+
gene_checker = get_gene_checker(organism)
|
|
46
|
+
if gene_checker.is_valid_id(feature_id):
|
|
47
|
+
return organism
|
|
48
|
+
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class GeneChecker:
|
|
53
|
+
"""Handles checking gene ids, retrieves symbols"""
|
|
54
|
+
|
|
55
|
+
GENE_FILES = {
|
|
56
|
+
SupportedOrganisms.HOMO_SAPIENS: os.path.join(env.GENCODE_DIR, "genes_homo_sapiens.csv.gz"),
|
|
57
|
+
SupportedOrganisms.MUS_MUSCULUS: os.path.join(env.GENCODE_DIR, "genes_mus_musculus.csv.gz"),
|
|
58
|
+
SupportedOrganisms.SARS_COV_2: os.path.join(env.GENCODE_DIR, "genes_sars_cov_2.csv.gz"),
|
|
59
|
+
SupportedOrganisms.ERCC: os.path.join(env.GENCODE_DIR, "genes_ercc.csv.gz"),
|
|
60
|
+
SupportedOrganisms.DROSOPHILA_MELANOGASTER: os.path.join(
|
|
61
|
+
env.GENCODE_DIR, "genes_drosophila_melanogaster.csv.gz"
|
|
62
|
+
),
|
|
63
|
+
SupportedOrganisms.DANIO_RERIO: os.path.join(env.GENCODE_DIR, "genes_danio_rerio.csv.gz"),
|
|
64
|
+
SupportedOrganisms.CAENORHABDITIS_ELEGANS: os.path.join(env.GENCODE_DIR, "genes_caenorhabditis_elegans.csv.gz"),
|
|
65
|
+
SupportedOrganisms.MACACA_FASCICULARIS: os.path.join(env.GENCODE_DIR, "genes_macaca_fascicularis.csv.gz"),
|
|
66
|
+
SupportedOrganisms.ORYCTOLAGUS_CUNICULUS: os.path.join(env.GENCODE_DIR, "genes_oryctolagus_cuniculus.csv.gz"),
|
|
67
|
+
SupportedOrganisms.CALLITHRIX_JACCHUS: os.path.join(env.GENCODE_DIR, "genes_callithrix_jacchus.csv.gz"),
|
|
68
|
+
SupportedOrganisms.GORILLA_GORILLA: os.path.join(env.GENCODE_DIR, "genes_gorilla_gorilla.csv.gz"),
|
|
69
|
+
SupportedOrganisms.MACACA_MULATTA: os.path.join(env.GENCODE_DIR, "genes_macaca_mulatta.csv.gz"),
|
|
70
|
+
SupportedOrganisms.PAN_TROGLODYTES: os.path.join(env.GENCODE_DIR, "genes_pan_troglodytes.csv.gz"),
|
|
71
|
+
SupportedOrganisms.SUS_SCROFA: os.path.join(env.GENCODE_DIR, "genes_sus_scrofa.csv.gz"),
|
|
72
|
+
SupportedOrganisms.MICROCEBUS_MURINUS: os.path.join(env.GENCODE_DIR, "genes_microcebus_murinus.csv.gz"),
|
|
73
|
+
SupportedOrganisms.RATTUS_NORVEGICUS: os.path.join(env.GENCODE_DIR, "genes_rattus_norvegicus.csv.gz"),
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
def __init__(self, species: SupportedOrganisms):
|
|
77
|
+
"""
|
|
78
|
+
:param enum.Enum.SupportedSpecies species: item from SupportedOrganisms
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
if species not in self.GENE_FILES:
|
|
82
|
+
raise ValueError(f"{species} not supported.")
|
|
83
|
+
|
|
84
|
+
self.species = species
|
|
85
|
+
self.gene_dict = {}
|
|
86
|
+
with gzip.open(self.GENE_FILES[species], "rt") as genes:
|
|
87
|
+
for gene in genes:
|
|
88
|
+
gene = gene.rstrip().split(",") # type: ignore
|
|
89
|
+
gene_id = gene[0]
|
|
90
|
+
gene_label = gene[1]
|
|
91
|
+
gene_length = int(gene[3])
|
|
92
|
+
gene_type = gene[4]
|
|
93
|
+
|
|
94
|
+
self.gene_dict[gene_id] = (gene_label, gene_length, gene_type)
|
|
95
|
+
|
|
96
|
+
def is_valid_id(self, gene_id: str) -> bool:
|
|
97
|
+
"""
|
|
98
|
+
Checks for validity of gene id
|
|
99
|
+
|
|
100
|
+
:param str gene_id: ENSEMBL gene id
|
|
101
|
+
|
|
102
|
+
:rtype bool
|
|
103
|
+
:return True if the gene_id is a valid ENSEMBL id, False otherwise
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
return gene_id in self.gene_dict
|
|
107
|
+
|
|
108
|
+
def get_symbol(self, gene_id: str) -> str:
|
|
109
|
+
"""
|
|
110
|
+
Gets symbol associated to the ENSEBML id
|
|
111
|
+
|
|
112
|
+
:param str gene_id: ENSEMBL gene id
|
|
113
|
+
|
|
114
|
+
:rtype str
|
|
115
|
+
:return A gene symbol
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
if self.is_valid_id(gene_id):
|
|
119
|
+
return self.gene_dict[gene_id][0]
|
|
120
|
+
else:
|
|
121
|
+
raise ValueError(f"The id '{gene_id}' is not a valid ENSEMBL id for '{self.species}'")
|
|
122
|
+
|
|
123
|
+
def get_length(self, gene_id: str) -> int:
|
|
124
|
+
"""
|
|
125
|
+
Gets feature length associated to the ENSEBML id
|
|
126
|
+
|
|
127
|
+
:param str gene_id: ENSEMBL gene id
|
|
128
|
+
|
|
129
|
+
:rtype int
|
|
130
|
+
:return A gene length
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
if self.is_valid_id(gene_id):
|
|
134
|
+
return self.gene_dict[gene_id][1]
|
|
135
|
+
else:
|
|
136
|
+
raise ValueError(f"The id '{gene_id}' is not a valid ENSEMBL id for '{self.species}'")
|
|
137
|
+
|
|
138
|
+
def get_type(self, gene_id: str) -> str:
|
|
139
|
+
"""
|
|
140
|
+
Gets feature type associated to the ENSEBML id
|
|
141
|
+
|
|
142
|
+
:param str gene_id: ENSEMBL gene id
|
|
143
|
+
|
|
144
|
+
:rtype str
|
|
145
|
+
:return A feature type
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
if self.is_valid_id(gene_id):
|
|
149
|
+
return self.gene_dict[gene_id][2]
|
|
150
|
+
else:
|
|
151
|
+
raise ValueError(f"The id '{gene_id}' is not a valid ENSEMBL id for '{self.species}'")
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
# cache the gene checkers
|
|
155
|
+
_gene_checkers = {}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def get_gene_checker(species: SupportedOrganisms) -> GeneChecker:
|
|
159
|
+
# Values will be instances of gencode.GeneChecker,
|
|
160
|
+
# keys will be one of gencode.SupportedOrganisms
|
|
161
|
+
if species not in _gene_checkers:
|
|
162
|
+
_gene_checkers[species] = GeneChecker(species)
|
|
163
|
+
return _gene_checkers[species]
|
hca_schema_validator/_vendored/cellxgene_schema/gencode_files/drosophila_melanogaster_diff.txt
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
FBgn0011655
|
|
2
|
+
FBgn0086613
|
|
3
|
+
FBgn0038893
|
|
4
|
+
FBgn0086059
|
|
5
|
+
FBgn0263118
|
|
6
|
+
FBgn0086060
|
|
7
|
+
FBgn0051320
|
|
8
|
+
FBgn0039632
|
|
9
|
+
FBgn0086052
|
|
10
|
+
FBgn0086058
|
|
11
|
+
FBgn0086073
|
|
12
|
+
FBti0062685
|
|
13
|
+
FBgn0086082
|
|
14
|
+
FBgn0086076
|
|
15
|
+
FBgn0086077
|
|
16
|
+
FBgn0082953
|
|
17
|
+
FBgn0086080
|
|
18
|
+
FBgn0086081
|
|
19
|
+
FBti0062686
|
|
20
|
+
FBgn0086026
|
|
21
|
+
FBgn0082993
|
|
22
|
+
FBgn0086022
|
|
23
|
+
FBgn0086029
|
|
24
|
+
FBgn0025830
|
|
25
|
+
FBgn0086030
|
|
26
|
+
FBgn0027585
|
|
27
|
+
FBgn0086047
|
|
28
|
+
FBgn0086044
|
|
29
|
+
FBgn0086045
|
|
30
|
+
FBgn0086046
|
|
31
|
+
FBgn0086043
|
|
32
|
+
FBgn0029656
|
|
33
|
+
FBgn0026749
|
|
34
|
+
FBgn0082990
|
|
35
|
+
FBgn0086038
|
|
36
|
+
FBgn0086032
|
|
37
|
+
FBgn0086034
|
|
38
|
+
FBgn0086031
|
|
39
|
+
FBgn0086036
|
|
40
|
+
FBgn0086035
|
|
41
|
+
FBgn0086040
|
|
42
|
+
FBgn0086037
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
This file describes the expected format of *[gene_info.yml](./gene_info.yml)*. It is used to track the
|
|
2
|
+
current version of gene data to be download from various sources.
|
|
3
|
+
|
|
4
|
+
### FORMAT
|
|
5
|
+
|
|
6
|
+
Bellow is a description of the expected fields.
|
|
7
|
+
|
|
8
|
+
| Field | type | required | default | description |
|
|
9
|
+
|-------------|--------|----------|---------|------------------------------------------------------------------------------------------------------------------------------------|
|
|
10
|
+
| {id} | object | True | | Used to identify the dataset. |
|
|
11
|
+
| description | str | True | | Can only contain characters valid in a file name. |
|
|
12
|
+
| version | str | False | None | Use to track the current version of the data used. A version must be present to support auto updating. |
|
|
13
|
+
| url | str | True | | The URL pointing at the data to download or a python formatting string that can be used to build the URL by adding in the version. |
|
|
14
|
+
|
|
15
|
+
### example
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
human:
|
|
19
|
+
description: homo_sapiens
|
|
20
|
+
version: '38'
|
|
21
|
+
url: http://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_{version}/gencode.v{version}.primary_assembly.annotation.gtf.gz
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Updating
|
|
25
|
+
|
|
26
|
+
There are two way to update *[gene_info.yml](./gene_info.yml)*.
|
|
27
|
+
The first approach is to run the recipe `make genes_update`. This is the automated approach and will pull the latest
|
|
28
|
+
version from Gencode and update `gene_info.yml` to reflect those changes. The second approach is to update the fields
|
|
29
|
+
`version` in *[gene_info.yml](./gene_info.yml)* to the desired version.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Changes to this file will trigger a run of the gencode_process.yml GHA job, which will run the gene_processing.py script.
|
|
2
|
+
ercc:
|
|
3
|
+
description: ercc
|
|
4
|
+
url: https://assets.thermofisher.com/TFS-Assets/LSG/manuals/cms_095047.txt
|
|
5
|
+
human:
|
|
6
|
+
description: homo_sapiens
|
|
7
|
+
url: https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_{version}/gencode.v{version}.primary_assembly.annotation.gtf.gz
|
|
8
|
+
version: 48
|
|
9
|
+
mouse:
|
|
10
|
+
description: mus_musculus
|
|
11
|
+
url: https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_mouse/release_{version}/gencode.v{version}.primary_assembly.annotation.gtf.gz
|
|
12
|
+
version: M37
|
|
13
|
+
sars_cov_2:
|
|
14
|
+
description: sars_cov_2
|
|
15
|
+
url: ftp://ftp.ensemblgenomes.org/pub/viruses/gtf/sars_cov_2/Sars_cov_2.ASM985889v3.101.gtf.gz
|
|
16
|
+
fruit_fly:
|
|
17
|
+
description: drosophila_melanogaster
|
|
18
|
+
url: https://ftp.ensembl.org/pub/release-114/gtf/drosophila_melanogaster/Drosophila_melanogaster.BDGP6.54.114.gtf.gz
|
|
19
|
+
zebrafish:
|
|
20
|
+
description: danio_rerio
|
|
21
|
+
url: https://ftp.ensembl.org/pub/release-114/gtf/danio_rerio/Danio_rerio.GRCz11.114.gtf.gz
|
|
22
|
+
roundworm:
|
|
23
|
+
description: caenorhabditis_elegans
|
|
24
|
+
url: https://ftp.ensembl.org/pub/release-114/gtf/caenorhabditis_elegans/Caenorhabditis_elegans.WBcel235.114.gtf.gz
|
|
25
|
+
macaque:
|
|
26
|
+
description: macaca_fascicularis
|
|
27
|
+
url: https://ftp.ensembl.org/pub/release-114/gtf/macaca_fascicularis/Macaca_fascicularis.Macaca_fascicularis_6.0.114.gtf.gz
|
|
28
|
+
rabbit:
|
|
29
|
+
description: oryctolagus_cuniculus
|
|
30
|
+
url: https://ftp.ensembl.org/pub/release-114/gtf/oryctolagus_cuniculus/Oryctolagus_cuniculus.OryCun2.0.114.gtf.gz
|
|
31
|
+
marmoset:
|
|
32
|
+
description: callithrix_jacchus
|
|
33
|
+
url: https://ftp.ensembl.org/pub/release-114/gtf/callithrix_jacchus/Callithrix_jacchus.mCalJac1.pat.X.114.gtf.gz
|
|
34
|
+
gorilla:
|
|
35
|
+
description: gorilla_gorilla
|
|
36
|
+
url: https://ftp.ensembl.org/pub/release-114/gtf/gorilla_gorilla/Gorilla_gorilla.gorGor4.114.gtf.gz
|
|
37
|
+
rhesus_macaque:
|
|
38
|
+
description: macaca_mulatta
|
|
39
|
+
url: https://ftp.ensembl.org/pub/release-114/gtf/macaca_mulatta/Macaca_mulatta.Mmul_10.114.gtf.gz
|
|
40
|
+
troglodyte:
|
|
41
|
+
description: pan_troglodytes
|
|
42
|
+
url: https://ftp.ensembl.org/pub/release-114/gtf/pan_troglodytes/Pan_troglodytes.Pan_tro_3.0.114.gtf.gz
|
|
43
|
+
pig:
|
|
44
|
+
description: sus_scrofa
|
|
45
|
+
url: https://ftp.ensembl.org/pub/release-114/gtf/sus_scrofa/Sus_scrofa.Sscrofa11.1.114.gtf.gz
|
|
46
|
+
lemur:
|
|
47
|
+
description: microcebus_murinus
|
|
48
|
+
url: https://ftp.ensembl.org/pub/release-114/gtf/microcebus_murinus/Microcebus_murinus.Mmur_3.0.114.gtf.gz
|
|
49
|
+
rat:
|
|
50
|
+
description: rattus_norvegicus
|
|
51
|
+
url: https://ftp.ensembl.org/pub/release-114/gtf/rattus_norvegicus/Rattus_norvegicus.GRCr8.114.gtf.gz
|
hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_caenorhabditis_elegans.csv.gz
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_drosophila_melanogaster.csv.gz
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_macaca_fascicularis.csv.gz
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
hca_schema_validator/_vendored/cellxgene_schema/gencode_files/genes_oryctolagus_cuniculus.csv.gz
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|