eva-sub-cli 0.4.14__tar.gz → 0.5.0__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 (147) hide show
  1. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/PKG-INFO +1 -1
  2. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/docker/Dockerfile +1 -1
  3. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/_version.py +3 -3
  4. eva_sub_cli-0.5.0/eva_sub_cli/etc/EVA_Submission_Example.xlsx +0 -0
  5. eva_sub_cli-0.5.0/eva_sub_cli/etc/EVA_Submission_template.xlsx +0 -0
  6. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/etc/eva_schema.json +71 -56
  7. eva_sub_cli-0.5.0/eva_sub_cli/etc/spreadsheet2json_conf.yaml +139 -0
  8. eva_sub_cli-0.4.14/eva_sub_cli/etc/spreadsheet2json_conf.yaml → eva_sub_cli-0.5.0/eva_sub_cli/etc/spreadsheet2json_conf_V2.yaml +5 -3
  9. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/executables/cli.py +3 -0
  10. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/executables/xlsx2json.py +11 -4
  11. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/jinja_templates/html/file_validation.html +1 -1
  12. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/jinja_templates/text/file_validation.txt +3 -1
  13. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/nextflow/validation.nf +10 -8
  14. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/orchestrator.py +33 -13
  15. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/semantic_metadata.py +11 -7
  16. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/submit.py +3 -2
  17. eva_sub_cli-0.5.0/eva_sub_cli/utils.py +20 -0
  18. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/validators/docker_validator.py +8 -7
  19. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/validators/native_validator.py +5 -4
  20. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/validators/validator.py +18 -6
  21. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli.egg-info/PKG-INFO +1 -1
  22. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli.egg-info/SOURCES.txt +5 -0
  23. eva_sub_cli-0.5.0/tests/resources/EVA_Submission_Docker_Test.xlsx +0 -0
  24. eva_sub_cli-0.5.0/tests/resources/EVA_Submission_test.xlsx +0 -0
  25. eva_sub_cli-0.5.0/tests/resources/EVA_Submission_test_V2.xlsx +0 -0
  26. eva_sub_cli-0.5.0/tests/resources/EVA_Submission_test_fails.xlsx +0 -0
  27. eva_sub_cli-0.5.0/tests/resources/EVA_Submission_test_version_missing.xlsx +0 -0
  28. eva_sub_cli-0.5.0/tests/resources/EVA_Submission_test_with_project_accession.json +151 -0
  29. eva_sub_cli-0.5.0/tests/resources/EVA_Submission_test_with_project_accession.xlsx +0 -0
  30. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/metadata_with_filename.json +7 -1
  31. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_docker_validator.py +5 -1
  32. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_orchestrator.py +83 -13
  33. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_semantic_metadata.py +27 -0
  34. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_validator.py +24 -9
  35. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_xlsx2json.py +62 -1
  36. eva_sub_cli-0.4.14/eva_sub_cli/etc/EVA_Submission_Example.xlsx +0 -0
  37. eva_sub_cli-0.4.14/eva_sub_cli/etc/EVA_Submission_template.xlsx +0 -0
  38. eva_sub_cli-0.4.14/tests/resources/EVA_Submission_Docker_Test.xlsx +0 -0
  39. eva_sub_cli-0.4.14/tests/resources/EVA_Submission_test.xlsx +0 -0
  40. eva_sub_cli-0.4.14/tests/resources/EVA_Submission_test_fails.xlsx +0 -0
  41. eva_sub_cli-0.4.14/tests/resources/EVA_Submission_test_version_missing.xlsx +0 -0
  42. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/.github/workflows/publish.yml +0 -0
  43. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/.github/workflows/publish_docs.yml +0 -0
  44. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/.github/workflows/publish_packages.yml +0 -0
  45. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/.github/workflows/tests.yml +0 -0
  46. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/.github/workflows/trigger-eva-sub-cli-integration-tests.yml +0 -0
  47. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/.gitignore +0 -0
  48. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/LICENSE +0 -0
  49. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/README.md +0 -0
  50. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/conda/build.sh +0 -0
  51. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/conda/meta.yaml +0 -0
  52. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/docs/README.md +0 -0
  53. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/docs/_config.yml +0 -0
  54. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/docs/how_to_submit.md +0 -0
  55. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/docs/input_file_overview.md +0 -0
  56. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/docs/installation.md +0 -0
  57. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/docs/using_nextflow.md +0 -0
  58. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/docs/validation_overview.md +0 -0
  59. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/__init__.py +0 -0
  60. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/auth.py +0 -0
  61. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/date_utils.py +0 -0
  62. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/etc/eva-biosamples.json +0 -0
  63. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/etc/eva_logo.png +0 -0
  64. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/exceptions/__init__.py +0 -0
  65. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/exceptions/invalid_file_type_exception.py +0 -0
  66. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/exceptions/metadata_template_version_exception.py +0 -0
  67. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/exceptions/submission_not_found_exception.py +0 -0
  68. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/exceptions/submission_status_exception.py +0 -0
  69. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/executables/__init__.py +0 -0
  70. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/executables/check_fasta_insdc.py +0 -0
  71. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/executables/check_metadata_semantics.py +0 -0
  72. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/executables/evidence_type_checker.py +0 -0
  73. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/executables/samples_checker.py +0 -0
  74. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/executables/trim_down.py +0 -0
  75. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/file_utils.py +0 -0
  76. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/jinja_templates/html/fasta_check.html +0 -0
  77. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/jinja_templates/html/metadata_validation.html +0 -0
  78. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/jinja_templates/html/project_details.html +0 -0
  79. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/jinja_templates/html/report.html +0 -0
  80. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/jinja_templates/html/sample_name_check.html +0 -0
  81. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/jinja_templates/html/shallow_validation.html +0 -0
  82. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/jinja_templates/text/fasta_check.txt +0 -0
  83. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/jinja_templates/text/metadata_validation.txt +0 -0
  84. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/jinja_templates/text/project_details.txt +0 -0
  85. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/jinja_templates/text/report.txt +0 -0
  86. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/jinja_templates/text/sample_name_check.txt +0 -0
  87. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/jinja_templates/text/shallow_validation.txt +0 -0
  88. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/metadata.py +0 -0
  89. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/report.py +0 -0
  90. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/submission_ws.py +0 -0
  91. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/validators/__init__.py +0 -0
  92. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli/validators/validation_results_parsers.py +0 -0
  93. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli.egg-info/dependency_links.txt +0 -0
  94. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli.egg-info/entry_points.txt +0 -0
  95. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli.egg-info/requires.txt +0 -0
  96. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/eva_sub_cli.egg-info/top_level.txt +0 -0
  97. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/pyproject.toml +0 -0
  98. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/pytest.ini +0 -0
  99. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/requirements.txt +0 -0
  100. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/setup.cfg +0 -0
  101. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/setup.py +0 -0
  102. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/build_and_test_docker_locally.py +0 -0
  103. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/ignore_test_nextflow_validation.yml +0 -0
  104. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/EVA_Submission_test.json +0 -0
  105. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/EVA_Submission_test_with_asm_report.json +0 -0
  106. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/assembly_check/invalid.vcf.assembly_check.log +0 -0
  107. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/assembly_check/invalid.vcf.text_assembly_report.txt +0 -0
  108. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/assembly_reports/input_passed.txt +0 -0
  109. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/fasta_files/Saccharomyces_cerevisiae_I.fa +0 -0
  110. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/fasta_files/input_passed.fa +0 -0
  111. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/fasta_files/multi_seq.fa +0 -0
  112. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/sample_checker/example1.vcf.gz +0 -0
  113. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/sample_checker/example2.vcf +0 -0
  114. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/sample_checker/example3.vcf +0 -0
  115. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/sample_checker/metadata.json +0 -0
  116. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/expected_report_metadata_json.html +0 -0
  117. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/expected_report_metadata_json.txt +0 -0
  118. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/expected_report_metadata_xlsx.html +0 -0
  119. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/expected_report_metadata_xlsx.txt +0 -0
  120. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/expected_shallow_metadata_xlsx_report.html +0 -0
  121. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/expected_shallow_metadata_xlsx_report.txt +0 -0
  122. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.assembly_check.log +0 -0
  123. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.text_assembly_report.1680102476700.txt +0 -0
  124. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.valid_assembly_report.1680102476700.txt +0 -0
  125. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/validation_output/other_validations/evidence_type_checker.yml +0 -0
  126. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/validation_output/other_validations/input_passed.fa_check.yml +0 -0
  127. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/validation_output/other_validations/metadata_conversion_errors.yml +0 -0
  128. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/validation_output/other_validations/metadata_semantic_check.yml +0 -0
  129. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/validation_output/other_validations/metadata_validation.txt +0 -0
  130. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/validation_output/other_validations/sample_checker.yml +0 -0
  131. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.errors.1680102476854.db +0 -0
  132. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.errors.1680102476854.txt +0 -0
  133. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.vcf_format.log +0 -0
  134. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/vcf_files/example2.vcf.gz +0 -0
  135. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/resources/vcf_files/input_passed.vcf +0 -0
  136. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_auth.py +0 -0
  137. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_check_fasta_insdc.py +0 -0
  138. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_cli.py +0 -0
  139. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_evidence_type_checker.py +0 -0
  140. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_file_utils.py +0 -0
  141. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_metadata.py +0 -0
  142. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_report.py +0 -0
  143. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_samples_checker.py +0 -0
  144. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_submit.py +0 -0
  145. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_trim_down.py +0 -0
  146. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_utils.py +0 -0
  147. {eva_sub_cli-0.4.14 → eva_sub_cli-0.5.0}/tests/test_validaton_results_parsers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eva_sub_cli
