@orcabus/platform-cdk-constructs 0.0.6 → 0.0.7-alpha.3

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 (83) hide show
  1. package/.jsii +858 -6
  2. package/api-gateway/api-gateway.js +22 -4
  3. package/deployment-stack-pipeline/pipeline.js +6 -4
  4. package/dynamodb/config.d.ts +3 -0
  5. package/dynamodb/config.js +7 -0
  6. package/dynamodb/index.d.ts +27 -0
  7. package/dynamodb/index.js +106 -0
  8. package/ecs/config.d.ts +4 -0
  9. package/ecs/config.js +8 -0
  10. package/ecs/index.d.ts +46 -0
  11. package/ecs/index.js +103 -0
  12. package/index.d.ts +5 -2
  13. package/index.js +47 -5
  14. package/index.ts +16 -2
  15. package/lambda/build_python/Dockerfile +60 -0
  16. package/lambda/config.d.ts +11 -0
  17. package/lambda/config.js +19 -0
  18. package/lambda/index.d.ts +59 -0
  19. package/lambda/index.js +242 -0
  20. package/lambda/layers/mart_tools/poetry.lock +303 -0
  21. package/lambda/layers/mart_tools/pyproject.toml +27 -0
  22. package/lambda/layers/mart_tools/src/mart_tools/__init__.py +0 -0
  23. package/lambda/layers/mart_tools/src/mart_tools/mart/__init__.py +8 -0
  24. package/lambda/layers/mart_tools/src/mart_tools/mart/aws_helpers.py +79 -0
  25. package/lambda/layers/mart_tools/src/mart_tools/mart/dataframe_helpers.py +29 -0
  26. package/lambda/layers/mart_tools/src/mart_tools/mart/globals.py +5 -0
  27. package/lambda/layers/mart_tools/src/mart_tools/mart/models.py +71 -0
  28. package/lambda/layers/orcabus_api_tools/poetry.lock +273 -0
  29. package/lambda/layers/orcabus_api_tools/pyproject.toml +27 -0
  30. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/__init__.py +0 -0
  31. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/__init__.py +172 -0
  32. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/create_helpers.py +47 -0
  33. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/globals.py +13 -0
  34. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/job_helpers.py +53 -0
  35. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/models.py +253 -0
  36. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/query_helpers.py +248 -0
  37. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/update_helpers.py +221 -0
  38. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/workflow_helpers.py +25 -0
  39. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/__init__.py +92 -0
  40. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/create_helpers.py +27 -0
  41. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/globals.py +21 -0
  42. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/models.py +51 -0
  43. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/query_helpers.py +52 -0
  44. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/update_helpers.py +45 -0
  45. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/__init__.py +98 -0
  46. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/errors.py +45 -0
  47. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/file_helpers.py +341 -0
  48. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/globals.py +70 -0
  49. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/models.py +59 -0
  50. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/__init__.py +8 -0
  51. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/aws_helpers.py +79 -0
  52. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/dataframe_helpers.py +29 -0
  53. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/globals.py +5 -0
  54. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/models.py +71 -0
  55. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/__init__.py +250 -0
  56. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/contact_helpers.py +109 -0
  57. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/errors.py +104 -0
  58. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/globals.py +16 -0
  59. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/individual_helpers.py +139 -0
  60. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/library_helpers.py +196 -0
  61. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/lims_helpers.py +36 -0
  62. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/models.py +112 -0
  63. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/project_helpers.py +129 -0
  64. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/sample_helpers.py +132 -0
  65. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/subject_helpers.py +151 -0
  66. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/__init__.py +15 -0
  67. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/globals.py +2 -0
  68. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/models.py +44 -0
  69. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/sequence_helpers.py +62 -0
  70. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/__init__.py +0 -0
  71. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/aws_helpers.py +123 -0
  72. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/miscell.py +17 -0
  73. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/requests_helpers.py +163 -0
  74. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/__init__.py +0 -0
  75. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/errors.py +37 -0
  76. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/metadata_helpers.py +28 -0
  77. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/models.py +85 -0
  78. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/payload_helpers.py +64 -0
  79. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/workflow_run_helpers.py +80 -0
  80. package/package.json +13 -7
  81. package/typedoc.json +3 -0
  82. package/utils/index.d.ts +3 -0
  83. package/utils/index.js +50 -1
