ena-upload-cli 0.7.5__tar.gz → 0.8.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 (112) hide show
  1. {ena_upload_cli-0.7.5/ena_upload_cli.egg-info → ena_upload_cli-0.8.0}/PKG-INFO +18 -2
  2. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/README.md +17 -1
  3. ena_upload_cli-0.8.0/ena_upload/_version.py +1 -0
  4. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/ena_upload.py +20 -2
  5. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_PLATFORM.xml +2 -0
  6. ena_upload_cli-0.8.0/ena_upload/templates/ENA_template_READ_TYPE.xml +9 -0
  7. ena_upload_cli-0.8.0/ena_upload/templates/ENA_template_experiments.xml +86 -0
  8. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_runs.xml +22 -1
  9. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000011.xml +14 -6
  10. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000012.xml +14 -6
  11. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000013.xml +14 -6
  12. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000014.xml +14 -6
  13. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000015.xml +14 -6
  14. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000016.xml +14 -6
  15. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000017.xml +14 -6
  16. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000018.xml +14 -6
  17. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000019.xml +14 -6
  18. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000020.xml +14 -6
  19. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000021.xml +14 -6
  20. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000022.xml +14 -6
  21. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000023.xml +14 -6
  22. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000024.xml +14 -6
  23. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000025.xml +14 -6
  24. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000027.xml +14 -6
  25. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000028.xml +14 -6
  26. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000029.xml +14 -6
  27. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000030.xml +14 -6
  28. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000031.xml +14 -6
  29. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000032.xml +14 -6
  30. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000033.xml +14 -6
  31. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000034.xml +14 -6
  32. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000035.xml +14 -6
  33. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000036.xml +14 -6
  34. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000037.xml +14 -6
  35. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000038.xml +14 -6
  36. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000039.xml +14 -6
  37. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000040.xml +14 -6
  38. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000041.xml +14 -6
  39. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000043.xml +14 -6
  40. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000044.xml +14 -6
  41. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000045.xml +14 -6
  42. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000047.xml +14 -6
  43. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000048.xml +14 -6
  44. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000049.xml +14 -6
  45. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000050.xml +14 -6
  46. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000051.xml +14 -6
  47. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000052.xml +14 -6
  48. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000053.xml +14 -6
  49. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000055.xml +20 -7
  50. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000056.xml +15 -8
  51. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000057.xml +21 -7
  52. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_samples_ERC000058.xml +15 -7
  53. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_studies.xml +8 -0
  54. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/SRA.common.xsd +2 -0
  55. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0/ena_upload_cli.egg-info}/PKG-INFO +18 -2
  56. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload_cli.egg-info/SOURCES.txt +1 -0
  57. ena_upload_cli-0.7.5/ena_upload/_version.py +0 -1
  58. ena_upload_cli-0.7.5/ena_upload/templates/ENA_template_experiments.xml +0 -78
  59. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/LICENSE +0 -0
  60. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/MANIFEST.in +0 -0
  61. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/__init__.py +0 -0
  62. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/check_remote.py +0 -0
  63. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/__init__.py +0 -0
  64. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/characteristic.py +0 -0
  65. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/ena_experiment.py +0 -0
  66. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/ena_run.py +0 -0
  67. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/ena_sample.py +0 -0
  68. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/ena_std_lib.py +0 -0
  69. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/ena_study.py +0 -0
  70. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/ena_submission.py +0 -0
  71. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/assay_schema.json +0 -0
  72. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/comment_schema.json +0 -0
  73. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/data_schema.json +0 -0
  74. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/factor_schema.json +0 -0
  75. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/factor_value_schema.json +0 -0
  76. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/investigation_schema.json +0 -0
  77. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/material_attribute_schema.json +0 -0
  78. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/material_attribute_value_schema.json +0 -0
  79. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/material_schema.json +0 -0
  80. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/ontology_annotation_schema.json +0 -0
  81. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/ontology_source_reference_schema.json +0 -0
  82. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/organization_schema.json +0 -0
  83. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/person_schema.json +0 -0
  84. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/process_parameter_value_schema.json +0 -0
  85. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/process_schema.json +0 -0
  86. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/protocol_parameter_schema.json +0 -0
  87. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/protocol_schema.json +0 -0
  88. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/publication_schema.json +0 -0
  89. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/sample_schema.json +0 -0
  90. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/source_schema.json +0 -0
  91. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/json_schemas/study_schema.json +0 -0
  92. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/json_parsing/other_material.py +0 -0
  93. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA.project.xsd +0 -0
  94. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_FILE.xml +0 -0
  95. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_LIBRARY_SELECTION.xml +0 -0
  96. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_LIBRARY_SOURCE.xml +0 -0
  97. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_LIBRARY_STRATEGY.xml +0 -0
  98. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/ENA_template_submission.xml +0 -0
  99. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/SRA.experiment.xsd +0 -0
  100. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/SRA.run.xsd +0 -0
  101. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/SRA.sample.xsd +0 -0
  102. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/SRA.study.xsd +0 -0
  103. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload/templates/SRA.submission.xsd +0 -0
  104. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload_cli.egg-info/dependency_links.txt +0 -0
  105. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload_cli.egg-info/entry_points.txt +0 -0
  106. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload_cli.egg-info/requires.txt +0 -0
  107. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/ena_upload_cli.egg-info/top_level.txt +0 -0
  108. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/requirements.txt +0 -0
  109. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/setup.cfg +0 -0
  110. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/setup.py +0 -0
  111. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/tests/__init__.py +0 -0
  112. {ena_upload_cli-0.7.5 → ena_upload_cli-0.8.0}/tests/test_ena_objects.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ena-upload-cli
