eva-sub-cli 0.6.0__tar.gz → 0.6.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. eva_sub_cli-0.6.1/.github/workflows/integration-tests.yml +56 -0
  2. {eva_sub_cli-0.6.0/eva_sub_cli.egg-info → eva_sub_cli-0.6.1}/PKG-INFO +1 -1
  3. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/docker/Dockerfile +1 -1
  4. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/docs/input_file_overview.md +2 -1
  5. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/_version.py +3 -3
  6. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/etc/eva_schema.json +1 -2
  7. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/executables/check_metadata_semantics.py +8 -3
  8. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/executables/samples_checker.py +13 -12
  9. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/executables/xlsx2json.py +5 -4
  10. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/nextflow/validation.nf +22 -4
  11. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/semantic_metadata.py +15 -1
  12. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/validators/docker_validator.py +1 -1
  13. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1/eva_sub_cli.egg-info}/PKG-INFO +1 -1
  14. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli.egg-info/SOURCES.txt +10 -0
  15. eva_sub_cli-0.6.1/tests/resources/sample_checker/evidence_type.yaml +6 -0
  16. eva_sub_cli-0.6.1/tests/resources/sample_in_vcf_check/allele_freq.vcf +9 -0
  17. eva_sub_cli-0.6.1/tests/resources/sample_in_vcf_check/fake_fasta.fa +2 -0
  18. eva_sub_cli-0.6.1/tests/resources/sample_in_vcf_check/genotype.vcf +7 -0
  19. eva_sub_cli-0.6.1/tests/resources/sample_in_vcf_check/metadata_af_no_sample_in_vcf.json +1 -0
  20. eva_sub_cli-0.6.1/tests/resources/sample_in_vcf_check/metadata_af_with_sample_in_vcf.json +1 -0
  21. eva_sub_cli-0.6.1/tests/resources/sample_in_vcf_check/metadata_genotype_no_sample_in_vcf.json +1 -0
  22. eva_sub_cli-0.6.1/tests/resources/sample_in_vcf_check/metadata_genotype_with_sample_in_vcf.json +1 -0
  23. eva_sub_cli-0.6.1/tests/test_native_validator_sample_in_vcf.py +96 -0
  24. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_samples_checker.py +2 -1
  25. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_semantic_metadata.py +43 -17
  26. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_utils.py +3 -1
  27. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/.github/workflows/publish.yml +0 -0
  28. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/.github/workflows/publish_docs.yml +0 -0
  29. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/.github/workflows/tests.yml +0 -0
  30. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/.github/workflows/trigger-eva-sub-cli-integration-tests.yml +0 -0
  31. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/.gitignore +0 -0
  32. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/LICENSE +0 -0
  33. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/README.md +0 -0
  34. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/conda/build.sh +0 -0
  35. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/conda/meta.yaml +0 -0
  36. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/docs/README.md +0 -0
  37. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/docs/_config.yml +0 -0
  38. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/docs/how_to_submit.md +0 -0
  39. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/docs/installation.md +0 -0
  40. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/docs/using_nextflow.md +0 -0
  41. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/docs/validation_overview.md +0 -0
  42. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/__init__.py +0 -0
  43. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/auth.py +0 -0
  44. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/call_home.py +0 -0
  45. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/date_utils.py +0 -0
  46. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/etc/EVA_Submission_Example.xlsx +0 -0
  47. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/etc/EVA_Submission_template.xlsx +0 -0
  48. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/etc/call_home_payload_schema.json +0 -0
  49. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/etc/eva-biosamples.json +0 -0
  50. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/etc/eva_logo.png +0 -0
  51. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/etc/spreadsheet2json_conf.yaml +0 -0
  52. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/etc/spreadsheet2json_conf_V2.yaml +0 -0
  53. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/exceptions/__init__.py +0 -0
  54. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/exceptions/invalid_file_type_exception.py +0 -0
  55. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/exceptions/metadata_template_version_exception.py +0 -0
  56. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/exceptions/submission_not_found_exception.py +0 -0
  57. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/exceptions/submission_status_exception.py +0 -0
  58. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/exceptions/submission_upload_exception.py +0 -0
  59. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/executables/__init__.py +0 -0
  60. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/executables/check_fasta_insdc.py +0 -0
  61. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/executables/cli.py +0 -0
  62. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/executables/evidence_type_checker.py +0 -0
  63. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/executables/trim_down.py +0 -0
  64. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/file_utils.py +0 -0
  65. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/jinja_templates/html/fasta_check.html +0 -0
  66. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/jinja_templates/html/file_validation.html +0 -0
  67. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/jinja_templates/html/metadata_validation.html +0 -0
  68. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/jinja_templates/html/project_details.html +0 -0
  69. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/jinja_templates/html/report.html +0 -0
  70. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/jinja_templates/html/sample_name_check.html +0 -0
  71. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/jinja_templates/html/shallow_validation.html +0 -0
  72. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/jinja_templates/text/fasta_check.txt +0 -0
  73. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/jinja_templates/text/file_validation.txt +0 -0
  74. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/jinja_templates/text/metadata_validation.txt +0 -0
  75. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/jinja_templates/text/project_details.txt +0 -0
  76. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/jinja_templates/text/report.txt +0 -0
  77. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/jinja_templates/text/sample_name_check.txt +0 -0
  78. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/jinja_templates/text/shallow_validation.txt +0 -0
  79. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/metadata.py +0 -0
  80. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/orchestrator.py +0 -0
  81. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/report.py +0 -0
  82. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/submission_ws.py +0 -0
  83. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/submit.py +0 -0
  84. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/utils.py +0 -0
  85. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/validators/__init__.py +0 -0
  86. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/validators/native_validator.py +0 -0
  87. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/validators/validation_results_parsers.py +0 -0
  88. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli/validators/validator.py +0 -0
  89. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli.egg-info/dependency_links.txt +0 -0
  90. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli.egg-info/entry_points.txt +0 -0
  91. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli.egg-info/requires.txt +0 -0
  92. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/eva_sub_cli.egg-info/top_level.txt +0 -0
  93. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/pyproject.toml +0 -0
  94. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/pytest.ini +0 -0
  95. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/requirements.txt +0 -0
  96. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/setup.cfg +0 -0
  97. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/setup.py +0 -0
  98. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/build_and_test_docker_locally.py +0 -0
  99. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/ignore_test_nextflow_validation.yml +0 -0
  100. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/EVA_Submission_Docker_Test.xlsx +0 -0
  101. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/EVA_Submission_test.json +0 -0
  102. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/EVA_Submission_test.xlsx +0 -0
  103. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/EVA_Submission_test_V2.xlsx +0 -0
  104. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/EVA_Submission_test_fails.xlsx +0 -0
  105. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/EVA_Submission_test_version_missing.xlsx +0 -0
  106. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/EVA_Submission_test_with_asm_report.json +0 -0
  107. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/EVA_Submission_test_with_non_vcf_files.json +0 -0
  108. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/EVA_Submission_test_with_non_vcf_files.xlsx +0 -0
  109. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/EVA_Submission_test_with_project_accession.json +0 -0
  110. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/EVA_Submission_test_with_project_accession.xlsx +0 -0
  111. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/assembly_check/invalid.vcf.assembly_check.log +0 -0
  112. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/assembly_check/invalid.vcf.text_assembly_report.txt +0 -0
  113. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/assembly_reports/input_passed.txt +0 -0
  114. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/fasta_files/Saccharomyces_cerevisiae_I.fa +0 -0
  115. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/fasta_files/input_passed.fa +0 -0
  116. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/fasta_files/multi_seq.fa +0 -0
  117. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/metadata_with_filename.json +0 -0
  118. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/sample_checker/example1.vcf.gz +0 -0
  119. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/sample_checker/example2.vcf +0 -0
  120. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/sample_checker/example3.vcf +0 -0
  121. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/sample_checker/metadata.json +0 -0
  122. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/expected_metadata_json_report.html +0 -0
  123. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/expected_metadata_json_report.txt +0 -0
  124. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/expected_metadata_xlsx_report.html +0 -0
  125. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/expected_metadata_xlsx_report.txt +0 -0
  126. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/expected_report_metadata_json_process_not_run.html +0 -0
  127. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/expected_report_metadata_json_process_not_run.txt +0 -0
  128. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/expected_shallow_metadata_xlsx_report.html +0 -0
  129. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/expected_shallow_metadata_xlsx_report.txt +0 -0
  130. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.assembly_check.log +0 -0
  131. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.text_assembly_report.1680102476700.txt +0 -0
  132. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.valid_assembly_report.1680102476700.txt +0 -0
  133. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/validation_output/metadata.json +0 -0
  134. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/validation_output/other_validations/evidence_type_checker.yml +0 -0
  135. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/validation_output/other_validations/file_info.txt +0 -0
  136. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/validation_output/other_validations/input_passed.fa_check.yml +0 -0
  137. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/validation_output/other_validations/input_passed_trim_down.yml +0 -0
  138. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/validation_output/other_validations/metadata_conversion_errors.yml +0 -0
  139. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/validation_output/other_validations/metadata_semantic_check.yml +0 -0
  140. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/validation_output/other_validations/metadata_validation.txt +0 -0
  141. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/validation_output/other_validations/sample_checker.yml +0 -0
  142. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.errors.1680102476854.db +0 -0
  143. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.errors.1680102476854.txt +0 -0
  144. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.vcf_format.log +0 -0
  145. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/vcf_files/example2.vcf.gz +0 -0
  146. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/vcf_files/example2.vcf.gz.tbi +0 -0
  147. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/resources/vcf_files/input_passed.vcf +0 -0
  148. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_auth.py +0 -0
  149. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_call_home.py +0 -0
  150. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_check_fasta_insdc.py +0 -0
  151. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_cli.py +0 -0
  152. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_docker_validator.py +0 -0
  153. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_evidence_type_checker.py +0 -0
  154. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_file_utils.py +0 -0
  155. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_metadata.py +0 -0
  156. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_orchestrator.py +0 -0
  157. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_report.py +0 -0
  158. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_submit.py +0 -0
  159. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_trim_down.py +0 -0
  160. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_validaton_results_parsers.py +0 -0
  161. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_validator.py +0 -0
  162. {eva_sub_cli-0.6.0 → eva_sub_cli-0.6.1}/tests/test_xlsx2json.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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eva_sub_cli
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: EBI EVA - validation and submission command line tool
5
5
  Classifier: Development Status :: 5 - Production/Stable