@@ -0,0 +1,250 @@
1
+ #!/usr/bin/env python3
2
+ from functools import reduce
3
+ from itertools import batched
4
+ from operator import concat
5
+ # Standard imports
6
+ from typing import Dict, List, Any
7
+ from urllib.error import HTTPError
8
+
9
+ # Util imports
10
+ from ..utils.requests_helpers import (
11
+ get_request_response_results, get_url
12
+ )
13
+
14
+ # Local imports
15
+ from .globals import METADATA_SUBDOMAIN_NAME
16
+
17
+
18
+ def get_metadata_url(endpoint: str) -> str:
19
+ """
20
+ Get the URL for the Metadata endpoint
21
+ :param endpoint:
22
+ :return:
23
+ """
24
+ return get_url(
25
+ endpoint,
26
+ METADATA_SUBDOMAIN_NAME
27
+ )
28
+
29
+
30
+ def get_metadata_request_response_results(
31
+ endpoint: str,
32
+ params: Dict = None,
33
+ ):
34
+ return get_request_response_results(get_metadata_url(endpoint), params=params)
35
+
36
+
37
+ def get_item_objs_from_item_id_list(
38
+ item_id_list: List[str],
39
+ item_identifier: str,
40
+ endpoint: str,
41
+ accept_missing=False
42
+ ) -> List[Dict[str, Any]]:
43
+
44
+ # Get query list
45
+ try:
46
+ query_list = get_metadata_request_response_results(
47
+ endpoint,
48
+ {
49
+ item_identifier: item_id_list
50
+ }
51
+ )
52
+ except HTTPError as e:
53
+ raise HTTPError(f"Could not get item from item id list {item_id_list} from endpoint {endpoint}") from e
54
+
55
+ # Accept missing
56
+ if accept_missing:
57
+ return query_list
58
+
59
+ try:
60
+ assert len(query_list) == len(item_id_list)
61
+ except AssertionError:
62
+ # If we don't find all the items, we need to raise an error
63
+ item_ids_response = list(map(
64
+ lambda item_id_response_iter_: item_id_response_iter_[item_identifier],
65
+ query_list
66
+ ))
67
+ missing_items_list = list(set(item_id_list) - set(item_ids_response))
68
+ raise ValueError(f"Some items were not found in the response, {missing_items_list}")
69
+ return query_list
70
+
71
+
72
+ def get_item_from_item_id_list_batched(
73
+ item_id_list: List[str],
74
+ item_identifier: str,
75
+ endpoint: str,
76
+ accept_missing: bool = False,
77
+ batch_size: int = 50
78
+ ) -> List[Dict[str: Any]]:
79
+ """
80
+ Get items from a list of item ids
81
+ We batch the requests to avoid hitting the API limits
82
+ :param item_id_list:
83
+ :param item_identifier:
84
+ :param endpoint:
85
+ :param accept_missing:
86
+ :param batch_size:
87
+ :return:
88
+ """
89
+ item_id_lists = batched(item_id_list, batch_size)
90
+
91
+ # Get the items from the list of item ids
92
+ try:
93
+ return list(reduce(
94
+ concat,
95
+ list(map(
96
+ lambda item_batch_: (
97
+ get_item_objs_from_item_id_list(
98
+ item_id_list=item_batch_,
99
+ item_identifier=item_identifier,
100
+ endpoint=endpoint,
101
+ accept_missing=accept_missing
102
+ )
103
+ ),
104
+ item_id_lists
105
+ ))
106
+ ))
107
+ except TypeError as e:
108
+ # TypeError: reduce() of empty sequence with no initial value
109
+ return []
110
+
111
+ # Determine all the public classes and functions
112
+ # that should be available for import
113
+
114
+ from .contact_helpers import (
115
+ get_contact_from_contact_id,
116
+ get_contacts_list_from_contact_id_list,
117
+ get_contact_orcabus_id_from_contact_id,
118
+ get_contact_from_contact_orcabus_id,
119
+ get_contacts_list_from_contact_orcabus_id_list,
120
+ coerce_contact_id_or_orcabus_id_to_contact_orcabus_id,
121
+ get_all_contacts,
122
+ )
123
+
124
+ from .individual_helpers import (
125
+ get_individual_from_individual_id,
126
+ get_individuals_list_from_individual_id_list,
127
+ get_individual_orcabus_id_from_individual_id,
128
+ get_individual_from_individual_orcabus_id,
129
+ get_individuals_list_from_individual_orcabus_id_list,
130
+ coerce_individual_id_or_orcabus_id_to_individual_orcabus_id,
131
+ get_all_individuals,
132
+ list_libraries_in_individual,
133
+ )
134
+
135
+ from .library_helpers import (
136
+ get_library_from_library_id,
137
+ get_libraries_list_from_library_id_list,
138
+ get_library_orcabus_id_from_library_id,
139
+ get_library_id_from_library_orcabus_id,
140
+ coerce_library_id_or_orcabus_id_to_library_orcabus_id,
141
+ get_library_from_library_orcabus_id,
142
+ get_libraries_from_library_orcabus_id_list,
143
+ get_subject_from_library_id,
144
+ get_library_type,
145
+ get_library_assay_type,
146
+ get_library_phenotype,
147
+ get_library_workflow,
148
+ get_all_libraries
149
+ )
150
+
151
+ from .project_helpers import (
152
+ get_project_from_project_id,
153
+ get_projects_list_from_project_id_list,
154
+ get_project_orcabus_id_from_project_id,
155
+ coerce_project_id_or_orcabus_id_to_project_orcabus_id,
156
+ get_project_from_project_orcabus_id,
157
+ get_projects_list_from_project_orcabus_id_list,
158
+ get_all_projects,
159
+ list_libraries_in_project,
160
+ )
161
+
162
+ from .sample_helpers import (
163
+ get_sample_from_sample_id,
164
+ get_samples_list_from_sample_id_list,
165
+ get_sample_orcabus_id_from_sample_id,
166
+ get_sample_from_sample_orcabus_id,
167
+ get_samples_list_from_sample_orcabus_id_list,
168
+ coerce_sample_id_or_orcabus_id_to_sample_orcabus_id,
169
+ list_libraries_in_sample,
170
+ get_all_samples,
171
+ )
172
+
173
+ from .subject_helpers import (
174
+ get_subject_from_subject_id,
175
+ get_subjects_list_from_subject_id_list,
176
+ coerce_subject_id_or_orcabus_id_to_subject_orcabus_id,
177
+ get_subject_orcabus_id_from_subject_id,
178
+ get_subjects_list_from_subject_orcabus_id_list,
179
+ get_subject_from_subject_orcabus_id,
180
+ list_samples_in_subject,
181
+ list_libraries_in_subject,
182
+ get_all_subjects,
183
+ )
184
+
185
+ __all__ = [
186
+ # Contact Helpers
187
+ "get_contact_from_contact_id",
188
+ "get_contacts_list_from_contact_id_list",
189
+ "get_contact_orcabus_id_from_contact_id",
190
+ "get_contact_from_contact_orcabus_id",
191
+ "get_contacts_list_from_contact_orcabus_id_list",
192
+ "coerce_contact_id_or_orcabus_id_to_contact_orcabus_id",
193
+ "get_all_contacts",
194
+
195
+ # Individual Helpers
196
+ "get_individual_from_individual_id",
197
+ "get_individuals_list_from_individual_id_list",
198
+ "get_individual_orcabus_id_from_individual_id",
199
+ "get_individual_from_individual_orcabus_id",
200
+ "get_individuals_list_from_individual_orcabus_id_list",
201
+ "coerce_individual_id_or_orcabus_id_to_individual_orcabus_id",
202
+ "get_all_individuals",
203
+ "list_libraries_in_individual",
204
+
205
+ # Library Helpers
206
+ "get_library_from_library_id",
207
+ "get_libraries_list_from_library_id_list",
208
+ "get_library_orcabus_id_from_library_id",
209
+ "get_library_id_from_library_orcabus_id",
210
+ "coerce_library_id_or_orcabus_id_to_library_orcabus_id",
211
+ "get_library_from_library_orcabus_id",
212
+ "get_libraries_from_library_orcabus_id_list",
213
+ "get_subject_from_library_id",
214
+ "get_library_type",
215
+ "get_library_assay_type",
216
+ "get_library_phenotype",
217
+ "get_library_workflow",
218
+ "get_all_libraries",
219
+
220
+ # Project Helpers
221
+ "get_project_from_project_id",
222
+ "get_projects_list_from_project_id_list",
223
+ "get_project_orcabus_id_from_project_id",
224
+ "coerce_project_id_or_orcabus_id_to_project_orcabus_id",
225
+ "get_project_from_project_orcabus_id",
226
+ "get_projects_list_from_project_orcabus_id_list",
227
+ "get_all_projects",
228
+ "list_libraries_in_project",
229
+
230
+ # Sample Helpers
231
+ "get_sample_from_sample_id",
232
+ "get_samples_list_from_sample_id_list",
233
+ "get_sample_orcabus_id_from_sample_id",
234
+ "get_sample_from_sample_orcabus_id",
235
+ "get_samples_list_from_sample_orcabus_id_list",
236
+ "coerce_sample_id_or_orcabus_id_to_sample_orcabus_id",
237
+ "list_libraries_in_sample",
238
+ "get_all_samples",
239
+
240
+ # Subject Helpers
241
+ "get_subject_from_subject_id",
242
+ "get_subjects_list_from_subject_id_list",
243
+ "coerce_subject_id_or_orcabus_id_to_subject_orcabus_id",
244
+ "get_subject_orcabus_id_from_subject_id",
245
+ "get_subjects_list_from_subject_orcabus_id_list",
246
+ "get_subject_from_subject_orcabus_id",
247
+ "list_samples_in_subject",
248
+ "list_libraries_in_subject",
249
+ "get_all_subjects",
250
+ ]
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """
4
+ Helpers for using the contact API endpoint
5
+ """
6
+
7
+ # Standard imports
8
+ from typing import List
9
+ from requests import HTTPError
10
+
11
+ # Local imports
12
+ from . import get_metadata_request_response_results, get_item_objs_from_item_id_list
13
+ from .globals import CONTACT_ENDPOINT, ORCABUS_ULID_REGEX_MATCH
14
+ from .models import Contact
15
+ from .errors import ContactNotFoundError
16
+
17
+
18
+ def get_contact_from_contact_id(contact_id: str) -> Contact:
19
+ """
20
+ Get contact from the contact id
21
+ :param contact_id:
22
+ :return:
23
+ """
24
+ # We have an internal id, convert to int
25
+ params = {
26
+ "contactId": contact_id
27
+ }
28
+
29
+ # Get contact
30
+ try:
31
+ query_list = get_metadata_request_response_results(CONTACT_ENDPOINT, params)
32
+ assert len(query_list) == 1
33
+ return query_list[0]
34
+ except (HTTPError, AssertionError):
35
+ raise ContactNotFoundError(
36
+ contact_id=contact_id,
37
+ )
38
+
39
+
40
+ def get_contacts_list_from_contact_id_list(contact_id_list: List[str], accept_missing=False) -> List[Contact]:
41
+ """
42
+ Given a list of contact ids, return a list of Contact objects
43
+ :param contact_id_list:
44
+ :param accept_missing:
45
+ :return:
46
+ """
47
+ # We have an internal id, convert to int
48
+ return list(map(
49
+ lambda contact_iter_: Contact(**contact_iter_),
50
+ get_item_objs_from_item_id_list(
51
+ item_id_list=contact_id_list,
52
+ item_identifier="contactId",
53
+ endpoint=CONTACT_ENDPOINT,
54
+ accept_missing=accept_missing
55
+ )
56
+ ))
57
+
58
+
59
+ def get_contact_orcabus_id_from_contact_id(contact_id: str) -> str:
60
+ return get_contact_from_contact_id(contact_id)['orcabusId']
61
+
62
+
63
+ def get_contact_from_contact_orcabus_id(contact_orcabus_id: str) -> Contact:
64
+ """
65
+ Get contact from the contact id
66
+ :param contact_orcabus_id:
67
+ :return:
68
+ """
69
+ params = {
70
+ "orcabusId": contact_orcabus_id.split(".")[1]
71
+ }
72
+
73
+ # Get contact
74
+ try:
75
+ query_result = get_metadata_request_response_results(CONTACT_ENDPOINT, params)
76
+ assert len(query_result) == 1
77
+ return query_result[0]
78
+ except (HTTPError, AssertionError):
79
+ raise ContactNotFoundError(
80
+ contact_orcabus_id=contact_orcabus_id,
81
+ )
82
+
83
+
84
+ def get_contacts_list_from_contact_orcabus_id_list(contact_orcabus_id_list: List[str], accept_missing=False) -> List[Contact]:
85
+ # We have an internal id, convert to int
86
+ return list(map(
87
+ lambda contact_iter_: Contact(**contact_iter_),
88
+ get_item_objs_from_item_id_list(
89
+ item_id_list=contact_orcabus_id_list,
90
+ item_identifier="orcabusId",
91
+ endpoint=CONTACT_ENDPOINT,
92
+ accept_missing=accept_missing
93
+ )
94
+ ))
95
+
96
+
97
+ def coerce_contact_id_or_orcabus_id_to_contact_orcabus_id(id_: str) -> str:
98
+ if ORCABUS_ULID_REGEX_MATCH.match(id_):
99
+ return id_
100
+ else :
101
+ return get_contact_orcabus_id_from_contact_id(id_)
102
+
103
+
104
+ def get_all_contacts() -> List[Contact]:
105
+ """
106
+ Get all subjects
107
+ :return:
108
+ """
109
+ return get_metadata_request_response_results(CONTACT_ENDPOINT)
@@ -0,0 +1,104 @@
1
+ # SampleNotFoundError
2
+ from typing import Optional
3
+
4
+
5
+ class SampleNotFoundError(Exception):
6
+ def __init__(
7
+ self,
8
+ sample_id: Optional[str] = None,
9
+ sample_orcabus_id: Optional[str] = None
10
+ ):
11
+ self.sample_id = sample_id
12
+ self.sample_orcabus_id = sample_orcabus_id
13
+ if sample_id is not None:
14
+ self.message = f"Could not find sample with id '{sample_id}'"
15
+ elif sample_orcabus_id is not None:
16
+ self.message = f"Could not find sample with OrcaBus ID '{sample_orcabus_id}'"
17
+ else:
18
+ self.message = "Could not find sample"
19
+ super().__init__(self.message)
20
+
21
+
22
+ class SubjectNotFoundError(Exception):
23
+ def __init__(
24
+ self,
25
+ subject_id: Optional[str] = None,
26
+ subject_orcabus_id: Optional[str] = None
27
+ ):
28
+ self.subject_id = subject_id
29
+ self.subject_orcabus_id = subject_orcabus_id
30
+ if subject_id is not None:
31
+ self.message = f"Could not find subject with id '{subject_id}'"
32
+ elif subject_orcabus_id is not None:
33
+ self.message = f"Could not find subject with OrcaBus ID '{subject_orcabus_id}'"
34
+ else:
35
+ self.message = "Could not find subject"
36
+ super().__init__(self.message)
37
+
38
+
39
+ class ProjectNotFoundError(Exception):
40
+ def __init__(
41
+ self,
42
+ project_id: Optional[str] = None,
43
+ project_orcabus_id: Optional[str] = None
44
+ ):
45
+ self.project_id = project_id
46
+ self.project_orcabus_id = project_orcabus_id
47
+ if project_id is not None:
48
+ self.message = f"Could not find project with id '{project_id}'"
49
+ elif project_orcabus_id is not None:
50
+ self.message = f"Could not find project with OrcaBus ID '{project_orcabus_id}'"
51
+ else:
52
+ self.message = "Could not find project"
53
+ super().__init__(self.message)
54
+
55
+
56
+ class IndividualNotFoundError(Exception):
57
+ def __init__(
58
+ self,
59
+ individual_id: Optional[str] = None,
60
+ individual_orcabus_id: Optional[str] = None
61
+ ):
62
+ self.individual_id = individual_id
63
+ self.individual_orcabus_id = individual_orcabus_id
64
+ if individual_id is not None:
65
+ self.message = f"Could not find individual with id '{individual_id}'"
66
+ elif individual_orcabus_id is not None:
67
+ self.message = f"Could not find individual with OrcaBus ID '{individual_orcabus_id}'"
68
+ else:
69
+ self.message = "Could not find individual"
70
+ super().__init__(self.message)
71
+
72
+
73
+ class LibraryNotFoundError(Exception):
74
+ def __init__(
75
+ self,
76
+ library_id: Optional[str] = None,
77
+ library_orcabus_id: Optional[str] = None
78
+ ):
79
+ self.library_id = library_id
80
+ self.library_orcabus_id = library_orcabus_id
81
+ if library_id is not None:
82
+ self.message = f"Could not find library with id '{library_id}'"
83
+ elif library_orcabus_id is not None:
84
+ self.message = f"Could not find library with OrcaBus ID '{library_orcabus_id}'"
85
+ else:
86
+ self.message = "Could not find library"
87
+ super().__init__(self.message)
88
+
89
+
90
+ class ContactNotFoundError(Exception):
91
+ def __init__(
92
+ self,
93
+ contact_id: Optional[str] = None,
94
+ contact_orcabus_id: Optional[str] = None
95
+ ):
96
+ self.contact_id = contact_id
97
+ self.contact_orcabus_id = contact_orcabus_id
98
+ if contact_id is not None:
99
+ self.message = f"Could not find contact with id '{contact_id}'"
100
+ elif contact_orcabus_id is not None:
101
+ self.message = f"Could not find contact with OrcaBus ID '{contact_orcabus_id}'"
102
+ else:
103
+ self.message = "Could not find contact"
104
+ super().__init__(self.message)
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env python3
2
+
3
+ import re
4
+
5
+ # AWS PARAMETERS
6
+ METADATA_SUBDOMAIN_NAME = "metadata"
7
+
8
+ # API ENDPOINTS
9
+ LIBRARY_ENDPOINT = "api/v1/library"
10
+ SAMPLE_ENDPOINT = "api/v1/sample"
11
+ SUBJECT_ENDPOINT = "api/v1/subject"
12
+ PROJECT_ENDPOINT = "api/v1/project"
13
+ INDIVIDUAL_ENDPOINT = "api/v1/individual"
14
+ CONTACT_ENDPOINT = "api/v1/contact"
15
+
16
+ ORCABUS_ULID_REGEX_MATCH = re.compile(r'^(?:[a-z0-9]{3}\.)?[A-Z0-9]{26}$')
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """
4
+ This module contains helper functions for the individual class.
5
+ """
6
+
7
+ # Standard imports
8
+ from typing import List
9
+ from requests import HTTPError
10
+ from functools import reduce
11
+ from operator import concat
12
+
13
+ # Local imports
14
+ from . import get_metadata_request_response_results, get_item_objs_from_item_id_list
15
+ from .models import Individual, LibraryDetail
16
+ from .errors import IndividualNotFoundError
17
+ from .globals import INDIVIDUAL_ENDPOINT, ORCABUS_ULID_REGEX_MATCH
18
+
19
+
20
+ def get_individual_from_individual_id(individual_id: str) -> Individual:
21
+ """
22
+ Get individual from the individual id
23
+ :param individual_id:
24
+ :return:
25
+ """
26
+ # We have an internal id
27
+ params = {
28
+ "individual_id": individual_id
29
+ }
30
+
31
+ # Get individual
32
+ try:
33
+ query_results = get_metadata_request_response_results(INDIVIDUAL_ENDPOINT, params)
34
+ assert len(query_results) == 1
35
+ return query_results[0]
36
+ except (HTTPError, AssertionError):
37
+ raise IndividualNotFoundError(
38
+ individual_id=individual_id
39
+ )
40
+
41
+
42
+ def get_individuals_list_from_individual_id_list(individual_id_list: List[str], accept_missing=False) -> List[Individual]:
43
+ """
44
+ Get individual from the individual id list
45
+ :param accept_missing:
46
+ :param individual_id_list:
47
+ :return:
48
+ """
49
+ # We have an internal id, convert to int
50
+ return list(map(
51
+ lambda individual_iter_: Individual(**individual_iter_),
52
+ get_item_objs_from_item_id_list(
53
+ item_id_list=individual_id_list,
54
+ item_identifier="individualId",
55
+ endpoint=INDIVIDUAL_ENDPOINT,
56
+ accept_missing=accept_missing
57
+ )
58
+ ))
59
+
60
+
61
+ def get_individual_orcabus_id_from_individual_id(individual_id: str) -> str:
62
+ return get_individual_from_individual_id(individual_id)["orcabusId"]
63
+
64
+
65
+ def get_individual_from_individual_orcabus_id(individual_orcabus_id: str) -> Individual:
66
+ """
67
+ Get individual from the individual id
68
+ :param individual_orcabus_id:
69
+ :return:
70
+ """
71
+ # We have an internal id
72
+ params = {
73
+ "orcabus_id": individual_orcabus_id
74
+ }
75
+
76
+ # Get individual
77
+ try:
78
+ query_results = get_metadata_request_response_results(INDIVIDUAL_ENDPOINT, params)
79
+ assert len(query_results) == 1
80
+ return query_results[0]
81
+ except (HTTPError, AssertionError):
82
+ raise IndividualNotFoundError(
83
+ individual_orcabus_id=individual_orcabus_id
84
+ )
85
+
86
+
87
+ def get_individuals_list_from_individual_orcabus_id_list(individual_orcabus_id_list: List[str], accept_missing=False) -> List[Individual]:
88
+ """
89
+ Get individual from the individual id list
90
+ :param accept_missing:
91
+ :param individual_orcabus_id_list:
92
+ :return:
93
+ """
94
+ # We have an internal id, convert to int
95
+ return list(map(
96
+ lambda individual_iter_: Individual(**individual_iter_),
97
+ get_item_objs_from_item_id_list(
98
+ item_id_list=individual_orcabus_id_list,
99
+ item_identifier="orcabusId",
100
+ endpoint=INDIVIDUAL_ENDPOINT,
101
+ accept_missing=accept_missing
102
+ )
103
+ ))
104
+
105
+
106
+ def coerce_individual_id_or_orcabus_id_to_individual_orcabus_id(id_: str) -> str:
107
+ if ORCABUS_ULID_REGEX_MATCH.match(id_):
108
+ return id_
109
+ else :
110
+ return get_individual_orcabus_id_from_individual_id(id_)
111
+
112
+
113
+ def get_all_individuals():
114
+ """
115
+ Get all samples from the sample database
116
+ :return:
117
+ """
118
+ return get_metadata_request_response_results(INDIVIDUAL_ENDPOINT)
119
+
120
+
121
+ def list_libraries_in_individual(individual_orcabus_id: str) -> List[LibraryDetail]:
122
+ """
123
+ Given an individual id, return all the libraries associated with the individual
124
+ First we need to collect all subjects associated with the individual
125
+ Then we need to collect all libraries associated with the subjects
126
+
127
+ :param individual_orcabus_id:
128
+ :return:
129
+ """
130
+ from .subject_helpers import list_libraries_in_subject
131
+ return list(reduce(
132
+ concat,
133
+ list(map(
134
+ # For each subject, get libraries in subject
135
+ lambda subject_iter_: list_libraries_in_subject(subject_iter_['orcabusId']),
136
+ # Get list of subject orcabus ids
137
+ get_individual_from_individual_orcabus_id(individual_orcabus_id)["subjectSet"]
138
+ ))
139
+ ))