Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 133 additions & 3 deletions healthcare/api-client/dicom/dicomweb.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,20 +131,110 @@ def dicomweb_retrieve_study(
dicomweb_path = '{}/datasets/{}/dicomStores/{}/dicomWeb/studies/{}'.format(
url, dataset_id, dicom_store_id, study_uid)

file_name = 'study.dcm'

# Make an authenticated API request
session = get_session(service_account_json)

response = session.get(dicomweb_path)

response.raise_for_status()

with open(file_name, 'wb') as f:
f.write(response.content)
print('Retrieved study and saved to file ' +
'{} in current directory'.format(file_name))

return response
# [END healthcare_dicomweb_retrieve_study]


# [START healthcare_dicomweb_retrieve_instance]
def dicomweb_retrieve_instance(
service_account_json,
base_url,
project_id,
cloud_region,
dataset_id,
dicom_store_id,
study_uid,
series_uid,
instance_uid):
"""Handles the GET requests specified in the DICOMweb standard."""
url = '{}/projects/{}/locations/{}'.format(base_url,
project_id, cloud_region)

dicom_store_path = '{}/datasets/{}/dicomStores/{}'.format(
url, dataset_id, dicom_store_id)

dicomweb_path = '{}/dicomWeb/studies/{}/series/{}/instances/{}'.format(
dicom_store_path, study_uid, series_uid, instance_uid)

file_name = 'instance.dcm'

# Make an authenticated API request
session = get_session(service_account_json)

headers = {
'Content-Type': 'application/dicom+json; charset=utf-8'
'Accept': 'application/dicom; transfer-syntax=*'
}

response = session.get(dicomweb_path, headers=headers)

response.raise_for_status()

print('Retrieved study with UID: {}'.format(study_uid))
with open(file_name, 'wb') as f:
f.write(response.content)
print('Retrieved DICOM instance and saved to file ' +
'{} in current directory'.format(file_name))

return response
# [END healthcare_dicomweb_retrieve_study]
# [END healthcare_dicomweb_retrieve_instance]


# [START healthcare_dicomweb_retrieve_rendered]
def dicomweb_retrieve_rendered(
service_account_json,
base_url,
project_id,
cloud_region,
dataset_id,
dicom_store_id,
study_uid,
series_uid,
instance_uid):
"""Handles the GET requests specified in the DICOMweb standard."""
url = '{}/projects/{}/locations/{}'.format(base_url,
project_id, cloud_region)

dicom_store_path = '{}/datasets/{}/dicomStores/{}'.format(
url, dataset_id, dicom_store_id)

instance_path = '{}/dicomWeb/studies/{}/series/{}/instances/{}'.format(
dicom_store_path, study_uid, series_uid, instance_uid)

dicomweb_path = '{}/rendered'.format(instance_path)

file_name = 'rendered_image.png'

# Make an authenticated API request
session = get_session(service_account_json)

headers = {
'Accept': 'image/png'
}

response = session.get(dicomweb_path, headers=headers)

response.raise_for_status()

with open(file_name, 'wb') as f:
f.write(response.content)
print('Retrieved rendered image and saved to file ' +
'{} in current directory'.format(file_name))

return response
# [END healthcare_dicomweb_retrieve_rendered]


# [START healthcare_dicomweb_delete_study]
Expand Down Expand Up @@ -228,6 +318,16 @@ def parse_command_line_args():
default=None,
help='Unique identifier for a study.')

parser.add_argument(
'--series_uid',
default=None,
help='Unique identifier for a series.')

parser.add_argument(
'--instance_uid',
default=None,
help='Unique identifier for an instance.')

command = parser.add_subparsers(dest='command')

command.add_parser(
Expand All @@ -239,6 +339,12 @@ def parse_command_line_args():
command.add_parser(
'dicomweb-retrieve-study',
help=dicomweb_retrieve_study.__doc__)
command.add_parser(
'dicomweb-retrieve-instance',
help=dicomweb_retrieve_instance.__doc__)
command.add_parser(
'dicomweb-retrieve-rendered',
help=dicomweb_retrieve_rendered.__doc__)
command.add_parser(
'dicomweb-delete-study',
help=dicomweb_delete_study.__doc__)
Expand Down Expand Up @@ -282,6 +388,30 @@ def run_command(args):
args.dicom_store_id,
args.study_uid)

