@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.
- package/.jsii +858 -6
- package/api-gateway/api-gateway.js +22 -4
- package/deployment-stack-pipeline/pipeline.js +6 -4
- package/dynamodb/config.d.ts +3 -0
- package/dynamodb/config.js +7 -0
- package/dynamodb/index.d.ts +27 -0
- package/dynamodb/index.js +106 -0
- package/ecs/config.d.ts +4 -0
- package/ecs/config.js +8 -0
- package/ecs/index.d.ts +46 -0
- package/ecs/index.js +103 -0
- package/index.d.ts +5 -2
- package/index.js +47 -5
- package/index.ts +16 -2
- package/lambda/build_python/Dockerfile +60 -0
- package/lambda/config.d.ts +11 -0
- package/lambda/config.js +19 -0
- package/lambda/index.d.ts +59 -0
- package/lambda/index.js +242 -0
- package/lambda/layers/mart_tools/poetry.lock +303 -0
- package/lambda/layers/mart_tools/pyproject.toml +27 -0
- package/lambda/layers/mart_tools/src/mart_tools/__init__.py +0 -0
- package/lambda/layers/mart_tools/src/mart_tools/mart/__init__.py +8 -0
- package/lambda/layers/mart_tools/src/mart_tools/mart/aws_helpers.py +79 -0
- package/lambda/layers/mart_tools/src/mart_tools/mart/dataframe_helpers.py +29 -0
- package/lambda/layers/mart_tools/src/mart_tools/mart/globals.py +5 -0
- package/lambda/layers/mart_tools/src/mart_tools/mart/models.py +71 -0
- package/lambda/layers/orcabus_api_tools/poetry.lock +273 -0
- package/lambda/layers/orcabus_api_tools/pyproject.toml +27 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/__init__.py +0 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/__init__.py +172 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/create_helpers.py +47 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/globals.py +13 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/job_helpers.py +53 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/models.py +253 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/query_helpers.py +248 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/update_helpers.py +221 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/workflow_helpers.py +25 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/__init__.py +92 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/create_helpers.py +27 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/globals.py +21 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/models.py +51 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/query_helpers.py +52 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/update_helpers.py +45 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/__init__.py +98 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/errors.py +45 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/file_helpers.py +341 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/globals.py +70 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/models.py +59 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/__init__.py +8 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/aws_helpers.py +79 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/dataframe_helpers.py +29 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/globals.py +5 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/models.py +71 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/__init__.py +250 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/contact_helpers.py +109 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/errors.py +104 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/globals.py +16 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/individual_helpers.py +139 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/library_helpers.py +196 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/lims_helpers.py +36 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/models.py +112 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/project_helpers.py +129 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/sample_helpers.py +132 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/subject_helpers.py +151 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/__init__.py +15 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/globals.py +2 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/models.py +44 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/sequence_helpers.py +62 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/__init__.py +0 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/aws_helpers.py +123 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/miscell.py +17 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/requests_helpers.py +163 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/__init__.py +0 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/errors.py +37 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/metadata_helpers.py +28 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/models.py +85 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/payload_helpers.py +64 -0
- package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/workflow_run_helpers.py +80 -0
- package/package.json +13 -7
- package/typedoc.json +3 -0
- package/utils/index.d.ts +3 -0
- 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
|
+
))
|