Has anyone tried to feed DICOM data to the Slicer from the Google Health API? If so, any advice on how to do so?
Thanks
Howard
Has anyone tried to feed DICOM data to the Slicer from the Google Health API? If so, any advice on how to do so?
Thanks
Howard
Hi @howardlander - I’ve tinkered with this. The dicomweb-client python package bundled with Slicer. To talk with Google’s DICOMweb one needs to include the authentication token, which can be obtained either through the gcloud auth print-access-token
once you have logged in.
It would be good to add an example to the script repository for this. I can work on it with someone if needed.
I have added an example here:
Hi Andras: I’ve looked at your example. In the case of Google Health, how would I specify the project, region, dataset that I would like to download? Also, I guess there is nothing in the slicer GUI that would let you login to to Google and get the token without the command line?
Here’s an example that works in a colab notebook. We’d need to port the gcloud syntax to work with Slicer.
!pip install dicomweb-client
token = !gcloud auth print-access-token
token = token[0]
PROJECT_ID="chc-tcia"
REGION="us-central1"
DATASET_ID="qin-headneck"
DICOM_STORE_ID=DATASET_ID
url = f"https://healthcare.googleapis.com/v1beta1/projects/{PROJECT_ID}/locations/{REGION}/datasets/{DATASET_ID}/dicomStores/{DICOM_STORE_ID}/dicomWeb"
headers = {
"Authorization" : "Bearer %s" % token
}
import dicomweb_client
client = dicomweb_client.api.DICOMwebClient(url, headers=headers)
studies = client.search_for_studies()
print(f"\n{len(studies)} studies to query\n")
for study in studies:
studyMetadata = dicomweb_client.api.load_json_dataset(study)
if hasattr(studyMetadata, "ModalitiesInStudy"):
print(f"Modalities: {studyMetadata.ModalitiesInStudy}")
else:
print("Modalities not defined")
series = client.search_for_series(studyMetadata.StudyInstanceUID)
print(f" {len(series)} series")
for serie in series:
seriesMetadata = dicomweb_client.api.load_json_dataset(serie)
instances = client.search_for_instances(
study_instance_uid=studyMetadata.StudyInstanceUID,
series_instance_uid=seriesMetadata.SeriesInstanceUID
)
print(f" {len(instances)} instances ", end="", flush=True)
print()
We developed and tested importFromDICOMWeb
helper function with Kheops, but it is just a short Python code snippet, so it should be easy to change the API to work with Google Health API, too. Or, maybe we should add a more generic version of this function (which does not download a complete study but selected series only). @pieper’s example above probably contains all the necessary pieces.
It would be great if you could create this function and contribute it back to Slicer.
The other option for doing the login and getting the token would be to use the browser. We looked at this at the last project week.
The qSlicerWebWidget could be used to do the login and then we can uses the python/javascript interoperability to pull pass the token into Slicer to use with dicomweb_client.
This is all interesting and useful to me, though I will have to spend some time with it, as I am a Slicer novice. One thing is that I suppose this would be easier if I had all of the DICOM urls in advance. Since we are planning to build a cohort selection tool, that is a real possibility.
Probably the simplest is to just use Slicer’s built-in Pyhon console (Ctrl/Cmd-3). That is a standard Python environment that should already have all the Python packages that you need preinstalled (but you can install more, if needed) and also has all Slicer features available. Let us know if you make progress or get stuck at any point.
Steve: how would I try the qSlicerWebWidget?
Hi Howard -
This is something I’ve known was possible for a while but hadn’t had a driving use case to make an example, so thanks for the push to sort out the details. I’ll be needing this soon myself.
First, you can use the web widget (which is basically Chrome) to access an installation of OHIF with the Google API enabled. In my case I have one in firebase, but any https static server on a domain name you control will work for OIDC (unless you explicitly accept it, mine will give a warning about being unverified, so you can choose to try it or not at your peril).
Paste this in the python console:
ww = slicer.qSlicerWebWidget()
ww.show()
ww.url = "https://idc-sandbox-000.firebaseapp.com/"
Then, when you have logged in, use this to get the access token and current page info:
import json
ww.connect("evalResult(QString,QString)", lambda statement, result: print (json.loads(result)))
ww.evalJS("JSON.stringify([window.store.getState().oidc.user.access_token, window.location.href])")
Here’s an example output (with a few characters changed in the token to make it invalid).
['ya29.a0AfH6SSB_ageiit7LFdkDtzvVpi8fs5-0FJlqFuJnTVWHHU2tnNUzRoEPUTP9F-zMhAMMhHlQQvMxXJj2DVILO2PAPrj0xxKjbP1625rXXgfGWfl4mnRRspuxcCEcuNklu6fu-zW60iZR6rKg69WVTQMYUkHayt8QvaS6yw', 'https://idc-sandbox-000.firebaseapp.com/projects/chc-tcia/locations/us-central1/datasets/ct-lymph-nodes/dicomStores/ct-lymph-nodes/study/61.7.276186995443132562163463641799779941762']
This should be all the ingredients needed to use the dicomweb_client code from within Slicer to read and write via dicomweb.
The Google mirror of TCIA requires approval to access, but you can also access any dicom store, such as one you create under your own account.