Skip to content

Commit b4ba8e7

Browse files
meyertst-awsLaren-AWS
authored andcommitted
First commit for HealthLake
1 parent becbedb commit b4ba8e7

File tree

5 files changed

+820
-0
lines changed

5 files changed

+820
-0
lines changed
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# HealthImaging code examples for the SDK for Python
2+
3+
## Overview
4+
5+
Shows how to use the AWS SDK for Python (Boto3) to work with AWS HealthImaging.
6+
7+
<!--custom.overview.start-->
8+
<!--custom.overview.end-->
9+
10+
_HealthImaging is a HIPAA-eligible service that helps health care providers and their medical imaging ISV partners store, transform, and apply machine learning to medical images._
11+
12+
## ⚠ Important
13+
14+
* Running this code might result in charges to your AWS account. For more details, see [AWS Pricing](https://aws.amazon.com/pricing/) and [Free Tier](https://aws.amazon.com/free/).
15+
* Running the tests might result in charges to your AWS account.
16+
* We recommend that you grant your code least privilege. At most, grant only the minimum permissions required to perform the task. For more information, see [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege).
17+
* This code is not tested in every AWS Region. For more information, see [AWS Regional Services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services).
18+
19+
<!--custom.important.start-->
20+
<!--custom.important.end-->
21+
22+
## Code examples
23+
24+
### Prerequisites
25+
26+
For prerequisites, see the [README](../../README.md#Prerequisites) in the `python` folder.
27+
28+
Install the packages required by these examples by running the following in a virtual environment:
29+
30+
```
31+
python -m pip install -r requirements.txt
32+
```
33+
34+
<!--custom.prerequisites.start-->
35+
<!--custom.prerequisites.end-->
36+
37+
### Get started
38+
39+
- [Hello HealthImaging](imaging_set_and_frames_workflow/hello.py#L4) (`ListDatastores`)
40+
41+
42+
### Single actions
43+
44+
Code excerpts that show you how to call individual service functions.
45+
46+
- [CopyImageSet](health_lake_wrapper.py#L417)
47+
- [CreateDatastore](health_lake_wrapper.py#L31)
48+
- [DeleteDatastore](health_lake_wrapper.py#L104)
49+
- [DeleteImageSet](health_lake_wrapper.py#L489)
50+
- [GetDICOMImportJob](health_lake_wrapper.py#L158)
51+
- [GetDatastore](health_lake_wrapper.py#L54)
52+
- [GetImageFrame](health_lake_wrapper.py#L318)
53+
- [GetImageSet](health_lake_wrapper.py#L241)
54+
- [GetImageSetMetadata](health_lake_wrapper.py#L274)
55+
- [ListDICOMImportJobs](health_lake_wrapper.py#L183)
56+
- [ListDatastores](health_lake_wrapper.py#L79)
57+
- [ListImageSetVersions](health_lake_wrapper.py#L350)
58+
- [ListTagsForResource](health_lake_wrapper.py#L556)
59+
- [SearchImageSets](health_lake_wrapper.py#L211)
60+
- [StartDICOMImportJob](health_lake_wrapper.py#L124)
61+
- [TagResource](health_lake_wrapper.py#L514)
62+
- [UntagResource](health_lake_wrapper.py#L534)
63+
- [UpdateImageSetMetadata](health_lake_wrapper.py#L381)
64+
65+
### Scenarios
66+
67+
Code examples that show you how to accomplish a specific task by calling multiple
68+
functions within the same service.
69+
70+
- [Get started with image sets and image frames](imaging_set_and_frames_workflow/imaging_set_and_frames.py)
71+
- [Tagging a data store](tagging_data_stores.py)
72+
- [Tagging an image set](tagging_image_sets.py)
73+
74+
75+
<!--custom.examples.start-->
76+
<!--custom.examples.end-->
77+
78+
## Run the examples
79+
80+
### Instructions
81+
82+
83+
<!--custom.instructions.start-->
84+
<!--custom.instructions.end-->
85+
86+
#### Hello HealthImaging
87+
88+
This example shows you how to get started using HealthImaging.
89+
90+
```
91+
python imaging_set_and_frames_workflow/hello.py
92+
```
93+
94+
95+
#### Get started with image sets and image frames
96+
97+
This example shows you how to import DICOM files and download image frames in HealthImaging.</para>
98+
<para>The implementation is structured as a workflow command-line
99+
application.
100+
101+
102+
- Set up resources for a DICOM import.
103+
- Import DICOM files into a data store.
104+
- Retrieve the image set IDs for the import job.
105+
- Retrieve the image frame IDs for the image sets.
106+
- Download, decode and verify the image frames.
107+
- Clean up resources.
108+
109+
<!--custom.scenario_prereqs.medical-imaging_Scenario_ImageSetsAndFrames.start-->
110+
<!--custom.scenario_prereqs.medical-imaging_Scenario_ImageSetsAndFrames.end-->
111+
112+
Start the example by running the following at a command prompt:
113+
114+
```
115+
python imaging_set_and_frames_workflow/imaging_set_and_frames.py
116+
```
117+
118+
119+
<!--custom.scenarios.medical-imaging_Scenario_ImageSetsAndFrames.start-->
120+
<!--custom.scenarios.medical-imaging_Scenario_ImageSetsAndFrames.end-->
121+
122+
#### Tagging a data store
123+
124+
This example shows you how to tag a HealthImaging data store.
125+
126+
127+
<!--custom.scenario_prereqs.medical-imaging_Scenario_TaggingDataStores.start-->
128+
<!--custom.scenario_prereqs.medical-imaging_Scenario_TaggingDataStores.end-->
129+
130+
Start the example by running the following at a command prompt:
131+
132+
```
133+
python tagging_data_stores.py
134+
```
135+
136+
137+
<!--custom.scenarios.medical-imaging_Scenario_TaggingDataStores.start-->
138+
<!--custom.scenarios.medical-imaging_Scenario_TaggingDataStores.end-->
139+
140+
#### Tagging an image set
141+
142+
This example shows you how to tag a HealthImaging image set.
143+
144+
145+
<!--custom.scenario_prereqs.medical-imaging_Scenario_TaggingImageSets.start-->
146+
<!--custom.scenario_prereqs.medical-imaging_Scenario_TaggingImageSets.end-->
147+
148+
Start the example by running the following at a command prompt:
149+
150+
```
151+
python tagging_image_sets.py
152+
```
153+
154+
155+
<!--custom.scenarios.medical-imaging_Scenario_TaggingImageSets.start-->
156+
<!--custom.scenarios.medical-imaging_Scenario_TaggingImageSets.end-->
157+
158+
### Tests
159+
160+
⚠ Running tests might result in charges to your AWS account.
161+
162+
163+
To find instructions for running these tests, see the [README](../../README.md#Tests)
164+
in the `python` folder.
165+
166+
167+
168+
<!--custom.tests.start-->
169+
<!--custom.tests.end-->
170+
171+
## Additional resources
172+
173+
- [HealthImaging Developer Guide](https://docs.aws.amazon.com/healthimaging/latest/devguide/what-is.html)
174+
- [HealthImaging API Reference](https://docs.aws.amazon.com/healthimaging/latest/APIReference/Welcome.html)
175+
- [SDK for Python HealthImaging reference](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/medical-imaging.html)
176+
177+
<!--custom.resources.start-->
178+
<!--custom.resources.end-->
179+
180+
---
181+
182+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
183+
184+
SPDX-License-Identifier: Apache-2.0
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
"""
5+
Purpose
6+
7+
Shows how to use the AWS SDK for Python (Boto3) to manage and invoke AWS HealthImaging
8+
functions.
9+
"""
10+
11+
from boto3 import client
12+
import logging
13+
14+
import boto3
15+
from botocore.exceptions import ClientError
16+
17+
import time
18+
19+
logger = logging.getLogger(__name__)
20+
21+
22+
# snippet-start:[python.example_code.medical-imaging.HealthLakeWrapper]
23+
class HealthLakeWrapper:
24+
def __init__(self, health_lake_client):
25+
self.health_lake_client = health_lake_client
26+
27+
28+
# snippet-start:[python.example_code.medical-imaging.HealthLakeWrapper.decl]
29+
@classmethod
30+
def from_client(cls) -> "HealthLakeWrapper":
31+
"""
32+
Creates a HealthLakeWrapper instance with a default AWS HealthLake client.
33+
34+
:return: An instance of HealthLakeWrapper initialized with the default HealthLake client.
35+
"""
36+
kms_client = boto3.client("healthlake")
37+
return cls(kms_client)
38+
39+
# snippet-end:[python.example_code.medical-imaging.HealthLakeWrapper.decl]
40+
41+
# snippet-start:[python.example_code.medical-imaging.CreateFHIRDatastore]
42+
def create_fihr_datastore(self, datastore_name: str, sse_configuration : dict[str, any] = None,
43+
identity_provider_configuration : dict[str, any] = None) -> str:
44+
"""
45+
Creates a new HealthLake datastore.
46+
When creating a SMART on FHIR datastore, the following parameters are required:
47+
- sse_configuration: The server-side encryption configuration for a SMART on FHIR-enabled data store.
48+
- identity_provider_configuration: The identity provider configuration for a SMART on FHIR-enabled data store.
49+
50+
:param datastore_name: The name of the data store.
51+
:param sse_configuration: The server-side encryption configuration for a SMART on FHIR-enabled data store.
52+
:param identity_provider_configuration: The identity provider configuration for a SMART on FHIR-enabled data store.
53+
:return: The datastore ID.
54+
"""
55+
try:
56+
parameters = {
57+
'DatastoreName': datastore_name,
58+
'DatastoreTypeVersion' : 'R4'
59+
}
60+
if sse_configuration is not None and identity_provider_configuration is not None:
61+
# Creating a SMART on FHIR-enabled data store
62+
parameters['SseConfiguration'] = sse_configuration
63+
parameters['IdentityProviderConfiguration'] = identity_provider_configuration
64+
65+
response = self.health_lake_client.create_fhir_datastore(**parameters)
66+
return response['datastoreId']
67+
except ClientError as err:
68+
logger.exception("Couldn't create datastore %s. Here's why",
69+
datastore_name, err.response["Error"]["Message"])
70+
raise
71+
72+
# snippet-end:[python.example_code.medical-imaging.CreateFHIRDatastore]
73+
74+
# snippet-start:[python.example_code.medical-imaging.DescribeFHIRDatastore]
75+
def describe_fhir_datastore(self, datastore_id: str) -> dict[str, any]:
76+
"""
77+
Describes a HealthLake datastore.
78+
:param datastore_id: The datastore ID.
79+
:return: The datastore description.
80+
"""
81+
try:
82+
response = self.health_lake_client.describe_fhir_datastore(
83+
DatastoreId=datastore_id)
84+
return response['DatastoreProperties']
85+
except ClientError as err:
86+
logger.exception("Couldn't describe datastore with ID %s. Here's why",
87+
datastore_id, err.response["Error"]["Message"])
88+
raise
89+
90+
# snippet-end:[python.example_code.medical-imaging.HealthLakeWrapper]
91+
92+
def wait_datastore_active(self, datastore_id: str) -> None:
93+
"""
94+
Waits for a HealthLake datastore to become active.
95+
:param datastore_id: The datastore ID.
96+
"""
97+
counter = 0
98+
max_count_minutes = 40 # It can take a while to create a datastore, so we'll wait up to 40 minutes.
99+
data_store_active = False
100+
while counter < max_count_minutes:
101+
datastore = self.health_lake_client.describe_fhir_datastore(
102+
DatastoreId=datastore_id)
103+
if datastore["DatastoreProperties"]["DatastoreStatus"] == "ACTIVE":
104+
data_store_active = True
105+
break
106+
else:
107+
counter += 1
108+
time.sleep(60)
109+
110+
if data_store_active :
111+
logger.info("Datastore with ID %s is active after %d minutes.", datastore_id, counter)
112+
else:
113+
raise ClientError("Datastore with ID %s is not active after %d minutes.", datastore_id, counter)
114+
115+
try:
116+
waiter = self.health_lake_client.get_waiter("datastore_active")
117+
waiter.wait(DatastoreId=datastore_id)
118+
except ClientError as err:
119+
logger.exception("Data store with ID %s failed to become active. Here's why",
120+
datastore_id, err.response["Error"]["Message"])
121+
raise
122+
123+
def health_lake_demo(self) -> None:
124+
use_smart_data_store = False
125+
testing_code = True
126+
127+
datastore_name = "health_imaging_datastore"
128+
if use_smart_data_store:
129+
pass
130+
else:
131+
data_store_id = self.health_imaging_client.list_datastores(
132+
maxResults=1
133+
)['datastoreResults'][0]['datastoreId']
134+
135+
136+
if __name__ == "__main__":
137+
health_lake_wrapper = HealthLakeWrapper.from_client()
138+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
boto3>=1.34.149
2+
pytest>=7.2.1
3+
botocore>=1.34.149
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
"""
5+
Contains common test fixtures used to run AWS HealthImaging
6+
tests.
7+
"""
8+
9+
import sys
10+
11+
# This is needed so Python can find test_tools on the path.
12+
sys.path.append("../..")
13+
from test_tools.fixtures.common import *

0 commit comments

Comments
 (0)