elif args.command == 'dicomweb-retrieve-instance':
dicomweb_retrieve_instance(
args.service_account_json,
args.base_url,
args.project_id,
args.cloud_region,
args.dataset_id,
args.dicom_store_id,
args.study_uid,
args.series_uid,
args.instance_uid)

elif args.command == 'dicomweb-retrieve-rendered':
dicomweb_retrieve_rendered(
args.service_account_json,
args.base_url,
args.project_id,
args.cloud_region,
args.dataset_id,
args.dicom_store_id,
args.study_uid,
args.series_uid,
args.instance_uid)

elif args.command == 'dicomweb-delete-study':
dicomweb_delete_study(
args.service_account_json,
Expand Down
102 changes: 98 additions & 4 deletions healthcare/api-client/dicom/dicomweb_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,13 @@
RESOURCES = os.path.join(os.path.dirname(__file__), 'resources')
dcm_file_name = 'dicom_00000001_000.dcm'
dcm_file = os.path.join(RESOURCES, dcm_file_name)
# The study_uid is not assigned by the server and is part of the
# metadata of dcm_file
# The study_uid, series_uid, and instance_uid are not assigned by the
# server and are part of the metadata of dcm_file
study_uid = '1.3.6.1.4.1.11129.5.5.111396399361969898205364400549799252857604'
series_uid = '1.3.6.1.4.1.11129.5.5.195628213694300498946760767481291263511724'
instance_uid = '{}.{}'.format(
'1.3.6.1.4.1.11129.5.5',
'153751009835107614666834563294684339746480')


@pytest.fixture(scope='module')
Expand Down Expand Up @@ -154,10 +158,100 @@ def test_dicomweb_retrieve_study(test_dataset, test_dicom_store, capsys):
dicom_store_id,
study_uid)

# Assert study was downloaded
assert os.path.isfile('study.dcm')

out, _ = capsys.readouterr()

# Check that store instance worked
assert 'Retrieved study with UID:' in out
# Check that retrieve study worked
assert 'Retrieved study' in out

# Delete downloaded study
os.remove('study.dcm')

dicomweb.dicomweb_delete_study(
service_account_json,
base_url,
project_id,
cloud_region,
dataset_id,
dicom_store_id,
study_uid)


def test_dicomweb_retrieve_instance(test_dataset, test_dicom_store, capsys):
dicomweb.dicomweb_store_instance(
service_account_json,
base_url,
project_id,
cloud_region,
dataset_id,
dicom_store_id,
dcm_file)

dicomweb.dicomweb_retrieve_instance(
service_account_json,
base_url,
project_id,
cloud_region,
dataset_id,
dicom_store_id,
study_uid,
series_uid,
instance_uid)

# Assert instance was downloaded
assert os.path.isfile('instance.dcm')

out, _ = capsys.readouterr()

# Check that retrieve instance worked
assert 'Retrieved DICOM instance' in out

# Delete downloaded instance
os.remove('instance.dcm')

dicomweb.dicomweb_delete_study(
service_account_json,
base_url,
project_id,
cloud_region,
dataset_id,
dicom_store_id,
study_uid)


def test_dicomweb_retrieve_rendered(test_dataset, test_dicom_store, capsys):
dicomweb.dicomweb_store_instance(
service_account_json,
base_url,
project_id,
cloud_region,
dataset_id,
dicom_store_id,
dcm_file)

dicomweb.dicomweb_retrieve_rendered(
service_account_json,
base_url,
project_id,
cloud_region,
dataset_id,
dicom_store_id,
study_uid,
series_uid,
instance_uid)

# Assert rendered image was downloaded
assert os.path.isfile('rendered_image.png')

out, _ = capsys.readouterr()

# Check that retrieve rendered image worked
assert 'Retrieved rendered image' in out

# Delete downloaded rendered image
os.remove('rendered_image.png')

dicomweb.dicomweb_delete_study(
service_account_json,
Expand Down