Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | 34x 288x 288x 288x 345x 288x 288x 288x 288x 288x 288x 288x 1152x 288x 288x 288x 288x 288x 144x 144x 144x 144x 288x 288x 2736x 1440x 288x | /** * QIDO - Query based on ID for DICOM Objects * search for studies, series and instances by patient ID, and receive their * unique identifiers for further usage. * * Quick: https://www.dicomstandard.org/dicomweb/query-qido-rs/ * Standard: http://dicom.nema.org/medical/dicom/current/output/html/part18.html#sect_10.6 * * Routes: * ========== * /studies? * /studies/{studyInstanceUid}/series? * /studies/{studyInstanceUid}/series/{seriesInstanceUid}/instances? * * Query Parameters: * ================ * | KEY | VALUE | * |------------------|--------------------| * | {attributeId} | {value} | * | includeField | {attribute} or all | * | fuzzymatching | true OR false | * | limit | {number} | * | offset | {number} | */ import { DICOMWeb, utils } from '@ohif/core'; import { sortStudySeries } from '@ohif/core/src/utils/sortStudy'; const { getString, getName, getModalities } = DICOMWeb; /** * Parses resulting data from a QIDO call into a set of Study MetaData * * @param {Array} qidoStudies - An array of study objects. Each object contains a keys for DICOM tags. * @param {object} qidoStudies[0].qidoStudy - An object where each key is the DICOM Tag group+element * @param {object} qidoStudies[0].qidoStudy[dicomTag] - Optional object that represents DICOM Tag * @param {string} qidoStudies[0].qidoStudy[dicomTag].vr - Value Representation * @param {string[]} qidoStudies[0].qidoStudy[dicomTag].Value - Optional string array representation of the DICOM Tag's value * @returns {Array} An array of Study MetaData objects */ function processResults(qidoStudies) { Iif (!qidoStudies || !qidoStudies.length) { return []; } const studies = []; qidoStudies.forEach(qidoStudy => studies.push({ studyInstanceUid: getString(qidoStudy['0020000D']), date: getString(qidoStudy['00080020']), // YYYYMMDD time: getString(qidoStudy['00080030']), // HHmmss.SSS (24-hour, minutes, seconds, fractional seconds) accession: getString(qidoStudy['00080050']) || '', // short string, probably a number? mrn: getString(qidoStudy['00100020']) || '', // medicalRecordNumber patientName: utils.formatPN(getName(qidoStudy['00100010'])) || '', instances: Number(getString(qidoStudy['00201208'])) || 0, // number description: getString(qidoStudy['00081030']) || '', modalities: getString(getModalities(qidoStudy['00080060'], qidoStudy['00080061'])) || '', }) ); return studies; } /** * Parses resulting data from a QIDO call into a set of Study MetaData * * @param {Array} qidoSeries - An array of study objects. Each object contains a keys for DICOM tags. * @param {object} qidoSeries[0].qidoSeries - An object where each key is the DICOM Tag group+element * @param {object} qidoSeries[0].qidoSeries[dicomTag] - Optional object that represents DICOM Tag * @param {string} qidoSeries[0].qidoSeries[dicomTag].vr - Value Representation * @param {string[]} qidoSeries[0].qidoSeries[dicomTag].Value - Optional string array representation of the DICOM Tag's value * @returns {Array} An array of Study MetaData objects */ export function processSeriesResults(qidoSeries) { const series = []; Iif (qidoSeries && qidoSeries.length) { qidoSeries.forEach(qidoSeries => series.push({ studyInstanceUid: getString(qidoSeries['0020000D']), seriesInstanceUid: getString(qidoSeries['0020000E']), modality: getString(qidoSeries['00080060']), seriesNumber: getString(qidoSeries['00200011']), seriesDate: utils.formatDate(getString(qidoSeries['00080021'])), numSeriesInstances: Number(getString(qidoSeries['00201209'])), description: getString(qidoSeries['0008103E']), }) ); } sortStudySeries(series); return series; } /** * * @param {object} dicomWebClient - Client similar to what's provided by `dicomweb-client` library * @param {function} dicomWebClient.searchForStudies - * @param {string} [studyInstanceUid] * @param {string} [seriesInstanceUid] * @param {string} [queryParamaters] * @returns {Promise<results>} - Promise that resolves results */ async function search(dicomWebClient, studyInstanceUid, seriesInstanceUid, queryParameters) { let searchResult = await dicomWebClient.searchForStudies({ studyInstanceUid: undefined, queryParams: queryParameters, }); return searchResult; } /** * * @param {string} studyInstanceUID - ID of study to return a list of series for * @returns {Promise} - Resolves SeriesMetadata[] in study */ export function seriesInStudy(dicomWebClient, studyInstanceUID) { // Series Description // Already included? const commaSeparatedFields = ['0008103E', '00080021'].join(','); const queryParams = { includefield: commaSeparatedFields, }; return dicomWebClient.searchForSeries({ studyInstanceUID, queryParams }); } export default function searchStudies(server, filter) { const queryParams = getQIDOQueryParams(filter, server.qidoSupportsIncludeField); const options = { queryParams, }; return dicomWeb.searchForStudies(options).then(resultDataToStudies); } /** * Produces a QIDO URL given server details and a set of specified search filter * items * * @param filter * @param serverSupportsQIDOIncludeField * @returns {string} The URL with encoded filter query data */ function mapParams(params, options = {}) { Iif (!params) { return; } const commaSeparatedFields = [ '00081030', // Study Description '00080060', // Modality // Add more fields here if you want them in the result ].join(','); const useWildcard = params?.disableWildcard !== undefined ? !params.disableWildcard : options.supportsWildcard; const withWildcard = value => { return useWildcard && value ? `*${value}*` : value; }; const parameters = { // Named PatientName: withWildcard(params.patientName), //PatientID: withWildcard(params.patientId), '00100020': withWildcard(params.patientId), // Temporarily to make the tests pass with dicomweb-server.. Apparently it's broken? AccessionNumber: withWildcard(params.accessionNumber), StudyDescription: withWildcard(params.studyDescription), ModalitiesInStudy: params.modalitiesInStudy, // Other limit: params.limit || 101, offset: params.offset || 0, fuzzymatching: options.supportsFuzzyMatching === true, includefield: commaSeparatedFields, // serverSupportsQIDOIncludeField ? commaSeparatedFields : 'all', }; // build the StudyDate range parameter Iif (params.startDate && params.endDate) { parameters.StudyDate = `${params.startDate}-${params.endDate}`; } else Iif (params.startDate) { const today = new Date(); const DD = String(today.getDate()).padStart(2, '0'); const MM = String(today.getMonth() + 1).padStart(2, '0'); //January is 0! const YYYY = today.getFullYear(); const todayStr = `${YYYY}${MM}${DD}`; parameters.StudyDate = `${params.startDate}-${todayStr}`; } else Iif (params.endDate) { const oldDateStr = `19700102`; parameters.StudyDate = `${oldDateStr}-${params.endDate}`; } // Build the StudyInstanceUID parameter if (params.studyInstanceUid) { let studyUids = params.studyInstanceUid; studyUids = Array.isArray(studyUids) ? studyUids.join() : studyUids; studyUids = studyUids.replace(/[^0-9.]+/g, '\\'); parameters.StudyInstanceUID = studyUids; } // Clean query params of undefined values. const final = {}; Object.keys(parameters).forEach(key => { if (parameters[key] !== undefined && parameters[key] !== '') { final[key] = parameters[key]; } }); return final; } export { mapParams, search, processResults }; |