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

Updating Healthlake References to HealthImaging #30

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# OHIF AWS HealthImaging adapter

Note - The official name for the service is "AWS HealthImaging". Before GA it was called "Amazon HealthLake Imaging" and several references in the code and documentation still reference this old name. These references will be updated shortly
Note - The official name for the service is "AWS HealthImaging".

# Setting up

Expand Down Expand Up @@ -37,11 +37,11 @@ platform/app/public/config/default.js
//...
dataSources: [{
friendlyName: 'AWS HealthImaging',
namespace: 'ohif-aws-healthimaging.dataSourcesModule.healthlake',
sourceName: 'healthlake',
namespace: 'ohif-aws-healthimaging.dataSourcesModule.healthimaging',
sourceName: 'healthimaging',
configuration: {
name: 'healthlake',
healthlake: {
name: 'healthimaging',
healthimaging: {
datastoreID: $YOUR_DATASTORE_ID,
endpoint: 'http://localhost:8089',// Add here the address to you proxy
},
Expand Down
2 changes: 1 addition & 1 deletion proxy/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,5 @@ const proxy = createServer(async (req, res) => {
});
const port = process.env.PORT || 8089;
proxy.listen(port, () => {
console.log(`Healthlake proxy server is running on http://:::${port}`);
console.log(`Healthimaging proxy server is running on http://:::${port}`);
});
32 changes: 16 additions & 16 deletions src/createDicomWebTreeApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,20 @@ const metadataProvider = classes.MetadataProvider;

const retrievedStudies = {};

const initializeHealthlakeFetch = (healthlake) => {
if( !healthlake.endpoint ) throw new Error('endpoint is mandatory');
const initializeHealthimagingFetch = (healthimaging) => {
if( !healthimaging.endpoint ) throw new Error('endpoint is mandatory');
cornerstoneDICOMImageLoader.configure({
open: function (xhr: any, url: string) {
const urlParams = new URLSearchParams(url);
const datastoreId = urlParams.get('DatastoreID');
const collectionId = urlParams.get('ImageSetID');
const imageFrameId = urlParams.get('frameID');
const isAwsHealthImagingRequest = urlParams.get('healthlake');
const isAwsHealthImagingRequest = urlParams.get('healthimaging');
if(!isAwsHealthImagingRequest) {
return xhr.open('get', url, true);
}
const uri =
healthlake.endpoint +
healthimaging.endpoint +
'/datastore/' +
datastoreId +
'/imageSet/' +
Expand All @@ -60,8 +60,8 @@ const initializeHealthlakeFetch = (healthlake) => {
"imageFrameId" : imageFrameId
});

const signer = healthlake.awsAccessKeyID ? new AwsV4Signer({
...awsCredentials(healthlake),
const signer = healthimaging.awsAccessKeyID ? new AwsV4Signer({
...awsCredentials(healthimaging),
service: 'medical-imaging',
url: uri,
method: 'POST',
Expand Down Expand Up @@ -113,13 +113,13 @@ function createDicomWebTreeApi(dicomWebConfig, UserAuthenticationService) {
supportsWildcard,
staticWado,
singlepart,
healthlake,
healthimaging,
} = dicomWebConfig;

const qidoConfig = {
url: qidoRoot,
staticWado,
healthlake,
healthimaging,
singlepart,
headers: UserAuthenticationService.getAuthorizationHeader(),
errorInterceptor: errorHandler.getHTTPErrorHandler(),
Expand All @@ -129,7 +129,7 @@ function createDicomWebTreeApi(dicomWebConfig, UserAuthenticationService) {
url: wadoRoot,
singlepart,
staticWado,
healthlake,
healthimaging,
headers: UserAuthenticationService.getAuthorizationHeader(),
errorInterceptor: errorHandler.getHTTPErrorHandler(),
};
Expand All @@ -139,7 +139,7 @@ function createDicomWebTreeApi(dicomWebConfig, UserAuthenticationService) {
const qidoDicomWebClient = new DicomTreeClient(qidoConfig);
const wadoDicomWebClient = new DicomTreeClient(wadoConfig);

initializeHealthlakeFetch(qidoDicomWebClient.healthlake);
initializeHealthimagingFetch(qidoDicomWebClient.healthimaging);

const implementation = {
initialize: ({ params, query }) => {
Expand Down Expand Up @@ -168,9 +168,9 @@ function createDicomWebTreeApi(dicomWebConfig, UserAuthenticationService) {
supportsFuzzyMatching,
supportsWildcard,
}) || {};
if (window.healthlake && window.healthlake.ImageSetID) {
if (window.healthimaging && window.healthimaging.ImageSetID) {
// Todo implement image set id search
const { ImageSetID, datastoreID } = window.healthlake;
const { ImageSetID, datastoreID } = window.healthimaging;
const tree = await implementation._retrieveSeriesMetadataDeduplicated(
ImageSetID
);
Expand Down Expand Up @@ -421,7 +421,7 @@ function createDicomWebTreeApi(dicomWebConfig, UserAuthenticationService) {
'instances'
);
retrievedStudies[StudyInstanceUID] = naturalizedInstancesMetadata;
performance.measure('healthlake:retrieve-metadatatree', {
performance.measure('healthimaging:retrieve-metadatatree', {
start: startTime,
end: performance.now(),
});
Expand Down Expand Up @@ -478,7 +478,7 @@ function createDicomWebTreeApi(dicomWebConfig, UserAuthenticationService) {
Object.keys(instancesPerSeries).forEach(seriesUID =>
DicomMetadataStore.addInstances(instancesPerSeries[seriesUID], false)
);
performance.measure('healthlake:convert-metadataTree', {
performance.measure('healthimaging:convert-metadataTree', {
start: startTime,
end: performance.now(),
}
Expand Down Expand Up @@ -517,13 +517,13 @@ function createDicomWebTreeApi(dicomWebConfig, UserAuthenticationService) {
getImageIdsForInstance({ instance, frame = 0 }) {
const { DatastoreID, ImageFrames, ImageSetID } = instance;
const frameID = ImageFrames?.[frame]?.ID;
const healthlakeParam = qidoDicomWebClient.healthlake?.images ? "true" : "false";
const healthimagingParam = qidoDicomWebClient.healthimaging?.images ? "true" : "false";
const extraParameters =
(DatastoreID && {
DatastoreID,
frameID,
ImageSetID,
healthlake: healthlakeParam,
healthimaging: healthimagingParam,
}) ||
undefined;
const imageIds = getImageId({
Expand Down
2 changes: 1 addition & 1 deletion src/getDataSourcesModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import createDicomWebTreeApi from './createDicomWebTreeApi';
function getDataSourcesModule() {
return [
{
name: 'healthlake',
name: 'healthimaging',
type: 'webApi',
createDataSource: createDicomWebTreeApi,
},
Expand Down
34 changes: 17 additions & 17 deletions src/imageLoader/awsCredentials.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,27 @@ describe('awsCredentials', () => {
};

beforeEach(() => {
delete window.healthlake;
window.localStorage.removeItem('healthlake');
delete window.healthimaging;
window.localStorage.removeItem('healthimaging');
});

test('returns credentials from healthlake object if present', () => {
const healthlake = {
awsSecretAccessKey: 'healthlake-secret',
awsAccessKeyID: 'healthlake-access-key'
test('returns credentials from healthimaging object if present', () => {
const healthimaging = {
awsSecretAccessKey: 'healthimaging-secret',
awsAccessKeyID: 'healthimaging-access-key'
};
window.healthlake = healthlake;
window.healthimaging = healthimaging;

const result = awsCredentials(config);

expect(result).toEqual({
secretAccessKey: healthlake.awsSecretAccessKey,
accessKeyId: healthlake.awsAccessKeyID,
secretAccessKey: healthimaging.awsSecretAccessKey,
accessKeyId: healthimaging.awsAccessKeyID,
service: "medical-imaging"
});
});

test('returns credentials from config if healthlake object is not present', () => {
test('returns credentials from config if healthimaging object is not present', () => {
const result = awsCredentials(config);

expect(result).toEqual({
Expand All @@ -37,18 +37,18 @@ describe('awsCredentials', () => {
});
});

test('returns credentials from parsed local storage if healthlake object is not present', () => {
const healthlake = {
awsSecretAccessKey: 'healthlake-secret',
awsAccessKeyID: 'healthlake-access-key'
test('returns credentials from parsed local storage if healthimaging object is not present', () => {
const healthimaging = {
awsSecretAccessKey: 'healthimaging-secret',
awsAccessKeyID: 'healthimaging-access-key'
};
window.localStorage.setItem('healthlake', JSON.stringify(healthlake));
window.localStorage.setItem('healthimaging', JSON.stringify(healthimaging));

const result = awsCredentials(config);

expect(result).toEqual({
secretAccessKey: healthlake.awsSecretAccessKey,
accessKeyId: healthlake.awsAccessKeyID,
secretAccessKey: healthimaging.awsSecretAccessKey,
accessKeyId: healthimaging.awsAccessKeyID,
service: "medical-imaging"
});
});
Expand Down
16 changes: 8 additions & 8 deletions src/imageLoader/awsCredentials.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@

const awsCredentials = (config) => {
let { healthlake } = window;
if (!healthlake) {
const sHealthLake = window.localStorage.getItem("healthlake");
if (sHealthLake) {
healthlake = window.healthlake = JSON.parse(sHealthLake);
let { healthimaging } = window;
if (!healthimaging) {
const sHealthImaging = window.localStorage.getItem("healthimaging");
if (sHealthImaging) {
healthimaging = window.healthimaging = JSON.parse(sHealthImaging);
}
}
const credentials = {
secretAccessKey: healthlake?.awsSecretAccessKey || config.awsSecretAccessKey,
accessKeyId: healthlake?.awsAccessKeyID || config.awsAccessKeyID,
sessionToken: healthlake?.awsSessionToken || config.awsSessionToken,
secretAccessKey: healthimaging?.awsSecretAccessKey || config.awsSecretAccessKey,
accessKeyId: healthimaging?.awsAccessKeyID || config.awsAccessKeyID,
sessionToken: healthimaging?.awsSessionToken || config.awsSessionToken,
service: "medical-imaging"
};

Expand Down
4 changes: 2 additions & 2 deletions src/imageLoader/loadImageSets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const loadImageSets = async (config, filters) => {
const cached = loadImageSetsCache.get(cacheKey);
if (cached) {
performance.measure(
"healthlake:imagessets-load-from-cache", {
"healthimaging:imagessets-load-from-cache", {
start: startTime,
detail: "cached",
end: performance.now(),
Expand All @@ -83,7 +83,7 @@ const loadImageSets = async (config, filters) => {
} else {
const getImageSetPromise = getImageSets(config.datastoreID, config, aswFilter).then((imageSetsMetadataSummaries) => {
performance.measure(
"healthlake:imagessets-load", {
"healthimaging:imagessets-load", {
start: startTime,
detail: "request",
end: performance.now(),
Expand Down
2 changes: 1 addition & 1 deletion src/imageLoader/loadMetaData.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const loadMetaDataInternal = async (datastoreId, collectionId, config) => {
method: 'POST',
})
performance.measure(
"healthlake-metadata-load", {
"healthimaging-metadata-load", {
start: startTime,
end: performance.now(),
}
Expand Down
40 changes: 20 additions & 20 deletions src/utils/DicomTreeClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import loadMetaDataInternal from '../imageLoader/loadMetaData';
import loadImageSets from '../imageLoader/loadImageSets';


export type HealthLake = {
export type HealthImaging = {
collections: Record < string,
unknown > ;
awsAccessKeyID: string;
Expand All @@ -25,7 +25,7 @@ export type HealthLake = {
* by manually implementing a query option.
*/
export default class DicomTreeClient extends api.DICOMwebClient {
healthlake: HealthLake;
healthimaging: HealthImaging;
staticWado = false;

static studyFilterKeys = {
Expand All @@ -48,18 +48,18 @@ export default class DicomTreeClient extends api.DICOMwebClient {
super(qidoConfig);
this.staticWado = qidoConfig.staticWado;
const {
healthlake
healthimaging
} = qidoConfig;
this.healthlake = {
this.healthimaging = {
groupSeriesBy: 'SeriesInstanceUID',
maxImageSetsToReturn: 300,
region: 'us-east-1',
endpoint: 'https://runtime-medical-imaging.us-east-1.amazonaws.com',
tree: true,
images: true,
collections: {},
...window.healthlake,
...qidoConfig.healthlake,
...window.healthimaging,
...qidoConfig.healthimaging,
};
}

Expand All @@ -71,12 +71,12 @@ export default class DicomTreeClient extends api.DICOMwebClient {
*/
async searchForStudies(options) {
const search = new URLSearchParams(document.location.search);
const ImageSetID = search?.get("ImageSetID") || this.healthlake.imageSetID;
const ImageSetID = search?.get("ImageSetID") || this.healthimaging.imageSetID;
let searchResult;
if(this.healthlake?.queryJson) {
searchResult = this.healthlake.queryJson[0]==='[' ? JSON.parse(this.healthlake.queryJson) : await (await fetch(this.healthlake.queryJson)).json();
if(this.healthimaging?.queryJson) {
searchResult = this.healthimaging.queryJson[0]==='[' ? JSON.parse(this.healthimaging.queryJson) : await (await fetch(this.healthimaging.queryJson)).json();
} else {
searchResult = await loadImageSets(this.healthlake, options.queryParams);
searchResult = await loadImageSets(this.healthimaging, options.queryParams);
}
const {
queryParams
Expand Down Expand Up @@ -128,10 +128,10 @@ export default class DicomTreeClient extends api.DICOMwebClient {
}

let {
ImageSetID = search?.get("ImageSetID") || this.healthlake.imageSetID,
datastoreID = this.healthlake?.datastoreID,
ImageSetID = search?.get("ImageSetID") || this.healthimaging.imageSetID,
datastoreID = this.healthimaging?.datastoreID,
} = options;
if (this.healthlake) {
if (this.healthimaging) {
const studies = await this.searchForStudies({
...options,
queryParams: {
Expand All @@ -144,21 +144,21 @@ export default class DicomTreeClient extends api.DICOMwebClient {
const imageSetsIds = (study['00200010']?.Value ||[]);
// Todo do it one by one and go adding to the screen as they arrive
const metadataArray = await Promise.all(imageSetsIds.map(async (imageSetId: String) => {
const metadataLoaded = await loadMetaDataInternal(datastoreID, imageSetId, this.healthlake);
const metadataLoaded = await loadMetaDataInternal(datastoreID, imageSetId, this.healthimaging);
return enrichImageSetMetadataWithImageSetId(metadataLoaded, imageSetId);
}));
const finalMetadata = reduceMetadata(metadataArray, this.healthlake);
const finalMetadata = reduceMetadata(metadataArray, this.healthimaging);

return finalMetadata;
}
}
if (ImageSetID && datastoreID) {
if (this.healthlake.collections[ImageSetID]) {
return this.healthlake.collections[ImageSetID];
if (this.healthimaging.collections[ImageSetID]) {
return this.healthimaging.collections[ImageSetID];
}
return loadMetaDataInternal(datastoreID, ImageSetID, this.healthlake);
return loadMetaDataInternal(datastoreID, ImageSetID, this.healthimaging);
} else {
throw new Error(`Missing healthlake configuration`);
throw new Error(`Missing healthimaging configuration`);
}
}

Expand Down Expand Up @@ -233,7 +233,7 @@ export default class DicomTreeClient extends api.DICOMwebClient {
return this.compareValues(testValue, value) && true;
}
}
function reduceMetadata(metadataArray: any[], config: HealthLake) {
function reduceMetadata(metadataArray: any[], config: HealthImaging) {
const series = metadataArray.map((cur) => Object.values(cur.Study.Series)).flat();

const seriesBySerieId = reduceSeries(series, config);
Expand Down