diff --git a/Packages/ohif-studies/imports/server/services/index.js b/Packages/ohif-studies/imports/server/services/index.js index df351e030..b22669b9f 100644 --- a/Packages/ohif-studies/imports/server/services/index.js +++ b/Packages/ohif-studies/imports/server/services/index.js @@ -10,8 +10,3 @@ import './dimse/instances.js'; import './dimse/studies.js'; import './dimse/retrieveMetadata.js'; import './dimse/setup.js'; - -// Study, instance, and metadata retrieval from remote PACS via Orthanc as a proxy -import './remote/instances.js'; -import './remote/studies.js'; -import './remote/retrieveMetadata.js'; diff --git a/Packages/ohif-studies/imports/server/services/namespace.js b/Packages/ohif-studies/imports/server/services/namespace.js index a19d2ec29..99f2cb809 100644 --- a/Packages/ohif-studies/imports/server/services/namespace.js +++ b/Packages/ohif-studies/imports/server/services/namespace.js @@ -4,7 +4,6 @@ const Services = {}; Services.QIDO = {}; Services.WADO = {}; Services.DIMSE = {}; -Services.REMOTE = {}; OHIF.studies.services = Services; diff --git a/Packages/ohif-studies/imports/server/services/remote/instances.js b/Packages/ohif-studies/imports/server/services/remote/instances.js deleted file mode 100644 index 5950df557..000000000 --- a/Packages/ohif-studies/imports/server/services/remote/instances.js +++ /dev/null @@ -1,85 +0,0 @@ -import { OHIF } from 'meteor/ohif:core'; -import { remoteGetValue } from '../../lib/remoteGetValue'; - -/** - * Parses data returned from a QIDO search and transforms it into - * an array of series that are present in the study - * - * @param server The DICOM server - * @param studyInstanceUid - * @param resultData - * @returns {Array} Series List - */ -function resultDataToStudyMetadata(server, studyInstanceUid, resultData) { - var seriesMap = {}; - var seriesList = []; - - resultData.forEach(function(instance) { - // Use seriesMap to cache series data - // If the series instance UID has already been used to - // process series data, continue using that series - var seriesInstanceUid = remoteGetValue(instance['0020,000e']); - var series = seriesMap[seriesInstanceUid]; - - // If no series data exists in the seriesMap cache variable, - // process any available series data - if(!series) { - series = { - seriesInstanceUid : seriesInstanceUid, - seriesNumber : parseFloat(remoteGetValue(instance['0020,0011'])), - instances: [] - }; - - // Save this data in the seriesMap cache variable - seriesMap[seriesInstanceUid] = series; - seriesList.push(series); - } - - // The uri for the dicomweb - // NOTE: DCM4CHEE seems to return the data zipped - // NOTE: Orthanc returns the data with multi-part mime which cornerstoneWADOImageLoader doesn't - // know how to parse yet - //var uri = DICOMWeb.getString(instance['00081190']); - //uri = uri.replace('wado-rs', 'dicom-web'); - - // manually create a WADO-URI from the UIDs - // NOTE: Haven't been able to get Orthanc's WADO-URI to work yet - maybe its not configured? - var sopInstanceUid = remoteGetValue(instance['0008,0018']); - var uri = server.wadoUriRoot + '?requestType=WADO&studyUID=' + studyInstanceUid + '&seriesUID=' + seriesInstanceUid + '&objectUID=' + sopInstanceUid + "&contentType=application%2Fdicom"; - - // Add this instance to the current series - series.instances.push({ - sopClassUid: remoteGetValue(instance['0008,0016']), - sopInstanceUid: sopInstanceUid, - uri: uri, - instanceNumber: parseFloat(remoteGetValue(instance['0020,0013'])) - }); - }); - return seriesList; -} - -/** - * Retrieve a set of instances using a QIDO call - * @param server - * @param studyInstanceUid - * @returns {{wadoUriRoot: String, studyInstanceUid: String, seriesList: Array}} - */ -OHIF.studies.services.REMOTE.Instances = function(server, studyInstanceUid) { - var parameters = { - PatientName: "", - PatientID: "", - AccessionNumber: "", - SeriesInstanceUID: "", - SeriesNumber : "", - SOPClassUID : "", - InstanceNumber : "" - }; - - var remote = new OrthancRemote(server.root, server.sourceAE); - - return { - wadoUriRoot: server.wadoUriRoot, - studyInstanceUid: studyInstanceUid, - seriesList: resultDataToStudyMetadata(server, studyInstanceUid, remote.findInstances(server.modality, studyInstanceUid, null, parameters)) - }; -}; diff --git a/Packages/ohif-studies/imports/server/services/remote/retrieveMetadata.js b/Packages/ohif-studies/imports/server/services/remote/retrieveMetadata.js deleted file mode 100644 index 67aeed141..000000000 --- a/Packages/ohif-studies/imports/server/services/remote/retrieveMetadata.js +++ /dev/null @@ -1,142 +0,0 @@ -import { OHIF } from 'meteor/ohif:core'; -import { remoteGetValue } from '../../lib/remoteGetValue'; -import { parseFloatArray } from '../../lib/parseFloatArray'; - -/** - * Parses the SourceImageSequence, if it exists, in order - * to return a ReferenceSOPInstanceUID. The ReferenceSOPInstanceUID - * is used to refer to this image in any accompanying DICOM-SR documents. - * - * @param instance - * @returns {String} The ReferenceSOPInstanceUID - */ -function getSourceImageInstanceUid(instance) { - // TODO= Parse the whole Source Image Sequence - // This is a really poor workaround for now. - // Later we should probably parse the whole sequence. - var SourceImageSequence = remoteGetValue(instance['0008,2112']); - if (SourceImageSequence && SourceImageSequence.Value && SourceImageSequence.Value.length) { - return SourceImageSequence.Value[0]['0008,1155'].Value[0]; - } -} - -/** - * Parses result data from a WADO search into Study MetaData - * Returns an object populated with study metadata, including the - * series list. - * - * @param server - * @param studyInstanceUid - * @param resultData - * @returns {{seriesList: Array, patientName: *, patientId: *, accessionNumber: *, studyDate: *, modalities: *, studyDescription: *, imageCount: *, studyInstanceUid: *}} - */ -function resultDataToStudyMetadata(server, studyInstanceUid, resultData) { - var seriesMap = {}; - var seriesList = []; - - if (!resultData.length) { - return; - } - - var anInstance = resultData[0]; - if (!anInstance) { - return; - } - - var studyData = { - seriesList: seriesList, - patientName: remoteGetValue(anInstance['0010,0010']), - patientId: remoteGetValue(anInstance['0010,0020']), - accessionNumber: remoteGetValue(anInstance['0008,0050']), - studyDate: remoteGetValue(anInstance['0008,0020']), - modalities: remoteGetValue(anInstance['0008,0061']), - studyDescription: remoteGetValue(anInstance['0008,1030']), - imageCount: remoteGetValue(anInstance['0020,1208']), - studyInstanceUid: remoteGetValue(anInstance['0020,000d']) - }; - - resultData.forEach(function(instance) { - var seriesInstanceUid = remoteGetValue(instance['0020,000e']); - var series = seriesMap[seriesInstanceUid]; - if (!series) { - series = { - seriesDescription: remoteGetValue(instance['0008,103e']), - modality: remoteGetValue(instance['0008,0060']), - seriesInstanceUid: seriesInstanceUid, - seriesNumber: parseFloat(remoteGetValue(instance['0020,0011'])), - instances: [] - }; - seriesMap[seriesInstanceUid] = series; - seriesList.push(series); - } - - var sopInstanceUid = remoteGetValue(instance['0008,0018']); - - var instanceSummary = { - imageType: remoteGetValue(instance['0008,0008']), - sopClassUid: remoteGetValue(instance['0008,0016']), - sopInstanceUid: sopInstanceUid, - instanceNumber: parseFloat(remoteGetValue(instance['0020,0013'])), - imagePositionPatient: remoteGetValue(instance['0020,0032']), - imageOrientationPatient: remoteGetValue(instance['0020,0037']), - frameOfReferenceUID: remoteGetValue(instance['0020,0052']), - sliceLocation: parseFloat(remoteGetValue(instance['0020,1041'])), - samplesPerPixel: parseFloat(remoteGetValue(instance['0028,0002'])), - photometricInterpretation: remoteGetValue(instance['0028,0004']), - rows: parseFloat(remoteGetValue(instance['0028,0010'])), - columns: parseFloat(remoteGetValue(instance['0028,0011'])), - pixelSpacing: remoteGetValue(instance['0028,0030']), - bitsAllocated: parseFloat(remoteGetValue(instance['0028,0100'])), - bitsStored: parseFloat(remoteGetValue(instance['0028,0101'])), - highBit: parseFloat(remoteGetValue(instance['0028,0102'])), - pixelRepresentation: parseFloat(remoteGetValue(instance['0028,0103'])), - windowCenter: remoteGetValue(instance['0028,1050']), - windowWidth: remoteGetValue(instance['0028,1051']), - rescaleIntercept: parseFloat(remoteGetValue(instance['0028,1052'])), - rescaleSlope: parseFloat(remoteGetValue(instance['0028,1053'])), - sourceImageInstanceUid: getSourceImageInstanceUid(instance), - laterality: remoteGetValue(instance['0020,0062']), - viewPosition: remoteGetValue(instance['0018,5101']), - acquisitionDateTime: remoteGetValue(instance['0008,002A']), - numberOfFrames: parseFloat(remoteGetValue(instance['0028,0008'])), - frameIncrementPointer: remoteGetValue(instance['0028,0009']), - frameTime: parseFloat(remoteGetValue(instance['0018,1063'])), - frameTimeVector: parseFloatArray(remoteGetValue(instance['0018,1065'])), - echoNumber: remoteGetValue(instance['0018,0086']), - contrastBolusAgent: remoteGetValue(instance['0018,0010']) - }; - - var iid = instance['xxxx,0001'].Value; - if (server.imageRendering === 'wadouri') { - instanceSummary.wadouri = server.wadoUriRoot + '?requestType=WADO&studyUID=' + studyInstanceUid + '&seriesUID=' + seriesInstanceUid + '&objectUID=' + sopInstanceUid + "&contentType=application%2Fdicom"; - } else if (server.imageRendering == 'orthanc') { - instanceSummary.wadouri = server.root + '/instances/' + iid + '/file'; - } else { - instanceSummary.wadorsuri = server.wadoRoot + '/studies/' + studyInstanceUid + '/series/' + seriesInstanceUid + '/instances/' + sopInstanceUid + '/frames/1'; - } - - series.instances.push(instanceSummary); - }); -console.log(studyData.seriesList[0].instances); - return studyData; -} - -/** - * Retrieved Study MetaData from a DICOM server using a WADO call - * @param server - * @param studyInstanceUid - * @returns {{seriesList: Array, patientName: *, patientId: *, accessionNumber: *, studyDate: *, modalities: *, studyDescription: *, imageCount: *, studyInstanceUid: *}} - */ -OHIF.studies.services.REMOTE.RetrieveMetadata = function(server, studyInstanceUid) { - var remote = new OrthancRemote(server.root, server.sourceAE); - - var study = resultDataToStudyMetadata(server, studyInstanceUid, remote.retrieveMetadata(server.modality, studyInstanceUid)); - if (!study) { - study = {}; - } - - study.wadoUriRoot = server.wadoUriRoot; - study.studyInstanceUid = studyInstanceUid; - - return study; -}; diff --git a/Packages/ohif-studies/imports/server/services/remote/studies.js b/Packages/ohif-studies/imports/server/services/remote/studies.js deleted file mode 100644 index d2f598a62..000000000 --- a/Packages/ohif-studies/imports/server/services/remote/studies.js +++ /dev/null @@ -1,53 +0,0 @@ -import { OHIF } from 'meteor/ohif:core'; -import { remoteGetValue } from '../../lib/remoteGetValue'; - -function resultDataToStudies(resultData) { - const studies = []; - - resultData.forEach(function(study) { - studies.push({ - studyInstanceUid: remoteGetValue(study['0020,000d']), - // 00080005 = SpecificCharacterSet - studyDate: remoteGetValue(study['0008,0020']), - studyTime: remoteGetValue(study['0008,0030']), - accessionNumber: remoteGetValue(study['0008,0050']), - referringPhysicianName: remoteGetValue(study['0008,0090']), - // 00081190 = URL - patientName: remoteGetValue(study['0010,0010']), - patientId: remoteGetValue(study['0010,0020']), - patientBirthdate: remoteGetValue(study['0010,0030']), - patientSex: remoteGetValue(study['0010,0040']), - studyId: remoteGetValue(study['0020,0010']), - numberOfStudyRelatedSeries: parseFloat(remoteGetValue(study['0020,1206'])), - numberOfStudyRelatedInstances: parseFloat(remoteGetValue(study['0020,1208'])), - studyDescription: remoteGetValue(study['0008,1030']), - modalities: remoteGetValue(study['0008,0061']) - }); - }); - - return studies; -} - -OHIF.studies.services.REMOTE.Studies = function(server, filter) { - const parameters = { - studyInstanceUID: filter.studyInstanceUid || '', - PatientName: filter.patientName ? filter.patientName : '', - PatientID: filter.patientId, - AccessionNumber: filter.accessionNumber ? filter.accessionNumber : '', - StudyDescription: '', - StudyDate: '', - StudyTime: '', - ReferringPhysicianName: '', - PatientBirthDate: '', - PatientSex: '', - StudyID: '', - NumberOfStudyRelatedSeries: '', - NumberOfStudyRelatedInstances: '', - ModalitiesInStudy: '' - }; - - const remote = new OrthancRemote(server.root, server.sourceAE); - const data = remote.findStudies(server.modality, parameters); - - return resultDataToStudies(data.results); -}; diff --git a/Packages/orthanc-remote/package.js b/Packages/orthanc-remote/package.js deleted file mode 100755 index 9d8b9e96e..000000000 --- a/Packages/orthanc-remote/package.js +++ /dev/null @@ -1,15 +0,0 @@ -Package.describe({ - name: "orthanc-remote", - summary: "Orthanc Remote", - version: '0.0.1' -}); - -Package.onUse(function (api) { - api.use("http"); - - api.addFiles('server/require.js', 'server'); - api.addFiles('server/namespace.js', 'server'); - api.addFiles('server/lib.js', 'server'); - - api.export("OrthancRemote", 'server'); -}); diff --git a/Packages/orthanc-remote/server/lib.js b/Packages/orthanc-remote/server/lib.js deleted file mode 100755 index 773a5c74e..000000000 --- a/Packages/orthanc-remote/server/lib.js +++ /dev/null @@ -1,115 +0,0 @@ - -OrthancRemote.prototype.findStudies = function(modality, params) { - return this.query(modality, 'Study', params); -} - -OrthancRemote.prototype.findSeries = function(modality, studyId, params) { - params = Object.assign({StudyInstanceUID : studyId || ''}, params); - - return this.query(modality, 'Series', params); -} - -OrthancRemote.prototype.findInstances = function(modality, studyId, seriesId, params) { - params = Object.assign({StudyInstanceUID : studyId || '', SeriesInstanceUID : seriesId || ''}, params); - - return this.query(modality, 'Instance', params); -} - -OrthancRemote.prototype.query = function(modality, level, params) { - var url = this.root + '/modalities/' + modality + '/query', - postData = {Level : level, Query : params || {}}; - - var result = HTTP.call('POST', url, {content : JSON.stringify(postData)}); - return this.getAnswersFromQuery(result.data['ID']); -} - -OrthancRemote.prototype.getAnswersFromQuery = function(id) { - var url = this.root + '/queries/' + id + '/answers', - result = HTTP.call('GET', url); - - var resultCount = result.data.length, answers = [], i = 0; - while (i < resultCount) { - var contentUrl = this.root + '/queries/' + id + '/answers/' + result.data[i] + '/content'; - //fetch the result - var contentResult = HTTP.call('GET', contentUrl); - answers.push(contentResult.data); - i++; - } - return { - query : id, - length : resultCount, - results : answers - }; -} - -OrthancRemote.prototype.retrieveAnswer = function(query, index) { - var retrieveUrl = this.root + '/queries/' + query + '/answers/' + index + '/retrieve'; - - var result = HTTP.call('POST', retrieveUrl, {content : this.localAE}); - - return result.data; -} - -OrthancRemote.prototype.retrieveStudy = function(modality, studyInstanceUID) { - var id = this.findStudyID(studyInstanceUID); - if (id === null) { - //retrieve the study - console.log('RetrieveStudy', studyInstanceUID); - var result = this.findStudies(modality, {"StudyInstanceUID" : studyInstanceUID}); - if (result.results.length < 1) { - throw new Meteor.Error(404, "No such study"); - } - - this.retrieveAnswer(result.query, 0); - //check again - id = this.findStudyID(studyInstanceUID); - if (id === null) { - throw new Meteor.Error(500, "Failed to retrieve remote study"); - } - } - return id; -} - -OrthancRemote.prototype.retrieveMetadata = function(modality, studyInstanceUID) { - var studyId = this.retrieveStudy(modality, studyInstanceUID), - instances = this.getInstancesByStudy(studyId); - - var results = [], length = instances.length; - for (var i = 0;i < length;i++) { - var instanceId = instances[i].ID, metadata = this.getInstanceMetadata(instanceId); - metadata['xxxx,0001'] = {Value : instanceId}; - - results.push(metadata); - } - - return results; -} - -OrthancRemote.prototype.getInstancesByStudy = function(studyId) { - var url = this.root + '/studies/' + studyId + '/instances'; - - var result = this._getCall(url); - return result; -} - -OrthancRemote.prototype.getInstanceMetadata = function(instanceId) { - var url = this.root + '/instances/' + instanceId + '/tags'; - - return this._getCall(url); -} - -OrthancRemote.prototype.findStudyID = function(uid) { - var url = this.root + '/tools/lookup'; - - var result = HTTP.call('POST', url, {content : uid}), len = result.data.length; - for (var i = 0;i < len;i++) { - if (result.data[i].Type == 'Study') { - return result.data[i].ID; - } - } - return null; -} - -OrthancRemote.prototype._getCall = function(url) { - return HTTP.call('GET', url).data; -} \ No newline at end of file diff --git a/Packages/orthanc-remote/server/namespace.js b/Packages/orthanc-remote/server/namespace.js deleted file mode 100755 index f7b777743..000000000 --- a/Packages/orthanc-remote/server/namespace.js +++ /dev/null @@ -1,4 +0,0 @@ -OrthancRemote = function(root, localAE){ - this.root = root || 'http://localhost:8042'; - this.localAE = localAE || 'ORTHANCLOCAL'; -}; \ No newline at end of file diff --git a/Packages/orthanc-remote/server/require.js b/Packages/orthanc-remote/server/require.js deleted file mode 100755 index 8cbb4eced..000000000 --- a/Packages/orthanc-remote/server/require.js +++ /dev/null @@ -1 +0,0 @@ -//http = Npm.require("http"); \ No newline at end of file