chore(dicomweb-client): Switch to dicomweb-client.js to push logic out of OHIF
This commit is contained in:
parent
45c5867663
commit
89d97a7a3a
@ -92,7 +92,6 @@ ohif:core@0.0.1
|
||||
ohif:cornerstone@0.0.1
|
||||
ohif:cornerstone-settings@0.0.1
|
||||
ohif:design@0.0.1
|
||||
ohif:dicomweb-client@0.0.1
|
||||
ohif:hanging-protocols@0.0.1
|
||||
ohif:header@0.0.1
|
||||
ohif:hotkeys@0.0.1
|
||||
|
||||
@ -37,7 +37,6 @@ ohif:cornerstone
|
||||
ohif:cornerstone-settings
|
||||
ohif:viewerbase
|
||||
ohif:study-list
|
||||
ohif:dicomweb-client
|
||||
ohif:hanging-protocols
|
||||
ohif:metadata
|
||||
ohif:user-oidc
|
||||
|
||||
@ -82,7 +82,6 @@ ohif:core@0.0.1
|
||||
ohif:cornerstone@0.0.1
|
||||
ohif:cornerstone-settings@0.0.1
|
||||
ohif:design@0.0.1
|
||||
ohif:dicomweb-client@0.0.1
|
||||
ohif:hanging-protocols@0.0.1
|
||||
ohif:header@0.0.1
|
||||
ohif:hotkeys@0.0.1
|
||||
|
||||
@ -22,10 +22,10 @@ Meteor.startup(function() {
|
||||
|
||||
cornerstoneWADOImageLoader.configure({
|
||||
beforeSend: function(xhr) {
|
||||
const accessToken = OHIF.user.getAccessToken();
|
||||
const headers = OHIF.DICOMWeb.getAuthorizationHeader();
|
||||
|
||||
if (accessToken) {
|
||||
xhr.setRequestHeader("Authorization", `Bearer ${accessToken}`);
|
||||
if (headers.Authorization) {
|
||||
xhr.setRequestHeader("Authorization", headers.Authorization);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -5,7 +5,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
// Meteor packages
|
||||
api.use([
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
* @param [defaultValue] - The value to return if the element is not present
|
||||
* @returns {*}
|
||||
*/
|
||||
const getAttribute = function(element, defaultValue) {
|
||||
export default function getAttribute(element, defaultValue) {
|
||||
if (!element) {
|
||||
return defaultValue;
|
||||
}
|
||||
@ -42,5 +42,3 @@ function convertToInt(input) {
|
||||
|
||||
return parseInt(output, 16);
|
||||
}
|
||||
|
||||
export default getAttribute;
|
||||
@ -0,0 +1,26 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { btoa } from 'isomorphic-base64';
|
||||
|
||||
/**
|
||||
* Returns the Authorization header as part of an Object.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
export default function getAuthorizationHeader() {
|
||||
const headers = {};
|
||||
|
||||
// Check for OHIF.user since this can also be run on the server
|
||||
const accessToken = OHIF.user && OHIF.user.getAccessToken && OHIF.user.getAccessToken();
|
||||
const server = OHIF.servers.getCurrentServer();
|
||||
|
||||
if (server &&
|
||||
server.requestOptions &&
|
||||
server.requestOptions.auth) {
|
||||
// HTTP Basic Auth (user:password)
|
||||
headers.Authorization = `Basic ${btoa(server.requestOptions.auth)}`;
|
||||
} else if (accessToken) {
|
||||
headers.Authorization = `Bearer ${accessToken}`;
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
const getModalities = function(modality, modalitiesInStudy) {
|
||||
export default function getModalities(modality, modalitiesInStudy) {
|
||||
var modalities = {};
|
||||
if (modality) {
|
||||
modalities = modality;
|
||||
@ -19,5 +19,3 @@ const getModalities = function(modality, modalitiesInStudy) {
|
||||
}
|
||||
return modalities;
|
||||
};
|
||||
|
||||
export default getModalities;
|
||||
@ -1,25 +1,19 @@
|
||||
import get from './get.js';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
import getAttribute from './getAttribute.js';
|
||||
import getBulkData from './getBulkData.js';
|
||||
import getJSON from './getJSON.js';
|
||||
import getAuthorizationHeader from './getAuthorizationHeader.js';
|
||||
import getModalities from './getModalities.js';
|
||||
import getName from './getName.js';
|
||||
import getNumber from './getNumber.js';
|
||||
import getString from './getString.js';
|
||||
import getAccessToken from './getAccessToken.js';
|
||||
import makeRequest from './makeRequest.js';
|
||||
|
||||
const DICOMWeb = {
|
||||
get,
|
||||
getAttribute,
|
||||
getBulkData,
|
||||
getJSON,
|
||||
getAuthorizationHeader,
|
||||
getModalities,
|
||||
getName,
|
||||
getNumber,
|
||||
getString,
|
||||
getAccessToken,
|
||||
makeRequest
|
||||
};
|
||||
|
||||
export { DICOMWeb };
|
||||
OHIF.DICOMWeb = DICOMWeb;
|
||||
@ -1 +1,2 @@
|
||||
import './object.js';
|
||||
import './DICOMWeb/';
|
||||
|
||||
@ -16,4 +16,4 @@ OHIF.utils.absoluteUrl = function(path) {
|
||||
}
|
||||
|
||||
return absolutePath.replace(/\/\/+/g, '/');
|
||||
};
|
||||
};
|
||||
|
||||
@ -11,6 +11,7 @@ const OHIF = {
|
||||
viewer: {},
|
||||
cornerstone: {},
|
||||
user: {},
|
||||
DICOMWeb: {}, // Temporarily added
|
||||
};
|
||||
|
||||
// Expose the OHIF object to the client if it is on development mode
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
Npm.depends({
|
||||
'twbs-pagination': '1.4.1'
|
||||
'twbs-pagination': '1.4.1',
|
||||
'isomorphic-base64': '1.0.2',
|
||||
});
|
||||
|
||||
Package.describe({
|
||||
@ -9,7 +10,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('ecmascript');
|
||||
api.use('standard-app-packages');
|
||||
@ -44,5 +45,4 @@ Package.onUse(function(api) {
|
||||
|
||||
// Client and server imports
|
||||
api.addFiles('both/index.js', ['client', 'server']);
|
||||
|
||||
});
|
||||
|
||||
@ -5,7 +5,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.5');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('ecmascript');
|
||||
api.use('ohif:cornerstone');
|
||||
|
||||
@ -15,7 +15,7 @@ Npm.depends({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.5');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('ecmascript');
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4.2.3');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('ecmascript');
|
||||
api.use('standard-app-packages');
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
Package.describe({
|
||||
name: 'ohif:dicomweb-client',
|
||||
summary: 'DICOM Services: DICOMWeb',
|
||||
version: '0.0.1'
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
'url-parse': '1.4.1',
|
||||
'isomorphic-fetch': '2.2.1',
|
||||
'isomorphic-base64': '1.0.2'
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.6');
|
||||
|
||||
api.use('ecmascript');
|
||||
|
||||
// DICOMWeb functions
|
||||
api.mainModule('src/index.js');
|
||||
|
||||
api.export('DICOMWeb');
|
||||
});
|
||||
@ -1,33 +0,0 @@
|
||||
import makeRequest from "./makeRequest";
|
||||
|
||||
/**
|
||||
* Make a request to the URL given a set of options.
|
||||
* This function will add optional timing, request, and respone logging.
|
||||
*
|
||||
* @param {String} url
|
||||
* @param {Object} options
|
||||
* @return {Promise<*>}
|
||||
*/
|
||||
const get = async function get(url, options) {
|
||||
if (options.logRequests) {
|
||||
console.log(url);
|
||||
}
|
||||
|
||||
if (options.logTiming) {
|
||||
console.time(url);
|
||||
}
|
||||
|
||||
const result = await makeRequest(url, options);
|
||||
|
||||
if (options.logTiming) {
|
||||
console.timeEnd(url);
|
||||
}
|
||||
|
||||
if (options.logResponses) {
|
||||
console.info(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export default get;
|
||||
@ -1,14 +0,0 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
export default function getAccessToken() {
|
||||
if (!global.window || !window.sessionStorage || !sessionStorage) {
|
||||
return;
|
||||
}
|
||||
|
||||
const userAccessToken = OHIF.user.getAccessToken();
|
||||
if (userAccessToken) {
|
||||
return userAccessToken;
|
||||
}
|
||||
|
||||
return sessionStorage.token;
|
||||
}
|
||||
@ -1,133 +0,0 @@
|
||||
import get from './get.js';
|
||||
|
||||
const ASCII = 'ascii';
|
||||
|
||||
function getMultipartContentInfo(headers) {
|
||||
const multipartRegex = /^\s*multipart\/[^;]+/g;
|
||||
const contentType = headers.get('content-type');
|
||||
let dict = null;
|
||||
|
||||
if (typeof contentType === 'string' && multipartRegex.test(contentType)) {
|
||||
let match;
|
||||
let pairRegex = /;\s*([^=]+)=([^;\r\n]+)/g;
|
||||
|
||||
pairRegex.lastIndex = multipartRegex.lastIndex;
|
||||
while ((match = pairRegex.exec(contentType)) !== null) {
|
||||
let key = match[1]
|
||||
let value = match[2];
|
||||
|
||||
if (dict === null) {
|
||||
dict = {};
|
||||
}
|
||||
dict[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
function parseContentHeader(data, offset) {
|
||||
const endOfHeader = data.indexOf('\r\n\r\n', offset);
|
||||
|
||||
if (endOfHeader < 0 || endOfHeader <= offset || endOfHeader > data.length) {
|
||||
throw new Error('End of content header cannot be determined...');
|
||||
}
|
||||
|
||||
const header = {
|
||||
start: offset,
|
||||
end: endOfHeader + 4,
|
||||
fields: {}
|
||||
};
|
||||
const headerRegex = /([\w\-]+):\s*([^\r\n]+)(?:\r\n)?/g;
|
||||
const headerContentRegex = /\t([^\r\n]+)(?:\r\n)?/g;
|
||||
const headerString = data.slice(offset, endOfHeader);
|
||||
|
||||
let match;
|
||||
|
||||
while ((match = headerRegex.exec(headerString)) !== null) {
|
||||
const key = match[1].toLowerCase(), value = match[2];
|
||||
|
||||
while (headerString.charAt(headerRegex.lastIndex) === '\t') {
|
||||
headerContentRegex.lastIndex = headerRegex.lastIndex;
|
||||
|
||||
if ((match = headerContentRegex.exec(headerString)) !== null) {
|
||||
headerRegex.lastIndex = headerContentRegex.lastIndex;
|
||||
value += ' ' + match[1];
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
header.fields[key] = value;
|
||||
}
|
||||
|
||||
return header;
|
||||
|
||||
}
|
||||
|
||||
function toBytes(input) {
|
||||
const data = [];
|
||||
for (let i = 0; i < input.length; i++){
|
||||
data.push(input.charCodeAt(i));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
function parseResponse(headers, data) {
|
||||
const contentInfo = getMultipartContentInfo(headers);
|
||||
|
||||
if (!contentInfo || !contentInfo.boundary) {
|
||||
throw new Error('Content boundary not specified...');
|
||||
}
|
||||
|
||||
const boundary = contentInfo.boundary;
|
||||
const delimiter = '--' + boundary + '\r\n';
|
||||
let index = data.indexOf(delimiter, 0, ASCII);
|
||||
|
||||
if (index < 0) {
|
||||
throw new Error('DICOMWeb: The specified boundary could not be found...');
|
||||
}
|
||||
|
||||
let closingIndex
|
||||
let closingDelimiter = '\r\n--' + boundary + '--';
|
||||
|
||||
index += delimiter.length;
|
||||
if (data[index] !== 0x0D || data[index + 1] !== 0x0A) {
|
||||
// multipart content headers are present, so let's parse them...
|
||||
let contentHeader = parseContentHeader(data, index);
|
||||
if (contentHeader && contentHeader.end > index) {
|
||||
if (contentHeader.fields['content-length'] > 0) {
|
||||
let endOfData = contentHeader.end + parseInt(contentHeader.fields['content-length'], 10);
|
||||
if (endOfData === data.indexOf(closingDelimiter, endOfData)) {
|
||||
// content-length is valid...
|
||||
return data.slice(contentHeader.end, endOfData);
|
||||
}
|
||||
}
|
||||
index = contentHeader.end;
|
||||
}
|
||||
} else {
|
||||
// no headers, the content comes right after...
|
||||
index += 2;
|
||||
}
|
||||
|
||||
closingIndex = data.indexOf(closingDelimiter, index);
|
||||
if (closingIndex < 0 || closingIndex < index) {
|
||||
throw new Error('DICOMWeb: The end of the content could not be determined...')
|
||||
}
|
||||
|
||||
return toBytes(data.slice(index, closingIndex));
|
||||
}
|
||||
|
||||
const getBulkData = async function(url, options = {}) {
|
||||
options.headers = options.headers || {};
|
||||
options.headers.Accept = 'multipart/related; type=application/octet-stream';
|
||||
|
||||
const response = await get(url, options);
|
||||
const data = await response.text();
|
||||
|
||||
return parseResponse(response.headers, data);
|
||||
}
|
||||
|
||||
export default getBulkData;
|
||||
@ -1,16 +0,0 @@
|
||||
import get from './get.js';
|
||||
import getAttribute from "./getAttribute";
|
||||
|
||||
const getJSON = async function (url, options) {
|
||||
options.headers = options.headers || {};
|
||||
options.headers.Accept = 'application/json';
|
||||
return get(url, options).then(response => {
|
||||
if (!(response instanceof Response)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return response.json();
|
||||
});
|
||||
};
|
||||
|
||||
export default getJSON;
|
||||
@ -1,69 +0,0 @@
|
||||
import { Meteor } from "meteor/meteor";
|
||||
import URL from 'url-parse';
|
||||
import 'isomorphic-fetch';
|
||||
import { btoa } from 'isomorphic-base64';
|
||||
import getAccessToken from './getAccessToken.js';
|
||||
|
||||
async function makeRequest(url, options) {
|
||||
const parsed = new URL(url);
|
||||
|
||||
let requestOpt = {
|
||||
method: 'GET',
|
||||
headers: {}
|
||||
};
|
||||
|
||||
const accessToken = getAccessToken();
|
||||
if (accessToken) {
|
||||
requestOpt.headers = {
|
||||
Authorization: `Bearer ${accessToken}`
|
||||
};
|
||||
} else if (options.auth) {
|
||||
requestOpt.headers = {
|
||||
Authorization: `Basic ${btoa(options.auth)}`
|
||||
};
|
||||
}
|
||||
|
||||
if (options.headers) {
|
||||
Object.keys(options.headers).forEach(key => {
|
||||
requestOpt.headers[key] = options.headers[key];
|
||||
});
|
||||
}
|
||||
|
||||
if(options.method) {
|
||||
requestOpt.method = options.method;
|
||||
}
|
||||
|
||||
if (options.method === 'POST' && options.body) {
|
||||
requestOpt.body = options.body;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
// TODO: Kept getting weird build errors from RegExp
|
||||
const isAbsolute = parsed.href.indexOf('http://') === 0 || parsed.href.indexOf('https://') === 0;
|
||||
|
||||
let url = parsed.href;
|
||||
|
||||
if (isAbsolute === false) {
|
||||
url = Meteor.absoluteUrl(parsed.href);
|
||||
}
|
||||
|
||||
fetch(url, requestOpt).then((response) => {
|
||||
if (response.status >= 400) {
|
||||
reject(new Error(response.status));
|
||||
}
|
||||
|
||||
if (response.status === 204) {
|
||||
resolve([]);
|
||||
} else {
|
||||
// TODO: Handle 204 no content
|
||||
resolve(response);
|
||||
}
|
||||
}, (error) => {
|
||||
console.error('There was an error in the DICOMWeb Server');
|
||||
|
||||
reject(new Error(error));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export default makeRequest;
|
||||
@ -9,7 +9,7 @@ Npm.depends({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('ecmascript');
|
||||
api.use('standard-app-packages');
|
||||
|
||||
@ -5,7 +5,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4.2.3');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
// Meteor packages
|
||||
api.use('ecmascript');
|
||||
|
||||
@ -9,7 +9,7 @@ Npm.depends({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
// Meteor packages
|
||||
api.use([
|
||||
|
||||
@ -5,7 +5,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('ecmascript');
|
||||
api.use('standard-app-packages');
|
||||
|
||||
@ -9,7 +9,7 @@ Npm.depends({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('ecmascript');
|
||||
api.use('standard-app-packages');
|
||||
|
||||
@ -18,7 +18,7 @@ export const retrieveMeasurements = (patientId, timepointIds) => {
|
||||
|
||||
export const storeMeasurements = (measurementData, timepointIds) => {
|
||||
OHIF.log.info('storeMeasurements');
|
||||
|
||||
|
||||
const server = OHIF.servers.getCurrentServer();
|
||||
if (!server || server.type !== 'dicomWeb') {
|
||||
return Promise.resolve({});
|
||||
@ -28,6 +28,8 @@ export const storeMeasurements = (measurementData, timepointIds) => {
|
||||
|
||||
return stowSRFromMeasurements(measurementData).then( () => {
|
||||
OHIF.studies.deleteStudyMetadataPromise(studyInstanceUid);
|
||||
}, error => {
|
||||
throw new Error(error);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -1,60 +1,51 @@
|
||||
import { dcmjs } from 'meteor/ohif:cornerstone';
|
||||
import retrieveDataFromSR from './retrieveDataFromSR';
|
||||
import retrieveDataFromMeasurements from './retrieveDataFromMeasurements';
|
||||
import {
|
||||
multipartEncode
|
||||
} from './srUtils';
|
||||
|
||||
import DICOMwebClient from 'dicomweb-client';
|
||||
|
||||
const retrieveMeasurementFromSR = async (series) => {
|
||||
const instance = series.getFirstInstance();
|
||||
const options = {
|
||||
method: 'GET',
|
||||
responseType: 'arraybuffer',
|
||||
};
|
||||
const url = instance.getDataProperty('wadouri');
|
||||
const server = OHIF.servers.getCurrentServer();
|
||||
const url = WADOProxy.convertURL(server.wadoRoot, server);
|
||||
|
||||
try {
|
||||
const result = await DICOMWeb.makeRequest(url, options);
|
||||
const data = await result.arrayBuffer();
|
||||
const measurementData = retrieveDataFromSR(data);
|
||||
return Promise.resolve(measurementData);
|
||||
} catch(error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
const config = {
|
||||
url,
|
||||
headers: OHIF.DICOMWeb.getAuthorizationHeader()
|
||||
};
|
||||
|
||||
const dicomWeb = new DICOMwebClient.api.DICOMwebClient(config);
|
||||
|
||||
const instance = series.getFirstInstance();
|
||||
const options = {
|
||||
studyInstanceUID: instance.getStudyInstanceUID(),
|
||||
seriesInstanceUID: instance.getSeriesInstanceUID(),
|
||||
sopInstanceUID: instance.getSOPInstanceUID(),
|
||||
};
|
||||
|
||||
return dicomWeb.retrieveInstance(options).then(retrieveDataFromSR);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the DICOMWeb STOW-RS URL for the current server.
|
||||
*
|
||||
* See ftp://medical.nema.org/medical/dicom/current/output/html/part18.html#sect_6.6.1.1
|
||||
*
|
||||
* @return {string|null} The URL, rerouted to the proxy if the WADOProxy is enabled.
|
||||
*/
|
||||
function getStowRsUrl() {
|
||||
const server = OHIF.servers.getCurrentServer();
|
||||
const url = `${server.wadoRoot}/studies`;
|
||||
|
||||
return WADOProxy.convertURL(url, server);
|
||||
}
|
||||
|
||||
const stowSRFromMeasurements = async (measurements) => {
|
||||
const serverUrl = getStowRsUrl();
|
||||
const server = OHIF.servers.getCurrentServer();
|
||||
const url = WADOProxy.convertURL(server.wadoRoot, server);
|
||||
const reportDataset = retrieveDataFromMeasurements(measurements);
|
||||
const boundary = dcmjs.data.DicomMetaDictionary.uid();
|
||||
const options = {
|
||||
method: 'POST',
|
||||
body: multipartEncode(reportDataset, boundary),
|
||||
headers: {
|
||||
'Content-Type': `multipart/related; type=application/dicom; boundary=${boundary}`
|
||||
}
|
||||
const denaturalizedMetaheader = dcmjs.data.DicomMetaDictionary.denaturalizeDataset(dataset._meta);
|
||||
const dicomDict = new dcmjs.data.DicomDict(denaturalizedMetaheader);
|
||||
|
||||
dicomDict.dict = dcmjs.data.DicomMetaDictionary.denaturalizeDataset(dataset);
|
||||
|
||||
const part10Buffer = dicomDict.write();
|
||||
const config = {
|
||||
url,
|
||||
headers: OHIF.DICOMWeb.getAuthorizationHeader()
|
||||
};
|
||||
|
||||
try {
|
||||
await DICOMWeb.makeRequest(serverUrl, options);
|
||||
return Promise.resolve();
|
||||
} catch(error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
const dicomWeb = new DICOMwebClient.api.DICOMwebClient(config);
|
||||
const options = {
|
||||
datasets: [part10Buffer]
|
||||
};
|
||||
|
||||
return dicomWeb.storeInstances(options);
|
||||
};
|
||||
|
||||
export {
|
||||
|
||||
@ -55,7 +55,7 @@ const getLatestSRSeries = () => {
|
||||
if (supportedSopClassUIDs.includes(sopClassUid)) {
|
||||
if(!latestSeries) {
|
||||
latestSeries = series;
|
||||
} else if (series._data.seriesDate > latestSeries._data.seriesDate ||
|
||||
} else if (series._data.seriesDate > latestSeries._data.seriesDate ||
|
||||
(series._data.seriesDate === latestSeries._data.seriesDate && series._data.seriesTime > latestSeries._data.seriesTime)) {
|
||||
latestSeries = series;
|
||||
}
|
||||
@ -70,36 +70,10 @@ const stringToArray = (string) => {
|
||||
return Uint8Array.from(Array.from(string).map(letter => letter.charCodeAt(0)))
|
||||
};
|
||||
|
||||
const multipartEncode = (dataset, boundary) => {
|
||||
|
||||
const denaturalizedMetaheader = dcmjs.data.DicomMetaDictionary.denaturalizeDataset(dataset._meta);
|
||||
const dicomDict = new dcmjs.data.DicomDict(denaturalizedMetaheader);
|
||||
|
||||
dicomDict.dict = dcmjs.data.DicomMetaDictionary.denaturalizeDataset(dataset);
|
||||
|
||||
const part10Buffer = dicomDict.write();
|
||||
|
||||
const header = `\r\n--${boundary}\r\nContent-Type: application/dicom\r\n\r\n`;
|
||||
const footer = `\r\n--${boundary}--`;
|
||||
|
||||
headerArray = stringToArray(header);
|
||||
contentArray = new Uint8Array(part10Buffer);
|
||||
footerArray = stringToArray(footer);
|
||||
|
||||
const multipartArray = new Uint8Array(headerArray.length + contentArray.length + footerArray.length);
|
||||
|
||||
multipartArray.set(headerArray, 0);
|
||||
multipartArray.set(contentArray, headerArray.length);
|
||||
multipartArray.set(footerArray, headerArray.length + contentArray.length);
|
||||
|
||||
return(multipartArray.buffer);
|
||||
};
|
||||
|
||||
export {
|
||||
codeMeaningEquals,
|
||||
getAllDisplaySets,
|
||||
getInstanceMetadata,
|
||||
getLatestSRSeries,
|
||||
multipartEncode,
|
||||
toArray
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,8 +4,13 @@ Package.describe({
|
||||
version: '0.0.1'
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
'dicomweb-client': '0.3.2',
|
||||
'xhr2': '0.1.4'
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.6');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('ecmascript');
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('ecmascript');
|
||||
api.use('standard-app-packages');
|
||||
|
||||
@ -5,7 +5,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('ecmascript');
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
// Meteor packages
|
||||
api.use('ecmascript');
|
||||
|
||||
@ -5,7 +5,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
// Meteor packages
|
||||
api.use([
|
||||
|
||||
@ -64,15 +64,15 @@ export const DICOMWebServer = new SimpleSchema({
|
||||
imageRendering: {
|
||||
type: String,
|
||||
label: 'Image rendering',
|
||||
allowedValues: ['wadouri', 'wadors', 'orthanc'],
|
||||
valuesLabels: ['WADO URI', 'WADO RS', 'ORTHANC'],
|
||||
allowedValues: ['wadouri', 'wadors'],
|
||||
valuesLabels: ['WADO URI', 'WADO RS'],
|
||||
defaultValue: 'wadouri'
|
||||
},
|
||||
thumbnailRendering: {
|
||||
type: String,
|
||||
label: 'Thumbnail rendering',
|
||||
allowedValues: ['wadouri', 'wadors', 'orthanc'],
|
||||
valuesLabels: ['WADO URI', 'WADO RS', 'ORTHANC'],
|
||||
allowedValues: ['wadouri', 'wadors'],
|
||||
valuesLabels: ['WADO URI', 'WADO RS'],
|
||||
defaultValue: 'wadouri'
|
||||
},
|
||||
qidoRoot: {
|
||||
|
||||
@ -14,7 +14,6 @@ if (Meteor.settings &&
|
||||
const endpoints = servers[serverType];
|
||||
endpoints.forEach((endpoint) => {
|
||||
const server = Object.assign({}, endpoint);
|
||||
server.origin = 'json';
|
||||
server.type = serverType;
|
||||
|
||||
Servers.insert(server);
|
||||
|
||||
@ -5,14 +5,14 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('ecmascript');
|
||||
api.use('templating');
|
||||
api.use('jquery');
|
||||
api.use('stylus');
|
||||
api.use('aldeed:simple-schema');
|
||||
api.use('aldeed:collection2');
|
||||
api.use('templating', 'client');
|
||||
api.use('jquery', 'client');
|
||||
api.use('stylus', 'client');
|
||||
api.use('aldeed:simple-schema@1.5.4');
|
||||
api.use('aldeed:collection2@2.10.0');
|
||||
|
||||
// Our custom packages
|
||||
api.use('ohif:core');
|
||||
|
||||
@ -2,7 +2,6 @@ import { Meteor } from 'meteor/meteor';
|
||||
import { _ } from 'meteor/underscore';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Servers } from 'meteor/ohif:servers/both/collections';
|
||||
import { ServerConfiguration } from 'meteor/ohif:servers/both/schema/servers.js';
|
||||
|
||||
// Check the servers on meteor startup
|
||||
if (Meteor.settings &&
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
/**
|
||||
* Converts the properties to URL query parameters. Based on:
|
||||
* http://stackoverflow.com/questions/111529/create-query-parameters-in-javascript
|
||||
*
|
||||
* @param data
|
||||
* @returns {string}
|
||||
*/
|
||||
encodeQueryData = function(data) {
|
||||
var ret = [];
|
||||
|
||||
for (var d in data) {
|
||||
if (data[d]) {
|
||||
ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d]));
|
||||
}
|
||||
}
|
||||
|
||||
return ret.join('&');
|
||||
};
|
||||
@ -1,2 +1 @@
|
||||
import './encodeQueryData.js';
|
||||
import './parseFloatArray.js';
|
||||
|
||||
@ -1,15 +1,7 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { DICOMWeb } from 'meteor/ohif:dicomweb-client';
|
||||
import DICOMwebClient from 'dicomweb-client';
|
||||
|
||||
/**
|
||||
* Creates a QIDO URL given the server settings and a study instance UID
|
||||
* @param server
|
||||
* @param studyInstanceUid
|
||||
* @returns {string} URL to be used for QIDO calls
|
||||
*/
|
||||
function buildUrl(server, studyInstanceUid) {
|
||||
return server.qidoRoot + '/studies/' + studyInstanceUid + '/instances';
|
||||
}
|
||||
const { DICOMWeb } = OHIF;
|
||||
|
||||
/**
|
||||
* Parses data returned from a QIDO search and transforms it into
|
||||
@ -76,20 +68,23 @@ function resultDataToStudyMetadata(server, studyInstanceUid, resultData) {
|
||||
* @returns {{wadoUriRoot: String, studyInstanceUid: String, seriesList: Array}}
|
||||
*/
|
||||
OHIF.studies.services.QIDO.Instances = function(server, studyInstanceUid) {
|
||||
var url = buildUrl(server, studyInstanceUid);
|
||||
// TODO: Are we using this function anywhere?? Can we remove it?
|
||||
|
||||
try {
|
||||
var result = DICOMWeb.getJSON(url, server.requestOptions);
|
||||
const config = {
|
||||
url: server.qidoRoot,
|
||||
headers: OHIF.DICOMWeb.getAuthorizationHeader()
|
||||
};
|
||||
const dicomWeb = new DICOMwebClient.api.DICOMwebClient(config);
|
||||
const queryParams = getQIDOQueryParams(filter, server.qidoSupportsIncludeField);
|
||||
const options = {
|
||||
studyInstanceUID: studyInstanceUid
|
||||
};
|
||||
|
||||
return dicomWeb.searchForInstances(options).then(result => {
|
||||
return {
|
||||
wadoUriRoot: server.wadoUriRoot,
|
||||
studyInstanceUid: studyInstanceUid,
|
||||
seriesList: resultDataToStudyMetadata(server, studyInstanceUid, result.data)
|
||||
};
|
||||
} catch (error) {
|
||||
OHIF.log.trace();
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,5 +1,14 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { DICOMWeb } from 'meteor/ohif:dicomweb-client';
|
||||
import DICOMwebClient from 'dicomweb-client';
|
||||
|
||||
const { DICOMWeb } = OHIF;
|
||||
|
||||
// TODO: Is there an easier way to do this?
|
||||
if (Meteor.isServer) {
|
||||
var XMLHttpRequest = require('xhr2');
|
||||
|
||||
global.XMLHttpRequest = XMLHttpRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a QIDO date string for a date range query
|
||||
@ -27,7 +36,7 @@ function dateToString(date) {
|
||||
* @param filter
|
||||
* @returns {string} The URL with encoded filter query data
|
||||
*/
|
||||
function filterToQIDOURL(server, filter) {
|
||||
function getQIDOQueryParams(filter, serverSupportsQIDOIncludeField) {
|
||||
const commaSeparatedFields = [
|
||||
'00081030', // Study Description
|
||||
'00080060' //Modality
|
||||
@ -41,7 +50,7 @@ function filterToQIDOURL(server, filter) {
|
||||
StudyDescription: filter.studyDescription,
|
||||
ModalitiesInStudy: filter.modalitiesInStudy,
|
||||
limit: filter.limit,
|
||||
includefield: server.qidoSupportsIncludeField ? 'all' : commaSeparatedFields
|
||||
includefield: serverSupportsQIDOIncludeField ? commaSeparatedFields : 'all'
|
||||
};
|
||||
|
||||
// build the StudyDate range parameter
|
||||
@ -59,7 +68,16 @@ function filterToQIDOURL(server, filter) {
|
||||
parameters.StudyInstanceUID = studyUids;
|
||||
}
|
||||
|
||||
return server.qidoRoot + '/studies?' + encodeQueryData(parameters);
|
||||
// Clean query params of undefined values.
|
||||
const params = {};
|
||||
Object.keys(parameters).forEach(key => {
|
||||
if (parameters[key] !== undefined &&
|
||||
parameters[key] !== "") {
|
||||
params[key] = parameters[key];
|
||||
}
|
||||
});
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,13 +116,16 @@ function resultDataToStudies(resultData) {
|
||||
}
|
||||
|
||||
OHIF.studies.services.QIDO.Studies = (server, filter) => {
|
||||
const url = filterToQIDOURL(server, filter);
|
||||
const config = {
|
||||
url: server.qidoRoot,
|
||||
headers: OHIF.DICOMWeb.getAuthorizationHeader()
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
DICOMWeb.getJSON(url, server.requestOptions).then(result => {
|
||||
const studies = resultDataToStudies(result);
|
||||
const dicomWeb = new DICOMwebClient.api.DICOMwebClient(config);
|
||||
const queryParams = getQIDOQueryParams(filter, server.qidoSupportsIncludeField);
|
||||
const options = {
|
||||
queryParams
|
||||
};
|
||||
|
||||
resolve(studies);
|
||||
}, reject);
|
||||
});
|
||||
return dicomWeb.searchForStudies(options).then(resultDataToStudies);
|
||||
};
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { DICOMWeb } from 'meteor/ohif:dicomweb-client';
|
||||
import DICOMwebClient from 'dicomweb-client';
|
||||
|
||||
import { parseFloatArray } from '../../lib/parseFloatArray';
|
||||
|
||||
const { DICOMWeb } = OHIF;
|
||||
|
||||
/**
|
||||
* Simple cache schema for retrieved color palettes.
|
||||
*/
|
||||
@ -39,17 +42,6 @@ const paletteColorCache = {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a URL for a WADO search
|
||||
*
|
||||
* @param server
|
||||
* @param studyInstanceUid
|
||||
* @returns {string}
|
||||
*/
|
||||
function buildUrl(server, studyInstanceUid) {
|
||||
return server.wadoRoot + '/studies/' + studyInstanceUid + '/metadata';
|
||||
}
|
||||
|
||||
/** Returns a WADO url for an instance
|
||||
*
|
||||
* @param studyInstanceUid
|
||||
@ -58,6 +50,7 @@ function buildUrl(server, studyInstanceUid) {
|
||||
* @returns {string}
|
||||
*/
|
||||
function buildInstanceWadoUrl(server, studyInstanceUid, seriesInstanceUid, sopInstanceUid) {
|
||||
// TODO: This can be removed, since DICOMWebClient has the same function. Not urgent, though
|
||||
const params = [];
|
||||
|
||||
params.push('requestType=WADO');
|
||||
@ -102,23 +95,47 @@ function getSourceImageInstanceUid(instance) {
|
||||
}
|
||||
|
||||
function getPaletteColor(server, instance, tag, lutDescriptor) {
|
||||
const lut = [];
|
||||
const numLutEntries = lutDescriptor[0];
|
||||
const bits = lutDescriptor[2];
|
||||
const uri = WADOProxy.convertURL(instance[tag].BulkDataURI, server)
|
||||
const bulkDataPromise = DICOMWeb.getBulkData(uri);
|
||||
|
||||
return bulkDataPromise.then(data => {
|
||||
for (var i = 0; i < numLutEntries; i++) {
|
||||
if(bits === 16) {
|
||||
lut[i] = data[i * 65536] + data[i + 1];
|
||||
let uri = WADOProxy.convertURL(instance[tag].BulkDataURI, server)
|
||||
|
||||
// TODO: Workaround for dcm4chee behind SSL-terminating proxy returning
|
||||
// incorrect bulk data URIs
|
||||
if (server.wadoRoot.indexOf('https') === 0 &&
|
||||
!uri.includes('https')) {
|
||||
uri = uri.replace('http', 'https');
|
||||
}
|
||||
|
||||
const config = {
|
||||
url: server.wadoRoot, //BulkDataURI is absolute, so this isn't used
|
||||
headers: OHIF.DICOMWeb.getAuthorizationHeader()
|
||||
};
|
||||
const dicomWeb = new DICOMwebClient.api.DICOMwebClient(config);
|
||||
const options = {
|
||||
BulkDataURI: uri
|
||||
};
|
||||
|
||||
const readUInt16 = (byteArray, position) => {
|
||||
return byteArray[position] + (byteArray[position + 1] * 256);
|
||||
}
|
||||
|
||||
const arrayBufferToPaletteColorLUT = (arraybuffer) =>{
|
||||
const byteArray = new Uint8Array(arraybuffer);
|
||||
const lut = [];
|
||||
|
||||
for (let i = 0; i < numLutEntries; i++) {
|
||||
if (bits === 16) {
|
||||
lut[i] = readUInt16(byteArray, i * 2);
|
||||
} else {
|
||||
lut[i] = data[i];
|
||||
lut[i] = byteArray[i];
|
||||
}
|
||||
}
|
||||
|
||||
return lut;
|
||||
})
|
||||
}
|
||||
|
||||
return dicomWeb.retrieveBulkData(options).then(arrayBufferToPaletteColorLUT)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,13 +146,15 @@ function getPaletteColor(server, instance, tag, lutDescriptor) {
|
||||
* @returns {String} The ReferenceSOPInstanceUID
|
||||
*/
|
||||
async function getPaletteColors(server, instance, lutDescriptor) {
|
||||
let entry = null;
|
||||
let paletteUID = DICOMWeb.getString(instance['00281199']);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (paletteColorCache.isValidUID(paletteUID)) {
|
||||
entry = paletteColorCache.get(paletteUID);
|
||||
return resolve(entry);
|
||||
const entry = paletteColorCache.get(paletteUID);
|
||||
|
||||
if (entry) {
|
||||
return resolve(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// no entry in cache... Fetch remote data.
|
||||
@ -146,7 +165,11 @@ async function getPaletteColors(server, instance, lutDescriptor) {
|
||||
const promises = [r, g, b];
|
||||
|
||||
Promise.all(promises).then((args) => {
|
||||
entry = { red: r, green: g, blue: b };
|
||||
entry = {
|
||||
red: args[0],
|
||||
green: args[1],
|
||||
blue: args[2]
|
||||
};
|
||||
|
||||
// when paletteUID is present, the entry can be cached...
|
||||
entry.uid = paletteUID;
|
||||
@ -202,9 +225,6 @@ function getRadiopharmaceuticalInfo(instance) {
|
||||
* @returns {{seriesList: Array, patientName: *, patientId: *, accessionNumber: *, studyDate: *, modalities: *, studyDescription: *, imageCount: *, studyInstanceUid: *}}
|
||||
*/
|
||||
async function resultDataToStudyMetadata(server, studyInstanceUid, resultData) {
|
||||
const seriesMap = {};
|
||||
const seriesList = [];
|
||||
|
||||
if (!resultData.length) {
|
||||
return;
|
||||
}
|
||||
@ -215,7 +235,9 @@ async function resultDataToStudyMetadata(server, studyInstanceUid, resultData) {
|
||||
}
|
||||
|
||||
const studyData = {
|
||||
seriesList,
|
||||
seriesList: [],
|
||||
studyInstanceUid,
|
||||
wadoUriRoot: server.wadoUriRoot,
|
||||
patientName: DICOMWeb.getName(anInstance['00100010']),
|
||||
patientId: DICOMWeb.getString(anInstance['00100020']),
|
||||
patientAge: DICOMWeb.getNumber(anInstance['00101010']),
|
||||
@ -230,9 +252,12 @@ async function resultDataToStudyMetadata(server, studyInstanceUid, resultData) {
|
||||
institutionName: DICOMWeb.getString(anInstance['00080080'])
|
||||
};
|
||||
|
||||
const seriesMap = {};
|
||||
|
||||
await Promise.all(resultData.map(async function(instance) {
|
||||
var seriesInstanceUid = DICOMWeb.getString(instance['0020000E']);
|
||||
var series = seriesMap[seriesInstanceUid];
|
||||
const seriesInstanceUid = DICOMWeb.getString(instance['0020000E']);
|
||||
let series = seriesMap[seriesInstanceUid];
|
||||
|
||||
if (!series) {
|
||||
series = {
|
||||
seriesDescription: DICOMWeb.getString(instance['0008103E']),
|
||||
@ -244,7 +269,7 @@ async function resultDataToStudyMetadata(server, studyInstanceUid, resultData) {
|
||||
instances: []
|
||||
};
|
||||
seriesMap[seriesInstanceUid] = series;
|
||||
seriesList.push(series);
|
||||
studyData.seriesList.push(series);
|
||||
}
|
||||
|
||||
const sopInstanceUid = DICOMWeb.getString(instance['00080018']);
|
||||
@ -331,22 +356,23 @@ async function resultDataToStudyMetadata(server, studyInstanceUid, resultData) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieved Study MetaData from a DICOM server using a WADO call
|
||||
* Retrieve Study MetaData from a DICOM server using a WADO call
|
||||
*
|
||||
* @param server
|
||||
* @param studyInstanceUid
|
||||
* @returns {Promise}
|
||||
*/
|
||||
OHIF.studies.services.WADO.RetrieveMetadata = async function(server, studyInstanceUid) {
|
||||
const url = buildUrl(server, studyInstanceUid);
|
||||
const config = {
|
||||
url: server.wadoRoot,
|
||||
headers: OHIF.DICOMWeb.getAuthorizationHeader()
|
||||
};
|
||||
const dicomWeb = new DICOMwebClient.api.DICOMwebClient(config);
|
||||
const options = {
|
||||
studyInstanceUID: studyInstanceUid
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
DICOMWeb.getJSON(url, server.requestOptions).then(result => {
|
||||
resultDataToStudyMetadata(server, studyInstanceUid, result).then((study) => {
|
||||
study.wadoUriRoot = server.wadoUriRoot;
|
||||
study.studyInstanceUid = studyInstanceUid;
|
||||
|
||||
resolve(study);
|
||||
}, reject);
|
||||
}, reject);
|
||||
return dicomWeb.retrieveStudyMetadata(options).then(result => {
|
||||
return resultDataToStudyMetadata(server, studyInstanceUid, result);
|
||||
});
|
||||
};
|
||||
|
||||
@ -5,11 +5,13 @@ Package.describe({
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
dimse: '0.0.2'
|
||||
})
|
||||
dimse: '0.0.2',
|
||||
'dicomweb-client': '0.3.2',
|
||||
'xhr2': '0.1.4'
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.6');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use([
|
||||
'ecmascript',
|
||||
@ -24,7 +26,6 @@ Package.onUse(function(api) {
|
||||
'ohif:core',
|
||||
'ohif:log',
|
||||
'ohif:servers',
|
||||
'ohif:dicomweb-client',
|
||||
'ohif:viewerbase',
|
||||
'ohif:wadoproxy'
|
||||
]);
|
||||
|
||||
@ -15,7 +15,6 @@ Template.studylistResult.helpers({
|
||||
*/
|
||||
studies() {
|
||||
const instance = Template.instance();
|
||||
let studies;
|
||||
let sortOption = {
|
||||
patientName: 1,
|
||||
studyDate: 1
|
||||
@ -32,7 +31,7 @@ Template.studylistResult.helpers({
|
||||
const offset = rowsPerPage * currentPage;
|
||||
const limit = offset + rowsPerPage;
|
||||
|
||||
studies = OHIF.studylist.collections.Studies.find({}, {
|
||||
const studies = OHIF.studylist.collections.Studies.find({}, {
|
||||
sort: sortOption
|
||||
}).fetch();
|
||||
|
||||
@ -90,17 +89,6 @@ function getFilter(filter) {
|
||||
return filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a value in a string
|
||||
*/
|
||||
function isIndexOf(mainVal, searchVal) {
|
||||
if (mainVal === undefined || mainVal === '' || mainVal.indexOf(searchVal) > -1){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace object if undefined
|
||||
*/
|
||||
@ -167,10 +155,21 @@ function search() {
|
||||
|
||||
// Loop through all identified studies
|
||||
studies.forEach(study => {
|
||||
// TODO: Why is this Modality filter different from QIDO?
|
||||
if (modality !== "" && study.modalities.includes(modality)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sometimes DICOM studies have incorrect Date entries with
|
||||
// periods such as '1990.10.04'
|
||||
let studyDate = study.studyDate;
|
||||
if (studyDate && studyDate.includes('.')) {
|
||||
studyDate = studyDate.replace('.', '');
|
||||
}
|
||||
|
||||
// Search the rest of the parameters that aren't done via the server call
|
||||
if (isIndexOf(study.modalities, modality) &&
|
||||
(new Date(studyDateFrom).setHours(0, 0, 0, 0) <= convertStringToStudyDate(study.studyDate) || !studyDateFrom || studyDateFrom === '') &&
|
||||
(convertStringToStudyDate(study.studyDate) <= new Date(studyDateTo).setHours(0, 0, 0, 0) || !studyDateTo || studyDateTo === '')) {
|
||||
if ((new Date(studyDateFrom).setHours(0, 0, 0, 0) <= studyDate || !studyDateFrom ) &&
|
||||
(studyDate <= new Date(studyDateTo).setHours(0, 0, 0, 0) || !studyDateTo || studyDateTo === '')) {
|
||||
|
||||
// Convert numberOfStudyRelatedInstance string into integer
|
||||
study.numberOfStudyRelatedInstances = !isNaN(study.numberOfStudyRelatedInstances) ? parseInt(study.numberOfStudyRelatedInstances) : undefined;
|
||||
|
||||
@ -10,7 +10,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('ecmascript');
|
||||
api.use('standard-app-packages');
|
||||
|
||||
@ -5,7 +5,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4.2.3');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('ecmascript');
|
||||
api.use('templating');
|
||||
|
||||
@ -5,7 +5,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4.2.3');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('stylus');
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('ecmascript');
|
||||
api.use('standard-app-packages');
|
||||
|
||||
@ -5,7 +5,7 @@ Package.describe({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use(['ecmascript',
|
||||
'standard-app-packages',
|
||||
@ -218,7 +218,7 @@ Package.onUse(function(api) {
|
||||
});
|
||||
|
||||
Package.onTest(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
/*
|
||||
* Really important dependencies to the project
|
||||
|
||||
@ -10,7 +10,7 @@ Npm.depends({
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
api.versionsFrom('1.7');
|
||||
|
||||
api.use('ecmascript');
|
||||
api.use('clinical:router@2.0.19');
|
||||
@ -22,7 +22,7 @@ Package.onUse(function(api) {
|
||||
api.addFiles('both/convertURL.js', ['client', 'server']);
|
||||
api.addFiles('both/initialize.js', ['client', 'server']);
|
||||
api.addFiles('server/routes.js', 'server');
|
||||
|
||||
|
||||
// Global exports
|
||||
api.export('WADOProxy');
|
||||
});
|
||||
|
||||
@ -27,7 +27,6 @@ ohif:cornerstone-settings
|
||||
ohif:viewerbase
|
||||
ohif:metadata
|
||||
ohif:study-list
|
||||
ohif:dicomweb-client
|
||||
ohif:measurement-table
|
||||
|
||||
aldeed:template-extension
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
accounts-base@1.4.2
|
||||
aldeed:collection2@2.10.0
|
||||
aldeed:collection2-core@1.2.0
|
||||
aldeed:schema-deny@1.1.0
|
||||
@ -28,7 +27,6 @@ cultofcoders:persistent-session@0.4.5
|
||||
ddp@1.4.0
|
||||
ddp-client@2.3.3
|
||||
ddp-common@1.4.0
|
||||
ddp-rate-limiter@1.0.7
|
||||
ddp-server@2.2.0
|
||||
deps@1.0.12
|
||||
diff-sequence@1.1.0
|
||||
@ -54,7 +52,6 @@ iron:layout@1.0.12
|
||||
jquery@1.11.11
|
||||
launch-screen@1.1.1
|
||||
livedata@1.0.18
|
||||
localstorage@1.2.0
|
||||
logging@1.1.20
|
||||
mdg:validation-error@0.5.1
|
||||
meteor@1.9.2
|
||||
@ -81,7 +78,6 @@ ohif:core@0.0.1
|
||||
ohif:cornerstone@0.0.1
|
||||
ohif:cornerstone-settings@0.0.1
|
||||
ohif:design@0.0.1
|
||||
ohif:dicomweb-client@0.0.1
|
||||
ohif:hanging-protocols@0.0.1
|
||||
ohif:header@0.0.1
|
||||
ohif:hotkeys@0.0.1
|
||||
@ -102,13 +98,11 @@ ordered-dict@1.1.0
|
||||
promise@0.11.1
|
||||
raix:eventemitter@0.1.3
|
||||
random@1.1.0
|
||||
rate-limit@1.0.9
|
||||
reactive-dict@1.2.0
|
||||
reactive-var@1.0.11
|
||||
reload@1.2.0
|
||||
retry@1.1.0
|
||||
routepolicy@1.0.13
|
||||
service-configuration@1.0.11
|
||||
session@1.1.7
|
||||
shell-server@0.3.1
|
||||
silentcicero:jszip@0.0.4
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
"wadoUriRoot": "http://localhost:8042/wado",
|
||||
"qidoRoot": "http://localhost:8042/dicom-web",
|
||||
"wadoRoot": "http://localhost:8042/dicom-web",
|
||||
"qidoSupportsIncludeField": false,
|
||||
"qidoSupportsIncludeField": true,
|
||||
"imageRendering": "wadouri",
|
||||
"thumbnailRendering": "wadouri",
|
||||
"requestOptions": {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user