3
- Version: 0.7.5
3
+ Version: 0.8.0
4
4
  Summary: Command Line Interface to upload data to the European Nucleotide Archive
5
5
  Home-page: https://github.com/usegalaxy-eu/ena-upload-cli
6
6
  Author: Dilmurat Yusuf
@@ -141,6 +141,15 @@ The command line tool will automatically fetch the correct scientific name based
141
141
  | sample_alias_4 | sample_title_2 | 2697049 | Severe acute respiratory syndrome coronavirus 2 | covid-19 | sample_description_1 | 2020-10-11 | Argentina |
142
142
  | sample_alias_5 | sample_title_3 | 2697049 | Severe acute respiratory syndrome coronavirus 2 | covid-19 | sample_description_2 | 2008-01-24 | Belgium |
143
143
 
144
+ #### Custom attributes
145
+
146
+ Additional custom attributes (i.e. attributes not specified in the ERC checklist) can be added to the sample table by adding columns which headers are named like `sample_attribute[attribute_name]`; for example `sample_attribute[treatment]`, `sample_attribute[age]`... An example tsv file using custom attributes can be found in [example_tables/ENA_template_samples_xtra_attrs.tsv](/example_tables/ENA_template_samples_xtra_attrs.tsv). The same syntax is also applicable for xlsx input files.
147
+
148
+ | alias | ... | sample_attribute[treatment] | sample_attribute[age]
149
+ |----------------|----------------|---------------------|------------------------|
150
+ | sample_alias_4 | ... | treated | 2 days
151
+ | sample_alias_5 | ... | untreated | 2 days
152
+
144
153
  #### Viral submissions
145
154
 
