eva-sub-cli 0.4.10__tar.gz → 0.4.12__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.
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/.github/workflows/trigger-eva-sub-cli-integration-tests.yml +2 -2
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/PKG-INFO +3 -2
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/docker/Dockerfile +1 -1
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/_version.py +2 -2
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/etc/eva_schema.json +10 -2
- eva_sub_cli-0.4.12/eva_sub_cli/executables/evidence_type_checker.py +61 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/executables/samples_checker.py +30 -35
- eva_sub_cli-0.4.12/eva_sub_cli/file_utils.py +224 -0
- eva_sub_cli-0.4.12/eva_sub_cli/jinja_templates/html/project_details.html +65 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/jinja_templates/html/report.html +1 -1
- eva_sub_cli-0.4.12/eva_sub_cli/jinja_templates/text/project_details.txt +37 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/jinja_templates/text/report.txt +1 -1
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/metadata.py +4 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/nextflow/validation.nf +22 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/report.py +15 -11
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/semantic_metadata.py +13 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/validators/docker_validator.py +1 -1
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/validators/validator.py +67 -9
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli.egg-info/PKG-INFO +3 -2
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli.egg-info/SOURCES.txt +3 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli.egg-info/entry_points.txt +1 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli.egg-info/requires.txt +2 -1
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/pyproject.toml +1 -0
- eva_sub_cli-0.4.12/requirements.txt +9 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/build_and_test_docker_locally.py +13 -8
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/validation_reports/expected_report_metadata_json.html +19 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/validation_reports/expected_report_metadata_json.txt +6 -0
- eva_sub_cli-0.4.10/tests/resources/validation_reports/expected_shallow_metadata_xlsx_report.html → eva_sub_cli-0.4.12/tests/resources/validation_reports/expected_report_metadata_xlsx.html +19 -24
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/validation_reports/expected_report_metadata_xlsx.txt +6 -0
- eva_sub_cli-0.4.10/tests/resources/validation_reports/expected_report_metadata_xlsx.html → eva_sub_cli-0.4.12/tests/resources/validation_reports/expected_shallow_metadata_xlsx_report.html +43 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/validation_reports/expected_shallow_metadata_xlsx_report.txt +6 -0
- eva_sub_cli-0.4.12/tests/resources/validation_reports/validation_output/other_validations/evidence_type_checker.yml +3 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_docker_validator.py +1 -1
- eva_sub_cli-0.4.12/tests/test_evidence_type_checker.py +70 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_report.py +28 -2
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_semantic_metadata.py +52 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_submit.py +2 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_validator.py +29 -11
- eva_sub_cli-0.4.10/eva_sub_cli/file_utils.py +0 -122
- eva_sub_cli-0.4.10/eva_sub_cli/jinja_templates/html/project_details.html +0 -37
- eva_sub_cli-0.4.10/eva_sub_cli/jinja_templates/text/project_details.txt +0 -21
- eva_sub_cli-0.4.10/requirements.txt +0 -8
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/.github/workflows/publish.yml +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/.github/workflows/publish_docs.yml +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/.github/workflows/publish_packages.yml +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/.github/workflows/tests.yml +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/.gitignore +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/LICENSE +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/README.md +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/conda/build.sh +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/conda/meta.yaml +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/docs/README.md +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/docs/_config.yml +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/docs/how_to_submit.md +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/docs/input_file_overview.md +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/docs/installation.md +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/docs/using_nextflow.md +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/docs/validation_overview.md +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/__init__.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/auth.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/date_utils.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/etc/EVA_Submission_Example.xlsx +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/etc/EVA_Submission_template.xlsx +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/etc/eva-biosamples.json +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/etc/eva_logo.png +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/etc/spreadsheet2json_conf.yaml +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/exceptions/__init__.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/exceptions/invalid_file_type_exception.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/exceptions/metadata_template_version_exception.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/exceptions/submission_not_found_exception.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/exceptions/submission_status_exception.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/executables/__init__.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/executables/check_fasta_insdc.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/executables/check_metadata_semantics.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/executables/cli.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/executables/trim_down.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/executables/xlsx2json.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/jinja_templates/html/fasta_check.html +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/jinja_templates/html/file_validation.html +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/jinja_templates/html/metadata_validation.html +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/jinja_templates/html/sample_name_check.html +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/jinja_templates/html/shallow_validation.html +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/jinja_templates/text/fasta_check.txt +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/jinja_templates/text/file_validation.txt +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/jinja_templates/text/metadata_validation.txt +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/jinja_templates/text/sample_name_check.txt +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/jinja_templates/text/shallow_validation.txt +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/orchestrator.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/submission_ws.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/submit.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/validators/__init__.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/validators/native_validator.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli/validators/validation_results_parsers.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli.egg-info/dependency_links.txt +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/eva_sub_cli.egg-info/top_level.txt +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/pytest.ini +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/setup.cfg +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/setup.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/ignore_test_nextflow_validation.yml +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/EVA_Submission_Docker_Test.xlsx +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/EVA_Submission_test.json +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/EVA_Submission_test.xlsx +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/EVA_Submission_test_fails.xlsx +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/EVA_Submission_test_version_missing.xlsx +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/EVA_Submission_test_with_asm_report.json +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/assembly_check/invalid.vcf.assembly_check.log +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/assembly_check/invalid.vcf.text_assembly_report.txt +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/assembly_reports/input_passed.txt +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/fasta_files/Saccharomyces_cerevisiae_I.fa +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/fasta_files/input_passed.fa +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/fasta_files/multi_seq.fa +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/metadata_with_filename.json +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/sample_checker/example1.vcf.gz +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/sample_checker/example2.vcf +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/sample_checker/example3.vcf +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/sample_checker/metadata.json +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.assembly_check.log +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.text_assembly_report.1680102476700.txt +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.valid_assembly_report.1680102476700.txt +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/validation_reports/validation_output/other_validations/input_passed.fa_check.yml +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/validation_reports/validation_output/other_validations/metadata_conversion_errors.yml +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/validation_reports/validation_output/other_validations/metadata_semantic_check.yml +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/validation_reports/validation_output/other_validations/metadata_validation.txt +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/validation_reports/validation_output/other_validations/sample_checker.yml +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.errors.1680102476854.db +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.errors.1680102476854.txt +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.vcf_format.log +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/vcf_files/example2.vcf.gz +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/resources/vcf_files/input_passed.vcf +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_auth.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_check_fasta_insdc.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_cli.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_file_utils.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_metadata.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_orchestrator.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_samples_checker.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_trim_down.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_utils.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_validaton_results_parsers.py +0 -0
- {eva_sub_cli-0.4.10 → eva_sub_cli-0.4.12}/tests/test_xlsx2json.py +0 -0
|
@@ -2,7 +2,7 @@ name: Trigger Eva Sub Cli Integration Tests
|
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
|
-
branches: [main
|
|
5
|
+
branches: [main]
|
|
6
6
|
|
|
7
7
|
jobs:
|
|
8
8
|
trigger-integration-tests:
|
|
@@ -11,6 +11,6 @@ jobs:
|
|
|
11
11
|
- name: Trigger eva sub cli integration tests
|
|
12
12
|
uses: peter-evans/repository-dispatch@v2
|
|
13
13
|
with:
|
|
14
|
-
token: ${{ secrets.
|
|
14
|
+
token: ${{ secrets.WORKFLOW_ACCESS_TOKEN }}
|
|
15
15
|
repository: EBIvariation/eva-integration-tests
|
|
16
16
|
event-type: trigger-eva-sub-cli-tests
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: eva_sub_cli
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.12
|
|
4
4
|
Summary: EBI EVA - validation and submission command line tool
|
|
5
5
|
Classifier: Development Status :: 5 - Production/Stable
|
|
6
6
|
Classifier: Environment :: Console
|
|
@@ -19,11 +19,12 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
19
19
|
Requires-Python: >=3.6
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE
|
|
22
|
-
Requires-Dist: ebi_eva_common_pyutils==0.*,>=0.7.
|
|
22
|
+
Requires-Dist: ebi_eva_common_pyutils==0.*,>=0.7.4
|
|
23
23
|
Requires-Dist: jinja2==3.*,>=3.0.0
|
|
24
24
|
Requires-Dist: jsonschema==4.*
|
|
25
25
|
Requires-Dist: openpyxl==3.*
|
|
26
26
|
Requires-Dist: pyyaml==6.*
|
|
27
|
+
Requires-Dist: pysam==0.*,>=0.23.3
|
|
27
28
|
Requires-Dist: requests==2.*
|
|
28
29
|
Requires-Dist: packaging==24.*
|
|
29
30
|
Requires-Dist: setuptools-scm
|
|
@@ -168,6 +168,14 @@
|
|
|
168
168
|
"type": "string",
|
|
169
169
|
"description": "Reference against which the analysis was performed. ENA or NCBI accession (starting with GCA) accepted."
|
|
170
170
|
},
|
|
171
|
+
"evidenceType": {
|
|
172
|
+
"type": "string",
|
|
173
|
+
"description": "The type of evidence (allele frequencies or genotypes) provided in the VCF files of the analysis",
|
|
174
|
+
"enum": [
|
|
175
|
+
"genotype",
|
|
176
|
+
"allele_frequency"
|
|
177
|
+
]
|
|
178
|
+
},
|
|
171
179
|
"referenceFasta": {
|
|
172
180
|
"type": "string",
|
|
173
181
|
"description": "The path to the reference in fasta format that was used to create the VCF. (This is a local path)"
|
|
@@ -322,7 +330,7 @@
|
|
|
322
330
|
"$ref": "eva-biosamples.json"
|
|
323
331
|
},
|
|
324
332
|
{
|
|
325
|
-
"$ref": "https://www.ebi.ac.uk/biosamples/schema
|
|
333
|
+
"$ref": "https://www.ebi.ac.uk/biosamples/schema-store/registry/schemas/ERC000011"
|
|
326
334
|
},
|
|
327
335
|
{
|
|
328
336
|
"$ref": "https://www.ebi.ac.uk/biosamples/schemas/certification/plant-miappe.json"
|
|
@@ -366,7 +374,7 @@
|
|
|
366
374
|
"projectAccession": {
|
|
367
375
|
"type": "string",
|
|
368
376
|
"description": "ENA project accession",
|
|
369
|
-
"pattern": "^PRJ(
|
|
377
|
+
"pattern": "^PRJ(E|D|N)[A-Z][0-9]+$"
|
|
370
378
|
}
|
|
371
379
|
}
|
|
372
380
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
3
|
+
import yaml
|
|
4
|
+
from ebi_eva_common_pyutils.logger import logging_config
|
|
5
|
+
|
|
6
|
+
from eva_sub_cli.file_utils import detect_vcf_evidence_type, associate_vcf_path_with_analysis
|
|
7
|
+
from eva_sub_cli.metadata import EvaMetadataJson
|
|
8
|
+
|
|
9
|
+
logger = logging_config.get_logger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def check_evidence_type(metadata_json, vcf_files, output_yaml):
|
|
13
|
+
metadata = EvaMetadataJson(metadata_json)
|
|
14
|
+
file_path_per_analysis = associate_vcf_path_with_analysis(metadata, vcf_files)
|
|
15
|
+
|
|
16
|
+
results_per_analysis_alias = {}
|
|
17
|
+
|
|
18
|
+
all_analysis_alias = set(metadata.files_per_analysis) | set(file_path_per_analysis)
|
|
19
|
+
for analysis_alias in all_analysis_alias:
|
|
20
|
+
results_per_analysis_alias[analysis_alias] = {
|
|
21
|
+
'evidence_type': None,
|
|
22
|
+
'errors': None
|
|
23
|
+
}
|
|
24
|
+
vcf_files = list(file_path_per_analysis.get(analysis_alias, []))
|
|
25
|
+
|
|
26
|
+
if not vcf_files:
|
|
27
|
+
results_per_analysis_alias[analysis_alias]['errors'] = f'No VCF file found for the analysis'
|
|
28
|
+
continue
|
|
29
|
+
|
|
30
|
+
evidence_types_for_vcf_files = [detect_vcf_evidence_type(vcf_file) for vcf_file in vcf_files]
|
|
31
|
+
|
|
32
|
+
if len(set(evidence_types_for_vcf_files)) == 1 and None not in evidence_types_for_vcf_files:
|
|
33
|
+
results_per_analysis_alias[analysis_alias]['evidence_type'] = set(evidence_types_for_vcf_files).pop()
|
|
34
|
+
elif None in evidence_types_for_vcf_files:
|
|
35
|
+
indices = [i for i, x in enumerate(evidence_types_for_vcf_files) if x is None]
|
|
36
|
+
results_per_analysis_alias[analysis_alias][
|
|
37
|
+
'errors'] = f'VCF file evidence type could not be determined: {", ".join([vcf_files[i] for i in indices])}'
|
|
38
|
+
else:
|
|
39
|
+
results_per_analysis_alias[analysis_alias][
|
|
40
|
+
'errors'] = f'Multiple evidence types found: {", ".join(set(evidence_types_for_vcf_files))}'
|
|
41
|
+
|
|
42
|
+
write_result_yaml(output_yaml, results_per_analysis_alias)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def write_result_yaml(output_yaml, results_per_analysis_alias):
|
|
46
|
+
with open(output_yaml, 'w') as open_yaml:
|
|
47
|
+
yaml.safe_dump(data=results_per_analysis_alias, stream=open_yaml, default_flow_style=False)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def main():
|
|
51
|
+
arg_parser = argparse.ArgumentParser(description='Check the evidence type in the VCF files for all analysis')
|
|
52
|
+
arg_parser.add_argument('--metadata_json', required=True, dest='metadata_json',
|
|
53
|
+
help='EVA metadata json file')
|
|
54
|
+
arg_parser.add_argument('--vcf_files', dest='vcf_files', nargs='+',
|
|
55
|
+
help='Path to the vcf files to compare to the metadata')
|
|
56
|
+
arg_parser.add_argument('--output_yaml', required=True, dest='output_yaml',
|
|
57
|
+
help='Path to the location of the results')
|
|
58
|
+
|
|
59
|
+
args = arg_parser.parse_args()
|
|
60
|
+
logging_config.add_stdout_handler()
|
|
61
|
+
check_evidence_type(args.metadata_json, args.vcf_files, args.output_yaml)
|
|
@@ -5,7 +5,7 @@ from ebi_eva_common_pyutils.logger import logging_config
|
|
|
5
5
|
|
|
6
6
|
import yaml
|
|
7
7
|
|
|
8
|
-
from eva_sub_cli.file_utils import open_gzip_if_required
|
|
8
|
+
from eva_sub_cli.file_utils import open_gzip_if_required, detect_vcf_evidence_type, associate_vcf_path_with_analysis
|
|
9
9
|
from eva_sub_cli.metadata import EvaMetadataJson
|
|
10
10
|
|
|
11
11
|
logger = logging_config.get_logger(__name__)
|
|
@@ -64,44 +64,39 @@ def compare_all_analysis(metadata, files_per_analysis):
|
|
|
64
64
|
file_path: get_samples_from_vcf(file_path)
|
|
65
65
|
for file_path in files_per_analysis.get(analysis_alias, [])
|
|
66
66
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
67
|
+
|
|
68
|
+
if need_to_check_samples(sample_name_per_file):
|
|
69
|
+
(
|
|
70
|
+
has_difference, more_per_submitted_files_metadata,
|
|
71
|
+
more_submitted_files_metadata, more_metadata_submitted_files
|
|
72
|
+
) = compare_names_in_files_and_samples(sample_name_in_analysis, sample_name_per_file)
|
|
73
|
+
overall_differences = overall_differences or has_difference
|
|
74
|
+
results_per_analysis_alias[analysis_alias] = {
|
|
75
|
+
'difference': has_difference,
|
|
76
|
+
'more_per_submitted_files_metadata': more_per_submitted_files_metadata,
|
|
77
|
+
'more_submitted_files_metadata': more_submitted_files_metadata,
|
|
78
|
+
'more_metadata_submitted_files': more_metadata_submitted_files
|
|
79
|
+
}
|
|
80
|
+
else:
|
|
81
|
+
results_per_analysis_alias[analysis_alias] = {
|
|
82
|
+
'difference': False,
|
|
83
|
+
'more_per_submitted_files_metadata': [],
|
|
84
|
+
'more_submitted_files_metadata': [],
|
|
85
|
+
'more_metadata_submitted_files': []
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
78
89
|
return overall_differences, results_per_analysis_alias
|
|
79
90
|
|
|
80
91
|
|
|
81
|
-
def
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
:returns dictionary of analysis and their associated vcf file path
|
|
88
|
-
"""
|
|
89
|
-
result_files_per_analysis = dict()
|
|
90
|
-
for analysis in metadata.files_per_analysis:
|
|
91
|
-
result_files_per_analysis[analysis] = []
|
|
92
|
-
for vcf_file in vcf_files:
|
|
93
|
-
analysis_aliases = metadata.get_analysis_for_vcf_file(vcf_file)
|
|
94
|
-
if len(analysis_aliases) == 1:
|
|
95
|
-
result_files_per_analysis[analysis_aliases[0]].append(vcf_file)
|
|
96
|
-
elif len(analysis_aliases) == 0:
|
|
97
|
-
logger.error(f'No analysis found for vcf {vcf_file}')
|
|
98
|
-
if 'No analysis' not in result_files_per_analysis:
|
|
99
|
-
result_files_per_analysis['No analysis'] = []
|
|
100
|
-
result_files_per_analysis['No analysis'].append(vcf_file)
|
|
101
|
-
else:
|
|
102
|
-
logger.error(f'More than one analysis were match to vcf {vcf_file}')
|
|
92
|
+
def need_to_check_samples(sample_name_per_file):
|
|
93
|
+
no_samples_in_vcf = all(len(v) == 0 for v in sample_name_per_file.values())
|
|
94
|
+
if no_samples_in_vcf:
|
|
95
|
+
evidence_types_for_vcf_files = [detect_vcf_evidence_type(vcf_file) for vcf_file in sample_name_per_file.keys()]
|
|
96
|
+
if set(evidence_types_for_vcf_files) == {'allele_frequency'}:
|
|
97
|
+
return False
|
|
103
98
|
|
|
104
|
-
return
|
|
99
|
+
return True
|
|
105
100
|
|
|
106
101
|
|
|
107
102
|
def write_result_yaml(output_yaml, overall_differences, results_per_analysis_alias):
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import glob
|
|
2
|
+
import gzip
|
|
3
|
+
import os
|
|
4
|
+
import shutil
|
|
5
|
+
import time
|
|
6
|
+
from itertools import groupby
|
|
7
|
+
|
|
8
|
+
import pysam
|
|
9
|
+
from ebi_eva_common_pyutils.logger import logging_config
|
|
10
|
+
|
|
11
|
+
logger = logging_config.get_logger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def resolve_single_file_path(file_path):
|
|
15
|
+
files = glob.glob(file_path)
|
|
16
|
+
if len(files) == 0:
|
|
17
|
+
return None
|
|
18
|
+
elif len(files) > 0:
|
|
19
|
+
return files[0]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def is_submission_dir_writable(submission_dir):
|
|
23
|
+
if not os.path.exists(submission_dir):
|
|
24
|
+
os.makedirs(submission_dir)
|
|
25
|
+
if not os.path.isdir(submission_dir):
|
|
26
|
+
return False
|
|
27
|
+
if not os.access(submission_dir, os.W_OK):
|
|
28
|
+
return False
|
|
29
|
+
return True
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def is_vcf_file(file_path):
|
|
33
|
+
if file_path:
|
|
34
|
+
file_path = file_path.strip().lower()
|
|
35
|
+
return file_path.endswith('.vcf') or file_path.endswith('.vcf.gz')
|
|
36
|
+
return False
|
|
37
|
+
|
|
38
|
+
def associate_vcf_path_with_analysis(metadata, vcf_files):
|
|
39
|
+
"""
|
|
40
|
+
Match the files names associated with analysis provided in the metadata with the given file path
|
|
41
|
+
|
|
42
|
+
:param vcf_files the list of full path to the vcf files
|
|
43
|
+
:param files_per_analysis: dictionary of the analysis and their associated VCF file names
|
|
44
|
+
:returns dictionary of analysis and their associated vcf file path
|
|
45
|
+
"""
|
|
46
|
+
result_files_per_analysis = dict()
|
|
47
|
+
for analysis in metadata.files_per_analysis:
|
|
48
|
+
result_files_per_analysis[analysis] = []
|
|
49
|
+
for vcf_file in vcf_files:
|
|
50
|
+
analysis_aliases = metadata.get_analysis_for_vcf_file(vcf_file)
|
|
51
|
+
if len(analysis_aliases) == 1:
|
|
52
|
+
result_files_per_analysis[analysis_aliases[0]].append(vcf_file)
|
|
53
|
+
elif len(analysis_aliases) == 0:
|
|
54
|
+
logger.error(f'No analysis found for vcf {vcf_file}')
|
|
55
|
+
if 'No analysis' not in result_files_per_analysis:
|
|
56
|
+
result_files_per_analysis['No analysis'] = []
|
|
57
|
+
result_files_per_analysis['No analysis'].append(vcf_file)
|
|
58
|
+
else:
|
|
59
|
+
logger.error(f'More than one analysis were match to vcf {vcf_file}')
|
|
60
|
+
|
|
61
|
+
return result_files_per_analysis
|
|
62
|
+
|
|
63
|
+
def detect_vcf_evidence_type(vcf_file):
|
|
64
|
+
"""
|
|
65
|
+
Detect the type of evidence (genotype aggregation) provided in the VCF file by checking the first 10 data lines
|
|
66
|
+
The evidence type is determined to be "genotype" (meaning genotype are all present) if a GT field can be found in
|
|
67
|
+
all the samples. It is determined to be "allele_frequency" if it is not "genotype" and an AF field or AN and AC fields are found
|
|
68
|
+
in every line checked.
|
|
69
|
+
Otherwise, it returns None meaning that the evidence type could not be determined.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
samples, af_in_info, gt_in_format = _assess_vcf_evidence_type_with_pysam(vcf_file)
|
|
74
|
+
except Exception:
|
|
75
|
+
logger.error(f"Pysam Failed to open and read {vcf_file}")
|
|
76
|
+
try:
|
|
77
|
+
samples, af_in_info, gt_in_format = _assess_vcf_evidence_type_manual(vcf_file)
|
|
78
|
+
except Exception:
|
|
79
|
+
logger.error(f"Manual parsing Failed to open or read {vcf_file}")
|
|
80
|
+
return None
|
|
81
|
+
if len(samples) > 0 and gt_in_format:
|
|
82
|
+
return 'genotype'
|
|
83
|
+
elif len(samples) == 0 and af_in_info:
|
|
84
|
+
return 'allele_frequency'
|
|
85
|
+
else:
|
|
86
|
+
logger.error(f'Aggregation type could not be detected for {vcf_file}')
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _assess_vcf_evidence_type_with_pysam(vcf_file):
|
|
91
|
+
with pysam.VariantFile(vcf_file, 'r') as vcf_in:
|
|
92
|
+
samples = list(vcf_in.header.samples)
|
|
93
|
+
# check that the first 10 lines have genotypes for all the samples present and if they have allele frequency
|
|
94
|
+
nb_line_checked = 0
|
|
95
|
+
max_line_check = 10
|
|
96
|
+
gt_in_format = True
|
|
97
|
+
af_in_info = True
|
|
98
|
+
for vcf_rec in vcf_in:
|
|
99
|
+
gt_in_format = gt_in_format and all('GT' in vcf_rec.samples.get(sample, {}) for sample in samples)
|
|
100
|
+
af_in_info = af_in_info and ('AF' in vcf_rec.info or ('AC' in vcf_rec.info and 'AN' in vcf_rec.info))
|
|
101
|
+
nb_line_checked += 1
|
|
102
|
+
if nb_line_checked >= max_line_check:
|
|
103
|
+
break
|
|
104
|
+
return samples, af_in_info, gt_in_format
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _assess_vcf_evidence_type_manual(vcf_file):
|
|
108
|
+
try:
|
|
109
|
+
if vcf_file.endswith('.gz'):
|
|
110
|
+
open_file = gzip.open(vcf_file, 'rt')
|
|
111
|
+
else:
|
|
112
|
+
open_file = open(vcf_file, 'r')
|
|
113
|
+
|
|
114
|
+
nb_line_checked = 0
|
|
115
|
+
max_line_check = 10
|
|
116
|
+
gt_in_format = True
|
|
117
|
+
af_in_info = True
|
|
118
|
+
samples = []
|
|
119
|
+
for line in open_file:
|
|
120
|
+
sp_line = line.strip().split('\t')
|
|
121
|
+
if line.startswith('#CHROM'):
|
|
122
|
+
if len(sp_line) > 9:
|
|
123
|
+
samples = sp_line[9:]
|
|
124
|
+
if not line.startswith('#'):
|
|
125
|
+
gt_in_format = gt_in_format and len(sp_line) > 8 and 'GT' in sp_line[8]
|
|
126
|
+
af_in_info = af_in_info and (
|
|
127
|
+
sp_line[7].find('AF=') or (sp_line[7].find('AC=') and sp_line[7].find('AN=')))
|
|
128
|
+
if nb_line_checked >= max_line_check:
|
|
129
|
+
break
|
|
130
|
+
return samples, af_in_info, gt_in_format
|
|
131
|
+
finally:
|
|
132
|
+
open_file.close()
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def backup_file_or_directory(file_name, max_backups=None):
|
|
136
|
+
"""
|
|
137
|
+
Rename a file or directory by adding a '.1' at the end. If the '.1' file exists it move it to a '.2' and so on.
|
|
138
|
+
Keep at most the specified number of backups, if None will keep all.
|
|
139
|
+
"""
|
|
140
|
+
suffix = 1
|
|
141
|
+
backup_name = f'{file_name}.{suffix}'
|
|
142
|
+
while os.path.exists(backup_name):
|
|
143
|
+
suffix += 1
|
|
144
|
+
backup_name = f'{file_name}.{suffix}'
|
|
145
|
+
|
|
146
|
+
for i in range(suffix, 1, -1):
|
|
147
|
+
if max_backups and i > max_backups:
|
|
148
|
+
if os.path.isfile(file_name):
|
|
149
|
+
os.remove(f'{file_name}.{i - 1}')
|
|
150
|
+
else:
|
|
151
|
+
shutil.rmtree(f'{file_name}.{i - 1}')
|
|
152
|
+
else:
|
|
153
|
+
os.rename(f'{file_name}.{i - 1}', f'{file_name}.{i}')
|
|
154
|
+
os.rename(file_name, file_name + '.1')
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def open_gzip_if_required(input_file, mode='r'):
|
|
158
|
+
"""Open a file in read mode using gzip if the file extension says .gz"""
|
|
159
|
+
if input_file.endswith('.gz'):
|
|
160
|
+
return gzip.open(input_file, mode + 't')
|
|
161
|
+
else:
|
|
162
|
+
return open(input_file, mode)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def fasta_iter(input_fasta):
|
|
166
|
+
"""
|
|
167
|
+
Given a fasta file. yield tuples of header, sequence
|
|
168
|
+
"""
|
|
169
|
+
# first open the file outside
|
|
170
|
+
with open_gzip_if_required(input_fasta) as open_file:
|
|
171
|
+
# ditch the boolean (x[0]) and just keep the header or sequence since
|
|
172
|
+
# we know they alternate.
|
|
173
|
+
faiter = (x[1] for x in groupby(open_file, lambda line: line[0] == ">"))
|
|
174
|
+
|
|
175
|
+
for header in faiter:
|
|
176
|
+
# drop the ">"
|
|
177
|
+
headerStr = header.__next__()[1:].strip()
|
|
178
|
+
|
|
179
|
+
# join all sequence lines to one.
|
|
180
|
+
seq = "".join(s.strip() for s in faiter.__next__())
|
|
181
|
+
yield (headerStr, seq)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class DirLockError(Exception):
|
|
185
|
+
pass
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class DirLock(object):
|
|
189
|
+
_SPIN_PERIOD_SECONDS = 0.05
|
|
190
|
+
|
|
191
|
+
def __init__(self, dirname, timeout=3):
|
|
192
|
+
"""Prepare a file lock to protect access to dirname. timeout is the
|
|
193
|
+
period (in seconds) after an acquisition attempt is aborted.
|
|
194
|
+
The directory must exist, otherwise aquire() will timeout.
|
|
195
|
+
"""
|
|
196
|
+
self._lockfilename = os.path.join(dirname, ".lock")
|
|
197
|
+
self._timeout = timeout
|
|
198
|
+
|
|
199
|
+
def acquire(self):
|
|
200
|
+
start_time = time.time()
|
|
201
|
+
while True:
|
|
202
|
+
try:
|
|
203
|
+
# O_EXCL: fail if file exists or create it (atomically)
|
|
204
|
+
os.close(os.open(self._lockfilename,
|
|
205
|
+
os.O_CREAT | os.O_EXCL | os.O_RDWR))
|
|
206
|
+
break
|
|
207
|
+
except OSError:
|
|
208
|
+
if (time.time() - start_time) > self._timeout:
|
|
209
|
+
raise DirLockError(f"could not create {self._lockfilename} after {self._timeout} seconds")
|
|
210
|
+
else:
|
|
211
|
+
time.sleep(self._SPIN_PERIOD_SECONDS)
|
|
212
|
+
|
|
213
|
+
def release(self):
|
|
214
|
+
try:
|
|
215
|
+
os.remove(self._lockfilename)
|
|
216
|
+
except OSError:
|
|
217
|
+
pass
|
|
218
|
+
|
|
219
|
+
def __enter__(self):
|
|
220
|
+
self.acquire()
|
|
221
|
+
return self
|
|
222
|
+
|
|
223
|
+
def __exit__(self, type_, value, traceback):
|
|
224
|
+
self.release()
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{% macro project_details_report(validation_results, project_title, validation_date, submission_dir, consent_statement_required, vcf_fasta_analysis_mapping) -%}
|
|
2
|
+
<div class="report-section info">
|
|
3
|
+
{% if project_title %}
|
|
4
|
+
<p><b>Project Title:</b> {{ project_title }}</p>
|
|
5
|
+
{% else %}
|
|
6
|
+
<p><b>Project Title:</b> Not Found</p>
|
|
7
|
+
{% endif %}
|
|
8
|
+
<p><b>Validation Date:</b> {{ validation_date }}</p>
|
|
9
|
+
<p><b>Submission Directory:</b> {{ submission_dir }}</p>
|
|
10
|
+
{% if consent_statement_required %}
|
|
11
|
+
<br>
|
|
12
|
+
<p><b>Note for human genotype data:</b></p> <p>You will need to provide a signed copy of our <a href="https://docs.google.com/document/d/1UaRmimAe919IZYIH55mDXMe-4sHsRVqaP4moqx2IYE4" target="_blank">Consent Statement</a> via email to <a href="mailto:eva-helpdesk@ebi.ac.uk">eva-helpdesk@ebi.ac.uk</a> after submission.
|
|
13
|
+
Your submission will only be processed after receiving the consent statement. For more info, please see our <a href="https://www.ebi.ac.uk/eva/?Help#submissionPanel&link=consent-statement-for-human-genotype-data" target="_blank">help</a> section.</p>
|
|
14
|
+
{% endif %}
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
{% if vcf_fasta_analysis_mapping %}
|
|
19
|
+
{% set row_class = "report-section info collapsible" %}
|
|
20
|
+
{% set expand_icon = "▶" %}
|
|
21
|
+
<div class='{{ row_class }}'><span class="expand_icon">{{ expand_icon }}</span> Files mapping</div>
|
|
22
|
+
<div class="no-show">
|
|
23
|
+
<table>
|
|
24
|
+
<tr>
|
|
25
|
+
<th><strong>VCF File</strong></th>
|
|
26
|
+
<th><strong>Fasta File</strong></th>
|
|
27
|
+
<th><strong>Analysis</strong></th>
|
|
28
|
+
</tr>
|
|
29
|
+
{% for mapping in vcf_fasta_analysis_mapping %}
|
|
30
|
+
<tr>
|
|
31
|
+
<td>{{ mapping.vcf_file }}</td>
|
|
32
|
+
<td>{{ mapping.fasta_file }}</td>
|
|
33
|
+
<td>{{ mapping.analysis }}</td>
|
|
34
|
+
</tr>
|
|
35
|
+
{% endfor %}
|
|
36
|
+
</table>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
{% endif %}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
{% set evidence_type_check_results = validation_results.get('evidence_type_check', {}) %}
|
|
43
|
+
{% set evidence_check_type_pass = evidence_type_check_results.get('pass', true) %}
|
|
44
|
+
{% if not evidence_check_type_pass %}
|
|
45
|
+
<div class="report-section fail collapsible"><span class="expand_icon">▶</span>❌ Evidence Type Check Failures </div>
|
|
46
|
+
<div class="error-list">
|
|
47
|
+
<table>
|
|
48
|
+
<tr>
|
|
49
|
+
<th>Analysis Alias</th><th>Errors</th>
|
|
50
|
+
</tr>
|
|
51
|
+
{% for alias, alias_result in evidence_type_check_results.items() if alias != 'pass' %}
|
|
52
|
+
{% if alias_result.evidence_type is none and alias_result.errors %}
|
|
53
|
+
<tr>
|
|
54
|
+
<td><strong>{{ alias }} </strong></td>
|
|
55
|
+
<td>{{ alias_result.errors }}</td>
|
|
56
|
+
</tr>
|
|
57
|
+
{% endif %}
|
|
58
|
+
{% endfor %}
|
|
59
|
+
</table>
|
|
60
|
+
</div>
|
|
61
|
+
{% endif %}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
{%- endmacro %}
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
<div class="description">
|
|
55
55
|
General details about the project
|
|
56
56
|
</div>
|
|
57
|
-
{{ project_details_report(project_title, validation_date, submission_dir, vcf_fasta_analysis_mapping) }}
|
|
57
|
+
{{ project_details_report(validation_results, project_title, validation_date, submission_dir, consent_statement_required, vcf_fasta_analysis_mapping) }}
|
|
58
58
|
</section>
|
|
59
59
|
|
|
60
60
|
<section>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{% macro project_details_report(validation_results, project_title, validation_date, submission_dir, consent_statement_required, vcf_fasta_analysis_mapping) -%}
|
|
2
|
+
|
|
3
|
+
{% if project_title %}
|
|
4
|
+
Project Title: {{ project_title }}
|
|
5
|
+
{% else %}
|
|
6
|
+
Project Title: Not Found
|
|
7
|
+
{% endif %}
|
|
8
|
+
Validation Date: {{ validation_date }}
|
|
9
|
+
Submission Directory: {{ submission_dir }}
|
|
10
|
+
{% if consent_statement_required %}
|
|
11
|
+
Note for human genotype data:
|
|
12
|
+
You will need to provide a signed copy of our Consent Statement (https://docs.google.com/document/d/1UaRmimAe919IZYIH55mDXMe-4sHsRVqaP4moqx2IYE4) via email to eva-helpdesk@ebi.ac.uk after submission.
|
|
13
|
+
Your submission will only be processed after receiving the consent statement.For more info, please see our help section (https://www.ebi.ac.uk/eva/?Help#submissionPanel&link=consent-statement-for-human-genotype-data).
|
|
14
|
+
{% endif %}
|
|
15
|
+
|
|
16
|
+
{% if vcf_fasta_analysis_mapping %}
|
|
17
|
+
Files mapping:
|
|
18
|
+
{% for mapping in vcf_fasta_analysis_mapping %}
|
|
19
|
+
---
|
|
20
|
+
VCF File: {{ mapping.vcf_file }}
|
|
21
|
+
Fasta File: {{ mapping.fasta_file }}
|
|
22
|
+
Analysis: {{ mapping.analysis }}
|
|
23
|
+
{% endfor %}
|
|
24
|
+
{% endif %}
|
|
25
|
+
|
|
26
|
+
{% set evidence_type_check_results = validation_results.get('evidence_type_check', {}) %}
|
|
27
|
+
{% set evidence_check_type_pass = evidence_type_check_results.get('pass', true) %}
|
|
28
|
+
{% if not evidence_check_type_pass %}
|
|
29
|
+
Evidence Type Check Failures:
|
|
30
|
+
{% for alias, alias_result in evidence_type_check_results.items() if alias != 'pass' %}
|
|
31
|
+
{% if alias_result.evidence_type is none and alias_result.errors %}
|
|
32
|
+
{{ alias }}: {{ alias_result.errors }}
|
|
33
|
+
{% endif %}
|
|
34
|
+
{% endfor %}
|
|
35
|
+
{% endif %}
|
|
36
|
+
|
|
37
|
+
{%- endmacro %}
|
|
@@ -15,7 +15,7 @@ eva-sub-cli v{{cli_version}}
|
|
|
15
15
|
PROJECT SUMMARY
|
|
16
16
|
General details about the project
|
|
17
17
|
|
|
18
|
-
{{ project_details_report(project_title, validation_date, submission_dir, vcf_fasta_analysis_mapping) }}
|
|
18
|
+
{{ project_details_report(validation_results, project_title, validation_date, submission_dir, consent_statement_required, vcf_fasta_analysis_mapping) }}
|
|
19
19
|
|
|
20
20
|
-
|
|
21
21
|
|
|
@@ -49,6 +49,10 @@ class EvaMetadataJson(AppLogger):
|
|
|
49
49
|
if self.resolved_files:
|
|
50
50
|
del self.resolved_files
|
|
51
51
|
|
|
52
|
+
def set_analyses(self, analysis_list):
|
|
53
|
+
assert isinstance(analysis_list, list)
|
|
54
|
+
self.content['analysis'] = analysis_list
|
|
55
|
+
|
|
52
56
|
@cached_property
|
|
53
57
|
def samples_per_analysis(self):
|
|
54
58
|
"""Returns mapping of analysis alias to sample names, based on metadata."""
|
|
@@ -28,6 +28,7 @@ params.executable = [
|
|
|
28
28
|
// python scripts - installed as part of eva-sub-cli
|
|
29
29
|
params.python_scripts = [
|
|
30
30
|
"samples_checker": "samples_checker.py",
|
|
31
|
+
"evidence_type_checker": "evidence_type_checker.py",
|
|
31
32
|
"fasta_checker": "check_fasta_insdc.py",
|
|
32
33
|
"xlsx2json": "xlsx2json.py",
|
|
33
34
|
"semantic_checker": "check_metadata_semantics.py",
|
|
@@ -99,6 +100,7 @@ workflow {
|
|
|
99
100
|
metadata_json_validation(metadata_json)
|
|
100
101
|
metadata_semantic_check(metadata_json)
|
|
101
102
|
sample_name_concordance(metadata_json, vcf_files.collect())
|
|
103
|
+
evidence_type_check(metadata_json, vcf_files.collect())
|
|
102
104
|
insdc_checker(metadata_json, fasta_to_vcfs)
|
|
103
105
|
}
|
|
104
106
|
}
|
|
@@ -265,6 +267,26 @@ process sample_name_concordance {
|
|
|
265
267
|
}
|
|
266
268
|
|
|
267
269
|
|
|
270
|
+
process evidence_type_check {
|
|
271
|
+
publishDir output_dir,
|
|
272
|
+
overwrite: true,
|
|
273
|
+
mode: "copy"
|
|
274
|
+
|
|
275
|
+
input:
|
|
276
|
+
path(metadata_json)
|
|
277
|
+
path(vcf_files)
|
|
278
|
+
|
|
279
|
+
output:
|
|
280
|
+
path "evidence_type_checker.yml", emit: evidence_type_checker_yml
|
|
281
|
+
path "evidence_type_checker.log", emit: evidence_type_checker_log
|
|
282
|
+
|
|
283
|
+
script:
|
|
284
|
+
"""
|
|
285
|
+
$params.python_scripts.evidence_type_checker --metadata_json $metadata_json --vcf_files $vcf_files --output_yaml evidence_type_checker.yml > evidence_type_checker.log 2>&1
|
|
286
|
+
"""
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
|
|
268
290
|
process insdc_checker {
|
|
269
291
|
publishDir output_dir,
|
|
270
292
|
overwrite: true,
|