Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BEAM-10601] DICOM API Beam IO connector #12331

Merged
merged 44 commits into from
Aug 3, 2020
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
2fa1e78
First commit, after modifying codes based on design doc feedbacks 7/20
George-Wu Jul 21, 2020
816c63a
fix some comments
George-Wu Jul 21, 2020
66fcda5
Merge pull request #1 from George-Wu/working
George-Wu Jul 21, 2020
29f7b02
fix style and add license
George-Wu Jul 21, 2020
7401988
Merge pull request #2 from George-Wu/working
George-Wu Jul 21, 2020
e5d825a
fix style lint
George-Wu Jul 21, 2020
e32bf7e
Merge pull request #3 from George-Wu/working
George-Wu Jul 21, 2020
fae3482
minor fix
George-Wu Jul 22, 2020
0de3c2c
add pagination support
George-Wu Jul 22, 2020
30e8ca1
add file path support to storeinstance
George-Wu Jul 23, 2020
a0e1bcb
Merge pull request #4 from George-Wu/work2
George-Wu Jul 23, 2020
5ba1a9b
fix some typos
George-Wu Jul 23, 2020
8986c5a
Merge pull request #5 from George-Wu/work2
George-Wu Jul 23, 2020
432480b
removed path support and added fileio supports
George-Wu Jul 24, 2020
9289cf5
Merge pull request #6 from George-Wu/work2
George-Wu Jul 24, 2020
192ac8d
fix bug in client
George-Wu Jul 24, 2020
045669b
add unit tests
George-Wu Jul 27, 2020
46ff235
Merge pull request #7 from George-Wu/work2
George-Wu Jul 27, 2020
60f96aa
Update dicomio_test.py
George-Wu Jul 27, 2020
a1621cb
fix patching
George-Wu Jul 27, 2020
05d1ee2
remove non-Non-ASCII character
George-Wu Jul 27, 2020
803cfcb
add google.auth support and fix client
George-Wu Jul 27, 2020
122383d
try inject dependency
George-Wu Jul 28, 2020
b1f8e9e
roll back injection
George-Wu Jul 28, 2020
fb42e31
add dependency
George-Wu Jul 28, 2020
abf7600
change place to inject
George-Wu Jul 28, 2020
5d664eb
change the order
George-Wu Jul 28, 2020
04d37cd
fix typos and pydocs
George-Wu Jul 29, 2020
4dde591
Merge branch 'master' of github.com:apache/beam into master
George-Wu Jul 29, 2020
fb9bbd4
fix style
George-Wu Jul 29, 2020
3690b10
fix annoying style
George-Wu Jul 29, 2020
21fd738
Add concurrent support
George-Wu Jul 30, 2020
51294ea
fixed bugs and docs style, added custom client supports, timestamp re…
George-Wu Jul 31, 2020
73ffeb9
fix py2 support issues
George-Wu Jul 31, 2020
593692d
fix some minor bugs
George-Wu Jul 31, 2020
ad6c49e
fix style and modify tests
George-Wu Jul 31, 2020
a19ecd1
fix format
George-Wu Jul 31, 2020
a2706dd
fix test skip
George-Wu Jul 31, 2020
b5a018b
Merge branch 'master' into master
George-Wu Aug 3, 2020
37375db
Update sdks/python/apache_beam/io/gcp/dicomio.py
George-Wu Aug 3, 2020
91d9516
Update sdks/python/apache_beam/io/gcp/dicomio.py
George-Wu Aug 3, 2020
ff2fc3c
Update sdks/python/apache_beam/io/gcp/dicomio.py
George-Wu Aug 3, 2020
ff07e98
Update sdks/python/apache_beam/io/gcp/dicomio.py
George-Wu Aug 3, 2020
0ccc2c5
function name change
George-Wu Aug 3, 2020
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
128 changes: 128 additions & 0 deletions sdks/python/apache_beam/io/gcp/dicomclient.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# pytype: skip-file

from __future__ import absolute_import

from google.auth import default
from google.auth.transport import requests


class DicomApiHttpClient:
"""DICOM api client that talk to api via http request"""
healthcare_base_url = "https://healthcare.googleapis.com/v1"
session = None

def get_session(self, credential):
if self.session:
return self.session

# if the credential is not provided, use the default credential.
if not credential:
credential, _ = default()
new_seesion = requests.AuthorizedSession(credential)
self.session = new_seesion
return new_seesion

def qido_search(
self,
project_id,
region,
dataset_id,
dicom_store_id,
search_type,
params=None,
credential=None):
"""function for searching a DICOM store"""

# sending request to the REST healthcare api.
api_endpoint = "{}/projects/{}/locations/{}".format(
self.healthcare_base_url, project_id, region)

# base of dicomweb path.
dicomweb_path = "{}/datasets/{}/dicomStores/{}/dicomWeb/{}".format(
api_endpoint, dataset_id, dicom_store_id, search_type)

# Make an authenticated API request
session = self.get_session(credential)
headers = {"Content-Type": "application/dicom+json; charset=utf-8"}
page_size = 500

if params and 'limit' in params:
page_size = params['limit']
elif params:
params['limit'] = page_size
else:
params = {'limit': page_size}

offset = 0
output = []
# iterate to get all the results
while True:
params['offset'] = offset
response = session.get(dicomweb_path, headers=headers, params=params)
response.raise_for_status()
status = response.status_code
if status != 200:
if offset == 0:
return [], status
params['offset'] = offset - 1
params['limit'] = 1
response = session.get(dicomweb_path, headers=headers, params=params)
response.raise_for_status()
check_status = response.status_code
if check_status == 200:
# if the number of results equals to page size
return output, check_status
else:
# something wrong with the request or server
return [], status
results = response.json()
output += results
if len(results) < page_size:
# got all the results, return
break
offset += len(results)

return output, status

def dicomweb_store_instance(
self,
project_id,
region,
dataset_id,
dicom_store_id,
dcm_file,
credential=None):
"""function for storing an instance."""

api_endpoint = "{}/projects/{}/locations/{}".format(
self.healthcare_base_url, project_id, region)

dicomweb_path = "{}/datasets/{}/dicomStores/{}/dicomWeb/studies".format(
api_endpoint, dataset_id, dicom_store_id)

# Make an authenticated API request
session = self.get_session(credential)
content_type = "application/dicom"
headers = {"Content-Type": content_type}

response = session.post(dicomweb_path, data=dcm_file, headers=headers)
response.raise_for_status()

return None, response.status_code
Loading