6
6
  Classifier: Environment :: Console
@@ -1,4 +1,4 @@
1
- FROM --platform=linux/amd64 python:3.10
1
+ FROM python:3.10
2
2
 
3
3
  ENV vcf_validator_version=0.10.2
4
4
  ENV NXF_VER=23.10.0
@@ -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.0'
32
- __version_tuple__ = version_tuple = (0, 6, 0)
31
+ __version__ = version = '0.6.1'
32
+ __version_tuple__ = version_tuple = (0, 6, 1)
33
33
 
34
- __commit_id__ = commit_id = 'g9b7431423'
34
+ __commit_id__ = commit_id = 'g13513250e'
@@ -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
- checker = SemanticMetadataChecker(metadata)
17
- checker.check_all()
18
- checker.write_result_yaml(args.output_yaml)
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)
@@ -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(sample_name_per_file):
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(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
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
- analysis_alias_list = data[analysis_alias].split(',')
229
- sample_in_vcf_val = data[sample_name_in_vcf]
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)
@@ -105,20 +105,31 @@ workflow {
105
105
  collect_file_size_and_md5(generate_file_size_and_md5_digests.out.file_size_and_digest_info.collect())
106
106
 
107
107
  // Task-specific processing
108
+ evidence_type_results = null
109
+
108
110
  if (params.tasks.contains(VCF_CHECK)) {
109
111
  check_vcf_valid(vcf_and_ref_ch)
110
112
  evidence_type_check(metadata_json, vcf_files.collect())
113
+ evidence_type_results = evidence_type_check.out.evidence_type_checker_yml
111
114
  }
112
115
  if (params.tasks.contains(ASSEMBLY_CHECK)) {
113
116
  check_vcf_reference(vcf_and_ref_ch)
114
117
  insdc_checker(metadata_json, fasta_to_vcfs)
115
118
  }
116
119
  if (params.tasks.contains(METADATA_CHECK)) {
120
+ if (!evidence_type_results) {
121
+ evidence_type_check(metadata_json, vcf_files.collect())
122
+ evidence_type_results = evidence_type_check.out.evidence_type_checker_yml
123
+ }
117
124
  metadata_json_validation(metadata_json)
118
- metadata_semantic_check(metadata_json)
125
+ metadata_semantic_check(metadata_json, evidence_type_results)
119
126
  }
120
127
  if (params.tasks.contains(SAMPLE_CHECK)) {
121
- sample_name_concordance(metadata_json, vcf_files.collect())
128
+ if (!evidence_type_results){
129
+ evidence_type_check(metadata_json, vcf_files.collect())
130
+ evidence_type_results = evidence_type_check.out.evidence_type_checker_yml
131
+ }
132
+ sample_name_concordance(metadata_json, vcf_files.collect(), evidence_type_results)
122
133
  }
123
134
  }
