eva-sub-cli 0.6.0__tar.gz → 0.6.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.
- eva_sub_cli-0.6.2/.github/workflows/integration-tests.yml +56 -0
- {eva_sub_cli-0.6.0/eva_sub_cli.egg-info → eva_sub_cli-0.6.2}/PKG-INFO +1 -1
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/docker/Dockerfile +1 -1
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/docs/input_file_overview.md +2 -1
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/_version.py +3 -3
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/etc/eva_schema.json +1 -2
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/etc/spreadsheet2json_conf.yaml +1 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/executables/check_metadata_semantics.py +8 -3
- eva_sub_cli-0.6.2/eva_sub_cli/executables/format_metadata.py +42 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/executables/samples_checker.py +13 -12
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/executables/xlsx2json.py +5 -4
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/file_utils.py +0 -23
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/nextflow/validation.nf +52 -6
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/semantic_metadata.py +15 -1
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/validators/docker_validator.py +1 -1
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/validators/validator.py +12 -10
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2/eva_sub_cli.egg-info}/PKG-INFO +1 -1
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli.egg-info/SOURCES.txt +13 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli.egg-info/entry_points.txt +1 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/pyproject.toml +1 -0
- eva_sub_cli-0.6.2/tests/resources/EVA_Submission_test_with_links.xlsx +0 -0
- eva_sub_cli-0.6.2/tests/resources/sample_checker/evidence_type.yaml +6 -0
- eva_sub_cli-0.6.2/tests/resources/sample_in_vcf_check/allele_freq.vcf +9 -0
- eva_sub_cli-0.6.2/tests/resources/sample_in_vcf_check/fake_fasta.fa +2 -0
- eva_sub_cli-0.6.2/tests/resources/sample_in_vcf_check/genotype.vcf +7 -0
- eva_sub_cli-0.6.2/tests/resources/sample_in_vcf_check/metadata_af_no_sample_in_vcf.json +1 -0
- eva_sub_cli-0.6.2/tests/resources/sample_in_vcf_check/metadata_af_with_sample_in_vcf.json +1 -0
- eva_sub_cli-0.6.2/tests/resources/sample_in_vcf_check/metadata_genotype_no_sample_in_vcf.json +1 -0
- eva_sub_cli-0.6.2/tests/resources/sample_in_vcf_check/metadata_genotype_with_sample_in_vcf.json +1 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_file_utils.py +1 -32
- eva_sub_cli-0.6.2/tests/test_format_metadata.py +64 -0
- eva_sub_cli-0.6.2/tests/test_native_validator_sample_in_vcf.py +96 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_samples_checker.py +2 -1
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_semantic_metadata.py +43 -17
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_utils.py +3 -1
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_validator.py +33 -2
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_xlsx2json.py +29 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/.github/workflows/publish.yml +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/.github/workflows/publish_docs.yml +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/.github/workflows/tests.yml +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/.github/workflows/trigger-eva-sub-cli-integration-tests.yml +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/.gitignore +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/LICENSE +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/README.md +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/conda/build.sh +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/conda/meta.yaml +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/docs/README.md +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/docs/_config.yml +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/docs/how_to_submit.md +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/docs/installation.md +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/docs/using_nextflow.md +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/docs/validation_overview.md +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/__init__.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/auth.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/call_home.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/date_utils.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/etc/EVA_Submission_Example.xlsx +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/etc/EVA_Submission_template.xlsx +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/etc/call_home_payload_schema.json +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/etc/eva-biosamples.json +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/etc/eva_logo.png +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/etc/spreadsheet2json_conf_V2.yaml +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/exceptions/__init__.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/exceptions/invalid_file_type_exception.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/exceptions/metadata_template_version_exception.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/exceptions/submission_not_found_exception.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/exceptions/submission_status_exception.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/exceptions/submission_upload_exception.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/executables/__init__.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/executables/check_fasta_insdc.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/executables/cli.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/executables/evidence_type_checker.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/executables/trim_down.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/jinja_templates/html/fasta_check.html +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/jinja_templates/html/file_validation.html +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/jinja_templates/html/metadata_validation.html +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/jinja_templates/html/project_details.html +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/jinja_templates/html/report.html +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/jinja_templates/html/sample_name_check.html +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/jinja_templates/html/shallow_validation.html +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/jinja_templates/text/fasta_check.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/jinja_templates/text/file_validation.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/jinja_templates/text/metadata_validation.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/jinja_templates/text/project_details.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/jinja_templates/text/report.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/jinja_templates/text/sample_name_check.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/jinja_templates/text/shallow_validation.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/metadata.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/orchestrator.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/report.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/submission_ws.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/submit.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/utils.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/validators/__init__.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/validators/native_validator.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli/validators/validation_results_parsers.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli.egg-info/dependency_links.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli.egg-info/requires.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/eva_sub_cli.egg-info/top_level.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/pytest.ini +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/requirements.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/setup.cfg +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/setup.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/build_and_test_docker_locally.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/ignore_test_nextflow_validation.yml +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/EVA_Submission_Docker_Test.xlsx +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/EVA_Submission_test.json +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/EVA_Submission_test.xlsx +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/EVA_Submission_test_V2.xlsx +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/EVA_Submission_test_fails.xlsx +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/EVA_Submission_test_version_missing.xlsx +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/EVA_Submission_test_with_asm_report.json +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/EVA_Submission_test_with_non_vcf_files.json +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/EVA_Submission_test_with_non_vcf_files.xlsx +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/EVA_Submission_test_with_project_accession.json +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/EVA_Submission_test_with_project_accession.xlsx +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/assembly_check/invalid.vcf.assembly_check.log +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/assembly_check/invalid.vcf.text_assembly_report.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/assembly_reports/input_passed.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/fasta_files/Saccharomyces_cerevisiae_I.fa +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/fasta_files/input_passed.fa +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/fasta_files/multi_seq.fa +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/metadata_with_filename.json +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/sample_checker/example1.vcf.gz +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/sample_checker/example2.vcf +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/sample_checker/example3.vcf +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/sample_checker/metadata.json +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/expected_metadata_json_report.html +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/expected_metadata_json_report.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/expected_metadata_xlsx_report.html +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/expected_metadata_xlsx_report.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/expected_report_metadata_json_process_not_run.html +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/expected_report_metadata_json_process_not_run.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/expected_shallow_metadata_xlsx_report.html +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/expected_shallow_metadata_xlsx_report.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.assembly_check.log +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.text_assembly_report.1680102476700.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.valid_assembly_report.1680102476700.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/validation_output/metadata.json +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/validation_output/other_validations/evidence_type_checker.yml +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/validation_output/other_validations/file_info.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/validation_output/other_validations/input_passed.fa_check.yml +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/validation_output/other_validations/input_passed_trim_down.yml +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/validation_output/other_validations/metadata_conversion_errors.yml +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/validation_output/other_validations/metadata_semantic_check.yml +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/validation_output/other_validations/metadata_validation.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/validation_output/other_validations/sample_checker.yml +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.errors.1680102476854.db +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.errors.1680102476854.txt +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.vcf_format.log +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/vcf_files/example2.vcf.gz +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/vcf_files/example2.vcf.gz.tbi +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/resources/vcf_files/input_passed.vcf +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_auth.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_call_home.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_check_fasta_insdc.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_cli.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_docker_validator.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_evidence_type_checker.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_metadata.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_orchestrator.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_report.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_submit.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_trim_down.py +0 -0
- {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.2}/tests/test_validaton_results_parsers.py +0 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
name: Integration tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main]
|
|
8
|
+
|
|
9
|
+
env:
|
|
10
|
+
VCF_VALIDATOR_VERSION: "0.10.2"
|
|
11
|
+
NXF_VER: "23.10.0"
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
integration-tests:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python 3.11
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.11"
|
|
24
|
+
|
|
25
|
+
- name: Install Java and Node
|
|
26
|
+
run: sudo apt update && sudo apt install -y default-jdk nodejs npm git curl
|
|
27
|
+
|
|
28
|
+
- name: Install vcf-validator and vcf-assembly-checker
|
|
29
|
+
run: |
|
|
30
|
+
curl -LJo /usr/local/bin/vcf_validator \
|
|
31
|
+
https://github.com/EBIvariation/vcf-validator/releases/download/v${VCF_VALIDATOR_VERSION}/vcf_validator_linux
|
|
32
|
+
curl -LJo /usr/local/bin/vcf_assembly_checker \
|
|
33
|
+
https://github.com/EBIvariation/vcf-validator/releases/download/v${VCF_VALIDATOR_VERSION}/vcf_assembly_checker_linux
|
|
34
|
+
chmod 755 /usr/local/bin/vcf_validator /usr/local/bin/vcf_assembly_checker
|
|
35
|
+
|
|
36
|
+
- name: Install biovalidator
|
|
37
|
+
run: |
|
|
38
|
+
git clone https://github.com/elixir-europe/biovalidator.git
|
|
39
|
+
cd biovalidator
|
|
40
|
+
npm install
|
|
41
|
+
sudo npm link
|
|
42
|
+
|
|
43
|
+
- name: Install Nextflow
|
|
44
|
+
run: |
|
|
45
|
+
curl -L "https://github.com/nextflow-io/nextflow/releases/download/v${NXF_VER}/nextflow-${NXF_VER}-all" | bash
|
|
46
|
+
sudo mv nextflow /usr/local/bin/
|
|
47
|
+
|
|
48
|
+
- name: Install Python dependencies
|
|
49
|
+
run: |
|
|
50
|
+
python -m pip install --upgrade pip
|
|
51
|
+
pip install pytest
|
|
52
|
+
python -m pip install .
|
|
53
|
+
|
|
54
|
+
- name: Run integration tests
|
|
55
|
+
run: |
|
|
56
|
+
PYTHONPATH=. pytest tests -m integration
|
|
@@ -98,7 +98,8 @@ alias, which is a shortened identifier you must provide for each analysis.
|
|
|
98
98
|
|
|
99
99
|
This is where you describe the biological samples used for your analyses. Each row describes one sample and must include
|
|
100
100
|
the Analysis Alias to indicate which analysis it belongs to, and "Sample Name in VCF" which is the exact name of the
|
|
101
|
-
sample as it appears in the VCF file.
|
|
101
|
+
sample as it appears in the VCF file. If you are submitting a VCF without sample names (containing only allele frequencies),
|
|
102
|
+
then you can omit the "Sample Name in VCF" column.
|
|
102
103
|
|
|
103
104
|
We accept preregistered samples, which should be provided using BioSamples sample or sampleset accessions. Please
|
|
104
105
|
ensure these are publicly accessible, as otherwise EVA will not be able to validate them.
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.6.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 6,
|
|
31
|
+
__version__ = version = '0.6.2'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 6, 2)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g1dbfe4351'
|
|
@@ -318,7 +318,6 @@
|
|
|
318
318
|
{
|
|
319
319
|
"required": [
|
|
320
320
|
"analysisAlias",
|
|
321
|
-
"sampleInVCF",
|
|
322
321
|
"bioSampleObject"
|
|
323
322
|
]
|
|
324
323
|
}
|
|
@@ -334,7 +333,7 @@
|
|
|
334
333
|
},
|
|
335
334
|
"sampleInVCF": {
|
|
336
335
|
"type": "string",
|
|
337
|
-
"description": "Sample Name used in the VCF file"
|
|
336
|
+
"description": "Sample Name used in the VCF file. It is a required field when genotypes are provided."
|
|
338
337
|
},
|
|
339
338
|
"bioSampleAccession": {
|
|
340
339
|
"type": "string",
|
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
import json
|
|
3
3
|
|
|
4
|
+
import yaml
|
|
5
|
+
|
|
4
6
|
from eva_sub_cli.semantic_metadata import SemanticMetadataChecker
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
def main():
|
|
8
10
|
arg_parser = argparse.ArgumentParser(description='Perform semantic checks on the metadata')
|
|
9
11
|
arg_parser.add_argument('--metadata_json', required=True, dest='metadata_json', help='EVA metadata json file')
|
|
12
|
+
arg_parser.add_argument('--evidence_type_results', required=True, dest='evidence_type_results', help='Results of the evidence check')
|
|
10
13
|
arg_parser.add_argument('--output_yaml', required=True, dest='output_yaml',
|
|
11
14
|
help='Path to the location of the results')
|
|
12
15
|
args = arg_parser.parse_args()
|
|
13
16
|
|
|
14
17
|
with open(args.metadata_json) as open_json:
|
|
15
18
|
metadata = json.load(open_json)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
with open(args.evidence_type_results) as open_yaml:
|
|
20
|
+
evidence_type_results = yaml.safe_load(open_yaml)
|
|
21
|
+
checker = SemanticMetadataChecker(metadata, evidence_type_results)
|
|
22
|
+
checker.check_all()
|
|
23
|
+
checker.write_result_yaml(args.output_yaml)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import argparse
|
|
3
|
+
import json
|
|
4
|
+
import shutil
|
|
5
|
+
|
|
6
|
+
from ebi_eva_common_pyutils.logger import logging_config
|
|
7
|
+
logger = logging_config.get_logger(__name__)
|
|
8
|
+
|
|
9
|
+
def format_experiment_type(json_file_input, json_file_output):
|
|
10
|
+
try:
|
|
11
|
+
with open(json_file_input, 'r') as input:
|
|
12
|
+
json_data = json.load(input)
|
|
13
|
+
|
|
14
|
+
for analysis_item in json_data.get("analysis", []):
|
|
15
|
+
original_experiment_type = analysis_item.get("experimentType", "")
|
|
16
|
+
logger.info(f"Formatting metadata - experiment type to capitalized - {original_experiment_type}")
|
|
17
|
+
experiment_type_capital = original_experiment_type.capitalize()
|
|
18
|
+
analysis_item["experimentType"] = experiment_type_capital or ""
|
|
19
|
+
|
|
20
|
+
with open(json_file_output, 'w') as output:
|
|
21
|
+
json.dump(json_data, output, indent=4)
|
|
22
|
+
return json_file_output
|
|
23
|
+
|
|
24
|
+
except (FileNotFoundError, json.JSONDecodeError, KeyError) as e:
|
|
25
|
+
# if the try block fails, copy the input file (because nextflow is expecting the output file).
|
|
26
|
+
logger.error(f"Failed to process JSON: {e}")
|
|
27
|
+
shutil.copy(json_file_input, json_file_output)
|
|
28
|
+
return None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def main():
|
|
32
|
+
arg_parser = argparse.ArgumentParser(
|
|
33
|
+
description='Formats experiment type for the metadata.')
|
|
34
|
+
arg_parser.add_argument('--metadata_json_input', required=True, dest='metadata_json_input',
|
|
35
|
+
help='EVA metadata json file INPUT')
|
|
36
|
+
arg_parser.add_argument('--metadata_json_output', required=True, dest='metadata_json_output',
|
|
37
|
+
help='EVA metadata json file OUTPUT')
|
|
38
|
+
args = arg_parser.parse_args()
|
|
39
|
+
format_experiment_type(args.metadata_json_input, args.metadata_json_output)
|
|
40
|
+
|
|
41
|
+
if __name__ == "__main__":
|
|
42
|
+
main()
|
|
@@ -54,7 +54,7 @@ def compare_names_in_files_and_samples(sample_name_in_analysis, sample_name_per_
|
|
|
54
54
|
more_metadata_submitted_files)
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
def compare_all_analysis(metadata, files_per_analysis):
|
|
57
|
+
def compare_all_analysis(metadata, files_per_analysis, evidence_type_results):
|
|
58
58
|
overall_differences = False
|
|
59
59
|
results_per_analysis_alias = {}
|
|
60
60
|
all_analysis_alias = set(metadata.samples_per_analysis) | set(files_per_analysis)
|
|
@@ -65,7 +65,7 @@ def compare_all_analysis(metadata, files_per_analysis):
|
|
|
65
65
|
for file_path in files_per_analysis.get(analysis_alias, [])
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
if need_to_check_samples(
|
|
68
|
+
if need_to_check_samples(evidence_type_results, analysis_alias):
|
|
69
69
|
(
|
|
70
70
|
has_difference, more_per_submitted_files_metadata,
|
|
71
71
|
more_submitted_files_metadata, more_metadata_submitted_files
|
|
@@ -89,13 +89,9 @@ def compare_all_analysis(metadata, files_per_analysis):
|
|
|
89
89
|
return overall_differences, results_per_analysis_alias
|
|
90
90
|
|
|
91
91
|
|
|
92
|
-
def need_to_check_samples(
|
|
93
|
-
|
|
94
|
-
|
|
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
|
|
98
|
-
|
|
92
|
+
def need_to_check_samples(evidence_type_results, analysis_alias):
|
|
93
|
+
if evidence_type_results.get(analysis_alias, {}).get('evidence_type') == 'allele_frequency':
|
|
94
|
+
return False
|
|
99
95
|
return True
|
|
100
96
|
|
|
101
97
|
|
|
@@ -107,14 +103,16 @@ def write_result_yaml(output_yaml, overall_differences, results_per_analysis_ali
|
|
|
107
103
|
}, stream=open_yaml)
|
|
108
104
|
|
|
109
105
|
|
|
110
|
-
def check_sample_name_concordance(metadata_json, vcf_files, output_yaml):
|
|
106
|
+
def check_sample_name_concordance(metadata_json, vcf_files, output_yaml, evidence_type_result_file):
|
|
111
107
|
"""
|
|
112
108
|
Take the metadata following EVA standard and formatted in JSON then compare the sample names in it to the ones
|
|
113
109
|
found in the VCF files
|
|
114
110
|
"""
|
|
115
111
|
metadata = EvaMetadataJson(metadata_json)
|
|
112
|
+
with open(evidence_type_result_file) as open_yaml:
|
|
113
|
+
evidence_type_results = yaml.safe_load(open_yaml)
|
|
116
114
|
file_path_per_analysis = associate_vcf_path_with_analysis(metadata, vcf_files)
|
|
117
|
-
overall_differences, results_per_analysis_alias = compare_all_analysis(metadata, file_path_per_analysis)
|
|
115
|
+
overall_differences, results_per_analysis_alias = compare_all_analysis(metadata, file_path_per_analysis, evidence_type_results)
|
|
118
116
|
write_result_yaml(output_yaml, overall_differences, results_per_analysis_alias)
|
|
119
117
|
|
|
120
118
|
|
|
@@ -127,7 +125,10 @@ def main():
|
|
|
127
125
|
help='Path to the vcf files to compare to the metadata')
|
|
128
126
|
arg_parser.add_argument('--output_yaml', required=True, dest='output_yaml',
|
|
129
127
|
help='Path to the location of the results')
|
|
128
|
+
arg_parser.add_argument('--evidence_type_results', required=True, dest='evidence_type_results',
|
|
129
|
+
help='Results of the evidence check')
|
|
130
|
+
|
|
130
131
|
|
|
131
132
|
args = arg_parser.parse_args()
|
|
132
133
|
logging_config.add_stdout_handler()
|
|
133
|
-
check_sample_name_concordance(args.metadata_json, args.vcf_files, args.output_yaml)
|
|
134
|
+
check_sample_name_concordance(args.metadata_json, args.vcf_files, args.output_yaml, args.evidence_type_results)
|
|
@@ -225,8 +225,9 @@ class XlsxParser:
|
|
|
225
225
|
return str(value)
|
|
226
226
|
|
|
227
227
|
def get_sample_data_with_split_analysis_alias(self, data, analysis_alias, sample_name_in_vcf):
|
|
228
|
-
|
|
229
|
-
|
|
228
|
+
analysis_alias_val = data.get(analysis_alias)
|
|
229
|
+
analysis_alias_list = analysis_alias_val.split(',') if analysis_alias_val else []
|
|
230
|
+
sample_in_vcf_val = data.get(sample_name_in_vcf)
|
|
230
231
|
return {analysis_alias: analysis_alias_list, sample_name_in_vcf: sample_in_vcf_val}
|
|
231
232
|
|
|
232
233
|
def get_sample_json_data(self):
|
|
@@ -245,8 +246,8 @@ class XlsxParser:
|
|
|
245
246
|
sample_data.update(bioSampleAccession=json_value[bio_sample_acc])
|
|
246
247
|
sample_json[json_key].append(sample_data)
|
|
247
248
|
else:
|
|
248
|
-
json_value.pop(analysis_alias)
|
|
249
|
-
json_value.pop(sample_name_in_vcf)
|
|
249
|
+
json_value.pop(analysis_alias, None)
|
|
250
|
+
json_value.pop(sample_name_in_vcf, None)
|
|
250
251
|
|
|
251
252
|
biosample_obj = self.get_biosample_object(json_value)
|
|
252
253
|
sample_data.update(bioSampleObject=biosample_obj)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import glob
|
|
2
2
|
import gzip
|
|
3
3
|
import os
|
|
4
|
-
import shutil
|
|
5
4
|
import time
|
|
6
5
|
from itertools import groupby
|
|
7
6
|
|
|
@@ -132,28 +131,6 @@ def _assess_vcf_evidence_type_manual(vcf_file):
|
|
|
132
131
|
open_file.close()
|
|
133
132
|
|
|
134
133
|
|
|
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
134
|
def open_gzip_if_required(input_file, mode='r'):
|
|
158
135
|
"""Open a file in read mode using gzip if the file extension says .gz"""
|
|
159
136
|
if input_file.endswith('.gz'):
|
|
@@ -42,7 +42,8 @@ params.python_scripts = [
|
|
|
42
42
|
"fasta_checker": "check_fasta_insdc.py",
|
|
43
43
|
"xlsx2json": "xlsx2json.py",
|
|
44
44
|
"semantic_checker": "check_metadata_semantics.py",
|
|
45
|
-
"trim_down": "trim_down.py"
|
|
45
|
+
"trim_down": "trim_down.py",
|
|
46
|
+
"format_metadata": "format_metadata.py"
|
|
46
47
|
]
|
|
47
48
|
// prefix to prepend to all provided path
|
|
48
49
|
params.base_dir = ""
|
|
@@ -98,27 +99,41 @@ workflow {
|
|
|
98
99
|
convert_xlsx_2_json(joinBasePath(params.metadata_xlsx))
|
|
99
100
|
metadata_json = convert_xlsx_2_json.out.metadata_json
|
|
100
101
|
} else {
|
|
101
|
-
metadata_json = joinBasePath(params.metadata_json)
|
|
102
|
+
metadata_json = file(joinBasePath(params.metadata_json), checkIfExists:true)
|
|
102
103
|
}
|
|
104
|
+
|
|
105
|
+
metadata_json_format(metadata_json)
|
|
106
|
+
metadata_json = metadata_json_format.out.metadata_formatted_json
|
|
103
107
|
// File size and MD5
|
|
104
108
|
generate_file_size_and_md5_digests(vcf_files)
|
|
105
109
|
collect_file_size_and_md5(generate_file_size_and_md5_digests.out.file_size_and_digest_info.collect())
|
|
106
110
|
|
|
107
111
|
// Task-specific processing
|
|
112
|
+
evidence_type_results = null
|
|
113
|
+
|
|
108
114
|
if (params.tasks.contains(VCF_CHECK)) {
|
|
109
115
|
check_vcf_valid(vcf_and_ref_ch)
|
|
110
116
|
evidence_type_check(metadata_json, vcf_files.collect())
|
|
117
|
+
evidence_type_results = evidence_type_check.out.evidence_type_checker_yml
|
|
111
118
|
}
|
|
112
119
|
if (params.tasks.contains(ASSEMBLY_CHECK)) {
|
|
113
120
|
check_vcf_reference(vcf_and_ref_ch)
|
|
114
121
|
insdc_checker(metadata_json, fasta_to_vcfs)
|
|
115
122
|
}
|
|
116
123
|
if (params.tasks.contains(METADATA_CHECK)) {
|
|
124
|
+
if (!evidence_type_results) {
|
|
125
|
+
evidence_type_check(metadata_json, vcf_files.collect())
|
|
126
|
+
evidence_type_results = evidence_type_check.out.evidence_type_checker_yml
|
|
127
|
+
}
|
|
117
128
|
metadata_json_validation(metadata_json)
|
|
118
|
-
metadata_semantic_check(metadata_json)
|
|
129
|
+
metadata_semantic_check(metadata_json, evidence_type_results)
|
|
119
130
|
}
|
|
120
131
|
if (params.tasks.contains(SAMPLE_CHECK)) {
|
|
121
|
-
|
|
132
|
+
if (!evidence_type_results){
|
|
133
|
+
evidence_type_check(metadata_json, vcf_files.collect())
|
|
134
|
+
evidence_type_results = evidence_type_check.out.evidence_type_checker_yml
|
|
135
|
+
}
|
|
136
|
+
sample_name_concordance(metadata_json, vcf_files.collect(), evidence_type_results)
|
|
122
137
|
}
|
|
123
138
|
}
|
|
124
139
|
|
|
@@ -166,6 +181,7 @@ process check_vcf_valid {
|
|
|
166
181
|
"""
|
|
167
182
|
trap 'if [[ \$? == 1 ]]; then exit 0; fi' EXIT
|
|
168
183
|
|
|
184
|
+
rm -rf ${output_dir}/vcf_format
|
|
169
185
|
mkdir -p vcf_format
|
|
170
186
|
$params.executable.vcf_validator -i $vcf -r text -o vcf_format --require-evidence > vcf_format/${vcf}.vcf_format.log 2>&1
|
|
171
187
|
"""
|
|
@@ -195,6 +211,7 @@ process check_vcf_reference {
|
|
|
195
211
|
"""
|
|
196
212
|
trap 'if [[ \$? == 1 || \$? == 139 ]]; then exit 0; fi' EXIT
|
|
197
213
|
|
|
214
|
+
rm -rf ${output_dir}/assembly_check
|
|
198
215
|
mkdir -p assembly_check
|
|
199
216
|
$params.executable.vcf_assembly_checker -i $vcf -f $fasta $report_opt -r summary,text -o assembly_check --require-genbank > assembly_check/${vcf}.assembly_check.log 2>&1
|
|
200
217
|
"""
|
|
@@ -263,6 +280,28 @@ process convert_xlsx_2_json {
|
|
|
263
280
|
"""
|
|
264
281
|
}
|
|
265
282
|
|
|
283
|
+
process metadata_json_format {
|
|
284
|
+
|
|
285
|
+
label 'short_time', 'small_mem'
|
|
286
|
+
|
|
287
|
+
publishDir output_dir,
|
|
288
|
+
overwrite: true,
|
|
289
|
+
mode: "copy"
|
|
290
|
+
|
|
291
|
+
input:
|
|
292
|
+
path(metadata_json)
|
|
293
|
+
|
|
294
|
+
output:
|
|
295
|
+
path "metadata_formatted.log", emit: metadata_formatted
|
|
296
|
+
path "metadata_formatted_case_insensitive.json", emit: metadata_formatted_json
|
|
297
|
+
|
|
298
|
+
script:
|
|
299
|
+
def output_json = "metadata_formatted_case_insensitive.json"
|
|
300
|
+
"""
|
|
301
|
+
$params.python_scripts.format_metadata --metadata_json_input $metadata_json --metadata_json_output $output_json > metadata_formatted.log 2>&1
|
|
302
|
+
"""
|
|
303
|
+
}
|
|
304
|
+
|
|
266
305
|
process metadata_json_validation {
|
|
267
306
|
|
|
268
307
|
label 'short_time', 'small_mem'
|
|
@@ -294,6 +333,7 @@ process sample_name_concordance {
|
|
|
294
333
|
input:
|
|
295
334
|
path(metadata_json)
|
|
296
335
|
path(vcf_files)
|
|
336
|
+
path(evidence_type_results)
|
|
297
337
|
|
|
298
338
|
output:
|
|
299
339
|
path "sample_checker.yml", emit: sample_checker_yml
|
|
@@ -301,7 +341,9 @@ process sample_name_concordance {
|
|
|
301
341
|
|
|
302
342
|
script:
|
|
303
343
|
"""
|
|
304
|
-
$params.python_scripts.samples_checker --metadata_json $metadata_json
|
|
344
|
+
$params.python_scripts.samples_checker --metadata_json $metadata_json \
|
|
345
|
+
--vcf_files $vcf_files --output_yaml sample_checker.yml \
|
|
346
|
+
--evidence_type_results $evidence_type_results > sample_checker.log 2>&1
|
|
305
347
|
"""
|
|
306
348
|
}
|
|
307
349
|
|
|
@@ -362,6 +404,7 @@ process metadata_semantic_check {
|
|
|
362
404
|
|
|
363
405
|
input:
|
|
364
406
|
path(metadata_json)
|
|
407
|
+
path(evidence_type_results)
|
|
365
408
|
|
|
366
409
|
output:
|
|
367
410
|
path "metadata_semantic_check.yml", emit: metadata_semantic_check_yml
|
|
@@ -369,6 +412,9 @@ process metadata_semantic_check {
|
|
|
369
412
|
|
|
370
413
|
script:
|
|
371
414
|
"""
|
|
372
|
-
$params.python_scripts.semantic_checker
|
|
415
|
+
$params.python_scripts.semantic_checker \
|
|
416
|
+
--metadata_json $metadata_json \
|
|
417
|
+
--evidence_type_results $evidence_type_results \
|
|
418
|
+
--output_yaml metadata_semantic_check.yml > semantic_checker.log 2>&1
|
|
373
419
|
"""
|
|
374
420
|
}
|
|
@@ -20,6 +20,7 @@ PROJECT_ACCESSION_KEY = 'projectAccession'
|
|
|
20
20
|
PARENT_PROJECT_KEY = 'parentProject'
|
|
21
21
|
CHILD_PROJECTS_KEY = 'childProjects'
|
|
22
22
|
PEER_PROJECTS_KEY = 'peerProjects'
|
|
23
|
+
SAMPLE_IN_VCF_KEY = 'sampleInVCF'
|
|
23
24
|
BIOSAMPLE_OBJECT_KEY = 'bioSampleObject'
|
|
24
25
|
BIOSAMPLE_ACCESSION_KEY = 'bioSampleAccession'
|
|
25
26
|
CHARACTERISTICS_KEY = 'characteristics'
|
|
@@ -40,9 +41,10 @@ def cast_list(l, type_to_cast=str):
|
|
|
40
41
|
|
|
41
42
|
class SemanticMetadataChecker(AppLogger):
|
|
42
43
|
|
|
43
|
-
def __init__(self, metadata, sample_checklist='ERC000011'):
|
|
44
|
+
def __init__(self, metadata, evidence_type_results, sample_checklist='ERC000011'):
|
|
44
45
|
self.sample_checklist = sample_checklist
|
|
45
46
|
self.metadata = metadata
|
|
47
|
+
self.evidence_type_results = evidence_type_results
|
|
46
48
|
self.errors = []
|
|
47
49
|
# Caches whether taxonomy code is valid or not, and maps to scientific name if valid
|
|
48
50
|
self.taxonomy_valid = {}
|
|
@@ -60,6 +62,7 @@ class SemanticMetadataChecker(AppLogger):
|
|
|
60
62
|
self.check_all_analysis_run_accessions()
|
|
61
63
|
self.check_analysis_alias_coherence()
|
|
62
64
|
self.check_all_analysis_contain_samples()
|
|
65
|
+
self.check_all_samples_have_sample_in_vcf()
|
|
63
66
|
self.check_hold_date()
|
|
64
67
|
|
|
65
68
|
def check_hold_date(self):
|
|
@@ -316,3 +319,14 @@ class SemanticMetadataChecker(AppLogger):
|
|
|
316
319
|
json_path = f'/{ANALYSIS_KEY}/{idx}'
|
|
317
320
|
self.add_error(property=json_path,
|
|
318
321
|
description=f'No sample found for the analysis. Should have at the least one sample.')
|
|
322
|
+
|
|
323
|
+
def check_all_samples_have_sample_in_vcf(self):
|
|
324
|
+
for idx, sample in enumerate(self.metadata[SAMPLE_KEY]):
|
|
325
|
+
json_path = f'/{SAMPLE_KEY}/{idx}/{SAMPLE_IN_VCF_KEY}'
|
|
326
|
+
analysis_aliases = sample.get(ANALYSIS_ALIAS_KEY, [])
|
|
327
|
+
if any([self.evidence_type_results.get(analysis_alias, {}).get('evidence_type') != 'allele_frequency' for
|
|
328
|
+
analysis_alias in analysis_aliases]):
|
|
329
|
+
# SampleInVCF is required
|
|
330
|
+
if sample.get(SAMPLE_IN_VCF_KEY) is None or sample.get(SAMPLE_IN_VCF_KEY) == '':
|
|
331
|
+
self.add_error(json_path, f'{SAMPLE_IN_VCF_KEY} must be provided when Genotypes are present in the VCF file')
|
|
332
|
+
|
|
@@ -9,7 +9,7 @@ from retry import retry
|
|
|
9
9
|
from eva_sub_cli.validators.validator import Validator, ALL_VALIDATION_TASKS
|
|
10
10
|
|
|
11
11
|
default_container_image = 'ebivariation/eva-sub-cli'
|
|
12
|
-
default_container_tag = 'v0.0.
|
|
12
|
+
default_container_tag = 'v0.0.13'
|
|
13
13
|
container_validation_dir = '/opt/vcf_validation'
|
|
14
14
|
container_validation_output_dir = 'vcf_validation_output'
|
|
15
15
|
|
|
@@ -3,17 +3,18 @@ import csv
|
|
|
3
3
|
import datetime
|
|
4
4
|
import logging
|
|
5
5
|
import os
|
|
6
|
+
import shutil
|
|
6
7
|
from functools import lru_cache, cached_property
|
|
7
8
|
|
|
8
9
|
import yaml
|
|
9
10
|
from ebi_eva_common_pyutils.command_utils import run_command_with_output
|
|
10
11
|
from ebi_eva_common_pyutils.config import WritableConfig
|
|
11
|
-
from ebi_eva_common_pyutils.logger import
|
|
12
|
+
from ebi_eva_common_pyutils.logger import AppLogger
|
|
12
13
|
from packaging import version
|
|
13
14
|
|
|
14
15
|
import eva_sub_cli
|
|
15
16
|
from eva_sub_cli import ETC_DIR, SUB_CLI_CONFIG_FILE, __version__
|
|
16
|
-
from eva_sub_cli.file_utils import
|
|
17
|
+
from eva_sub_cli.file_utils import resolve_single_file_path
|
|
17
18
|
from eva_sub_cli.metadata import EvaMetadataJson
|
|
18
19
|
from eva_sub_cli.report import generate_html_report, generate_text_report
|
|
19
20
|
from eva_sub_cli.validators.validation_results_parsers import parse_assembly_check_log, parse_assembly_check_report, \
|
|
@@ -43,7 +44,6 @@ RUN_STATUS_KEY = 'run_status'
|
|
|
43
44
|
PASS = 'pass'
|
|
44
45
|
|
|
45
46
|
|
|
46
|
-
|
|
47
47
|
class Validator(AppLogger):
|
|
48
48
|
|
|
49
49
|
def __init__(self, mapping_file, submission_dir, project_title=None, metadata_json=None, metadata_xlsx=None,
|
|
@@ -54,6 +54,7 @@ class Validator(AppLogger):
|
|
|
54
54
|
self.tasks = validation_tasks
|
|
55
55
|
self.submission_dir = submission_dir
|
|
56
56
|
self.output_dir = os.path.join(submission_dir, VALIDATION_OUTPUT_DIR)
|
|
57
|
+
self.nextflow_work_dir = os.path.join(self.submission_dir, 'work') # Default location when we chdir in self.submission_dir
|
|
57
58
|
self.validation_result_file = os.path.join(submission_dir, VALIDATION_RESULTS_FILE)
|
|
58
59
|
self.mapping_file = mapping_file
|
|
59
60
|
vcf_files, fasta_files = self._find_vcf_and_fasta_files()
|
|
@@ -130,20 +131,22 @@ class Validator(AppLogger):
|
|
|
130
131
|
raise NotImplementedError
|
|
131
132
|
|
|
132
133
|
def set_up_output_dir(self):
|
|
133
|
-
if os.path.exists(self.output_dir):
|
|
134
|
-
|
|
135
|
-
os.makedirs(self.output_dir, exist_ok=True)
|
|
134
|
+
if not os.path.exists(self.output_dir):
|
|
135
|
+
os.makedirs(self.output_dir, exist_ok=True)
|
|
136
136
|
|
|
137
137
|
def clean_up_output_dir(self):
|
|
138
138
|
# Move intermediate validation outputs into a subdir except metadata.json
|
|
139
139
|
subdir = os.path.join(self.output_dir, 'other_validations')
|
|
140
|
-
os.
|
|
140
|
+
os.makedirs(subdir, exist_ok=True)
|
|
141
141
|
for file_name in os.listdir(self.output_dir):
|
|
142
|
-
if file_name
|
|
142
|
+
if file_name in ['metadata.json', 'report.txt', 'report.html']:
|
|
143
143
|
continue
|
|
144
144
|
file_path = os.path.join(self.output_dir, file_name)
|
|
145
145
|
if os.path.isfile(file_path):
|
|
146
146
|
os.rename(file_path, os.path.join(subdir, file_name))
|
|
147
|
+
# Remove the nextflow work directory if it exists
|
|
148
|
+
if os.path.exists(self.nextflow_work_dir):
|
|
149
|
+
shutil.rmtree(self.nextflow_work_dir)
|
|
147
150
|
|
|
148
151
|
@staticmethod
|
|
149
152
|
def _validation_file_path_for(file_path):
|
|
@@ -210,7 +213,6 @@ class Validator(AppLogger):
|
|
|
210
213
|
del self.results[SHALLOW_VALIDATION]['required']
|
|
211
214
|
del self.results[SHALLOW_VALIDATION]['requested']
|
|
212
215
|
|
|
213
|
-
|
|
214
216
|
def _collect_validation_workflow_results(self):
|
|
215
217
|
# Collect information from the output and summarise in the config
|
|
216
218
|
if self.shallow_validation:
|
|
@@ -550,7 +552,7 @@ class Validator(AppLogger):
|
|
|
550
552
|
file_path_2_file_size[vcf_file] = file_size
|
|
551
553
|
file_name_2_file_size[os.path.basename(vcf_file)] = file_size
|
|
552
554
|
else:
|
|
553
|
-
error_txt =
|
|
555
|
+
error_txt = f"Cannot locate file_info.txt at {os.path.join(self.output_dir, 'other_validations', 'file_info.txt')}"
|
|
554
556
|
self.error(error_txt)
|
|
555
557
|
raise FileNotFoundError(error_txt)
|
|
556
558
|
|
|
@@ -6,6 +6,7 @@ pytest.ini
|
|
|
6
6
|
requirements.txt
|
|
7
7
|
setup.cfg
|
|
8
8
|
setup.py
|
|
9
|
+
.github/workflows/integration-tests.yml
|
|
9
10
|
.github/workflows/publish.yml
|
|
10
11
|
.github/workflows/publish_docs.yml
|
|
11
12
|
.github/workflows/tests.yml
|
|
@@ -58,6 +59,7 @@ eva_sub_cli/executables/check_fasta_insdc.py
|
|
|
58
59
|
eva_sub_cli/executables/check_metadata_semantics.py
|
|
59
60
|
eva_sub_cli/executables/cli.py
|
|
60
61
|
eva_sub_cli/executables/evidence_type_checker.py
|
|
62
|
+
eva_sub_cli/executables/format_metadata.py
|
|
61
63
|
eva_sub_cli/executables/samples_checker.py
|
|
62
64
|
eva_sub_cli/executables/trim_down.py
|
|
63
65
|
eva_sub_cli/executables/xlsx2json.py
|
|
@@ -90,7 +92,9 @@ tests/test_cli.py
|
|
|
90
92
|
tests/test_docker_validator.py
|
|
91
93
|
tests/test_evidence_type_checker.py
|
|
92
94
|
tests/test_file_utils.py
|
|
95
|
+
tests/test_format_metadata.py
|
|
93
96
|
tests/test_metadata.py
|
|
97
|
+
tests/test_native_validator_sample_in_vcf.py
|
|
94
98
|
tests/test_orchestrator.py
|
|
95
99
|
tests/test_report.py
|
|
96
100
|
tests/test_samples_checker.py
|
|
@@ -108,6 +112,7 @@ tests/resources/EVA_Submission_test_V2.xlsx
|
|
|
108
112
|
tests/resources/EVA_Submission_test_fails.xlsx
|
|
109
113
|
tests/resources/EVA_Submission_test_version_missing.xlsx
|
|
110
114
|
tests/resources/EVA_Submission_test_with_asm_report.json
|
|
115
|
+
tests/resources/EVA_Submission_test_with_links.xlsx
|
|
111
116
|
tests/resources/EVA_Submission_test_with_non_vcf_files.json
|
|
112
117
|
tests/resources/EVA_Submission_test_with_non_vcf_files.xlsx
|
|
113
118
|
tests/resources/EVA_Submission_test_with_project_accession.json
|
|
@@ -119,10 +124,18 @@ tests/resources/assembly_reports/input_passed.txt
|
|
|
119
124
|
tests/resources/fasta_files/Saccharomyces_cerevisiae_I.fa
|
|
120
125
|
tests/resources/fasta_files/input_passed.fa
|
|
121
126
|
tests/resources/fasta_files/multi_seq.fa
|
|
127
|
+
tests/resources/sample_checker/evidence_type.yaml
|
|
122
128
|
tests/resources/sample_checker/example1.vcf.gz
|
|
123
129
|
tests/resources/sample_checker/example2.vcf
|
|
124
130
|
tests/resources/sample_checker/example3.vcf
|
|
125
131
|
tests/resources/sample_checker/metadata.json
|
|
132
|
+
tests/resources/sample_in_vcf_check/allele_freq.vcf
|
|
133
|
+
tests/resources/sample_in_vcf_check/fake_fasta.fa
|
|
134
|
+
tests/resources/sample_in_vcf_check/genotype.vcf
|
|
135
|
+
tests/resources/sample_in_vcf_check/metadata_af_no_sample_in_vcf.json
|
|
136
|
+
tests/resources/sample_in_vcf_check/metadata_af_with_sample_in_vcf.json
|
|
137
|
+
tests/resources/sample_in_vcf_check/metadata_genotype_no_sample_in_vcf.json
|
|
138
|
+
tests/resources/sample_in_vcf_check/metadata_genotype_with_sample_in_vcf.json
|
|
126
139
|
tests/resources/validation_reports/expected_metadata_json_report.html
|
|
127
140
|
tests/resources/validation_reports/expected_metadata_json_report.txt
|
|
128
141
|
tests/resources/validation_reports/expected_metadata_xlsx_report.html
|
|
@@ -3,6 +3,7 @@ check_fasta_insdc.py = eva_sub_cli.executables.check_fasta_insdc:main
|
|
|
3
3
|
check_metadata_semantics.py = eva_sub_cli.executables.check_metadata_semantics:main
|
|
4
4
|
eva-sub-cli.py = eva_sub_cli.executables.cli:main
|
|
5
5
|
evidence_type_checker.py = eva_sub_cli.executables.evidence_type_checker:main
|
|
6
|
+
format_metadata.py = eva_sub_cli.executables.format_metadata:main
|
|
6
7
|
samples_checker.py = eva_sub_cli.executables.samples_checker:main
|
|
7
8
|
trim_down.py = eva_sub_cli.executables.trim_down:main
|
|
8
9
|
xlsx2json.py = eva_sub_cli.executables.xlsx2json:main
|