146
155
  If you want to submit viral samples you can use the [ENA virus pathogen](https://www.ebi.ac.uk/ena/browser/view/ERC000033) checklist by adding `ERC000033` to the checklist parameter. Check out our [viral example command](#test-the-tool) as demonstration. Please use the [ENA virus pathogen](https://github.com/ELIXIR-Belgium/ENA-metadata-templates/tree/main/templates/ERC000033) checklist in our template repo to know what is allowed/possible in the `Controlled vocabulary`fields.
@@ -149,6 +158,13 @@ If you want to submit viral samples you can use the [ENA virus pathogen](https:/
149
158
 
150
159
  Please check out the [template](https://github.com/ELIXIR-Belgium/ENA-metadata-templates) of your checklist to discover which attributes are mandatory for the study, experiment and run ENA object.
151
160
 
161
+ #### Read info run attributes
162
+
163
+ Using `read_type` and `read_label` as header in the columns of ENA run objects will allow you to set information about reads. Values are listed in a comma separated way, without spaces. `read_type` has a controlled vocabulary, which can be found in the [ENA Documentation](https://ena-docs.readthedocs.io/en/latest/submit/reads/webin-cli.html#json-manifest-file-format). An example tsv file using these attributes can be found in [example_tables/ENA_template_runs_read_info.tsv](/example_tables/ENA_template_runs_read_info.tsv). The same syntax is also applicable for xlsx input files.
164
+
165
+ #### Study and experiment custom attributes
166
+
167
+ Similarly to samples, additional custom attributes can be added to the experiment and study tables by adding columns which headers are named like `experiment_attribute[attribute_name]` and `study_attribute[attribute_name]` in the experiment and study tables, respectively.
152
168
 
153
169
  ### Dev instance
154
170
 
@@ -264,7 +280,7 @@ By default the updated tables after submission will have the action `added` in t
264
280
 
265
281
  * **Release submission**
266
282
  ```
267
- ena-upload-cli --action release --center'your_center_name' --study example_tables/ENA_template_studies_release.tsv --dev --secret .secret.yml
283
+ ena-upload-cli --action release --center 'your_center_name' --study example_tables/ENA_template_studies_release.tsv --dev --secret .secret.yml
268
284
  ```
269
285
 
270
286
  > **Note for Windows users:** Windows, by default, does not support wildcard expansion in command-line arguments.
@@ -108,6 +108,15 @@ The command line tool will automatically fetch the correct scientific name based
108
108
  | sample_alias_4 | sample_title_2 | 2697049 | Severe acute respiratory syndrome coronavirus 2 | covid-19 | sample_description_1 | 2020-10-11 | Argentina |
109
109
  | sample_alias_5 | sample_title_3 | 2697049 | Severe acute respiratory syndrome coronavirus 2 | covid-19 | sample_description_2 | 2008-01-24 | Belgium |
110
110
 
111
+ #### Custom attributes
112
+
113
+ Additional custom attributes (i.e. attributes not specified in the ERC checklist) can be added to the sample table by adding columns which headers are named like `sample_attribute[attribute_name]`; for example `sample_attribute[treatment]`, `sample_attribute[age]`... An example tsv file using custom attributes can be found in [example_tables/ENA_template_samples_xtra_attrs.tsv](/example_tables/ENA_template_samples_xtra_attrs.tsv). The same syntax is also applicable for xlsx input files.
114
+
115
+ | alias | ... | sample_attribute[treatment] | sample_attribute[age]
116
+ |----------------|----------------|---------------------|------------------------|
117
+ | sample_alias_4 | ... | treated | 2 days
118
+ | sample_alias_5 | ... | untreated | 2 days
119
+
111
120
  #### Viral submissions
112
121
 
113
122
  If you want to submit viral samples you can use the [ENA virus pathogen](https://www.ebi.ac.uk/ena/browser/view/ERC000033) checklist by adding `ERC000033` to the checklist parameter. Check out our [viral example command](#test-the-tool) as demonstration. Please use the [ENA virus pathogen](https://github.com/ELIXIR-Belgium/ENA-metadata-templates/tree/main/templates/ERC000033) checklist in our template repo to know what is allowed/possible in the `Controlled vocabulary`fields.
@@ -116,6 +125,13 @@ If you want to submit viral samples you can use the [ENA virus pathogen](https:/
116
125
 
117
126
  Please check out the [template](https://github.com/ELIXIR-Belgium/ENA-metadata-templates) of your checklist to discover which attributes are mandatory for the study, experiment and run ENA object.
118
127
 
128
+ #### Read info run attributes
129
+
130
+ Using `read_type` and `read_label` as header in the columns of ENA run objects will allow you to set information about reads. Values are listed in a comma separated way, without spaces. `read_type` has a controlled vocabulary, which can be found in the [ENA Documentation](https://ena-docs.readthedocs.io/en/latest/submit/reads/webin-cli.html#json-manifest-file-format). An example tsv file using these attributes can be found in [example_tables/ENA_template_runs_read_info.tsv](/example_tables/ENA_template_runs_read_info.tsv). The same syntax is also applicable for xlsx input files.
131
+
132
+ #### Study and experiment custom attributes
133
+
134
+ Similarly to samples, additional custom attributes can be added to the experiment and study tables by adding columns which headers are named like `experiment_attribute[attribute_name]` and `study_attribute[attribute_name]` in the experiment and study tables, respectively.
119
135
 
120
136
  ### Dev instance
121
137
 
@@ -231,7 +247,7 @@ By default the updated tables after submission will have the action `added` in t
231
247
 
232
248
  * **Release submission**
233
249
  ```
234
- ena-upload-cli --action release --center'your_center_name' --study example_tables/ENA_template_studies_release.tsv --dev --secret .secret.yml
250
+ ena-upload-cli --action release --center 'your_center_name' --study example_tables/ENA_template_studies_release.tsv --dev --secret .secret.yml
235
251
  ```
236
252
 
237
253
  > **Note for Windows users:** Windows, by default, does not support wildcard expansion in command-line arguments.
@@ -0,0 +1 @@
1
+ __version__ = "0.8.0"
@@ -214,6 +214,16 @@ def generate_stream(schema, targets, Template, center, tool):
214
214
  :return: stream
215
215
  '''
216
216
 
217
+ # find all columns in targets which column header matches the pattern attribute[(.*)], extract the group
218
+ # and return a dict[header] = group
219
+ # eg for header run_attribute[sex] => {'run_attribute[sex]': 'sex'}
220
+ pattern = re.compile(rf"{schema}_attribute\[(.*)\]")
221
+ extra_attributes = {}
222
+ for column in targets.columns:
223
+ match = re.match(pattern, column)
224
+ if match:
225
+ extra_attributes[column] = match.group(1)
226
+
217
227
  if schema == 'run':
218
228
  # These attributes are required for rendering
219
229
  # the run xml templates
@@ -221,6 +231,11 @@ def generate_stream(schema, targets, Template, center, tool):
221
231
  if 'file_format' in targets:
222
232
  targets.rename(columns={'file_format': 'file_type'}, inplace=True)
223
233
  file_attrib = ['file_name', 'file_type', 'file_checksum']
234
+ if 'read_type' in targets:
235
+ file_attrib.append('read_type')
236
+ if 'read_label' in targets:
237
+ file_attrib.append('read_label')
238
+
224
239
  other_attrib = ['alias', 'experiment_alias']
225
240
  # Create groups with alias as index
226
241
  run_groups = targets[other_attrib].groupby('alias')['experiment_alias'].first().to_dict()
@@ -230,11 +245,14 @@ def generate_stream(schema, targets, Template, center, tool):
230
245
  stream = Template.generate(run_groups=run_groups,
231
246
  file_groups=file_groups,
232
247
  center=center,
248
+ extra_attributes=extra_attributes,
233
249
  tool_name=tool['tool_name'],
234
250
  tool_version=tool['tool_version'])
235
251
  else:
236
252
  stream = Template.generate(
237
- df=targets, center=center, tool_name=tool['tool_name'], tool_version=tool['tool_version'])
253
+ df=targets, center=center, extra_attributes=extra_attributes,
254
+ tool_name=tool['tool_name'], tool_version=tool['tool_version']
255
+ )
238
256
 
239
257
  return stream
240
258
 
@@ -982,7 +1000,7 @@ def main():
982
1000
  if pd.notna(row['scientific_name']) and pd.isna(row['taxon_id']):
983
1001
  # retrieve taxon id using scientific name
984
1002
  taxonID = get_taxon_id(row['scientific_name'])
985
- df.loc[index, 'taxon_id'] = taxonID
1003
+ df.loc[index, 'taxon_id'] = int(taxonID)
986
1004
  elif pd.notna(row['taxon_id']) and pd.isna(row['scientific_name']):
987
1005
  # retrieve scientific name using taxon id
988
1006
  scientificName = get_scientific_name(row['taxon_id'])
@@ -26,6 +26,7 @@
26
26
  <INSTRUMENT_MODEL py:when="row.instrument_model.lower().strip() == 'illumina miseq'">Illumina MiSeq</INSTRUMENT_MODEL>
27
27
  <INSTRUMENT_MODEL py:when="row.instrument_model.lower().strip() == 'illumina miniseq'">Illumina MiniSeq</INSTRUMENT_MODEL>
28
28
  <INSTRUMENT_MODEL py:when="row.instrument_model.lower().strip() == 'illumina novaseq x'">Illumina NovaSeq X</INSTRUMENT_MODEL>
29
+ <INSTRUMENT_MODEL py:when="row.instrument_model.lower().strip() == 'illumina novaseq x plus'">Illumina NovaSeq X Plus</INSTRUMENT_MODEL>
29
30
  <INSTRUMENT_MODEL py:when="row.instrument_model.lower().strip() == 'illumina novaseq 6000'">Illumina NovaSeq 6000</INSTRUMENT_MODEL>
30
31
  <INSTRUMENT_MODEL py:when="row.instrument_model.lower().strip() == 'nextseq 500'">NextSeq 500</INSTRUMENT_MODEL>
31
32
  <INSTRUMENT_MODEL py:when="row.instrument_model.lower().strip() == 'nextseq 550'">NextSeq 550</INSTRUMENT_MODEL>
@@ -101,6 +102,7 @@
101
102
  <INSTRUMENT_MODEL py:when="row.instrument_model.lower().strip() == 'dnbseq-g400'">DNBSEQ-G400</INSTRUMENT_MODEL>
102
103
  <INSTRUMENT_MODEL py:when="row.instrument_model.lower().strip() == 'dnbseq-g50'">DNBSEQ-G50</INSTRUMENT_MODEL>
103
104
  <INSTRUMENT_MODEL py:when="row.instrument_model.lower().strip() == 'dnbseq-g400 fast'">DNBSEQ-G400 FAST</INSTRUMENT_MODEL>
105
+ <INSTRUMENT_MODEL py:when="row.instrument_model.lower().strip() == 'dnbseq-t10x4rs'">DNBSEQ-T10x4RS</INSTRUMENT_MODEL>
104
106
  <INSTRUMENT_MODEL py:when="row.instrument_model.lower().strip() == 'unspecified'">unspecified</INSTRUMENT_MODEL>
105
107
  </DNBSEQ>
106
108
  <ELEMENT py:when="row.platform.lower().strip() == 'element'" py:choose="">
@@ -0,0 +1,9 @@
1
+ <py:choose xmlns:py="http://genshi.edgewall.org/" test="">
2
+ <READ_TYPE py:when="rtype.strip().lower() == 'single'">single</READ_TYPE>
3
+ <READ_TYPE py:when="rtype.strip().lower() == 'paired'">paired</READ_TYPE>
4
+ <READ_TYPE py:when="rtype.strip().lower() == 'cell_barcode'">cell_barcode</READ_TYPE>
5
+ <READ_TYPE py:when="rtype.strip().lower() == 'umi_barcode'">umi_barcode</READ_TYPE>
6
+ <READ_TYPE py:when="rtype.strip().lower() == 'feature_barcode'">feature_barcode</READ_TYPE>
7
+ <READ_TYPE py:when="rtype.strip().lower() == 'sample_barcode'">sample_barcode</READ_TYPE>
8
+ <READ_TYPE py:when="rtype.strip().lower() == 'spatial_barcode'">spatial_barcode</READ_TYPE>
9
+ </py:choose>
@@ -0,0 +1,86 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <?python
3
+ import pandas as pd
4
+ import sys
5
+ def attributetest(row, column):
6
+ if hasattr(row, column) and pd.notna(row[column]) and not str(row[column]).isspace():
7
+ return True
8
+ def mandatorytest(row, column, index):
9
+ if hasattr(row, column) and pd.notna(row[column]) and not str(row[column]).isspace():
10
+ return True
11
+ else:
12
+ print("MISSING VALUE ERROR: The mandatory column '"+ str(column) + "' is not filled in at row '" + str(index) + "'" + "\n")
13
+ sys.exit("This process is terminated")
14
+ ?>
15
+ <EXPERIMENT_SET xmlns:py="http://genshi.edgewall.org/"
16
+ xmlns:xi="http://www.w3.org/2001/XInclude"
17
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
18
+ xsi:noNamespaceSchemaLocation="ftp://ftp.sra.ebi.ac.uk/meta/xsd/sra_1_6/SRA.experiment.xsd">
19
+ <py:for each="index, row in df.iterrows()">
20
+ <EXPERIMENT alias="${row.alias}" center_name="${center}">
21
+ <py:if test="mandatorytest(row, 'title', index)">
22
+ <TITLE>${row.title}</TITLE>
23
+ </py:if>
24
+ <py:if test="mandatorytest(row, 'study_alias', index)">
25
+ <STUDY_REF refname="${row.study_alias}"/>
26
+ </py:if>
27
+ <DESIGN>
28
+ <py:if test="mandatorytest(row, 'design_description', index)">
29
+ <DESIGN_DESCRIPTION>${row.design_description}</DESIGN_DESCRIPTION>
30
+ </py:if>
31
+ <py:if test="attributetest(row, 'spot_descriptor')">
32
+ <SPOT_DESCRIPTOR>${row.spot_descriptor}</SPOT_DESCRIPTOR>
33
+ </py:if>
34
+ <py:if test="mandatorytest(row, 'sample_alias', index)">
35
+ <SAMPLE_DESCRIPTOR refname="${row.sample_alias}"/>
36
+ </py:if>
37
+ <LIBRARY_DESCRIPTOR>
38
+ <py:if test="attributetest(row, 'library_name')">
39
+ <LIBRARY_NAME>${row.library_name}</LIBRARY_NAME>
40
+ </py:if>
41
+ <py:if test="mandatorytest(row, 'library_strategy', index)">
42
+ <xi:include href="ENA_template_LIBRARY_STRATEGY.xml" />
43
+ </py:if>
44
+ <py:if test="mandatorytest(row, 'library_source', index)">
45
+ <xi:include href="ENA_template_LIBRARY_SOURCE.xml" />
46
+ </py:if>
47
+ <py:if test="mandatorytest(row, 'library_selection', index)">
48
+ <xi:include href="ENA_template_LIBRARY_SELECTION.xml" />
49
+ </py:if>
50
+ <py:if test="mandatorytest(row, 'library_layout', index)">
51
+ <LIBRARY_LAYOUT py:choose="">
52
+ <PAIRED py:when="row.library_layout.lower().strip() == 'paired'" NOMINAL_LENGTH="${int(row.insert_size)}" />
53
+ <SINGLE py:when="row.library_layout.lower().strip() == 'single'" />
54
+ </LIBRARY_LAYOUT>
55
+ </py:if>
56
+ <py:if test="attributetest(row, 'library_construction_protocol')">
57
+ <LIBRARY_CONSTRUCTION_PROTOCOL>${row.library_construction_protocol}</LIBRARY_CONSTRUCTION_PROTOCOL>
58
+ </py:if>
59
+ </LIBRARY_DESCRIPTOR>
60
+ </DESIGN>
61
+ <py:if test="mandatorytest(row, 'platform', index)">
62
+ <py:if test="mandatorytest(row, 'instrument_model', index)">
63
+ <xi:include href="ENA_template_PLATFORM.xml" />
64
+ </py:if>
65
+ </py:if>
66
+ <EXPERIMENT_ATTRIBUTES>
67
+ <py:for each="header, tag in extra_attributes.items()">
68
+ <py:if test="attributetest(row, header)">
69
+ <EXPERIMENT_ATTRIBUTE>
70
+ <TAG>${tag}</TAG>
71
+ <VALUE>${row[header]}</VALUE>
72
+ </EXPERIMENT_ATTRIBUTE>
73
+ </py:if>
74
+ </py:for>
75
+ <EXPERIMENT_ATTRIBUTE>
76
+ <TAG>SUBMISSION_TOOL</TAG>
77
+ <VALUE>${tool_name}</VALUE>
78
+ </EXPERIMENT_ATTRIBUTE>
79
+ <EXPERIMENT_ATTRIBUTE>
80
+ <TAG>SUBMISSION_TOOL_VERSION</TAG>
81
+ <VALUE>${tool_version}</VALUE>
82
+ </EXPERIMENT_ATTRIBUTE>
83
+ </EXPERIMENT_ATTRIBUTES>
84
+ </EXPERIMENT>
85
+ </py:for>
86
+ </EXPERIMENT_SET>
@@ -2,6 +2,9 @@
2
2
  <?python
3
3
  import pandas as pd
4
4
  import sys
5
+ def attributetest(row, column):
6
+ if hasattr(row, column) and pd.notna(row[column]) and not str(row[column]).isspace():
7
+ return True
5
8
  def mandatorytest(row, column, index):
6
9
  if hasattr(row, column) and pd.notna(row[column]) and not str(row[column]).isspace():
7
10
  return True
@@ -20,7 +23,25 @@ def mandatorytest(row, column, index):
20
23
  <FILES>
21
24
  <py:for each="index, row in file_groups.get_group(alias).iterrows()">
22
25
  <py:if test="mandatorytest(row, 'file_type', index)">
23
- <xi:include href="ENA_template_FILE.xml" />
26
+ <py:choose xmlns:py="http://genshi.edgewall.org/" test="">
27
+ <py:when test="row.file_type.lower().strip() == 'fastq'">
28
+ <FILE filename="${row.file_name}" filetype="fastq" checksum_method="MD5" checksum="${row.file_checksum}">
29
+ <py:if test="attributetest(row, 'read_label')">
30
+ <py:for each="rlabel in row.read_label.split(',')">
31
+ <READ_LABEL>${rlabel.strip()}</READ_LABEL>
32
+ </py:for>
33
+ </py:if>
34
+ <py:if test="attributetest(row, 'read_type')">
35
+ <py:for each="rtype in row.read_type.split(',')">
36
+ <xi:include href="ENA_template_READ_TYPE.xml" />
37
+ </py:for>
38
+ </py:if>
39
+ </FILE>
40
+ </py:when>
41
+ <py:otherwise>
42
+ <xi:include href="ENA_template_FILE.xml" />
43
+ </py:otherwise>
44
+ </py:choose>
24
45
  </py:if>
25
46
  </py:for>
26
47
  </FILES>
@@ -87,12 +87,6 @@ def mandatorytest(row, column, index):
87
87
  <VALUE>${row['collection date']}</VALUE>
88
88
  </SAMPLE_ATTRIBUTE>
89
89
  </py:if>
90
- <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
91
- <SAMPLE_ATTRIBUTE>
92
- <TAG>geographic location (country and/or sea)</TAG>
93
- <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
94
- </SAMPLE_ATTRIBUTE>
95
- </py:if>
96
90
  <py:if test="attributetest(row, 'geographic location (region and locality)')">
97
91
  <SAMPLE_ATTRIBUTE>
98
92
  <TAG>geographic location (region and locality)</TAG>
@@ -123,6 +117,12 @@ def mandatorytest(row, column, index):
123
117
  <VALUE>${row['sex']}</VALUE>
124
118
  </SAMPLE_ATTRIBUTE>
125
119
  </py:if>
120
+ <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
121
+ <SAMPLE_ATTRIBUTE>
122
+ <TAG>geographic location (country and/or sea)</TAG>
123
+ <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
124
+ </SAMPLE_ATTRIBUTE>
125
+ </py:if>
126
126
  <py:if test="attributetest(row, 'lab_host')">
127
127
  <SAMPLE_ATTRIBUTE>
128
128
  <TAG>lab_host</TAG>
@@ -213,6 +213,14 @@ def mandatorytest(row, column, index):
213
213
  <VALUE>${row['strain']}</VALUE>
214
214
  </SAMPLE_ATTRIBUTE>
215
215
  </py:if>
216
+ <py:for each="header, tag in extra_attributes.items()">
217
+ <py:if test="attributetest(row, header)">
218
+ <SAMPLE_ATTRIBUTE>
219
+ <TAG>${tag}</TAG>
220
+ <VALUE>${row[header]}</VALUE>
221
+ </SAMPLE_ATTRIBUTE>
222
+ </py:if>
223
+ </py:for>
216
224
  <SAMPLE_ATTRIBUTE>
217
225
  <TAG>SUBMISSION_TOOL</TAG>
218
226
  <VALUE>${tool_name}</VALUE>
@@ -179,12 +179,6 @@ def mandatorytest(row, column, index):
179
179
  <UNITS>m</UNITS>
180
180
  </SAMPLE_ATTRIBUTE>
181
181
  </py:if>
182
- <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
183
- <SAMPLE_ATTRIBUTE>
184
- <TAG>geographic location (country and/or sea)</TAG>
185
- <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
186
- </SAMPLE_ATTRIBUTE>
187
- </py:if>
188
182
  <py:if test="mandatorytest(row, 'geographic location (latitude)', index)">
189
183
  <SAMPLE_ATTRIBUTE>
190
184
  <TAG>geographic location (latitude)</TAG>
@@ -262,6 +256,12 @@ def mandatorytest(row, column, index):
262
256
  <VALUE>${row['sample storage duration']}</VALUE>
263
257
  </SAMPLE_ATTRIBUTE>
264
258
  </py:if>
259
+ <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
260
+ <SAMPLE_ATTRIBUTE>
261
+ <TAG>geographic location (country and/or sea)</TAG>
262
+ <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
263
+ </SAMPLE_ATTRIBUTE>
264
+ </py:if>
265
265
  <py:if test="attributetest(row, 'host disease status')">
266
266
  <SAMPLE_ATTRIBUTE>
267
267
  <TAG>host disease status</TAG>
@@ -516,6 +516,14 @@ def mandatorytest(row, column, index):
516
516
  <VALUE>${row['chemical administration']}</VALUE>
517
517
  </SAMPLE_ATTRIBUTE>
518
518
  </py:if>
519
+ <py:for each="header, tag in extra_attributes.items()">
520
+ <py:if test="attributetest(row, header)">
521
+ <SAMPLE_ATTRIBUTE>
522
+ <TAG>${tag}</TAG>
523
+ <VALUE>${row[header]}</VALUE>
524
+ </SAMPLE_ATTRIBUTE>
525
+ </py:if>
526
+ </py:for>
519
527
  <SAMPLE_ATTRIBUTE>
520
528
  <TAG>SUBMISSION_TOOL</TAG>
521
529
  <VALUE>${tool_name}</VALUE>
@@ -203,12 +203,6 @@ def mandatorytest(row, column, index):
203
203
  <UNITS>m</UNITS>
204
204
  </SAMPLE_ATTRIBUTE>
205
205
  </py:if>
206
- <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
207
- <SAMPLE_ATTRIBUTE>
208
- <TAG>geographic location (country and/or sea)</TAG>
209
- <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
210
- </SAMPLE_ATTRIBUTE>
211
- </py:if>
212
206
  <py:if test="mandatorytest(row, 'geographic location (latitude)', index)">
213
207
  <SAMPLE_ATTRIBUTE>
214
208
  <TAG>geographic location (latitude)</TAG>
@@ -285,6 +279,12 @@ def mandatorytest(row, column, index):
285
279
  <VALUE>${row['sample storage duration']}</VALUE>
286
280
  </SAMPLE_ATTRIBUTE>
287
281
  </py:if>
282
+ <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
283
+ <SAMPLE_ATTRIBUTE>
284
+ <TAG>geographic location (country and/or sea)</TAG>
285
+ <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
286
+ </SAMPLE_ATTRIBUTE>
287
+ </py:if>
288
288
  <py:if test="attributetest(row, 'host disease status')">
289
289
  <SAMPLE_ATTRIBUTE>
290
290
  <TAG>host disease status</TAG>
@@ -645,6 +645,14 @@ def mandatorytest(row, column, index):
645
645
  <VALUE>${row['chemical administration']}</VALUE>
646
646
  </SAMPLE_ATTRIBUTE>
647
647
  </py:if>
648
+ <py:for each="header, tag in extra_attributes.items()">
649
+ <py:if test="attributetest(row, header)">
650
+ <SAMPLE_ATTRIBUTE>
651
+ <TAG>${tag}</TAG>
652
+ <VALUE>${row[header]}</VALUE>
653
+ </SAMPLE_ATTRIBUTE>
654
+ </py:if>
655
+ </py:for>
648
656
  <SAMPLE_ATTRIBUTE>
649
657
  <TAG>SUBMISSION_TOOL</TAG>
650
658
  <VALUE>${tool_name}</VALUE>
@@ -203,12 +203,6 @@ def mandatorytest(row, column, index):
203
203
  <UNITS>m</UNITS>
204
204
  </SAMPLE_ATTRIBUTE>
205
205
  </py:if>
206
- <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
207
- <SAMPLE_ATTRIBUTE>
208
- <TAG>geographic location (country and/or sea)</TAG>
209
- <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
210
- </SAMPLE_ATTRIBUTE>
211
- </py:if>
212
206
  <py:if test="mandatorytest(row, 'geographic location (latitude)', index)">
213
207
  <SAMPLE_ATTRIBUTE>
214
208
  <TAG>geographic location (latitude)</TAG>
@@ -273,6 +267,12 @@ def mandatorytest(row, column, index):
273
267
  <VALUE>${row['sample storage duration']}</VALUE>
274
268
  </SAMPLE_ATTRIBUTE>
275
269
  </py:if>
270
+ <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
271
+ <SAMPLE_ATTRIBUTE>
272
+ <TAG>geographic location (country and/or sea)</TAG>
273
+ <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
274
+ </SAMPLE_ATTRIBUTE>
275
+ </py:if>
276
276
  <py:if test="attributetest(row, 'nose/mouth/teeth/throat disorder')">
277
277
  <SAMPLE_ATTRIBUTE>
278
278
  <TAG>nose/mouth/teeth/throat disorder</TAG>
@@ -667,6 +667,14 @@ def mandatorytest(row, column, index):
667
667
  <VALUE>${row['chemical administration']}</VALUE>
668
668
  </SAMPLE_ATTRIBUTE>
669
669
  </py:if>
670
+ <py:for each="header, tag in extra_attributes.items()">
671
+ <py:if test="attributetest(row, header)">
672
+ <SAMPLE_ATTRIBUTE>
673
+ <TAG>${tag}</TAG>
674
+ <VALUE>${row[header]}</VALUE>
675
+ </SAMPLE_ATTRIBUTE>
676
+ </py:if>
677
+ </py:for>
670
678
  <SAMPLE_ATTRIBUTE>
671
679
  <TAG>SUBMISSION_TOOL</TAG>
672
680
  <VALUE>${tool_name}</VALUE>
@@ -191,12 +191,6 @@ def mandatorytest(row, column, index):
191
191
  <UNITS>m</UNITS>
192
192
  </SAMPLE_ATTRIBUTE>
193
193
  </py:if>
194
- <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
195
- <SAMPLE_ATTRIBUTE>
196
- <TAG>geographic location (country and/or sea)</TAG>
197
- <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
198
- </SAMPLE_ATTRIBUTE>
199
- </py:if>
200
194
  <py:if test="mandatorytest(row, 'geographic location (latitude)', index)">
201
195
  <SAMPLE_ATTRIBUTE>
202
196
  <TAG>geographic location (latitude)</TAG>
@@ -261,6 +255,12 @@ def mandatorytest(row, column, index):
261
255
  <VALUE>${row['sample storage duration']}</VALUE>
262
256
  </SAMPLE_ATTRIBUTE>
263
257
  </py:if>
258
+ <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
259
+ <SAMPLE_ATTRIBUTE>
260
+ <TAG>geographic location (country and/or sea)</TAG>
261
+ <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
262
+ </SAMPLE_ATTRIBUTE>
263
+ </py:if>
264
264
  <py:if test="attributetest(row, 'gastrointestinal tract disorder')">
265
265
  <SAMPLE_ATTRIBUTE>
266
266
  <TAG>gastrointestinal tract disorder</TAG>
@@ -564,6 +564,14 @@ def mandatorytest(row, column, index):
564
564
  <VALUE>${row['chemical administration']}</VALUE>
565
565
  </SAMPLE_ATTRIBUTE>
566
566
  </py:if>
567
+ <py:for each="header, tag in extra_attributes.items()">
568
+ <py:if test="attributetest(row, header)">
569
+ <SAMPLE_ATTRIBUTE>
570
+ <TAG>${tag}</TAG>
571
+ <VALUE>${row[header]}</VALUE>
572
+ </SAMPLE_ATTRIBUTE>
573
+ </py:if>
574
+ </py:for>
567
575
  <SAMPLE_ATTRIBUTE>
568
576
  <TAG>SUBMISSION_TOOL</TAG>
569
577
  <VALUE>${tool_name}</VALUE>
@@ -197,12 +197,6 @@ def mandatorytest(row, column, index):
197
197
  <UNITS>m</UNITS>
198
198
  </SAMPLE_ATTRIBUTE>
199
199
  </py:if>
200
- <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
201
- <SAMPLE_ATTRIBUTE>
202
- <TAG>geographic location (country and/or sea)</TAG>
203
- <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
204
- </SAMPLE_ATTRIBUTE>
205
- </py:if>
206
200
  <py:if test="mandatorytest(row, 'geographic location (latitude)', index)">
207
201
  <SAMPLE_ATTRIBUTE>
208
202
  <TAG>geographic location (latitude)</TAG>
@@ -267,6 +261,12 @@ def mandatorytest(row, column, index):
267
261
  <VALUE>${row['sample storage duration']}</VALUE>
268
262
  </SAMPLE_ATTRIBUTE>
269
263
  </py:if>
264
+ <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
265
+ <SAMPLE_ATTRIBUTE>
266
+ <TAG>geographic location (country and/or sea)</TAG>
267
+ <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
268
+ </SAMPLE_ATTRIBUTE>
269
+ </py:if>
270
270
  <py:if test="attributetest(row, 'nose/mouth/teeth/throat disorder')">
271
271
  <SAMPLE_ATTRIBUTE>
272
272
  <TAG>nose/mouth/teeth/throat disorder</TAG>
@@ -565,6 +565,14 @@ def mandatorytest(row, column, index):
565
565
  <VALUE>${row['chemical administration']}</VALUE>
566
566
  </SAMPLE_ATTRIBUTE>
567
567
  </py:if>
568
+ <py:for each="header, tag in extra_attributes.items()">
569
+ <py:if test="attributetest(row, header)">
570
+ <SAMPLE_ATTRIBUTE>
571
+ <TAG>${tag}</TAG>
572
+ <VALUE>${row[header]}</VALUE>
573
+ </SAMPLE_ATTRIBUTE>
574
+ </py:if>
575
+ </py:for>
568
576
  <SAMPLE_ATTRIBUTE>
569
577
  <TAG>SUBMISSION_TOOL</TAG>
570
578
  <VALUE>${tool_name}</VALUE>
@@ -191,12 +191,6 @@ def mandatorytest(row, column, index):
191
191
  <UNITS>m</UNITS>
192
192
  </SAMPLE_ATTRIBUTE>
193
193
  </py:if>
194
- <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
195
- <SAMPLE_ATTRIBUTE>
196
- <TAG>geographic location (country and/or sea)</TAG>
197
- <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
198
- </SAMPLE_ATTRIBUTE>
199
- </py:if>
200
194
  <py:if test="mandatorytest(row, 'geographic location (latitude)', index)">
201
195
  <SAMPLE_ATTRIBUTE>
202
196
  <TAG>geographic location (latitude)</TAG>
@@ -261,6 +255,12 @@ def mandatorytest(row, column, index):
261
255
  <VALUE>${row['sample storage duration']}</VALUE>
262
256
  </SAMPLE_ATTRIBUTE>
263
257
  </py:if>
258
+ <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
259
+ <SAMPLE_ATTRIBUTE>
260
+ <TAG>geographic location (country and/or sea)</TAG>
261
+ <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
262
+ </SAMPLE_ATTRIBUTE>
263
+ </py:if>
264
264
  <py:if test="attributetest(row, 'dermatology disorder')">
265
265
  <SAMPLE_ATTRIBUTE>
266
266
  <TAG>dermatology disorder</TAG>
@@ -565,6 +565,14 @@ def mandatorytest(row, column, index):
565
565
  <VALUE>${row['chemical administration']}</VALUE>
566
566
  </SAMPLE_ATTRIBUTE>
567
567
  </py:if>
568
+ <py:for each="header, tag in extra_attributes.items()">
569
+ <py:if test="attributetest(row, header)">
570
+ <SAMPLE_ATTRIBUTE>
571
+ <TAG>${tag}</TAG>
572
+ <VALUE>${row[header]}</VALUE>
573
+ </SAMPLE_ATTRIBUTE>
574
+ </py:if>
575
+ </py:for>
568
576
  <SAMPLE_ATTRIBUTE>
569
577
  <TAG>SUBMISSION_TOOL</TAG>
570
578
  <VALUE>${tool_name}</VALUE>
@@ -191,12 +191,6 @@ def mandatorytest(row, column, index):
191
191
  <UNITS>m</UNITS>
192
192
  </SAMPLE_ATTRIBUTE>
193
193
  </py:if>
194
- <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
195
- <SAMPLE_ATTRIBUTE>
196
- <TAG>geographic location (country and/or sea)</TAG>
197
- <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
198
- </SAMPLE_ATTRIBUTE>
199
- </py:if>
200
194
  <py:if test="mandatorytest(row, 'geographic location (latitude)', index)">
201
195
  <SAMPLE_ATTRIBUTE>
202
196
  <TAG>geographic location (latitude)</TAG>
@@ -261,6 +255,12 @@ def mandatorytest(row, column, index):
261
255
  <VALUE>${row['sample storage duration']}</VALUE>
262
256
  </SAMPLE_ATTRIBUTE>
263
257
  </py:if>
258
+ <py:if test="mandatorytest(row, 'geographic location (country and/or sea)', index)">
259
+ <SAMPLE_ATTRIBUTE>
260
+ <TAG>geographic location (country and/or sea)</TAG>
261
+ <VALUE>${row['geographic location (country and/or sea)']}</VALUE>
262
+ </SAMPLE_ATTRIBUTE>
263
+ </py:if>
264
264
  <py:if test="attributetest(row, 'gynecological disorder')">
265
265
  <SAMPLE_ATTRIBUTE>
266
266
  <TAG>gynecological disorder</TAG>
@@ -613,6 +613,14 @@ def mandatorytest(row, column, index):
613
613
  <VALUE>${row['chemical administration']}</VALUE>
614
614
  </SAMPLE_ATTRIBUTE>
615
615
  </py:if>
616
+ <py:for each="header, tag in extra_attributes.items()">
617
+ <py:if test="attributetest(row, header)">
618
+ <SAMPLE_ATTRIBUTE>
619
+ <TAG>${tag}</TAG>
620
+ <VALUE>${row[header]}</VALUE>
621
+ </SAMPLE_ATTRIBUTE>
622
+ </py:if>
623
+ </py:for>
616
624
  <SAMPLE_ATTRIBUTE>
617
625
  <TAG>SUBMISSION_TOOL</TAG>
618
626
  <VALUE>${tool_name}</VALUE>