3
- Version: 0.4.14
3
+ Version: 0.5.0
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,7 +1,7 @@
1
1
  FROM python:3.10
2
2
 
3
3
  ENV vcf_validator_version=0.10.2
4
- ENV NXF_VER=22.10.6
4
+ ENV NXF_VER=23.10.0
5
5
 
6
6
  WORKDIR /opt
7
7
 
@@ -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.4.14'
32
- __version_tuple__ = version_tuple = (0, 4, 14)
31
+ __version__ = version = '0.5.0'
32
+ __version_tuple__ = version_tuple = (0, 5, 0)
33
33
 
34
- __commit_id__ = commit_id = 'g1808b05b1'
34
+ __commit_id__ = commit_id = 'g1b663fd41'
@@ -64,66 +64,81 @@
64
64
  }
65
65
  },
66
66
  "project": {
67
- "type": "object",
68
- "description": "General information about the Project",
69
- "required": [
70
- "title",
71
- "description",
72
- "taxId",
73
- "centre"
74
- ],
75
- "properties": {
76
- "title": {
77
- "type": "string",
78
- "description": "Title of the project",
79
- "maxLength": 500
80
- },
81
- "description": {
82
- "type": "string",
83
- "description": "Description of the project",
84
- "maxLength": 5000
85
- },
86
- "centre": {
87
- "type": "string",
88
- "description": "Centre, institute or company submitting the project"
89
- },
90
- "taxId": {
91
- "type": "number",
92
- "description": "Taxonomy ID of the species associated with the project (found here: http://www.ncbi.nlm.nih.gov/taxonomy)"
93
- },
94
- "publications": {
95
- "type": "array",
96
- "items": true
97
- },
98
- "parentProject": {
99
- "$ref": "#/definitions/projectAccession"
100
- },
101
- "childProjects": {
102
- "type": "array",
103
- "items": {
104
- "$ref": "#/definitions/projectAccession"
105
- }
106
- },
107
- "peerProjects": {
108
- "type": "array",
109
- "items": {
110
- "$ref": "#/definitions/projectAccession"
67
+ "oneOf": [
68
+ {
69
+ "type": "object",
70
+ "required": [
71
+ "projectAccession"
72
+ ],
73
+ "properties": {
74
+ "projectAccession": {
75
+ "$ref": "#/definitions/projectAccession"
76
+ }
111
77
  }
112
78
  },
113
- "links": {
114
- "type": "array",
115
- "items": {
116
- "type": "string"
79
+ {
80
+ "type": "object",
81
+ "description": "General information about the Project",
82
+ "required": [
83
+ "title",
84
+ "description",
85
+ "taxId",
86
+ "centre"
87
+ ],
88
+ "properties": {
89
+ "title": {
90
+ "type": "string",
91
+ "description": "Title of the project",
92
+ "maxLength": 500
93
+ },
94
+ "description": {
95
+ "type": "string",
96
+ "description": "Description of the project",
97
+ "maxLength": 5000
98
+ },
99
+ "centre": {
100
+ "type": "string",
101
+ "description": "Centre, institute or company submitting the project"
102
+ },
103
+ "taxId": {
104
+ "type": "number",
105
+ "description": "Taxonomy ID of the species associated with the project (found here: http://www.ncbi.nlm.nih.gov/taxonomy)"
106
+ },
107
+ "publications": {
108
+ "type": "array",
109
+ "items": true
110
+ },
111
+ "parentProject": {
112
+ "$ref": "#/definitions/projectAccession"
113
+ },
114
+ "childProjects": {
115
+ "type": "array",
116
+ "items": {
117
+ "$ref": "#/definitions/projectAccession"
118
+ }
119
+ },
120
+ "peerProjects": {
121
+ "type": "array",
122
+ "items": {
123
+ "$ref": "#/definitions/projectAccession"
124
+ }
125
+ },
126
+ "links": {
127
+ "type": "array",
128
+ "items": {
129
+ "type": "string"
130
+ }
131
+ },
132
+ "holdDate": {
133
+ "type": "string",
134
+ "format": "date",
135
+ "examples": [
136
+ "2018-11-13"
137
+ ]
138
+ }
117
139
  }
118
- },
119
- "holdDate": {
120
- "type": "string",
121
- "format": "date",
122
- "examples": [
123
- "2018-11-13"
124
- ]
125
140
  }
126
- }
141
+ ]
127
142
  },
128
143
  "analysis": {
129
144
  "type": "array",
@@ -0,0 +1,139 @@
1
+ #Configuration for defining which fields in which worksheets to be parsed in an Excel file
2
+ #
3
+ #At the top level, "worksheets" defines a list of worksheets (titles) to be parsed.
4
+ #Then for each worksheet, you define which fields to be parsed from this worksheet.
5
+ #These fields are either "required", "optional" and/or header_row. "required" fields must be found
6
+ #in the worksheet so that this worksheet is valid. Otherwise this worksheet is not
7
+ #valid. The field names must match those values in the header row in the worksheet.
8
+ #
9
+ #This is a YAML file
10
+
11
+ # List of worksheets to be parsed.
12
+ worksheets:
13
+ Submitter Details: submitterDetails
14
+ Project: project
15
+ Analysis: analysis
16
+ Sample: sample
17
+ Files: files
18
+
19
+ Submitter Details:
20
+ required:
21
+ Last Name: lastName
22
+ First Name: firstName
23
+ Email Address: email
24
+ Laboratory: laboratory
25
+ Center: centre
26
+ optional:
27
+ Address: address
28
+
29
+ # List of field for Projects
30
+ Project:
31
+ header_row: 3
32
+ optional:
33
+ Project Accession: projectAccession
34
+ Project Title: title
35
+ Description: description
36
+ Center: centre
37
+ Taxonomy ID: taxId
38
+ Publication(s): publications
39
+ Parent Project: parentProject
40
+ Child Project(s): childProjects
41
+ Peer Project(s): peerProjects
42
+ Link(s): links
43
+ Hold Date: holdDate
44
+ Collaborator(s): collaborators
45
+ Strain: strain
46
+ Breed: breed
47
+ Broker: broker
48
+ cast:
49
+ Publication(s): list
50
+ Child Project(s): list
51
+ Peer Project(s): list
52
+ Link(s): list
53
+ Hold Date: date
54
+ Taxonomy ID: integer
55
+
56
+ Analysis:
57
+ required:
58
+ Analysis Title: analysisTitle
59
+ Analysis Alias: analysisAlias
60
+ Description: description
61
+ Experiment Type: experimentType
62
+ Reference: referenceGenome
63
+ optional:
64
+ Reference Fasta Path: referenceFasta
65
+ Platform: platform
66
+ Software: software
67
+ Pipeline Description: pipelineDescriptions
68
+ Imputation: imputation
69
+ Phasing: phasing
70
+ Centre: centre
71
+ Date: date
72
+ Link(s): links
73
+ Run Accession(s): runAccessions
74
+ cast:
75
+ Run Accession(s): list
76
+ Imputation: boolean
77
+ Phasing: boolean
78
+ Date: date
79
+ Software: list
80
+
81
+ Sample:
82
+ header_row: 3
83
+ required:
84
+ Analysis Alias: analysisAlias
85
+ Sample Name in VCF: sampleInVCF
86
+ # Sample property names taken from ERC000011 where present
87
+ # See https://www.ebi.ac.uk/biosamples/schema-store/registry/schemas/ERC000011
88
+ optional:
89
+ Sample Accession: bioSampleAccession
90
+ BioSample Name: bioSampleName
91
+ Title: title
92
+ Description: description
93
+ Unique Name: uniqueName
94
+ Prefix: prefix
95
+ Subject: subject
96
+ Derived From: derivedFrom
97
+ Taxonomy ID: taxId
98
+ Scientific Name: scientific name
99
+ Common Name: commonName
100
+ mating_type: mating_type
101
+ sex: sex
102
+ population: population
103
+ cell_type: cell_type
104
+ dev_stage: dev_stage
105
+ germline: germline
106
+ tissue_lib: tissue_lib
107
+ tissue_type: tissue_type
108
+ bio_material: bio_material
109
+ culture_collection: culture_collection
110
+ specimen_voucher: specimen_voucher
111
+ collected_by: collected_by
112
+ collection_date: collection date
113
+ geographic location (country and/or sea): geographic location (country and/or sea)
114
+ geographic location (region and locality): geographic location (region and locality)
115
+ host: host
116
+ identified_by: identified_by
117
+ isolation_source: isolation_source
118
+ lat_lon: lat_lon
119
+ lab_host: lab_host
120
+ environmental_sample: environmental_sample
121
+ cultivar: cultivar
122
+ ecotype: ecotype
123
+ isolate: isolate
124
+ strain: strain
125
+ sub_species: sub_species
126
+ variety: variety
127
+ sub_strain: sub_strain
128
+ cell_line: cell_line
129
+ serotype: serotype
130
+ serovar: serovar
131
+ cast:
132
+ collection_date: date
133
+ Taxonomy ID: integer
134
+
135
+
136
+ Files:
137
+ required:
138
+ Analysis Alias: analysisAlias
139
+ File Name: fileName
@@ -50,6 +50,8 @@ Project:
50
50
  Peer Project(s): list
51
51
  Link(s): list
52
52
  Hold Date: date
53
+ Taxonomy ID: integer
54
+
53
55
 
54
56
  Analysis:
55
57
  required:
@@ -127,12 +129,12 @@ Sample:
127
129
  serotype: serotype
128
130
  serovar: serovar
129
131
  cast:
130
- Sample ID: string
131
- BioSample Name: string
132
132
  collection_date: date
133
+ Taxonomy ID: integer
134
+
133
135
 
134
136
 
135
137
  Files:
136
138
  required:
137
139
  Analysis Alias: analysisAlias
138
- File Name: fileName
140
+ File Name: fileName
@@ -151,4 +151,7 @@ def main():
151
151
  except MetadataTemplateVersionNotFoundException as mte:
152
152
  print(mte)
153
153
  exit_status = 70
154
+ except Exception as ex:
155
+ print(ex)
156
+ exit_status = 71
154
157
  return exit_status
@@ -103,9 +103,7 @@ class XlsxParser:
103
103
  @staticmethod
104
104
  def cast_value(value, type_name):
105
105
  # Do not cast None values
106
- if type_name and value is not None:
107
- if type_name == 'string':
108
- return str(value)
106
+ if value is not None:
109
107
  if type_name == 'boolean':
110
108
  return str(value).lower() in ['true', '1', "'1'", 't', 'y', 'yes']
111
109
  if type_name == 'list':
@@ -114,6 +112,10 @@ class XlsxParser:
114
112
  return [v for v in split_values if v]
115
113
  if type_name == 'date':
116
114
  return XlsxParser.serialize(value)
115
+ if type_name == 'integer':
116
+ return int(value)
117
+ # Default any value is cast to string
118
+ return str(value)
117
119
  return value
118
120
 
119
121
  @staticmethod
@@ -179,15 +181,20 @@ class XlsxParser:
179
181
  return rows
180
182
 
181
183
  def get_project_json_data(self):
184
+ json_key = self.xlsx_conf[WORKSHEETS_KEY_NAME][PROJECT]
185
+
182
186
  project_data = self.get_rows()
183
187
  if len(project_data) > 1:
184
188
  logger.warning(f"{PROJECT} worksheet expects a single row of info but more than one found in the file. "
185
189
  f"Only the first row's data will be taken into consideration")
190
+ elif len(project_data) == 0:
191
+ logger.error(f"{PROJECT} worksheet expects a single row of info but no info is found in the file.")
192
+ self.add_error(f"{PROJECT} worksheet expects a single row of info but no info is found in the file.")
193
+ return {json_key: {}}
186
194
 
187
195
  first_row = project_data[0]
188
196
  first_row.pop('row_num')
189
197
 
190
- json_key = self.xlsx_conf[WORKSHEETS_KEY_NAME][PROJECT]
191
198
  json_value = {self.translate_header(PROJECT, k): v for k, v in first_row.items() if v is not None}
192
199
  return {json_key: json_value}
193
200
 
@@ -20,7 +20,7 @@
20
20
  {% set row_class = "report-section fail collapsible" %}
21
21
  {% elif error_count > 0 %}
22
22
  {% set expand_icon = "▶" %}
23
- {% set icon = "❌" %}
23
+ {% set icon = "❗" %}
24
24
  {% set row_class = "report-section warn collapsible" %}
25
25
  {% else %}
26
26
  {% set icon = "✔" %}
@@ -13,8 +13,10 @@
13
13
  {% macro vcf_check(vcf_check_result) %}
14
14
  {% set critical_count = vcf_check_result.get("critical_count", 0) %}
15
15
  {% set error_count = vcf_check_result.get("error_count", 0) %}
16
- {% if critical_count > 0 or error_count > 0 %}
16
+ {% if critical_count > 0 %}
17
17
  {% set icon = "\u274C" %}
18
+ {% elif error_count > 0 %}
19
+ {% set icon = "\u26A0" %}
18
20
  {% else %}
19
21
  {% set icon = "\u2714" %}
20
22
  {% endif %}
@@ -7,10 +7,11 @@ def helpMessage() {
7
7
  Validate a set of VCF files and metadata to check if they are valid to be submitted to EVA.
8
8
 
9
9
  Inputs:
10
- --vcf_files_mapping csv file with the mappings for vcf files, fasta and assembly report
11
- --output_dir output_directory where the reports will be output
12
- --metadata_json Json file describing the project, analysis, samples and files
13
- --metadata_xlsx Excel file describing the project, analysis, samples and files
10
+ --vcf_files_mapping csv file with the mappings for vcf files, fasta and assembly report
11
+ --output_dir output_directory where the reports will be output
12
+ --metadata_json Json file describing the project, analysis, samples and files
13
+ --metadata_xlsx Excel file describing the project, analysis, samples and files
14
+ --conversion_configuration_name Name of the configuration file for converting metadata_xlsx to metadata_json. This is only needed if you are working with metadata spreadsheet and not json
14
15
  """
15
16
  }
16
17
 
@@ -44,16 +45,18 @@ params.shallow_validation = false
44
45
  if (params.help) exit 0, helpMessage()
45
46
 
46
47
  // Test input files
47
- if (!params.vcf_files_mapping || !params.output_dir || (!params.metadata_json && !params.metadata_xlsx)) {
48
+ if (!params.vcf_files_mapping || !params.output_dir || (!params.metadata_json && !params.metadata_xlsx) || (!params.metadata_json && params.metadata_xlsx && !params.conversion_configuration_name)) {
48
49
  if (!params.vcf_files_mapping) log.warn('Provide a csv file with the mappings (vcf, fasta, assembly report) --vcf_files_mapping')
49
- if (!params.metadata_xlsx) log.warn('Provide a json file with the metadata description of the project and analysis --metadata_json')
50
50
  if (!params.output_dir) log.warn('Provide an output directory where the reports will be copied using --output_dir')
51
51
  if (!params.metadata_json && !params.metadata_xlsx) log.warn('Provide a json or Excel file with the metadata description of the project and analysis --metadata_json or --metadata_xlsx')
52
+ if (params.metadata_xlsx && !params.conversion_configuration_name) log.warn('Provide a name of the configuration file to convert the metadata xlsx file to json --params.conversion_configuration_name')
52
53
  exit 1, helpMessage()
53
54
  }
54
55
 
55
56
  schema_dir = file(projectDir).parent + '/etc'
56
- conversion_configuration = schema_dir + '/spreadsheet2json_conf.yaml'
57
+ conversion_configuration = "${schema_dir}/$params.conversion_configuration_name"
58
+
59
+
57
60
 
58
61
  def joinBasePath(path) {
59
62
  if (path){
@@ -240,7 +243,6 @@ process convert_xlsx_2_json {
240
243
 
241
244
  script:
242
245
  metadata_json = metadata_xlsx.getBaseName() + '.json'
243
-
244
246
  """
245
247
  $params.python_scripts.xlsx2json --metadata_xlsx $metadata_xlsx --metadata_json metadata.json --errors_yaml metadata_conversion_errors.yml --conversion_configuration $conversion_configuration > xlsx2json.log 2>&1
246
248
  """
@@ -25,6 +25,7 @@ from eva_sub_cli.metadata import EvaMetadataJson
25
25
  from eva_sub_cli.submission_ws import SubmissionWSClient
26
26
  from eva_sub_cli.submit import StudySubmitter, SUB_CLI_CONFIG_KEY_SUBMISSION_ID, \
27
27
  SUB_CLI_CONFIG_KEY_SUBMISSION_UPLOAD_URL
28
+ from eva_sub_cli.utils import get_project_title_from_ena
28
29
  from eva_sub_cli.validators.docker_validator import DockerValidator
29
30
  from eva_sub_cli.validators.native_validator import NativeValidator
30
31
  from eva_sub_cli.validators.validator import READY_FOR_SUBMISSION_TO_EVA
@@ -47,7 +48,7 @@ def get_vcf_files(mapping_file):
47
48
 
48
49
 
49
50
  def get_project_title_and_create_vcf_files_mapping(submission_dir, vcf_files, reference_fasta,
50
- metadata_json, metadata_xlsx):
51
+ metadata_json, metadata_xlsx, metadata_xlsx_version):
51
52
  """
52
53
  Get project title and mapping between VCF files and reference FASTA files, from three sources: command line
53
54
  arguments, metadata JSON file, or metadata XLSX file.
@@ -57,6 +58,7 @@ def get_project_title_and_create_vcf_files_mapping(submission_dir, vcf_files, re
57
58
  :param reference_fasta: Reference FASTA from command line, if present
58
59
  :param metadata_json: Metadata JSON from command line, if present
59
60
  :param metadata_xlsx: Metadata XLSX from command line, if present
61
+ :param metadata_xlsx_version: Version of metadata XLSX
60
62
  :return: Project title and path to the mapping file
61
63
  """
62
64
  mapping_file = os.path.join(submission_dir, 'vcf_mapping_file.csv')
@@ -71,11 +73,11 @@ def get_project_title_and_create_vcf_files_mapping(submission_dir, vcf_files, re
71
73
  if metadata_json:
72
74
  project_title, _ = get_project_and_vcf_fasta_mapping_from_metadata_json(metadata_json, False)
73
75
  elif metadata_xlsx:
74
- project_title, _ = get_project_and_vcf_fasta_mapping_from_metadata_xlsx(metadata_xlsx, False)
76
+ project_title, _ = get_project_and_vcf_fasta_mapping_from_metadata_xlsx(metadata_xlsx, metadata_xlsx_version, False)
75
77
  elif metadata_json:
76
78
  project_title, vcf_files_mapping = get_project_and_vcf_fasta_mapping_from_metadata_json(metadata_json, True)
77
79
  elif metadata_xlsx:
78
- project_title, vcf_files_mapping = get_project_and_vcf_fasta_mapping_from_metadata_xlsx(metadata_xlsx, True)
80
+ project_title, vcf_files_mapping = get_project_and_vcf_fasta_mapping_from_metadata_xlsx(metadata_xlsx, metadata_xlsx_version, True)
79
81
 
80
82
  # Filter out non-vcf files
81
83
  vcf_files_mapping = [(vcf, fasta, report) for vcf, fasta, report in vcf_files_mapping if is_vcf_file(vcf)]
@@ -109,6 +111,10 @@ def get_project_and_vcf_fasta_mapping_from_metadata_json(metadata_json, mapping_
109
111
  metadata = EvaMetadataJson(metadata_json)
110
112
 
111
113
  project_title = metadata.project.get('title')
114
+ if not project_title:
115
+ project_accession = metadata.project.get('projectAccession')
116
+ if project_accession:
117
+ project_title = get_project_title_from_ena(project_accession)
112
118
 
113
119
  vcf_fasta_report_mapping = []
114
120
  if mapping_req:
@@ -168,7 +174,7 @@ def get_metadata_xlsx_template_link():
168
174
  return 'https://raw.githubusercontent.com/EBIvariation/eva-sub-cli/main/eva_sub_cli/etc/EVA_Submission_template.xlsx'
169
175
 
170
176
 
171
- def verify_metadata_xlsx_version(metadata_xlsx, min_req_version):
177
+ def verify_and_get_metadata_xlsx_version(metadata_xlsx, min_req_version):
172
178
  workbook = load_workbook(metadata_xlsx)
173
179
  instructions_sheet = workbook['PLEASE READ FIRST']
174
180
  xlsx_sheet_version_value = instructions_sheet[3][0].value
@@ -184,15 +190,27 @@ def verify_metadata_xlsx_version(metadata_xlsx, min_req_version):
184
190
  f"No version information found in metadata xlsx sheet {metadata_xlsx}. "
185
191
  f"Please download the correct template from EVA github project {get_metadata_xlsx_template_link()}")
186
192
 
193
+ return xlsx_version
187
194
 
188
- def get_project_and_vcf_fasta_mapping_from_metadata_xlsx(metadata_xlsx, mapping_req=False):
195
+
196
+ def get_project_and_vcf_fasta_mapping_from_metadata_xlsx(metadata_xlsx, metadata_xlsx_version, mapping_req=False):
189
197
  workbook = load_workbook(metadata_xlsx)
190
198
 
191
199
  project_sheet = workbook['Project']
192
200
  project_headers = {}
193
- for cell in project_sheet[1]:
194
- project_headers[cell.value] = cell.column
195
- project_title = project_sheet.cell(row=2, column=project_headers['Project Title']).value
201
+
202
+ if version.parse(metadata_xlsx_version) < version.parse('3.0.0'):
203
+ for cell in project_sheet[1]:
204
+ project_headers[cell.value] = cell.column
205
+ project_title = project_sheet.cell(row=2, column=project_headers['Project Title']).value
206
+ else:
207
+ for cell in project_sheet[3]:
208
+ project_headers[cell.value] = cell.column
209
+ project_title = project_sheet.cell(row=4, column=project_headers['Project Title']).value
210
+ if not project_title:
211
+ project_accession = project_sheet.cell(row=4, column=project_headers['Project Accession']).value
212
+ if project_accession:
213
+ project_title = get_project_title_from_ena(project_accession)
196
214
 
197
215
  vcf_fasta_report_mapping = []
198
216
  if mapping_req:
@@ -273,14 +291,15 @@ def orchestrate_process(submission_dir, vcf_files, reference_fasta, metadata_jso
273
291
 
274
292
  if metadata_json:
275
293
  metadata_json = os.path.abspath(metadata_json)
294
+ metadata_xlsx_version = None
276
295
  if metadata_xlsx:
277
296
  metadata_xlsx = os.path.abspath(metadata_xlsx)
278
297
  # check metadata xlsx version is not lower than the required min metadata template version
279
- verify_metadata_xlsx_version(metadata_xlsx, MINIMUM_METADATA_XLSX_TEMPLATE_VERSION)
298
+ metadata_xlsx_version = verify_and_get_metadata_xlsx_version(metadata_xlsx, MINIMUM_METADATA_XLSX_TEMPLATE_VERSION)
280
299
 
281
300
  # Get the provided Project Title and VCF files mapping (VCF, Fasta and Report)
282
301
  project_title, vcf_files_mapping = get_project_title_and_create_vcf_files_mapping(
283
- submission_dir, vcf_files, reference_fasta, metadata_json, metadata_xlsx
302
+ submission_dir, vcf_files, reference_fasta, metadata_json, metadata_xlsx, metadata_xlsx_version
284
303
  )
285
304
  vcf_files = get_vcf_files(vcf_files_mapping)
286
305
 
@@ -290,12 +309,13 @@ def orchestrate_process(submission_dir, vcf_files, reference_fasta, metadata_jso
290
309
  if VALIDATE in tasks:
291
310
  if executor == DOCKER:
292
311
  validator = DockerValidator(vcf_files_mapping, submission_dir, project_title, metadata_json, metadata_xlsx,
293
- shallow_validation=shallow_validation, submission_config=sub_config)
312
+ metadata_xlsx_version, shallow_validation=shallow_validation,
313
+ submission_config=sub_config)
294
314
  # default to native execution
295
315
  else:
296
316
  validator = NativeValidator(vcf_files_mapping, submission_dir, project_title, metadata_json, metadata_xlsx,
297
- shallow_validation=shallow_validation, submission_config=sub_config,
298
- nextflow_config=nextflow_config)
317
+ metadata_xlsx_version, shallow_validation=shallow_validation,
318
+ submission_config=sub_config, nextflow_config=nextflow_config)
299
319
  with validator:
300
320
  validator.validate_and_report()
301
321
  if not metadata_json:
@@ -4,12 +4,11 @@ from copy import deepcopy
4
4
  from datetime import datetime
5
5
 
6
6
  import yaml
7
- from requests import HTTPError
8
-
9
- from retry import retry
10
7
  from ebi_eva_common_pyutils.biosamples_communicators import NoAuthHALCommunicator
11
8
  from ebi_eva_common_pyutils.ena_utils import download_xml_from_ena, get_scientific_name_and_common_name
12
9
  from ebi_eva_common_pyutils.logger import AppLogger
10
+ from requests import HTTPError
11
+ from retry import retry
13
12
 
14
13
  from eva_sub_cli.date_utils import check_date
15
14
 
@@ -17,6 +16,7 @@ PROJECT_KEY = 'project'
17
16
  ANALYSIS_KEY = 'analysis'
18
17
  SAMPLE_KEY = 'sample'
19
18
  FILES_KEY = 'files'
19
+ PROJECT_ACCESSION_KEY = 'projectAccession'
20
20
  PARENT_PROJECT_KEY = 'parentProject'
21
21
  CHILD_PROJECTS_KEY = 'childProjects'
22
22
  PEER_PROJECTS_KEY = 'peerProjects'
@@ -29,7 +29,8 @@ ANALYSIS_ALIAS_KEY = 'analysisAlias'
29
29
  ANALYSIS_RUNS_KEY = 'runAccessions'
30
30
 
31
31
  # Samples created before this date are not required to have collection date or geographic location
32
- threshold_2023 = datetime(2023,1,1)
32
+ threshold_2023 = datetime(2023, 1, 1)
33
+
33
34
 
34
35
  def cast_list(l, type_to_cast=str):
35
36
  for e in l:
@@ -62,6 +63,8 @@ class SemanticMetadataChecker(AppLogger):
62
63
  def check_all_project_accessions(self):
63
64
  """Check that ENA project accessions exist and are public."""
64
65
  project = self.metadata[PROJECT_KEY]
66
+ if PROJECT_ACCESSION_KEY in project:
67
+ self.check_project_accession(project[PROJECT_ACCESSION_KEY], f'/{PROJECT_KEY}/{PROJECT_ACCESSION_KEY}')
65
68
  if PARENT_PROJECT_KEY in project:
66
69
  self.check_project_accession(project[PARENT_PROJECT_KEY], f'/{PROJECT_KEY}/{PARENT_PROJECT_KEY}')
67
70
  for idx, accession in enumerate(project.get(CHILD_PROJECTS_KEY, [])):
@@ -225,9 +228,9 @@ class SemanticMetadataChecker(AppLogger):
225
228
  def _should_bypass_error(self, sample_data, error):
226
229
  try:
227
230
  try:
228
- created_dated = datetime.strptime(sample_data['create'],'%Y-%m-%dT%H:%M:%S.%fZ')
231
+ created_dated = datetime.strptime(sample_data['create'], '%Y-%m-%dT%H:%M:%S.%fZ')
229
232
  except ValueError:
230
- created_dated = datetime.strptime(sample_data['create'],'%Y-%m-%dT%H:%M:%SZ')
233
+ created_dated = datetime.strptime(sample_data['create'], '%Y-%m-%dT%H:%M:%SZ')
231
234
  if created_dated < threshold_2023 and (
232
235
  'collection date' in error or
233
236
  'geographic location (country and/or sea)' in error
@@ -300,4 +303,5 @@ class SemanticMetadataChecker(AppLogger):
300
303
  analysis_alias = analysis.get(ANALYSIS_ALIAS_KEY)
301
304
  if analysis_alias and analysis_alias not in sample_analysis_aliases_set:
302
305
  json_path = f'/{ANALYSIS_KEY}/{idx}'
303
- self.add_error(property=json_path, description=f'No sample found for the analysis. Should have at the least one sample.')
306
+ self.add_error(property=json_path,
307
+ description=f'No sample found for the analysis. Should have at the least one sample.')
@@ -103,9 +103,10 @@ class StudySubmitter(AppLogger):
103
103
  return
104
104
 
105
105
  # upload submission
106
- self.info(f'Upload data')
106
+ self.info(f'Start Uploading data')
107
107
  self._upload_submission()
108
+ self.info(f'Data Uploaded successfully')
108
109
 
109
110
  # Complete the submission
110
- self.info(f'Complete submission')
111
111
  self._complete_submission()
112
+ self.info(f'Submission completed successfully')