124
135
 
@@ -294,6 +305,7 @@ process sample_name_concordance {
294
305
  input:
295
306
  path(metadata_json)
296
307
  path(vcf_files)
308
+ path(evidence_type_results)
297
309
 
298
310
  output:
299
311
  path "sample_checker.yml", emit: sample_checker_yml
@@ -301,7 +313,9 @@ process sample_name_concordance {
301
313
 
302
314
  script:
303
315
  """
304
- $params.python_scripts.samples_checker --metadata_json $metadata_json --vcf_files $vcf_files --output_yaml sample_checker.yml > sample_checker.log 2>&1
316
+ $params.python_scripts.samples_checker --metadata_json $metadata_json \
317
+ --vcf_files $vcf_files --output_yaml sample_checker.yml \
318
+ --evidence_type_results $evidence_type_results > sample_checker.log 2>&1
305
319
  """
306
320
  }
307
321
 
@@ -362,6 +376,7 @@ process metadata_semantic_check {
362
376
 
363
377
  input:
364
378
  path(metadata_json)
379
+ path(evidence_type_results)
365
380
 
366
381
  output:
367
382
  path "metadata_semantic_check.yml", emit: metadata_semantic_check_yml
@@ -369,6 +384,9 @@ process metadata_semantic_check {
369
384
 
370
385
  script:
371
386
  """
372
- $params.python_scripts.semantic_checker --metadata_json $metadata_json --output_yaml metadata_semantic_check.yml > semantic_checker.log 2>&1
387
+ $params.python_scripts.semantic_checker \
388
+ --metadata_json $metadata_json \
389
+ --evidence_type_results $evidence_type_results \
390
+ --output_yaml metadata_semantic_check.yml > semantic_checker.log 2>&1
373
391
  """
374
392
  }
@@ -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.11'
12
+ default_container_tag = 'v0.0.12'
13
13
  container_validation_dir = '/opt/vcf_validation'
14
14
  container_validation_output_dir = 'vcf_validation_output'
15
15
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eva_sub_cli
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: EBI EVA - validation and submission command line tool
5
5
  Classifier: Development Status :: 5 - Production/Stable
6
6
  Classifier: Environment :: Console
@@ -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
@@ -91,6 +92,7 @@ tests/test_docker_validator.py
91
92
  tests/test_evidence_type_checker.py
92
93
  tests/test_file_utils.py
93
94
  tests/test_metadata.py
95
+ tests/test_native_validator_sample_in_vcf.py
94
96
  tests/test_orchestrator.py
95
97
  tests/test_report.py
96
98
  tests/test_samples_checker.py
@@ -119,10 +121,18 @@ tests/resources/assembly_reports/input_passed.txt
119
121
  tests/resources/fasta_files/Saccharomyces_cerevisiae_I.fa
120
122
  tests/resources/fasta_files/input_passed.fa
121
123
  tests/resources/fasta_files/multi_seq.fa
124
+ tests/resources/sample_checker/evidence_type.yaml
122
125
  tests/resources/sample_checker/example1.vcf.gz
123
126
  tests/resources/sample_checker/example2.vcf
124
127
  tests/resources/sample_checker/example3.vcf
125
128
  tests/resources/sample_checker/metadata.json
129
+ tests/resources/sample_in_vcf_check/allele_freq.vcf
130
+ tests/resources/sample_in_vcf_check/fake_fasta.fa
131
+ tests/resources/sample_in_vcf_check/genotype.vcf
132
+ tests/resources/sample_in_vcf_check/metadata_af_no_sample_in_vcf.json
133
+ tests/resources/sample_in_vcf_check/metadata_af_with_sample_in_vcf.json
134
+ tests/resources/sample_in_vcf_check/metadata_genotype_no_sample_in_vcf.json
135
+ tests/resources/sample_in_vcf_check/metadata_genotype_with_sample_in_vcf.json
126
136
  tests/resources/validation_reports/expected_metadata_json_report.html
127
137
  tests/resources/validation_reports/expected_metadata_json_report.txt
128
138
  tests/resources/validation_reports/expected_metadata_xlsx_report.html
@@ -0,0 +1,6 @@
1
+ VD1:
2
+ evidence_type: genotype
3
+ VD2:
4
+ evidence_type: genotype
5
+ VD3:
6
+ evidence_type: genotype
@@ -0,0 +1,9 @@
1
+ ##fileformat=VCFv4.1
2
+ ##FILTER=<ID=PASS,Description="All filters passed">
3
+ ##contig=<ID=1,length=249250621>
4
+ ##INFO=<ID=AF,Number=A,Type=Float,Description="Allele Frequency">
5
+ ##INFO=<ID=AN,Number=1,Type=Integer,Description="Total Allele Count">
6
+ ##INFO=<ID=AC,Number=A,Type=Integer,Description="Allele Count">
7
+ #CHROM POS ID REF ALT QUAL FILTER INFO
8
+ 1 10177 rs367896724 A AC 100 PASS AF=0.11;AN=2000;AC=220
9
+ 1 10505 rs548419688 A T 100 PASS AF=0.09;AN=2000;AC=180
@@ -0,0 +1,7 @@
1
+ ##fileformat=VCFv4.1
2
+ ##FILTER=<ID=PASS,Description="All filters passed">
3
+ ##contig=<ID=1,assembly=b37,length=249250621>
4
+ ##FORMAT=<ID=GT,Number=1,Type=String,Description="Genotype">
5
+ #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT sample1 sample2 sample3
6
+ 1 10177 rs367896724 A AC 100 PASS . GT 1|0 0|1 0|0
7
+ 1 10505 rs548419688 A T 100 PASS . GT 0|0 0|0 0|1
@@ -0,0 +1 @@
1
+ {"project": {"title": "Test AF Project", "description": "Project with allele frequency VCF", "taxId": 9606, "centre": "Test Centre"}, "sample": [{"analysisAlias": ["AF1"], "bioSampleAccession": "SAME00001"}], "analysis": [{"analysisTitle": "AF Analysis", "analysisAlias": "AF1", "description": "Allele frequency analysis", "experimentType": "Whole genome sequencing", "referenceGenome": "GCA_000001405.27"}], "files": [{"analysisAlias": "AF1", "fileName": "allele_freq.vcf", "fileType": "vcf", "md5": "b8ab2c9d58e5f430ce70783d8d0a0b88", "fileSize": 458}]}
@@ -0,0 +1 @@
1
+ {"project": {"title": "Test AF Project", "description": "Project with allele frequency VCF", "taxId": 9606, "centre": "Test Centre"}, "sample": [{"analysisAlias": ["AF1"], "sampleInVCF": "sample1", "bioSampleAccession": "SAME00001"}], "analysis": [{"analysisTitle": "AF Analysis", "analysisAlias": "AF1", "description": "Allele frequency analysis", "experimentType": "Whole genome sequencing", "referenceGenome": "GCA_000001405.27"}], "files": [{"analysisAlias": "AF1", "fileName": "allele_freq.vcf", "fileType": "vcf", "md5": "b8ab2c9d58e5f430ce70783d8d0a0b88", "fileSize": 458}]}
@@ -0,0 +1 @@
1
+ {"project": {"title": "Test Genotype Project", "description": "Project with genotype VCF", "taxId": 9606, "centre": "Test Centre"}, "sample": [{"analysisAlias": ["GT1"], "bioSampleAccession": "SAME00001"}, {"analysisAlias": ["GT1"], "bioSampleAccession": "SAME00002"}, {"analysisAlias": ["GT1"], "bioSampleAccession": "SAME00003"}], "analysis": [{"analysisTitle": "Genotype Analysis", "analysisAlias": "GT1", "description": "Genotype analysis", "experimentType": "Whole genome sequencing", "referenceGenome": "GCA_000001405.27"}], "files": [{"analysisAlias": "GT1", "fileName": "genotype.vcf", "fileType": "vcf", "md5": "81ca0b3a6e5b657bc2be50085c76546a", "fileSize": 350}]}
@@ -0,0 +1 @@
1
+ {"project": {"title": "Test Genotype Project", "description": "Project with genotype VCF", "taxId": 9606, "centre": "Test Centre"}, "sample": [{"analysisAlias": ["GT1"], "sampleInVCF": "sample1", "bioSampleAccession": "SAME00001"}, {"analysisAlias": ["GT1"], "sampleInVCF": "sample2", "bioSampleAccession": "SAME00002"}, {"analysisAlias": ["GT1"], "sampleInVCF": "sample3", "bioSampleAccession": "SAME00003"}], "analysis": [{"analysisTitle": "Genotype Analysis", "analysisAlias": "GT1", "description": "Genotype analysis", "experimentType": "Whole genome sequencing", "referenceGenome": "GCA_000001405.27"}], "files": [{"analysisAlias": "GT1", "fileName": "genotype.vcf", "fileType": "vcf", "md5": "81ca0b3a6e5b657bc2be50085c76546a", "fileSize": 350}]}
@@ -0,0 +1,96 @@
1
+ import os
2
+ import shutil
3
+ from unittest import TestCase
4
+
5
+ import pytest
6
+ import yaml
7
+
8
+ from eva_sub_cli.validators.native_validator import NativeValidator
9
+ from eva_sub_cli.validators.validator import METADATA_CHECK
10
+ from tests.test_utils import create_mapping_file
11
+
12
+
13
+ @pytest.mark.integration('You need to install java, nextflow, vcf_validator, vcf_assembly_checker, biovalidator (and md5sum, stat for mac)')
14
+ class TestNativeValidatorSampleInVCF(TestCase):
15
+ resource_dir = os.path.join(os.path.dirname(__file__), 'resources')
16
+ sample_in_vcf_dir = os.path.join(resource_dir, 'sample_in_vcf_check')
17
+ fasta_file = os.path.join(sample_in_vcf_dir, 'fake_fasta.fa')
18
+
19
+ def setUp(self):
20
+ self.test_run_dir = os.path.join(self.resource_dir, 'test_native_run')
21
+ os.makedirs(self.test_run_dir, exist_ok=True)
22
+ self.mapping_file = os.path.join(self.test_run_dir, 'vcf_files_metadata.csv')
23
+
24
+ def tearDown(self):
25
+ shutil.rmtree(self.test_run_dir)
26
+
27
+ def _build_validator(self, metadata_json, vcf_file, tasks):
28
+ create_mapping_file(
29
+ self.mapping_file,
30
+ vcf_files=[vcf_file],
31
+ fasta_files=[self.fasta_file],
32
+ assembly_reports=None,
33
+ )
34
+ return NativeValidator(
35
+ mapping_file=self.mapping_file,
36
+ submission_dir=self.test_run_dir,
37
+ project_title='Test Project',
38
+ metadata_json=metadata_json,
39
+ validation_tasks=tasks,
40
+ )
41
+
42
+ def _get_semantic_errors(self):
43
+ semantic_yaml = os.path.join(
44
+ self.test_run_dir, 'validation_output', 'other_validations', 'metadata_semantic_check.yml'
45
+ )
46
+ with open(semantic_yaml) as f:
47
+ return yaml.safe_load(f) or []
48
+
49
+ def _sample_in_vcf_errors(self, errors):
50
+ return [e for e in errors if 'sampleInVCF' in e.get('property', '')]
51
+
52
+
53
+ def test_af_vcf_without_sample_in_vcf(self):
54
+ """AF evidence type: omitting sampleInVCF should produce no error."""
55
+ validator = self._build_validator(
56
+ os.path.join(self.sample_in_vcf_dir, 'metadata_af_no_sample_in_vcf.json'),
57
+ os.path.join(self.sample_in_vcf_dir, 'allele_freq.vcf'),
58
+ [METADATA_CHECK]
59
+ )
60
+ validator.validate()
61
+ errors = self._get_semantic_errors()
62
+ self.assertEqual(self._sample_in_vcf_errors(errors), [])
63
+
64
+ def test_af_vcf_with_sample_in_vcf(self):
65
+ """AF evidence type: providing sampleInVCF is permitted and should produce no error."""
66
+ validator = self._build_validator(
67
+ os.path.join(self.sample_in_vcf_dir, 'metadata_af_with_sample_in_vcf.json'),
68
+ os.path.join(self.sample_in_vcf_dir, 'allele_freq.vcf'),
69
+ [METADATA_CHECK]
70
+ )
71
+ validator.validate()
72
+ errors = self._get_semantic_errors()
73
+ self.assertEqual(self._sample_in_vcf_errors(errors), [])
74
+
75
+ def test_genotype_vcf_without_sample_in_vcf(self):
76
+ """Genotype evidence type: omitting sampleInVCF must produce one error per sample."""
77
+ validator = self._build_validator(
78
+ os.path.join(self.sample_in_vcf_dir, 'metadata_genotype_no_sample_in_vcf.json'),
79
+ os.path.join(self.sample_in_vcf_dir, 'genotype.vcf'),
80
+ [METADATA_CHECK]
81
+ )
82
+ validator.validate()
83
+ errors = self._get_semantic_errors()
84
+ sample_in_vcf_errors = self._sample_in_vcf_errors(errors)
85
+ self.assertEqual(len(sample_in_vcf_errors), 3)
86
+
87
+ def test_genotype_vcf_with_sample_in_vcf(self):
88
+ """Genotype evidence type: providing sampleInVCF for every sample should produce no error."""
89
+ validator = self._build_validator(
90
+ os.path.join(self.sample_in_vcf_dir, 'metadata_genotype_with_sample_in_vcf.json'),
91
+ os.path.join(self.sample_in_vcf_dir, 'genotype.vcf'),
92
+ [METADATA_CHECK]
93
+ )
94
+ validator.validate()
95
+ errors = self._get_semantic_errors()
96
+ self.assertEqual(self._sample_in_vcf_errors(errors), [])
@@ -49,7 +49,8 @@ class TestSampleChecker(TestCase):
49
49
  os.remove(updated_metadata)
50
50
 
51
51
  def run_and_assert_sample_check(self, metadata_json, vcf_files):
52
- check_sample_name_concordance(metadata_json, vcf_files, self.output_yaml)
52
+ evidence_type_yaml = os.path.join(self.resource_dir, 'sample_checker', 'evidence_type.yaml')
53
+ check_sample_name_concordance(metadata_json, vcf_files, self.output_yaml, evidence_type_yaml)
53
54
  expected_results = {
54
55
  'overall_differences': True,
55
56
  'results_per_analysis': {