-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy path206.bundle.830a70c0017adcf82b90.js.map
1 lines (1 loc) · 431 KB
/
206.bundle.830a70c0017adcf82b90.js.map
1
{"version":3,"file":"206.bundle.830a70c0017adcf82b90.js","mappings":"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","sources":["webpack:///../../../extensions/default/src/DicomWebDataSource/qido.js","webpack:///../../../extensions/default/src/DicomWebDataSource/utils/getImageId.js","webpack:///../../../extensions/default/src/DicomWebDataSource/utils/getWADORSImageId.js","webpack:///../../../extensions/default/src/DicomWebDataSource/wado/retrieveMetadataLoader.js","webpack:///../../../extensions/default/src/DicomWebDataSource/wado/retrieveMetadataLoaderSync.js","webpack:///../../../extensions/default/src/DicomWebDataSource/wado/retrieveMetadataLoaderAsync.js","webpack:///../../../extensions/default/src/DicomWebDataSource/wado/retrieveMetadata.js","webpack:///../../../extensions/default/src/DicomWebDataSource/utils/retrieveMetadataFiltered.js","webpack:///../../../extensions/default/src/DicomWebDataSource/retrieveStudyMetadata.js","webpack:///../../../extensions/default/src/DicomWebDataSource/utils/findIndexOfString.ts","webpack:///../../../extensions/default/src/DicomWebDataSource/utils/fixMultipart.ts","webpack:///../../../extensions/default/src/DicomWebDataSource/utils/StaticWadoClient.ts","webpack:///../../../extensions/default/src/utils/getDirectURL.js","webpack:///../../../extensions/default/src/DicomWebDataSource/utils/fixBulkDataURI.ts","webpack:///../../../extensions/default/src/DicomWebDataSource/index.js","webpack:///../../../extensions/default/src/DicomWebDataSource/dcm4cheeReject.js","webpack:///../../../extensions/default/src/DicomJSONDataSource/index.js","webpack:///../../../extensions/default/src/DicomLocalDataSource/index.js","webpack:///../../../extensions/default/src/DicomWebProxyDataSource/index.js","webpack:///../../../extensions/default/src/MergeDataSource/index.ts","webpack:///../../../extensions/default/src/getDataSourcesModule.js","webpack:///../../../extensions/default/src/Toolbar/Toolbar.tsx","webpack:///../../../extensions/default/src/ViewerLayout/ViewerHeader.tsx","webpack:///../../../extensions/default/src/Components/SidePanelWithServices.tsx","webpack:///../../../extensions/default/src/ViewerLayout/index.tsx","webpack:///../../../extensions/default/src/Panels/PanelStudyBrowser.tsx","webpack:///../../../extensions/default/src/Panels/getImageSrcFromImageId.js","webpack:///../../../extensions/default/src/Panels/getStudiesForPatientByMRN.js","webpack:///../../../extensions/default/src/Panels/requestDisplaySetCreationForStudy.js","webpack:///../../../extensions/default/src/Panels/WrappedPanelStudyBrowser.tsx","webpack:///../../../extensions/default/src/Panels/createReportDialogPrompt.tsx","webpack:///../../../extensions/default/src/Actions/createReportAsync.tsx","webpack:///../../../extensions/default/src/utils/getNextSRSeriesNumber.js","webpack:///../../../extensions/default/src/utils/findSRWithSameSeriesDescription.ts","webpack:///../../../extensions/default/src/Panels/PanelMeasurementTable.tsx","webpack:///../../../extensions/default/src/getPanelModule.tsx","webpack:///../../../extensions/default/src/id.js","webpack:///../../../extensions/default/src/utils/validations/areAllImagePositionsEqual.ts","webpack:///../../../extensions/default/src/utils/calculateScanAxisNormal.ts","webpack:///../../../extensions/default/src/utils/validations/checkSingleFrames.ts","webpack:///../../../extensions/default/src/utils/validations/areAllImageDimensionsEqual.ts","webpack:///../../../extensions/default/src/utils/validations/areAllImageComponentsEqual.ts","webpack:///../../../extensions/default/src/utils/validations/areAllImageOrientationsEqual.ts","webpack:///../../../extensions/default/src/utils/validations/areAllImageSpacingEqual.ts","webpack:///../../../extensions/default/src/getDisplaySetMessages.ts","webpack:///../../../extensions/default/src/utils/validations/checkMultiframe.ts","webpack:///../../../extensions/default/src/getDisplaySetsFromUnsupportedSeries.js","webpack:///../../../extensions/default/src/SOPClassHandlers/chartSOPClassHandler.ts","webpack:///../../../extensions/default/src/getSopClassHandlerModule.js","webpack:///../../../extensions/default/src/Toolbar/ToolbarDivider.tsx","webpack:///../../../extensions/default/src/Toolbar/ToolbarLayoutSelector.tsx","webpack:///../../../extensions/default/src/Toolbar/ToolbarSplitButtonWithServices.tsx","webpack:///../../../extensions/default/src/Toolbar/ToolbarButtonGroupWithServices.tsx","webpack:///../../../extensions/default/src/components/ProgressDropdownWithService/ProgressDropdownWithService.tsx","webpack:///../../../extensions/default/src/CustomizableContextMenu/ContextMenuItemsBuilder.ts","webpack:///../../../extensions/default/src/CustomizableContextMenu/ContextMenuController.tsx","webpack:///../../../extensions/default/src/CustomizableContextMenu/defaultContextMenu.ts","webpack:///../../../extensions/default/src/DicomTagBrowser/DicomTagTable.tsx","webpack:///../../../extensions/default/src/DicomTagBrowser/DicomTagBrowser.tsx","webpack:///../../../extensions/default/src/utils/reuseCachedLayouts.ts","webpack:///../../../extensions/default/src/findViewportsByPosition.ts","webpack:///../../../extensions/default/src/commandsModule.ts","webpack:///../../../extensions/default/src/hpMNGrid.ts","webpack:///../../../extensions/default/src/hpCompare.ts","webpack:///../../../extensions/default/src/getHangingProtocolModule.js","webpack:///../../../extensions/default/src/Panels/DataSourceSelector.tsx","webpack:///../../../extensions/default/src/Components/ItemListComponent.tsx","webpack:///../../../extensions/default/src/Components/DataSourceConfigurationModalComponent.tsx","webpack:///../../../extensions/default/src/Components/DataSourceConfigurationComponent.tsx","webpack:///../../../extensions/default/src/DataSourceConfigurationAPI/GoogleCloudDataSourceConfigurationAPI.ts","webpack:///../../../extensions/default/src/Components/LineChartViewport/LineChartViewport.tsx","webpack:///../../../extensions/default/src/getPTImageIdInstanceMetadata.ts","webpack:///../../../extensions/default/src/init.ts","webpack:///../../../extensions/default/src/index.ts","webpack:///../../../extensions/default/src/getViewportModule.tsx","webpack:///../../../extensions/default/src/getLayoutTemplateModule.js","webpack:///../../../extensions/default/src/getToolbarModule.tsx","webpack:///../../../extensions/default/src/getCustomizationModule.tsx"],"sourcesContent":["/**\n * QIDO - Query based on ID for DICOM Objects\n * search for studies, series and instances by patient ID, and receive their\n * unique identifiers for further usage.\n *\n * Quick: https://www.dicomstandard.org/dicomweb/query-qido-rs/\n * Standard: http://dicom.nema.org/medical/dicom/current/output/html/part18.html#sect_10.6\n *\n * Routes:\n * ==========\n * /studies?\n * /studies/{studyInstanceUid}/series?\n * /studies/{studyInstanceUid}/series/{seriesInstanceUid}/instances?\n *\n * Query Parameters:\n * ================\n * | KEY | VALUE |\n * |------------------|--------------------|\n * | {attributeId} | {value} |\n * | includeField | {attribute} or all |\n * | fuzzymatching | true OR false |\n * | limit | {number} |\n * | offset | {number} |\n */\nimport { DICOMWeb, utils } from '@ohif/core';\nimport { sortStudySeries } from '@ohif/core/src/utils/sortStudy';\n\nconst { getString, getName, getModalities } = DICOMWeb;\n\n/**\n * Parses resulting data from a QIDO call into a set of Study MetaData\n *\n * @param {Array} qidoStudies - An array of study objects. Each object contains a keys for DICOM tags.\n * @param {object} qidoStudies[0].qidoStudy - An object where each key is the DICOM Tag group+element\n * @param {object} qidoStudies[0].qidoStudy[dicomTag] - Optional object that represents DICOM Tag\n * @param {string} qidoStudies[0].qidoStudy[dicomTag].vr - Value Representation\n * @param {string[]} qidoStudies[0].qidoStudy[dicomTag].Value - Optional string array representation of the DICOM Tag's value\n * @returns {Array} An array of Study MetaData objects\n */\nfunction processResults(qidoStudies) {\n if (!qidoStudies || !qidoStudies.length) {\n return [];\n }\n\n const studies = [];\n\n qidoStudies.forEach(qidoStudy =>\n studies.push({\n studyInstanceUid: getString(qidoStudy['0020000D']),\n date: getString(qidoStudy['00080020']), // YYYYMMDD\n time: getString(qidoStudy['00080030']), // HHmmss.SSS (24-hour, minutes, seconds, fractional seconds)\n accession: getString(qidoStudy['00080050']) || '', // short string, probably a number?\n mrn: getString(qidoStudy['00100020']) || '', // medicalRecordNumber\n patientName: utils.formatPN(getName(qidoStudy['00100010'])) || '',\n instances: Number(getString(qidoStudy['00201208'])) || 0, // number\n description: getString(qidoStudy['00081030']) || '',\n modalities: getString(getModalities(qidoStudy['00080060'], qidoStudy['00080061'])) || '',\n })\n );\n\n return studies;\n}\n\n/**\n * Parses resulting data from a QIDO call into a set of Study MetaData\n *\n * @param {Array} qidoSeries - An array of study objects. Each object contains a keys for DICOM tags.\n * @param {object} qidoSeries[0].qidoSeries - An object where each key is the DICOM Tag group+element\n * @param {object} qidoSeries[0].qidoSeries[dicomTag] - Optional object that represents DICOM Tag\n * @param {string} qidoSeries[0].qidoSeries[dicomTag].vr - Value Representation\n * @param {string[]} qidoSeries[0].qidoSeries[dicomTag].Value - Optional string array representation of the DICOM Tag's value\n * @returns {Array} An array of Study MetaData objects\n */\nexport function processSeriesResults(qidoSeries) {\n const series = [];\n\n if (qidoSeries && qidoSeries.length) {\n qidoSeries.forEach(qidoSeries =>\n series.push({\n studyInstanceUid: getString(qidoSeries['0020000D']),\n seriesInstanceUid: getString(qidoSeries['0020000E']),\n modality: getString(qidoSeries['00080060']),\n seriesNumber: getString(qidoSeries['00200011']),\n seriesDate: utils.formatDate(getString(qidoSeries['00080021'])),\n numSeriesInstances: Number(getString(qidoSeries['00201209'])),\n description: getString(qidoSeries['0008103E']),\n })\n );\n }\n\n sortStudySeries(series);\n\n return series;\n}\n\n/**\n *\n * @param {object} dicomWebClient - Client similar to what's provided by `dicomweb-client` library\n * @param {function} dicomWebClient.searchForStudies -\n * @param {string} [studyInstanceUid]\n * @param {string} [seriesInstanceUid]\n * @param {string} [queryParamaters]\n * @returns {Promise<results>} - Promise that resolves results\n */\nasync function search(dicomWebClient, studyInstanceUid, seriesInstanceUid, queryParameters) {\n let searchResult = await dicomWebClient.searchForStudies({\n studyInstanceUid: undefined,\n queryParams: queryParameters,\n });\n\n return searchResult;\n}\n\n/**\n *\n * @param {string} studyInstanceUID - ID of study to return a list of series for\n * @returns {Promise} - Resolves SeriesMetadata[] in study\n */\nexport function seriesInStudy(dicomWebClient, studyInstanceUID) {\n // Series Description\n // Already included?\n const commaSeparatedFields = ['0008103E', '00080021'].join(',');\n const queryParams = {\n includefield: commaSeparatedFields,\n };\n\n return dicomWebClient.searchForSeries({ studyInstanceUID, queryParams });\n}\n\nexport default function searchStudies(server, filter) {\n const queryParams = getQIDOQueryParams(filter, server.qidoSupportsIncludeField);\n const options = {\n queryParams,\n };\n\n return dicomWeb.searchForStudies(options).then(resultDataToStudies);\n}\n\n/**\n * Produces a QIDO URL given server details and a set of specified search filter\n * items\n *\n * @param filter\n * @param serverSupportsQIDOIncludeField\n * @returns {string} The URL with encoded filter query data\n */\nfunction mapParams(params, options = {}) {\n if (!params) {\n return;\n }\n const commaSeparatedFields = [\n '00081030', // Study Description\n '00080060', // Modality\n // Add more fields here if you want them in the result\n ].join(',');\n\n const { supportsWildcard } = options;\n const withWildcard = value => {\n return supportsWildcard && value ? `*${value}*` : value;\n };\n\n const parameters = {\n // Named\n PatientName: withWildcard(params.patientName),\n //PatientID: withWildcard(params.patientId),\n '00100020': withWildcard(params.patientId), // Temporarily to make the tests pass with dicomweb-server.. Apparently it's broken?\n AccessionNumber: withWildcard(params.accessionNumber),\n StudyDescription: withWildcard(params.studyDescription),\n ModalitiesInStudy: params.modalitiesInStudy,\n // Other\n limit: params.limit || 101,\n offset: params.offset || 0,\n fuzzymatching: options.supportsFuzzyMatching === true,\n includefield: commaSeparatedFields, // serverSupportsQIDOIncludeField ? commaSeparatedFields : 'all',\n };\n\n // build the StudyDate range parameter\n if (params.startDate && params.endDate) {\n parameters.StudyDate = `${params.startDate}-${params.endDate}`;\n } else if (params.startDate) {\n const today = new Date();\n const DD = String(today.getDate()).padStart(2, '0');\n const MM = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!\n const YYYY = today.getFullYear();\n const todayStr = `${YYYY}${MM}${DD}`;\n\n parameters.StudyDate = `${params.startDate}-${todayStr}`;\n } else if (params.endDate) {\n const oldDateStr = `19700102`;\n\n parameters.StudyDate = `${oldDateStr}-${params.endDate}`;\n }\n\n // Build the StudyInstanceUID parameter\n if (params.studyInstanceUid) {\n let studyUids = params.studyInstanceUid;\n studyUids = Array.isArray(studyUids) ? studyUids.join() : studyUids;\n studyUids = studyUids.replace(/[^0-9.]+/g, '\\\\');\n parameters.StudyInstanceUID = studyUids;\n }\n\n // Clean query params of undefined values.\n const final = {};\n Object.keys(parameters).forEach(key => {\n if (parameters[key] !== undefined && parameters[key] !== '') {\n final[key] = parameters[key];\n }\n });\n\n return final;\n}\n\nexport { mapParams, search, processResults };\n","import getWADORSImageId from './getWADORSImageId';\n\nfunction buildInstanceWadoUrl(config, instance) {\n const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance;\n const params = [];\n\n params.push('requestType=WADO');\n params.push(`studyUID=${StudyInstanceUID}`);\n params.push(`seriesUID=${SeriesInstanceUID}`);\n params.push(`objectUID=${SOPInstanceUID}`);\n params.push('contentType=application/dicom');\n params.push('transferSyntax=*');\n\n const paramString = params.join('&');\n\n return `${config.wadoUriRoot}?${paramString}`;\n}\n\n/**\n * Obtain an imageId for Cornerstone from an image instance\n *\n * @param instance\n * @param frame\n * @param thumbnail\n * @returns {string} The imageId to be used by Cornerstone\n */\nexport default function getImageId({ instance, frame, config, thumbnail = false }) {\n if (!instance) {\n return;\n }\n\n if (instance.url) {\n return instance.url;\n }\n\n const renderingAttr = thumbnail ? 'thumbnailRendering' : 'imageRendering';\n\n if (!config[renderingAttr] || config[renderingAttr] === 'wadouri') {\n const wadouri = buildInstanceWadoUrl(config, instance);\n\n let imageId = 'dicomweb:' + wadouri;\n if (frame !== undefined) {\n imageId += '&frame=' + frame;\n }\n\n return imageId;\n } else {\n return getWADORSImageId(instance, config, frame); // WADO-RS Retrieve Frame\n }\n}\n","function buildInstanceWadoRsUri(instance, config) {\n const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance;\n return `${config.wadoRoot}/studies/${StudyInstanceUID}/series/${SeriesInstanceUID}/instances/${SOPInstanceUID}`;\n}\n\nfunction buildInstanceFrameWadoRsUri(instance, config, frame) {\n const baseWadoRsUri = buildInstanceWadoRsUri(instance, config);\n\n frame = frame || 1;\n\n return `${baseWadoRsUri}/frames/${frame}`;\n}\n\n// function getWADORSImageUrl(instance, frame) {\n// const wadorsuri = buildInstanceFrameWadoRsUri(instance, config, frame);\n\n// if (!wadorsuri) {\n// return;\n// }\n\n// // Use null to obtain an imageId which represents the instance\n// if (frame === null) {\n// wadorsuri = wadorsuri.replace(/frames\\/(\\d+)/, '');\n// } else {\n// // We need to sum 1 because WADO-RS frame number is 1-based\n// frame = frame ? parseInt(frame) + 1 : 1;\n\n// // Replaces /frame/1 by /frame/{frame}\n// wadorsuri = wadorsuri.replace(/frames\\/(\\d+)/, `frames/${frame}`);\n// }\n\n// return wadorsuri;\n// }\n\n/**\n * Obtain an imageId for Cornerstone based on the WADO-RS scheme\n *\n * @param {object} instanceMetada metadata object (InstanceMetadata)\n * @param {(string\\|number)} [frame] the frame number\n * @returns {string} The imageId to be used by Cornerstone\n */\nexport default function getWADORSImageId(instance, config, frame) {\n //const uri = getWADORSImageUrl(instance, frame);\n const uri = buildInstanceFrameWadoRsUri(instance, config, frame);\n\n if (!uri) {\n return;\n }\n\n return `wadors:${uri}`;\n}\n","/**\n * Class to define inheritance of load retrieve strategy.\n * The process can be async load (lazy) or sync load\n *\n * There are methods that must be implemented at consumer level\n * To retrieve study call execLoad\n */\nexport default class RetrieveMetadataLoader {\n /**\n * @constructor\n * @param {Object} client The dicomweb-client.\n * @param {Array} studyInstanceUID Study instance ui to be retrieved\n * @param {Object} [filters] - Object containing filters to be applied on retrieve metadata process\n * @param {string} [filters.seriesInstanceUID] - series instance uid to filter results against\n * @param {Object} [sortCriteria] - Custom sort criteria used for series\n * @param {Function} [sortFunction] - Custom sort function for series\n */\n constructor(\n client,\n studyInstanceUID,\n filters = {},\n sortCriteria = undefined,\n sortFunction = undefined\n ) {\n this.client = client;\n this.studyInstanceUID = studyInstanceUID;\n this.filters = filters;\n this.sortCriteria = sortCriteria;\n this.sortFunction = sortFunction;\n }\n\n async execLoad() {\n const preLoadData = await this.preLoad();\n const loadData = await this.load(preLoadData);\n const postLoadData = await this.posLoad(loadData);\n return postLoadData;\n }\n\n /**\n * It iterates over given loaders running each one. Loaders parameters must be bind when getting it.\n * @param {Array} loaders - array of loader to retrieve data.\n */\n async runLoaders(loaders) {\n let result;\n for (const loader of loaders) {\n result = await loader();\n if (result && result.length) {\n break; // closes iterator in case data is retrieved successfully\n }\n }\n\n if (loaders.next().done && !result) {\n throw new Error('RetrieveMetadataLoader failed');\n }\n\n return result;\n }\n\n // Methods to be overwrite\n async configLoad() {}\n async preLoad() {}\n async load(preLoadData) {}\n async posLoad(loadData) {}\n}\n","// import { api } from 'dicomweb-client';\n// import DICOMWeb from '../../../DICOMWeb/';\nimport { createStudyFromSOPInstanceList } from './studyInstanceHelpers';\nimport RetrieveMetadataLoader from './retrieveMetadataLoader';\n\n/**\n * Class for sync load of study metadata.\n * It inherits from RetrieveMetadataLoader\n *\n * A list of loaders (getLoaders) can be created so, it will be applied a fallback load strategy.\n * I.e Retrieve metadata using all loaders possibilities.\n */\nexport default class RetrieveMetadataLoaderSync extends RetrieveMetadataLoader {\n getOptions() {\n const { studyInstanceUID, filters } = this;\n\n const options = {\n studyInstanceUID,\n };\n\n const { seriesInstanceUID } = filters;\n if (seriesInstanceUID) {\n options['seriesInstanceUID'] = seriesInstanceUID;\n }\n\n return options;\n }\n\n /**\n * @returns {Array} Array of loaders. To be consumed as queue\n */\n *getLoaders() {\n const loaders = [];\n const { studyInstanceUID, filters: { seriesInstanceUID } = {}, client } = this;\n\n if (seriesInstanceUID) {\n loaders.push(\n client.retrieveSeriesMetadata.bind(client, {\n studyInstanceUID,\n seriesInstanceUID,\n })\n );\n }\n\n loaders.push(client.retrieveStudyMetadata.bind(client, { studyInstanceUID }));\n\n yield* loaders;\n }\n\n async load(preLoadData) {\n const loaders = this.getLoaders();\n const result = this.runLoaders(loaders);\n return result;\n }\n\n async posLoad(loadData) {\n return loadData;\n }\n}\n","import dcmjs from 'dcmjs';\nimport { sortStudySeries } from '@ohif/core/src/utils/sortStudy';\nimport RetrieveMetadataLoader from './retrieveMetadataLoader';\n\n// Series Date, Series Time, Series Description and Series Number to be included\n// in the series metadata query result\nconst includeField = ['00080021', '00080031', '0008103E', '00200011'].join(',');\n\nexport class DeferredPromise {\n metadata = undefined;\n processFunction = undefined;\n internalPromise = undefined;\n thenFunction = undefined;\n rejectFunction = undefined;\n\n setMetadata(metadata) {\n this.metadata = metadata;\n }\n setProcessFunction(func) {\n this.processFunction = func;\n }\n getPromise() {\n return this.start();\n }\n start() {\n if (this.internalPromise) {\n return this.internalPromise;\n }\n this.internalPromise = this.processFunction();\n // in case then and reject functions called before start\n if (this.thenFunction) {\n this.then(this.thenFunction);\n this.thenFunction = undefined;\n }\n if (this.rejectFunction) {\n this.reject(this.rejectFunction);\n this.rejectFunction = undefined;\n }\n return this.internalPromise;\n }\n then(func) {\n if (this.internalPromise) {\n return this.internalPromise.then(func);\n } else {\n this.thenFunction = func;\n }\n }\n reject(func) {\n if (this.internalPromise) {\n return this.internalPromise.reject(func);\n } else {\n this.rejectFunction = func;\n }\n }\n}\n/**\n * Creates an immutable series loader object which loads each series sequentially using the iterator interface.\n *\n * @param {DICOMWebClient} dicomWebClient The DICOMWebClient instance to be used for series load\n * @param {string} studyInstanceUID The Study Instance UID from which series will be loaded\n * @param {Array} seriesInstanceUIDList A list of Series Instance UIDs\n *\n * @returns {Object} Returns an object which supports loading of instances from each of given Series Instance UID\n */\nfunction makeSeriesAsyncLoader(client, studyInstanceUID, seriesInstanceUIDList) {\n return Object.freeze({\n hasNext() {\n return seriesInstanceUIDList.length > 0;\n },\n next() {\n const { seriesInstanceUID, metadata } = seriesInstanceUIDList.shift();\n const promise = new DeferredPromise();\n promise.setMetadata(metadata);\n promise.setProcessFunction(() => {\n return client.retrieveSeriesMetadata({\n studyInstanceUID,\n seriesInstanceUID,\n });\n });\n return promise;\n },\n });\n}\n\n/**\n * Class for async load of study metadata.\n * It inherits from RetrieveMetadataLoader\n *\n * It loads the one series and then append to seriesLoader the others to be consumed/loaded\n */\nexport default class RetrieveMetadataLoaderAsync extends RetrieveMetadataLoader {\n /**\n * @returns {Array} Array of preLoaders. To be consumed as queue\n */\n *getPreLoaders() {\n const preLoaders = [];\n const { studyInstanceUID, filters: { seriesInstanceUID } = {}, client } = this;\n\n // asking to include Series Date, Series Time, Series Description\n // and Series Number in the series metadata returned to better sort series\n // in preLoad function\n let options = {\n studyInstanceUID,\n queryParams: {\n includefield: includeField,\n },\n };\n\n if (seriesInstanceUID) {\n options.queryParams.SeriesInstanceUID = seriesInstanceUID;\n preLoaders.push(client.searchForSeries.bind(client, options));\n }\n // Fallback preloader\n preLoaders.push(client.searchForSeries.bind(client, options));\n\n yield* preLoaders;\n }\n\n async preLoad() {\n const preLoaders = this.getPreLoaders();\n const result = await this.runLoaders(preLoaders);\n const sortCriteria = this.sortCriteria;\n const sortFunction = this.sortFunction;\n\n const { naturalizeDataset } = dcmjs.data.DicomMetaDictionary;\n const naturalized = result.map(naturalizeDataset);\n\n return sortStudySeries(naturalized, sortCriteria, sortFunction);\n }\n\n async load(preLoadData) {\n const { client, studyInstanceUID } = this;\n\n const seriesInstanceUIDs = preLoadData.map(seriesMetadata => {\n return { seriesInstanceUID: seriesMetadata.SeriesInstanceUID, metadata: seriesMetadata };\n });\n\n const seriesAsyncLoader = makeSeriesAsyncLoader(client, studyInstanceUID, seriesInstanceUIDs);\n\n const promises = [];\n\n while (seriesAsyncLoader.hasNext()) {\n const promise = seriesAsyncLoader.next();\n promises.push(promise);\n }\n\n return {\n preLoadData,\n promises,\n };\n }\n\n async posLoad({ preLoadData, promises }) {\n return {\n preLoadData,\n promises,\n };\n }\n}\n","import RetrieveMetadataLoaderSync from './retrieveMetadataLoaderSync';\nimport RetrieveMetadataLoaderAsync from './retrieveMetadataLoaderAsync';\n\n/**\n * Retrieve Study metadata from a DICOM server. If the server is configured to use lazy load, only the first series\n * will be loaded and the property \"studyLoader\" will be set to let consumer load remaining series as needed.\n *\n * @param {*} dicomWebClient The DICOMWebClient instance to be used for series load\n * @param {*} StudyInstanceUID The UID of the Study to be retrieved\n * @param {*} enableStudyLazyLoad Whether the study metadata should be loaded asynchronously\n * @param {object} filters Object containing filters to be applied on retrieve metadata process\n * @param {string} [filters.seriesInstanceUID] Series instance uid to filter results against\n * @param {array} [filters.SeriesInstanceUIDs] Series instance uids to filter results against\n * @param {function} [sortCriteria] Sort criteria function\n * @param {function} [sortFunction] Sort function\n *\n * @returns {Promise} A promises that resolves the study descriptor object\n */\nasync function RetrieveMetadata(\n dicomWebClient,\n StudyInstanceUID,\n enableStudyLazyLoad,\n filters = {},\n sortCriteria,\n sortFunction\n) {\n const RetrieveMetadataLoader =\n enableStudyLazyLoad !== false ? RetrieveMetadataLoaderAsync : RetrieveMetadataLoaderSync;\n\n const retrieveMetadataLoader = new RetrieveMetadataLoader(\n dicomWebClient,\n StudyInstanceUID,\n filters,\n sortCriteria,\n sortFunction\n );\n const data = await retrieveMetadataLoader.execLoad();\n\n return data;\n}\n\nexport default RetrieveMetadata;\n","import RetrieveMetadata from '../wado/retrieveMetadata';\n\n/**\n * Retrieve metadata filtered.\n *\n * @param {*} dicomWebClient The DICOMWebClient instance to be used for series load\n * @param {*} StudyInstanceUID The UID of the Study to be retrieved\n * @param {*} enableStudyLazyLoad Whether the study metadata should be loaded asynchronously\n * @param {object} filters Object containing filters to be applied on retrieve metadata process\n * @param {string} [filters.seriesInstanceUID] Series instance uid to filter results against\n * @param {array} [filters.SeriesInstanceUIDs] Series instance uids to filter results against\n * @param {function} [sortCriteria] Sort criteria function\n * @param {function} [sortFunction] Sort function\n *\n * @returns\n */\nfunction retrieveMetadataFiltered(\n dicomWebClient,\n StudyInstanceUID,\n enableStudyLazyLoad,\n filters,\n sortCriteria,\n sortFunction\n) {\n const { SeriesInstanceUIDs } = filters;\n\n return new Promise((resolve, reject) => {\n const promises = SeriesInstanceUIDs.map(uid => {\n const seriesSpecificFilters = Object.assign({}, filters, {\n seriesInstanceUID: uid,\n });\n\n return RetrieveMetadata(\n dicomWebClient,\n StudyInstanceUID,\n enableStudyLazyLoad,\n seriesSpecificFilters,\n sortCriteria,\n sortFunction\n );\n });\n\n Promise.all(promises).then(results => {\n const aggregatedResult = { preLoadData: [], promises: [] };\n\n results.forEach(({ preLoadData, promises }) => {\n aggregatedResult.preLoadData = aggregatedResult.preLoadData.concat(preLoadData);\n aggregatedResult.promises = aggregatedResult.promises.concat(promises);\n });\n\n resolve(aggregatedResult);\n }, reject);\n });\n}\n\nexport default retrieveMetadataFiltered;\n","import retrieveMetadataFiltered from './utils/retrieveMetadataFiltered.js';\nimport RetrieveMetadata from './wado/retrieveMetadata.js';\n\nconst moduleName = 'RetrieveStudyMetadata';\n// Cache for promises. Prevents unnecessary subsequent calls to the server\nconst StudyMetaDataPromises = new Map();\n\n/**\n * Retrieves study metadata.\n *\n * @param {Object} dicomWebClient The DICOMWebClient instance to be used for series load\n * @param {string} StudyInstanceUID The UID of the Study to be retrieved\n * @param {boolean} enableStudyLazyLoad Whether the study metadata should be loaded asynchronously.\n * @param {Object} [filters] Object containing filters to be applied on retrieve metadata process\n * @param {string} [filters.seriesInstanceUID] Series instance uid to filter results against\n * @param {array} [filters.SeriesInstanceUIDs] Series instance uids to filter results against\n * @param {function} [sortCriteria] Sort criteria function\n * @param {function} [sortFunction] Sort function\n *\n * @returns {Promise} that will be resolved with the metadata or rejected with the error\n */\nexport function retrieveStudyMetadata(\n dicomWebClient,\n StudyInstanceUID,\n enableStudyLazyLoad,\n filters,\n sortCriteria,\n sortFunction,\n dicomWebConfig = {}\n) {\n // @TODO: Whenever a study metadata request has failed, its related promise will be rejected once and for all\n // and further requests for that metadata will always fail. On failure, we probably need to remove the\n // corresponding promise from the \"StudyMetaDataPromises\" map...\n\n if (!dicomWebClient) {\n throw new Error(`${moduleName}: Required 'dicomWebClient' parameter not provided.`);\n }\n if (!StudyInstanceUID) {\n throw new Error(`${moduleName}: Required 'StudyInstanceUID' parameter not provided.`);\n }\n\n const promiseId = `${dicomWebConfig.name}:${StudyInstanceUID}`;\n\n // Already waiting on result? Return cached promise\n if (StudyMetaDataPromises.has(promiseId)) {\n return StudyMetaDataPromises.get(promiseId);\n }\n\n let promise;\n\n if (filters && filters.SeriesInstanceUIDs) {\n promise = retrieveMetadataFiltered(\n dicomWebClient,\n StudyInstanceUID,\n enableStudyLazyLoad,\n filters,\n sortCriteria,\n sortFunction\n );\n } else {\n // Create a promise to handle the data retrieval\n promise = new Promise((resolve, reject) => {\n RetrieveMetadata(\n dicomWebClient,\n StudyInstanceUID,\n enableStudyLazyLoad,\n filters,\n sortCriteria,\n sortFunction\n ).then(function (data) {\n resolve(data);\n }, reject);\n });\n }\n\n // Store the promise in cache\n StudyMetaDataPromises.set(promiseId, promise);\n\n return promise;\n}\n\n/**\n * Delete the cached study metadata retrieval promise to ensure that the browser will\n * re-retrieve the study metadata when it is next requested.\n *\n * @param {String} StudyInstanceUID The UID of the Study to be removed from cache\n */\nexport function deleteStudyMetadataPromise(StudyInstanceUID) {\n if (StudyMetaDataPromises.has(StudyInstanceUID)) {\n StudyMetaDataPromises.delete(StudyInstanceUID);\n }\n}\n","function checkToken(token, data, dataOffset): boolean {\n if (dataOffset + token.length > data.length) {\n return false;\n }\n\n let endIndex = dataOffset;\n\n for (let i = 0; i < token.length; i++) {\n if (token[i] !== data[endIndex++]) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction stringToUint8Array(str: string): Uint8Array {\n const uint = new Uint8Array(str.length);\n\n for (let i = 0, j = str.length; i < j; i++) {\n uint[i] = str.charCodeAt(i);\n }\n\n return uint;\n}\n\nfunction findIndexOfString(\n data: Uint8Array,\n str: string,\n offset?: number\n): number {\n offset = offset || 0;\n\n const token = stringToUint8Array(str);\n\n for (let i = offset; i < data.length; i++) {\n if (token[0] === data[i]) {\n // console.log('match @', i);\n if (checkToken(token, data, i)) {\n return i;\n }\n }\n }\n\n return -1;\n}\nexport default findIndexOfString;\n","import findIndexOfString from './findIndexOfString';\n\n/**\n * Fix multipart data coming back from the retrieve bulkdata request, but\n * incorrectly tagged as application/octet-stream. Some servers don't handle\n * the response type correctly, and this method is relatively robust about\n * detecting multipart data correctly. It will only extract one value.\n */\nexport default function fixMultipart(arrayData) {\n const data = new Uint8Array(arrayData[0]);\n // Don't know the exact minimum length, but it is at least 25 to encode multipart\n if (data.length < 25) {\n return arrayData;\n }\n const dashIndex = findIndexOfString(data, '--');\n if (dashIndex > 6) {\n return arrayData;\n }\n const tokenIndex = findIndexOfString(data, '\\r\\n\\r\\n', dashIndex);\n if (tokenIndex > 512) {\n // Allow for 512 characters in the header - there is no apriori limit, but\n // this seems ok for now as we only expect it to have content type in it.\n return arrayData;\n }\n const header = uint8ArrayToString(data, 0, tokenIndex);\n // Now find the boundary marker\n const responseHeaders = header.split('\\r\\n');\n const boundary = findBoundary(responseHeaders);\n\n if (!boundary) {\n return arrayData;\n }\n // Start of actual data is 4 characters after the token\n const offset = tokenIndex + 4;\n\n const endIndex = findIndexOfString(data, boundary, offset);\n if (endIndex === -1) {\n return arrayData;\n }\n\n return [data.slice(offset, endIndex - 2).buffer];\n}\n\nexport function findBoundary(header: string[]): string {\n for (let i = 0; i < header.length; i++) {\n if (header[i].substr(0, 2) === '--') {\n return header[i];\n }\n }\n}\n\nexport function findContentType(header: string[]): string {\n for (let i = 0; i < header.length; i++) {\n if (header[i].substr(0, 13) === 'Content-Type:') {\n return header[i].substr(13).trim();\n }\n }\n}\n\nexport function uint8ArrayToString(data, offset, length) {\n offset = offset || 0;\n length = length || data.length - offset;\n let str = '';\n\n for (let i = offset; i < offset + length; i++) {\n str += String.fromCharCode(data[i]);\n }\n\n return str;\n}\n","import { api } from 'dicomweb-client';\nimport fixMultipart from './fixMultipart';\n\nconst { DICOMwebClient } = api;\n\nconst anyDicomwebClient = DICOMwebClient as any;\n\n// Ugly over-ride, but the internals aren't otherwise accessible.\nif (!anyDicomwebClient._orig_buildMultipartAcceptHeaderFieldValue) {\n anyDicomwebClient._orig_buildMultipartAcceptHeaderFieldValue =\n anyDicomwebClient._buildMultipartAcceptHeaderFieldValue;\n anyDicomwebClient._buildMultipartAcceptHeaderFieldValue = function (mediaTypes, acceptableTypes) {\n if (mediaTypes.length === 1 && mediaTypes[0].mediaType.endsWith('/*')) {\n return '*/*';\n } else {\n return anyDicomwebClient._orig_buildMultipartAcceptHeaderFieldValue(\n mediaTypes,\n acceptableTypes\n );\n }\n };\n}\n\n/**\n * An implementation of the static wado client, that fetches data from\n * a static response rather than actually doing real queries. This allows\n * fast encoding of test data, but because it is static, anything actually\n * performing searches doesn't work. This version fixes the query issue\n * by manually implementing a query option.\n */\n\nexport default class StaticWadoClient extends api.DICOMwebClient {\n static studyFilterKeys = {\n studyinstanceuid: '0020000D',\n patientname: '00100010',\n '00100020': 'mrn',\n studydescription: '00081030',\n studydate: '00080020',\n modalitiesinstudy: '00080061',\n accessionnumber: '00080050',\n };\n\n static seriesFilterKeys = {\n seriesinstanceuid: '0020000E',\n seriesnumber: '00200011',\n modality: '00080060',\n };\n\n protected config;\n protected staticWado;\n\n constructor(config) {\n super(config);\n this.staticWado = config.staticWado;\n this.config = config;\n }\n\n /**\n * Handle improperly specified multipart/related return type.\n * Note if the response is SUPPOSED to be multipart encoded already, then this\n * will double-decode it.\n *\n * @param options\n * @returns De-multiparted response data.\n *\n */\n public retrieveBulkData(options): Promise<any[]> {\n const shouldFixMultipart = this.config.fixBulkdataMultipart !== false;\n const useOptions = {\n ...options,\n };\n if (this.staticWado) {\n useOptions.mediaTypes = [{ mediaType: 'application/*' }];\n }\n return super\n .retrieveBulkData(useOptions)\n .then(result => (shouldFixMultipart ? fixMultipart(result) : result));\n }\n\n /**\n * Retrieves instance frames using the image/* media type when configured\n * to do so (static wado back end).\n */\n public retrieveInstanceFrames(options) {\n if (this.staticWado) {\n return super.retrieveInstanceFrames({\n ...options,\n mediaTypes: [{ mediaType: 'image/*' }],\n });\n } else {\n return super.retrieveInstanceFrames(options);\n }\n }\n\n /**\n * Replace the search for studies remote query with a local version which\n * retrieves a complete query list and then sub-selects from it locally.\n * @param {*} options\n * @returns\n */\n async searchForStudies(options) {\n if (!this.staticWado) {\n return super.searchForStudies(options);\n }\n\n const searchResult = await super.searchForStudies(options);\n const { queryParams } = options;\n\n if (!queryParams) {\n return searchResult;\n }\n\n const lowerParams = this.toLowerParams(queryParams);\n const filtered = searchResult.filter(study => {\n for (const key of Object.keys(StaticWadoClient.studyFilterKeys)) {\n if (!this.filterItem(key, lowerParams, study, StaticWadoClient.studyFilterKeys)) {\n return false;\n }\n }\n return true;\n });\n return filtered;\n }\n\n async searchForSeries(options) {\n if (!this.staticWado) {\n return super.searchForSeries(options);\n }\n\n const searchResult = await super.searchForSeries(options);\n const { queryParams } = options;\n if (!queryParams) {\n return searchResult;\n }\n const lowerParams = this.toLowerParams(queryParams);\n\n const filtered = searchResult.filter(series => {\n for (const key of Object.keys(StaticWadoClient.seriesFilterKeys)) {\n if (!this.filterItem(key, lowerParams, series, StaticWadoClient.seriesFilterKeys)) {\n return false;\n }\n }\n return true;\n });\n\n return filtered;\n }\n\n /**\n * Compares values, matching any instance of desired to any instance of\n * actual by recursively go through the paired set of values. That is,\n * this is O(m*n) where m is how many items in desired and n is the length of actual\n * Then, at the individual item node, compares the Alphabetic name if present,\n * and does a sub-string matching on string values, and otherwise does an\n * exact match comparison.\n *\n * @param {*} desired\n * @param {*} actual\n * @returns true if the values match\n */\n compareValues(desired, actual) {\n if (Array.isArray(desired)) {\n return desired.find(item => this.compareValues(item, actual));\n }\n if (Array.isArray(actual)) {\n return actual.find(actualItem => this.compareValues(desired, actualItem));\n }\n if (actual?.Alphabetic) {\n actual = actual.Alphabetic;\n }\n if (typeof actual == 'string') {\n if (actual.length === 0) {\n return true;\n }\n if (desired.length === 0 || desired === '*') {\n return true;\n }\n if (desired[0] === '*' && desired[desired.length - 1] === '*') {\n // console.log(`Comparing ${actual} to ${desired.substring(1, desired.length - 1)}`)\n return actual.indexOf(desired.substring(1, desired.length - 1)) != -1;\n } else if (desired[desired.length - 1] === '*') {\n return actual.indexOf(desired.substring(0, desired.length - 1)) != -1;\n } else if (desired[0] === '*') {\n return actual.indexOf(desired.substring(1)) === actual.length - desired.length + 1;\n }\n }\n return desired === actual;\n }\n\n /** Compares a pair of dates to see if the value is within the range */\n compareDateRange(range, value) {\n if (!value) {\n return true;\n }\n const dash = range.indexOf('-');\n if (dash === -1) {\n return this.compareValues(range, value);\n }\n const start = range.substring(0, dash);\n const end = range.substring(dash + 1);\n return (!start || value >= start) && (!end || value <= end);\n }\n\n /**\n * Filters the return list by the query parameters.\n *\n * @param anyCaseKey - a possible search key\n * @param queryParams -\n * @param {*} study\n * @param {*} sourceFilterMap\n * @returns\n */\n filterItem(key: string, queryParams, study, sourceFilterMap) {\n const altKey = sourceFilterMap[key] || key;\n if (!queryParams) {\n return true;\n }\n const testValue = queryParams[key] || queryParams[altKey];\n if (!testValue) {\n return true;\n }\n const valueElem = study[key] || study[altKey];\n if (!valueElem) {\n return false;\n }\n if (valueElem.vr === 'DA' && valueElem.Value?.[0]) {\n return this.compareDateRange(testValue, valueElem.Value[0]);\n }\n const value = valueElem.Value;\n return this.compareValues(testValue, value);\n }\n\n /** Converts the query parameters to lower case query parameters */\n toLowerParams(queryParams: Record<string, unknown>): Record<string, unknown> {\n const lowerParams = {};\n Object.entries(queryParams).forEach(([key, value]) => {\n lowerParams[key.toLowerCase()] = value;\n });\n return lowerParams;\n }\n}\n","import { utils } from '@ohif/core';\n\n/**\n * Generates a URL that can be used for direct retrieve of the bulkdata\n *\n * @param {object} params\n * @param {string} params.tag is the tag name of the URL to retrieve\n * @param {string} params.defaultPath path for the pixel data url\n * @param {object} params.instance is the instance object that the tag is in\n * @param {string} params.defaultType is the mime type of the response\n * @param {string} params.singlepart is the type of the part to retrieve\n * @param {string} params.fetchPart unknown?\n * @param {string} params.url unknown?\n * @returns an absolute URL to the resource, if the absolute URL can be retrieved as singlepart,\n * or is already retrieved, or a promise to a URL for such use if a BulkDataURI\n */\nconst getDirectURL = (config, params) => {\n const { wadoRoot, singlepart } = config;\n const {\n instance,\n tag = 'PixelData',\n defaultPath = '/pixeldata',\n defaultType = 'video/mp4',\n singlepart: fetchPart = 'video',\n url = null,\n } = params;\n if (url) {\n return url;\n }\n\n const value = instance[tag];\n if (!value) {\n return undefined;\n }\n\n if (value.DirectRetrieveURL) {\n return value.DirectRetrieveURL;\n }\n if (value.InlineBinary) {\n const blob = utils.b64toBlob(value.InlineBinary, defaultType);\n value.DirectRetrieveURL = URL.createObjectURL(blob);\n return value.DirectRetrieveURL;\n }\n if (!singlepart || (singlepart !== true && singlepart.indexOf(fetchPart) === -1)) {\n if (value.retrieveBulkData) {\n // Try the specified retrieve type.\n const options = {\n mediaType: defaultType,\n };\n return value.retrieveBulkData(options).then(arr => {\n value.DirectRetrieveURL = URL.createObjectURL(new Blob([arr], { type: defaultType }));\n return value.DirectRetrieveURL;\n });\n }\n console.warn('Unable to retrieve', tag, 'from', instance);\n return undefined;\n }\n\n const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance;\n const BulkDataURI =\n (value && value.BulkDataURI) ||\n `series/${SeriesInstanceUID}/instances/${SOPInstanceUID}${defaultPath}`;\n const hasQuery = BulkDataURI.indexOf('?') !== -1;\n const hasAccept = BulkDataURI.indexOf('accept=') !== -1;\n const acceptUri =\n BulkDataURI + (hasAccept ? '' : (hasQuery ? '&' : '?') + `accept=${defaultType}`);\n\n if (tag === 'PixelData' || tag === 'EncapsulatedDocument') {\n return `${wadoRoot}/studies/${StudyInstanceUID}/series/${SeriesInstanceUID}/instances/${SOPInstanceUID}/rendered`;\n }\n\n // The DICOMweb standard states that the default is multipart related, and then\n // separately states that the accept parameter is the URL parameter equivalent of the accept header.\n return acceptUri;\n};\n\nexport default getDirectURL;\n","/**\n * Modifies a bulkDataURI to ensure it is absolute based on the DICOMWeb configuration and\n * instance data. The modification is in-place.\n *\n * If the bulkDataURI is relative to the series or study (according to the DICOM standard),\n * it is made absolute by prepending the relevant paths.\n *\n * In scenarios where the bulkDataURI is a server-relative path (starting with '/'), the function\n * handles two cases:\n *\n * 1. If the wado root is absolute (starts with 'http'), it prepends the wado root to the bulkDataURI.\n * 2. If the wado root is relative, no changes are needed as the bulkDataURI is already correctly relative to the server root.\n *\n * @param value - The object containing BulkDataURI to be fixed.\n * @param instance - The object (DICOM instance data) containing StudyInstanceUID and SeriesInstanceUID.\n * @param dicomWebConfig - The DICOMWeb configuration object, containing wadoRoot and potentially bulkDataURI.relativeResolution.\n * @returns The function modifies `value` in-place, it does not return a value.\n */\nfunction fixBulkDataURI(value, instance, dicomWebConfig) {\n // in case of the relative path, make it absolute. The current DICOM standard says\n // the bulkdataURI is relative to the series. However, there are situations where\n // it can be relative to the study too\n if (!value.BulkDataURI.startsWith('http') && !value.BulkDataURI.startsWith('/')) {\n if (dicomWebConfig.bulkDataURI?.relativeResolution === 'studies') {\n value.BulkDataURI = `${dicomWebConfig.wadoRoot}/studies/${instance.StudyInstanceUID}/${value.BulkDataURI}`;\n } else if (\n dicomWebConfig.bulkDataURI?.relativeResolution === 'series' ||\n !dicomWebConfig.bulkDataURI?.relativeResolution\n ) {\n value.BulkDataURI = `${dicomWebConfig.wadoRoot}/studies/${instance.StudyInstanceUID}/series/${instance.SeriesInstanceUID}/${value.BulkDataURI}`;\n }\n\n return;\n }\n\n // in case it is relative path but starts at the server (e.g., /bulk/1e, note the missing http\n // in the beginning and the first character is /) There are two scenarios, whether the wado root\n // is absolute or relative. In case of absolute, we need to prepend the wado root to the bulkdata\n // uri (e.g., bulkData: /bulk/1e, wado root: http://myserver.com/dicomweb, output: http://myserver.com/bulk/1e)\n // and in case of relative wado root, we need to prepend the bulkdata uri to the wado root (e.g,. bulkData: /bulk/1e\n // wado root: /dicomweb, output: /bulk/1e)\n if (value.BulkDataURI[0] === '/') {\n if (dicomWebConfig.wadoRoot.startsWith('http')) {\n // Absolute wado root\n const url = new URL(dicomWebConfig.wadoRoot);\n value.BulkDataURI = `${url.origin}${value.BulkDataURI}`;\n } else {\n // Relative wado root, we don't need to do anything, bulkdata uri is already correct\n }\n }\n}\n\nexport { fixBulkDataURI };\n","import { api } from 'dicomweb-client';\nimport { DicomMetadataStore, IWebApiDataSource, utils, errorHandler, classes } from '@ohif/core';\n\nimport {\n mapParams,\n search as qidoSearch,\n seriesInStudy,\n processResults,\n processSeriesResults,\n} from './qido.js';\nimport dcm4cheeReject from './dcm4cheeReject';\n\nimport getImageId from './utils/getImageId';\nimport dcmjs from 'dcmjs';\nimport { retrieveStudyMetadata, deleteStudyMetadataPromise } from './retrieveStudyMetadata.js';\nimport StaticWadoClient from './utils/StaticWadoClient';\nimport getDirectURL from '../utils/getDirectURL';\nimport { fixBulkDataURI } from './utils/fixBulkDataURI';\n\nconst { DicomMetaDictionary, DicomDict } = dcmjs.data;\n\nconst { naturalizeDataset, denaturalizeDataset } = DicomMetaDictionary;\n\nconst ImplementationClassUID = '2.25.270695996825855179949881587723571202391.2.0.0';\nconst ImplementationVersionName = 'OHIF-VIEWER-2.0.0';\nconst EXPLICIT_VR_LITTLE_ENDIAN = '1.2.840.10008.1.2.1';\n\nconst metadataProvider = classes.MetadataProvider;\n\n/**\n * Creates a DICOM Web API based on the provided configuration.\n *\n * @param {object} dicomWebConfig - Configuration for the DICOM Web API\n * @param {string} dicomWebConfig.name - Data source name\n * @param {string} dicomWebConfig.wadoUriRoot - Legacy? (potentially unused/replaced)\n * @param {string} dicomWebConfig.qidoRoot - Base URL to use for QIDO requests\n * @param {string} dicomWebConfig.wadoRoot - Base URL to use for WADO requests\n * @param {string} dicomWebConfig.wadoUri - Base URL to use for WADO URI requests\n * @param {boolean} dicomWebConfig.qidoSupportsIncludeField - Whether QIDO supports the \"Include\" option to request additional fields in response\n * @param {string} dicomWebConfig.imageRendering - wadors | ? (unsure of where/how this is used)\n * @param {string} dicomWebConfig.thumbnailRendering - wadors | ? (unsure of where/how this is used)\n * @param {boolean} dicomWebConfig.supportsReject - Whether the server supports reject calls (i.e. DCM4CHEE)\n * @param {boolean} dicomWebConfig.lazyLoadStudy - \"enableStudyLazyLoad\"; Request series meta async instead of blocking\n * @param {string|boolean} dicomWebConfig.singlepart - indicates if the retrieves can fetch singlepart. Options are bulkdata, video, image, or boolean true\n * @param {string} dicomWebConfig.requestTransferSyntaxUID - Transfer syntax to request from the server\n * @param {object} dicomWebConfig.acceptHeader - Accept header to use for requests\n * @param {boolean} dicomWebConfig.omitQuotationForMultipartRequest - Whether to omit quotation marks for multipart requests\n * @param {boolean} dicomWebConfig.supportsFuzzyMatching - Whether the server supports fuzzy matching\n * @param {boolean} dicomWebConfig.supportsWildcard - Whether the server supports wildcard matching\n * @param {boolean} dicomWebConfig.supportsNativeDICOMModel - Whether the server supports the native DICOM model\n * @param {boolean} dicomWebConfig.enableStudyLazyLoad - Whether to enable study lazy loading\n * @param {boolean} dicomWebConfig.enableRequestTag - Whether to enable request tag\n * @param {boolean} dicomWebConfig.enableStudyLazyLoad - Whether to enable study lazy loading\n * @param {boolean} dicomWebConfig.bulkDataURI - Whether to enable bulkDataURI\n * @param {function} dicomWebConfig.onConfiguration - Function that is called after the configuration is initialized\n * @param {boolean} dicomWebConfig.staticWado - Whether to use the static WADO client\n * @param {object} userAuthenticationService - User authentication service\n * @param {object} userAuthenticationService.getAuthorizationHeader - Function that returns the authorization header\n * @returns {object} - DICOM Web API object\n */\nfunction createDicomWebApi(dicomWebConfig, servicesManager) {\n const { userAuthenticationService, customizationService } = servicesManager.services;\n let dicomWebConfigCopy,\n qidoConfig,\n wadoConfig,\n qidoDicomWebClient,\n wadoDicomWebClient,\n getAuthrorizationHeader,\n generateWadoHeader;\n\n const implementation = {\n initialize: ({ params, query }) => {\n if (dicomWebConfig.onConfiguration && typeof dicomWebConfig.onConfiguration === 'function') {\n dicomWebConfig = dicomWebConfig.onConfiguration(dicomWebConfig, {\n params,\n query,\n });\n }\n\n dicomWebConfigCopy = JSON.parse(JSON.stringify(dicomWebConfig));\n\n getAuthrorizationHeader = () => {\n const xhrRequestHeaders = {};\n const authHeaders = userAuthenticationService.getAuthorizationHeader();\n if (authHeaders && authHeaders.Authorization) {\n xhrRequestHeaders.Authorization = authHeaders.Authorization;\n }\n return xhrRequestHeaders;\n };\n\n generateWadoHeader = () => {\n let authorizationHeader = getAuthrorizationHeader();\n //Generate accept header depending on config params\n let formattedAcceptHeader = utils.generateAcceptHeader(\n dicomWebConfig.acceptHeader,\n dicomWebConfig.requestTransferSyntaxUID,\n dicomWebConfig.omitQuotationForMultipartRequest\n );\n\n return {\n ...authorizationHeader,\n Accept: formattedAcceptHeader,\n };\n };\n\n qidoConfig = {\n url: dicomWebConfig.qidoRoot,\n staticWado: dicomWebConfig.staticWado,\n singlepart: dicomWebConfig.singlepart,\n headers: userAuthenticationService.getAuthorizationHeader(),\n errorInterceptor: errorHandler.getHTTPErrorHandler(),\n };\n\n wadoConfig = {\n url: dicomWebConfig.wadoRoot,\n staticWado: dicomWebConfig.staticWado,\n singlepart: dicomWebConfig.singlepart,\n headers: userAuthenticationService.getAuthorizationHeader(),\n errorInterceptor: errorHandler.getHTTPErrorHandler(),\n };\n\n // TODO -> Two clients sucks, but its better than 1000.\n // TODO -> We'll need to merge auth later.\n qidoDicomWebClient = dicomWebConfig.staticWado\n ? new StaticWadoClient(qidoConfig)\n : new api.DICOMwebClient(qidoConfig);\n\n wadoDicomWebClient = dicomWebConfig.staticWado\n ? new StaticWadoClient(wadoConfig)\n : new api.DICOMwebClient(wadoConfig);\n },\n query: {\n studies: {\n mapParams: mapParams.bind(),\n search: async function (origParams) {\n qidoDicomWebClient.headers = getAuthrorizationHeader();\n const { studyInstanceUid, seriesInstanceUid, ...mappedParams } =\n mapParams(origParams, {\n supportsFuzzyMatching: dicomWebConfig.supportsFuzzyMatching,\n supportsWildcard: dicomWebConfig.supportsWildcard,\n }) || {};\n\n const results = await qidoSearch(qidoDicomWebClient, undefined, undefined, mappedParams);\n\n return processResults(results);\n },\n processResults: processResults.bind(),\n },\n series: {\n // mapParams: mapParams.bind(),\n search: async function (studyInstanceUid) {\n qidoDicomWebClient.headers = getAuthrorizationHeader();\n const results = await seriesInStudy(qidoDicomWebClient, studyInstanceUid);\n\n return processSeriesResults(results);\n },\n // processResults: processResults.bind(),\n },\n instances: {\n search: (studyInstanceUid, queryParameters) => {\n qidoDicomWebClient.headers = getAuthrorizationHeader();\n return qidoSearch.call(\n undefined,\n qidoDicomWebClient,\n studyInstanceUid,\n null,\n queryParameters\n );\n },\n },\n },\n retrieve: {\n /**\n * Generates a URL that can be used for direct retrieve of the bulkdata\n *\n * @param {object} params\n * @param {string} params.tag is the tag name of the URL to retrieve\n * @param {object} params.instance is the instance object that the tag is in\n * @param {string} params.defaultType is the mime type of the response\n * @param {string} params.singlepart is the type of the part to retrieve\n * @returns an absolute URL to the resource, if the absolute URL can be retrieved as singlepart,\n * or is already retrieved, or a promise to a URL for such use if a BulkDataURI\n */\n directURL: params => {\n return getDirectURL(\n {\n wadoRoot: dicomWebConfig.wadoRoot,\n singlepart: dicomWebConfig.singlepart,\n },\n params\n );\n },\n bulkDataURI: async ({ StudyInstanceUID, BulkDataURI }) => {\n qidoDicomWebClient.headers = getAuthrorizationHeader();\n const options = {\n multipart: false,\n BulkDataURI,\n StudyInstanceUID,\n };\n return qidoDicomWebClient.retrieveBulkData(options).then(val => {\n const ret = (val && val[0]) || undefined;\n return ret;\n });\n },\n series: {\n metadata: async ({\n StudyInstanceUID,\n filters,\n sortCriteria,\n sortFunction,\n madeInClient = false,\n returnPromises = false,\n } = {}) => {\n if (!StudyInstanceUID) {\n throw new Error('Unable to query for SeriesMetadata without StudyInstanceUID');\n }\n\n if (dicomWebConfig.enableStudyLazyLoad) {\n return implementation._retrieveSeriesMetadataAsync(\n StudyInstanceUID,\n filters,\n sortCriteria,\n sortFunction,\n madeInClient,\n returnPromises\n );\n }\n\n return implementation._retrieveSeriesMetadataSync(\n StudyInstanceUID,\n filters,\n sortCriteria,\n sortFunction,\n madeInClient\n );\n },\n },\n },\n\n store: {\n dicom: async (dataset, request, dicomDict) => {\n wadoDicomWebClient.headers = getAuthrorizationHeader();\n if (dataset instanceof ArrayBuffer) {\n const options = {\n datasets: [dataset],\n request,\n };\n await wadoDicomWebClient.storeInstances(options);\n } else {\n let effectiveDicomDict = dicomDict;\n\n if (!dicomDict) {\n const meta = {\n FileMetaInformationVersion: dataset._meta?.FileMetaInformationVersion?.Value,\n MediaStorageSOPClassUID: dataset.SOPClassUID,\n MediaStorageSOPInstanceUID: dataset.SOPInstanceUID,\n TransferSyntaxUID: EXPLICIT_VR_LITTLE_ENDIAN,\n ImplementationClassUID,\n ImplementationVersionName,\n };\n\n const denaturalized = denaturalizeDataset(meta);\n const defaultDicomDict = new DicomDict(denaturalized);\n defaultDicomDict.dict = denaturalizeDataset(dataset);\n\n effectiveDicomDict = defaultDicomDict;\n }\n\n const part10Buffer = effectiveDicomDict.write();\n\n const options = {\n datasets: [part10Buffer],\n request,\n };\n\n await wadoDicomWebClient.storeInstances(options);\n }\n },\n },\n\n _retrieveSeriesMetadataSync: async (\n StudyInstanceUID,\n filters,\n sortCriteria,\n sortFunction,\n madeInClient\n ) => {\n const enableStudyLazyLoad = false;\n wadoDicomWebClient.headers = generateWadoHeader();\n // data is all SOPInstanceUIDs\n const data = await retrieveStudyMetadata(\n wadoDicomWebClient,\n StudyInstanceUID,\n enableStudyLazyLoad,\n filters,\n sortCriteria,\n sortFunction,\n dicomWebConfig\n );\n\n // first naturalize the data\n const naturalizedInstancesMetadata = data.map(naturalizeDataset);\n\n const seriesSummaryMetadata = {};\n const instancesPerSeries = {};\n\n naturalizedInstancesMetadata.forEach(instance => {\n if (!seriesSummaryMetadata[instance.SeriesInstanceUID]) {\n seriesSummaryMetadata[instance.SeriesInstanceUID] = {\n StudyInstanceUID: instance.StudyInstanceUID,\n StudyDescription: instance.StudyDescription,\n SeriesInstanceUID: instance.SeriesInstanceUID,\n SeriesDescription: instance.SeriesDescription,\n SeriesNumber: instance.SeriesNumber,\n SeriesTime: instance.SeriesTime,\n SOPClassUID: instance.SOPClassUID,\n ProtocolName: instance.ProtocolName,\n Modality: instance.Modality,\n };\n }\n\n if (!instancesPerSeries[instance.SeriesInstanceUID]) {\n instancesPerSeries[instance.SeriesInstanceUID] = [];\n }\n\n const imageId = implementation.getImageIdsForInstance({\n instance,\n });\n\n instance.imageId = imageId;\n instance.wadoRoot = dicomWebConfig.wadoRoot;\n instance.wadoUri = dicomWebConfig.wadoUri;\n\n metadataProvider.addImageIdToUIDs(imageId, {\n StudyInstanceUID,\n SeriesInstanceUID: instance.SeriesInstanceUID,\n SOPInstanceUID: instance.SOPInstanceUID,\n });\n\n instancesPerSeries[instance.SeriesInstanceUID].push(instance);\n });\n\n // grab all the series metadata\n const seriesMetadata = Object.values(seriesSummaryMetadata);\n DicomMetadataStore.addSeriesMetadata(seriesMetadata, madeInClient);\n\n Object.keys(instancesPerSeries).forEach(seriesInstanceUID =>\n DicomMetadataStore.addInstances(instancesPerSeries[seriesInstanceUID], madeInClient)\n );\n\n return seriesSummaryMetadata;\n },\n\n _retrieveSeriesMetadataAsync: async (\n StudyInstanceUID,\n filters,\n sortCriteria,\n sortFunction,\n madeInClient = false,\n returnPromises = false\n ) => {\n const enableStudyLazyLoad = true;\n wadoDicomWebClient.headers = generateWadoHeader();\n // Get Series\n const { preLoadData: seriesSummaryMetadata, promises: seriesPromises } =\n await retrieveStudyMetadata(\n wadoDicomWebClient,\n StudyInstanceUID,\n enableStudyLazyLoad,\n filters,\n sortCriteria,\n sortFunction,\n dicomWebConfig\n );\n\n /**\n * naturalizes the dataset, and adds a retrieve bulkdata method\n * to any values containing BulkDataURI.\n * @param {*} instance\n * @returns naturalized dataset, with retrieveBulkData methods\n */\n const addRetrieveBulkData = instance => {\n const naturalized = naturalizeDataset(instance);\n\n // if we know the server doesn't use bulkDataURI, then don't\n if (!dicomWebConfig.bulkDataURI?.enabled) {\n return naturalized;\n }\n\n Object.keys(naturalized).forEach(key => {\n const value = naturalized[key];\n\n // The value.Value will be set with the bulkdata read value\n // in which case it isn't necessary to re-read this.\n if (value && value.BulkDataURI && !value.Value) {\n // Provide a method to fetch bulkdata\n value.retrieveBulkData = (options = {}) => {\n // handle the scenarios where bulkDataURI is relative path\n fixBulkDataURI(value, naturalized, dicomWebConfig);\n\n const { mediaType } = options;\n const useOptions = {\n // The bulkdata fetches work with either multipart or\n // singlepart, so set multipart to false to let the server\n // decide which type to respond with.\n multipart: false,\n BulkDataURI: value.BulkDataURI,\n // The study instance UID is required if the bulkdata uri\n // is relative - that isn't disallowed by DICOMweb, but\n // isn't well specified in the standard, but is needed in\n // any implementation that stores static copies of the metadata\n StudyInstanceUID: naturalized.StudyInstanceUID,\n mediaTypes: mediaType\n ? [{ mediaType }, { mediaType: 'application/octet-stream' }]\n : undefined,\n ...options,\n };\n // Todo: this needs to be from wado dicom web client\n return qidoDicomWebClient.retrieveBulkData(useOptions).then(val => {\n // There are DICOM PDF cases where the first ArrayBuffer in the array is\n // the bulk data and DICOM video cases where the second ArrayBuffer is\n // the bulk data. Here we play it safe and do a find.\n const ret =\n (val instanceof Array && val.find(arrayBuffer => arrayBuffer?.byteLength)) ||\n undefined;\n value.Value = ret;\n return ret;\n });\n };\n }\n });\n return naturalized;\n };\n\n // Async load series, store as retrieved\n function storeInstances(instances) {\n const naturalizedInstances = instances.map(addRetrieveBulkData);\n\n // Adding instanceMetadata to OHIF MetadataProvider\n naturalizedInstances.forEach(instance => {\n instance.wadoRoot = dicomWebConfig.wadoRoot;\n instance.wadoUri = dicomWebConfig.wadoUri;\n\n const imageId = implementation.getImageIdsForInstance({\n instance,\n });\n\n // Adding imageId to each instance\n // Todo: This is not the best way I can think of to let external\n // metadata handlers know about the imageId that is stored in the store\n instance.imageId = imageId;\n\n // Adding UIDs to metadataProvider\n // Note: storing imageURI in metadataProvider since stack viewports\n // will use the same imageURI\n metadataProvider.addImageIdToUIDs(imageId, {\n StudyInstanceUID,\n SeriesInstanceUID: instance.SeriesInstanceUID,\n SOPInstanceUID: instance.SOPInstanceUID,\n });\n });\n\n DicomMetadataStore.addInstances(naturalizedInstances, madeInClient);\n }\n\n function setSuccessFlag() {\n const study = DicomMetadataStore.getStudy(StudyInstanceUID);\n if (!study) {\n return;\n }\n study.isLoaded = true;\n }\n\n // Google Cloud Healthcare doesn't return StudyInstanceUID, so we need to add\n // it manually here\n seriesSummaryMetadata.forEach(aSeries => {\n aSeries.StudyInstanceUID = StudyInstanceUID;\n });\n\n DicomMetadataStore.addSeriesMetadata(seriesSummaryMetadata, madeInClient);\n\n const seriesDeliveredPromises = seriesPromises.map(promise => {\n if (!returnPromises) {\n promise?.start();\n }\n return promise.then(instances => {\n storeInstances(instances);\n });\n });\n\n if (returnPromises) {\n Promise.all(seriesDeliveredPromises).then(() => setSuccessFlag());\n return seriesPromises;\n } else {\n await Promise.all(seriesDeliveredPromises);\n setSuccessFlag();\n }\n\n return seriesSummaryMetadata;\n },\n deleteStudyMetadataPromise,\n getImageIdsForDisplaySet(displaySet) {\n const images = displaySet.images;\n const imageIds = [];\n\n if (!images) {\n return imageIds;\n }\n\n displaySet.images.forEach(instance => {\n const NumberOfFrames = instance.NumberOfFrames;\n\n if (NumberOfFrames > 1) {\n for (let frame = 1; frame <= NumberOfFrames; frame++) {\n const imageId = this.getImageIdsForInstance({\n instance,\n frame,\n });\n imageIds.push(imageId);\n }\n } else {\n const imageId = this.getImageIdsForInstance({ instance });\n imageIds.push(imageId);\n }\n });\n\n return imageIds;\n },\n getImageIdsForInstance({ instance, frame = undefined }) {\n const imageIds = getImageId({\n instance,\n frame,\n config: dicomWebConfig,\n });\n return imageIds;\n },\n getConfig() {\n return dicomWebConfigCopy;\n },\n getStudyInstanceUIDs({ params, query }) {\n const { StudyInstanceUIDs: paramsStudyInstanceUIDs } = params;\n const queryStudyInstanceUIDs = utils.splitComma(query.getAll('StudyInstanceUIDs'));\n\n const StudyInstanceUIDs =\n (queryStudyInstanceUIDs.length && queryStudyInstanceUIDs) || paramsStudyInstanceUIDs;\n const StudyInstanceUIDsAsArray =\n StudyInstanceUIDs && Array.isArray(StudyInstanceUIDs)\n ? StudyInstanceUIDs\n : [StudyInstanceUIDs];\n\n return StudyInstanceUIDsAsArray;\n },\n };\n\n if (dicomWebConfig.supportsReject) {\n implementation.reject = dcm4cheeReject(dicomWebConfig.wadoRoot);\n }\n\n return IWebApiDataSource.create(implementation);\n}\n\nexport { createDicomWebApi };\n","export default function (wadoRoot) {\n return {\n series: (StudyInstanceUID, SeriesInstanceUID) => {\n return new Promise((resolve, reject) => {\n // Reject because of Quality. (Seems the most sensible out of the options)\n const CodeValueAndCodeSchemeDesignator = `113001%5EDCM`;\n\n const url = `${wadoRoot}/studies/${StudyInstanceUID}/series/${SeriesInstanceUID}/reject/${CodeValueAndCodeSchemeDesignator}`;\n\n const xhr = new XMLHttpRequest();\n xhr.open('POST', url, true);\n\n //Send the proper header information along with the request\n // TODO -> Auth when we re-add authorization.\n\n console.log(xhr);\n\n xhr.onreadystatechange = function () {\n //Call a function when the state changes.\n if (xhr.readyState == 4) {\n switch (xhr.status) {\n case 204:\n resolve(xhr.responseText);\n\n break;\n case 404:\n reject('Your dataSource does not support reject functionality');\n }\n }\n };\n xhr.send();\n });\n },\n };\n}\n","import { DicomMetadataStore, IWebApiDataSource } from '@ohif/core';\nimport OHIF from '@ohif/core';\n\nimport getImageId from '../DicomWebDataSource/utils/getImageId';\nimport getDirectURL from '../utils/getDirectURL';\n\nconst metadataProvider = OHIF.classes.MetadataProvider;\n\nconst mappings = {\n studyInstanceUid: 'StudyInstanceUID',\n patientId: 'PatientID',\n};\n\nlet _store = {\n urls: [],\n studyInstanceUIDMap: new Map(), // map of urls to array of study instance UIDs\n // {\n // url: url1\n // studies: [Study1, Study2], // if multiple studies\n // }\n // {\n // url: url2\n // studies: [Study1],\n // }\n // }\n};\n\nfunction wrapSequences(obj) {\n return Object.keys(obj).reduce(\n (acc, key) => {\n if (typeof obj[key] === 'object' && obj[key] !== null) {\n // Recursively wrap sequences for nested objects\n acc[key] = wrapSequences(obj[key]);\n } else {\n acc[key] = obj[key];\n }\n if (key.endsWith('Sequence')) {\n acc[key] = OHIF.utils.addAccessors(acc[key]);\n }\n return acc;\n },\n Array.isArray(obj) ? [] : {}\n );\n}\nconst getMetaDataByURL = url => {\n return _store.urls.find(metaData => metaData.url === url);\n};\n\nconst findStudies = (key, value) => {\n let studies = [];\n _store.urls.map(metaData => {\n metaData.studies.map(aStudy => {\n if (aStudy[key] === value) {\n studies.push(aStudy);\n }\n });\n });\n return studies;\n};\n\nfunction createDicomJSONApi(dicomJsonConfig) {\n const { wadoRoot } = dicomJsonConfig;\n\n const implementation = {\n initialize: async ({ query, url }) => {\n if (!url) {\n url = query.get('url');\n }\n let metaData = getMetaDataByURL(url);\n\n // if we have already cached the data from this specific url\n // We are only handling one StudyInstanceUID to run; however,\n // all studies for patientID will be put in the correct tab\n if (metaData) {\n return metaData.studies.map(aStudy => {\n return aStudy.StudyInstanceUID;\n });\n }\n\n const response = await fetch(url);\n const data = await response.json();\n\n let StudyInstanceUID;\n let SeriesInstanceUID;\n data.studies.forEach(study => {\n StudyInstanceUID = study.StudyInstanceUID;\n\n study.series.forEach(series => {\n SeriesInstanceUID = series.SeriesInstanceUID;\n\n series.instances.forEach(instance => {\n const { url: imageId, metadata: naturalizedDicom } = instance;\n\n // Add imageId specific mapping to this data as the URL isn't necessarliy WADO-URI.\n metadataProvider.addImageIdToUIDs(imageId, {\n StudyInstanceUID,\n SeriesInstanceUID,\n SOPInstanceUID: naturalizedDicom.SOPInstanceUID,\n });\n });\n });\n });\n\n _store.urls.push({\n url,\n studies: [...data.studies],\n });\n _store.studyInstanceUIDMap.set(\n url,\n data.studies.map(study => study.StudyInstanceUID)\n );\n },\n query: {\n studies: {\n mapParams: () => {},\n search: async param => {\n const [key, value] = Object.entries(param)[0];\n const mappedParam = mappings[key];\n\n // todo: should fetch from dicomMetadataStore\n const studies = findStudies(mappedParam, value);\n\n return studies.map(aStudy => {\n return {\n accession: aStudy.AccessionNumber,\n date: aStudy.StudyDate,\n description: aStudy.StudyDescription,\n instances: aStudy.NumInstances,\n modalities: aStudy.Modalities,\n mrn: aStudy.PatientID,\n patientName: aStudy.PatientName,\n studyInstanceUid: aStudy.StudyInstanceUID,\n NumInstances: aStudy.NumInstances,\n time: aStudy.StudyTime,\n };\n });\n },\n processResults: () => {\n console.warn(' DICOMJson QUERY processResults not implemented');\n },\n },\n series: {\n // mapParams: mapParams.bind(),\n search: () => {\n console.warn(' DICOMJson QUERY SERIES SEARCH not implemented');\n },\n },\n instances: {\n search: () => {\n console.warn(' DICOMJson QUERY instances SEARCH not implemented');\n },\n },\n },\n retrieve: {\n /**\n * Generates a URL that can be used for direct retrieve of the bulkdata\n *\n * @param {object} params\n * @param {string} params.tag is the tag name of the URL to retrieve\n * @param {string} params.defaultPath path for the pixel data url\n * @param {object} params.instance is the instance object that the tag is in\n * @param {string} params.defaultType is the mime type of the response\n * @param {string} params.singlepart is the type of the part to retrieve\n * @param {string} params.fetchPart unknown?\n * @returns an absolute URL to the resource, if the absolute URL can be retrieved as singlepart,\n * or is already retrieved, or a promise to a URL for such use if a BulkDataURI\n */\n directURL: params => {\n return getDirectURL(dicomJsonConfig, params);\n },\n series: {\n metadata: async ({ StudyInstanceUID, madeInClient = false, customSort } = {}) => {\n if (!StudyInstanceUID) {\n throw new Error('Unable to query for SeriesMetadata without StudyInstanceUID');\n }\n\n const study = findStudies('StudyInstanceUID', StudyInstanceUID)[0];\n let series;\n\n if (customSort) {\n series = customSort(study.series);\n } else {\n series = study.series;\n }\n\n const seriesSummaryMetadata = series.map(series => {\n const seriesSummary = {\n StudyInstanceUID: study.StudyInstanceUID,\n ...series,\n };\n delete seriesSummary.instances;\n return seriesSummary;\n });\n\n // Async load series, store as retrieved\n function storeInstances(naturalizedInstances) {\n DicomMetadataStore.addInstances(naturalizedInstances, madeInClient);\n }\n\n DicomMetadataStore.addSeriesMetadata(seriesSummaryMetadata, madeInClient);\n\n function setSuccessFlag() {\n const study = DicomMetadataStore.getStudy(StudyInstanceUID, madeInClient);\n study.isLoaded = true;\n }\n\n const numberOfSeries = series.length;\n series.forEach((series, index) => {\n const instances = series.instances.map(instance => {\n // for instance.metadata if the key ends with sequence then\n // we need to add a proxy to the first item in the sequence\n // so that we can access the value of the sequence\n // by using sequenceName.value\n const modifiedMetadata = wrapSequences(instance.metadata);\n\n const obj = {\n ...modifiedMetadata,\n url: instance.url,\n imageId: instance.url,\n ...series,\n ...study,\n };\n delete obj.instances;\n delete obj.series;\n return obj;\n });\n storeInstances(instances);\n if (index === numberOfSeries - 1) {\n setSuccessFlag();\n }\n });\n },\n },\n },\n store: {\n dicom: () => {\n console.warn(' DICOMJson store dicom not implemented');\n },\n },\n getImageIdsForDisplaySet(displaySet) {\n const images = displaySet.images;\n const imageIds = [];\n\n if (!images) {\n return imageIds;\n }\n\n displaySet.images.forEach(instance => {\n const NumberOfFrames = instance.NumberOfFrames;\n\n if (NumberOfFrames > 1) {\n for (let i = 0; i < NumberOfFrames; i++) {\n const imageId = getImageId({\n instance,\n frame: i,\n config: dicomJsonConfig,\n });\n imageIds.push(imageId);\n }\n } else {\n const imageId = getImageId({ instance, config: dicomJsonConfig });\n imageIds.push(imageId);\n }\n });\n\n return imageIds;\n },\n getImageIdsForInstance({ instance, frame }) {\n const imageIds = getImageId({ instance, frame });\n return imageIds;\n },\n getStudyInstanceUIDs: ({ params, query }) => {\n const url = query.get('url');\n return _store.studyInstanceUIDMap.get(url);\n },\n };\n return IWebApiDataSource.create(implementation);\n}\n\nexport { createDicomJSONApi };\n","import { DicomMetadataStore, IWebApiDataSource, utils } from '@ohif/core';\nimport OHIF from '@ohif/core';\nimport dcmjs from 'dcmjs';\n\nconst metadataProvider = OHIF.classes.MetadataProvider;\nconst { EVENTS } = DicomMetadataStore;\n\nconst END_MODALITIES = {\n SR: true,\n SEG: true,\n DOC: true,\n};\n\nconst compareValue = (v1, v2, def = 0) => {\n if (v1 === v2) {\n return def;\n }\n if (v1 < v2) {\n return -1;\n }\n return 1;\n};\n\n// Sorting SR modalities to be at the end of series list\nconst customSort = (seriesA, seriesB) => {\n const instanceA = seriesA.instances[0];\n const instanceB = seriesB.instances[0];\n const modalityA = instanceA.Modality;\n const modalityB = instanceB.Modality;\n\n const isEndA = END_MODALITIES[modalityA];\n const isEndB = END_MODALITIES[modalityB];\n\n if (isEndA && isEndB) {\n // Compare by series date\n return compareValue(instanceA.SeriesNumber, instanceB.SeriesNumber);\n }\n if (!isEndA && !isEndB) {\n return compareValue(instanceB.SeriesNumber, instanceA.SeriesNumber);\n }\n return isEndA ? -1 : 1;\n};\n\nfunction createDicomLocalApi(dicomLocalConfig) {\n const { name } = dicomLocalConfig;\n\n const implementation = {\n initialize: ({ params, query }) => {},\n query: {\n studies: {\n mapParams: () => {},\n search: params => {\n const studyUIDs = DicomMetadataStore.getStudyInstanceUIDs();\n\n return studyUIDs.map(StudyInstanceUID => {\n let numInstances = 0;\n const modalities = new Set();\n\n // Calculating the number of instances in the study and modalities\n // present in the study\n const study = DicomMetadataStore.getStudy(StudyInstanceUID);\n study.series.forEach(aSeries => {\n numInstances += aSeries.instances.length;\n modalities.add(aSeries.instances[0].Modality);\n });\n\n // first instance in the first series\n const firstInstance = study?.series[0]?.instances[0];\n\n if (firstInstance) {\n return {\n accession: firstInstance.AccessionNumber,\n date: firstInstance.StudyDate,\n description: firstInstance.StudyDescription,\n mrn: firstInstance.PatientID,\n patientName: utils.formatPN(firstInstance.PatientName),\n studyInstanceUid: firstInstance.StudyInstanceUID,\n time: firstInstance.StudyTime,\n //\n instances: numInstances,\n modalities: Array.from(modalities).join('/'),\n NumInstances: numInstances,\n };\n }\n });\n },\n processResults: () => {\n console.warn(' DICOMLocal QUERY processResults not implemented');\n },\n },\n series: {\n search: studyInstanceUID => {\n const study = DicomMetadataStore.getStudy(studyInstanceUID);\n return study.series.map(aSeries => {\n const firstInstance = aSeries?.instances[0];\n return {\n studyInstanceUid: studyInstanceUID,\n seriesInstanceUid: firstInstance.SeriesInstanceUID,\n modality: firstInstance.Modality,\n seriesNumber: firstInstance.SeriesNumber,\n seriesDate: firstInstance.SeriesDate,\n numSeriesInstances: aSeries.instances.length,\n description: firstInstance.SeriesDescription,\n };\n });\n },\n },\n instances: {\n search: () => {\n console.warn(' DICOMLocal QUERY instances SEARCH not implemented');\n },\n },\n },\n retrieve: {\n directURL: params => {\n const { instance, tag, defaultType } = params;\n\n const value = instance[tag];\n if (value instanceof Array && value[0] instanceof ArrayBuffer) {\n return URL.createObjectURL(\n new Blob([value[0]], {\n type: defaultType,\n })\n );\n }\n },\n series: {\n metadata: async ({ StudyInstanceUID, madeInClient = false } = {}) => {\n if (!StudyInstanceUID) {\n throw new Error('Unable to query for SeriesMetadata without StudyInstanceUID');\n }\n\n // Instances metadata already added via local upload\n const study = DicomMetadataStore.getStudy(StudyInstanceUID, madeInClient);\n\n // Series metadata already added via local upload\n DicomMetadataStore._broadcastEvent(EVENTS.SERIES_ADDED, {\n StudyInstanceUID,\n madeInClient,\n });\n\n study.series.forEach(aSeries => {\n const { SeriesInstanceUID } = aSeries;\n\n const isMultiframe = aSeries.instances[0].NumberOfFrames > 1;\n\n aSeries.instances.forEach((instance, index) => {\n const {\n url: imageId,\n StudyInstanceUID,\n SeriesInstanceUID,\n SOPInstanceUID,\n } = instance;\n\n instance.imageId = imageId;\n\n // Add imageId specific mapping to this data as the URL isn't necessarily WADO-URI.\n metadataProvider.addImageIdToUIDs(imageId, {\n StudyInstanceUID,\n SeriesInstanceUID,\n SOPInstanceUID,\n frameIndex: isMultiframe ? index : 1,\n });\n });\n\n DicomMetadataStore._broadcastEvent(EVENTS.INSTANCES_ADDED, {\n StudyInstanceUID,\n SeriesInstanceUID,\n madeInClient,\n });\n });\n },\n },\n },\n store: {\n dicom: naturalizedReport => {\n const reportBlob = dcmjs.data.datasetToBlob(naturalizedReport);\n\n //Create a URL for the binary.\n var objectUrl = URL.createObjectURL(reportBlob);\n window.location.assign(objectUrl);\n },\n },\n getImageIdsForDisplaySet(displaySet) {\n const images = displaySet.images;\n const imageIds = [];\n\n if (!images) {\n return imageIds;\n }\n\n displaySet.images.forEach(instance => {\n const NumberOfFrames = instance.NumberOfFrames;\n if (NumberOfFrames > 1) {\n // in multiframe we start at frame 1\n for (let i = 1; i <= NumberOfFrames; i++) {\n const imageId = this.getImageIdsForInstance({\n instance,\n frame: i,\n });\n imageIds.push(imageId);\n }\n } else {\n const imageId = this.getImageIdsForInstance({ instance });\n imageIds.push(imageId);\n }\n });\n\n return imageIds;\n },\n getImageIdsForInstance({ instance, frame }) {\n const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance;\n const storedInstance = DicomMetadataStore.getInstance(\n StudyInstanceUID,\n SeriesInstanceUID,\n SOPInstanceUID\n );\n\n let imageId = storedInstance.url;\n\n if (frame !== undefined) {\n imageId += `&frame=${frame}`;\n }\n\n return imageId;\n },\n deleteStudyMetadataPromise() {\n console.log('deleteStudyMetadataPromise not implemented');\n },\n getStudyInstanceUIDs: ({ params, query }) => {\n const { StudyInstanceUIDs: paramsStudyInstanceUIDs } = params;\n const queryStudyInstanceUIDs = query.getAll('StudyInstanceUIDs');\n\n const StudyInstanceUIDs = queryStudyInstanceUIDs || paramsStudyInstanceUIDs;\n const StudyInstanceUIDsAsArray =\n StudyInstanceUIDs && Array.isArray(StudyInstanceUIDs)\n ? StudyInstanceUIDs\n : [StudyInstanceUIDs];\n\n // Put SRs at the end of series list to make sure images are loaded first\n let isStudyInCache = false;\n StudyInstanceUIDsAsArray.forEach(StudyInstanceUID => {\n const study = DicomMetadataStore.getStudy(StudyInstanceUID);\n if (study) {\n study.series = study.series.sort(customSort);\n isStudyInCache = true;\n }\n });\n\n return isStudyInCache ? StudyInstanceUIDsAsArray : [];\n },\n };\n return IWebApiDataSource.create(implementation);\n}\n\nexport { createDicomLocalApi };\n","import { IWebApiDataSource } from '@ohif/core';\nimport { createDicomWebApi } from '../DicomWebDataSource/index';\n\n/**\n * This datasource is initialized with a url that returns a JSON object with a\n * dicomWeb datasource configuration array present in a \"servers\" object.\n *\n * Only the first array item is parsed, if there are multiple items in the\n * dicomWeb configuration array\n *\n */\nfunction createDicomWebProxyApi(dicomWebProxyConfig, servicesManager) {\n const { name } = dicomWebProxyConfig;\n let dicomWebDelegate = undefined;\n\n const implementation = {\n initialize: async ({ params, query }) => {\n const url = query.get('url');\n\n if (!url) {\n throw new Error(`No url for '${name}'`);\n } else {\n const response = await fetch(url);\n let data = await response.json();\n if (!data.servers?.dicomWeb?.[0]) {\n throw new Error('Invalid configuration returned by url');\n }\n\n dicomWebDelegate = createDicomWebApi(\n data.servers.dicomWeb[0].configuration,\n servicesManager\n );\n dicomWebDelegate.initialize({ params, query });\n }\n },\n query: {\n studies: {\n search: params => dicomWebDelegate.query.studies.search(params),\n },\n series: {\n search: (...args) => dicomWebDelegate.query.series.search(...args),\n },\n instances: {\n search: (studyInstanceUid, queryParameters) =>\n dicomWebDelegate.query.instances.search(studyInstanceUid, queryParameters),\n },\n },\n retrieve: {\n directURL: (...args) => dicomWebDelegate.retrieve.directURL(...args),\n series: {\n metadata: async (...args) => dicomWebDelegate.retrieve.series.metadata(...args),\n },\n },\n store: {\n dicom: (...args) => dicomWebDelegate.store(...args),\n },\n deleteStudyMetadataPromise: (...args) => dicomWebDelegate.deleteStudyMetadataPromise(...args),\n getImageIdsForDisplaySet: (...args) => dicomWebDelegate.getImageIdsForDisplaySet(...args),\n getImageIdsForInstance: (...args) => dicomWebDelegate.getImageIdsForInstance(...args),\n getStudyInstanceUIDs({ params, query }) {\n let studyInstanceUIDs = [];\n\n // there seem to be a couple of variations of the case for this parameter\n const queryStudyInstanceUIDs =\n query.get('studyInstanceUIDs') || query.get('studyInstanceUids');\n if (!queryStudyInstanceUIDs) {\n throw new Error(`No studyInstanceUids in request for '${name}'`);\n }\n studyInstanceUIDs = queryStudyInstanceUIDs.split(';');\n return studyInstanceUIDs;\n },\n };\n return IWebApiDataSource.create(implementation);\n}\n\nexport { createDicomWebProxyApi };\n","import { DicomMetadataStore, IWebApiDataSource } from '@ohif/core';\nimport { get, uniqBy } from 'lodash';\nimport {\n MergeConfig,\n CallForAllDataSourcesAsyncOptions,\n CallForAllDataSourcesOptions,\n CallForDefaultDataSourceOptions,\n CallByRetrieveAETitleOptions,\n MergeMap,\n} from './types';\n\nexport const mergeMap: MergeMap = {\n 'query.studies.search': {\n mergeKey: 'studyInstanceUid',\n tagFunc: x => x,\n },\n 'query.series.search': {\n mergeKey: 'seriesInstanceUid',\n tagFunc: (series, sourceName) => {\n series.forEach(series => {\n series.RetrieveAETitle = sourceName;\n DicomMetadataStore.updateSeriesMetadata(series);\n });\n return series;\n },\n },\n};\n\n/**\n * Calls all data sources asynchronously and merges the results.\n * @param {CallForAllDataSourcesAsyncOptions} options - The options for calling all data sources.\n * @param {string} options.path - The path to the function to be called on each data source.\n * @param {unknown[]} options.args - The arguments to be passed to the function.\n * @param {ExtensionManager} options.extensionManager - The extension manager.\n * @param {string[]} options.dataSourceNames - The names of the data sources to be called.\n * @param {string} options.defaultDataSourceName - The name of the default data source.\n * @returns {Promise<unknown[]>} - A promise that resolves to the merged data from all data sources.\n */\nexport const callForAllDataSourcesAsync = async ({\n mergeMap,\n path,\n args,\n extensionManager,\n dataSourceNames,\n defaultDataSourceName,\n}: CallForAllDataSourcesAsyncOptions) => {\n const { mergeKey, tagFunc } = mergeMap[path] || { tagFunc: x => x };\n\n /** Sort by default data source */\n const defs = Object.values(extensionManager.dataSourceDefs);\n const defaultDataSourceDef = defs.find(def => def.sourceName === defaultDataSourceName);\n const dataSourceDefs = defs.filter(def => def.sourceName !== defaultDataSourceName);\n if (defaultDataSourceDef) {\n dataSourceDefs.unshift(defaultDataSourceDef);\n }\n\n const promises = [];\n const sourceNames = [];\n\n for (const dataSourceDef of dataSourceDefs) {\n const { configuration, sourceName } = dataSourceDef;\n if (!!configuration && dataSourceNames.includes(sourceName)) {\n const [dataSource] = extensionManager.getDataSources(sourceName);\n const func = get(dataSource, path);\n const promise = func.apply(dataSource, args);\n promises.push(promise);\n sourceNames.push(sourceName);\n }\n }\n\n const data = await Promise.allSettled(promises);\n const mergedData = data.map((data, i) => tagFunc(data.value, sourceNames[i]));\n\n let results = [];\n if (mergeKey) {\n results = uniqBy(mergedData.flat(), obj => get(obj, mergeKey));\n } else {\n results = mergedData.flat();\n }\n\n return results;\n};\n\n/**\n * Calls all data sources that match the provided names and merges their data.\n * @param options - The options for calling all data sources.\n * @param options.path - The path to the function to be called on each data source.\n * @param options.args - The arguments to be passed to the function.\n * @param options.extensionManager - The extension manager instance.\n * @param options.dataSourceNames - The names of the data sources to be called.\n * @param options.defaultDataSourceName - The name of the default data source.\n * @returns The merged data from all the matching data sources.\n */\nexport const callForAllDataSources = ({\n path,\n args,\n extensionManager,\n dataSourceNames,\n defaultDataSourceName,\n}: CallForAllDataSourcesOptions) => {\n /** Sort by default data source */\n const defs = Object.values(extensionManager.dataSourceDefs);\n const defaultDataSourceDef = defs.find(def => def.sourceName === defaultDataSourceName);\n const dataSourceDefs = defs.filter(def => def.sourceName !== defaultDataSourceName);\n if (defaultDataSourceDef) {\n dataSourceDefs.unshift(defaultDataSourceDef);\n }\n\n const mergedData = [];\n for (const dataSourceDef of dataSourceDefs) {\n const { configuration, sourceName } = dataSourceDef;\n if (!!configuration && dataSourceNames.includes(sourceName)) {\n const [dataSource] = extensionManager.getDataSources(sourceName);\n const func = get(dataSource, path);\n const data = func.apply(dataSource, args);\n mergedData.push(data);\n }\n }\n\n return mergedData.flat();\n};\n\n/**\n * Calls the default data source function specified by the given path with the provided arguments.\n * @param {CallForDefaultDataSourceOptions} options - The options for calling the default data source.\n * @param {string} options.path - The path to the function within the default data source.\n * @param {unknown[]} options.args - The arguments to pass to the function.\n * @param {string} options.defaultDataSourceName - The name of the default data source.\n * @param {ExtensionManager} options.extensionManager - The extension manager instance.\n * @returns {unknown} - The result of calling the default data source function.\n */\nexport const callForDefaultDataSource = ({\n path,\n args,\n defaultDataSourceName,\n extensionManager,\n}: CallForDefaultDataSourceOptions) => {\n const [dataSource] = extensionManager.getDataSources(defaultDataSourceName);\n const func = get(dataSource, path);\n return func.apply(dataSource, args);\n};\n\n/**\n * Calls the data source specified by the RetrieveAETitle of the given display set.\n * @typedef {Object} CallByRetrieveAETitleOptions\n * @property {string} path - The path of the method to call on the data source.\n * @property {any[]} args - The arguments to pass to the method.\n * @property {string} defaultDataSourceName - The name of the default data source.\n * @property {ExtensionManager} extensionManager - The extension manager.\n */\nexport const callByRetrieveAETitle = ({\n path,\n args,\n defaultDataSourceName,\n extensionManager,\n}: CallByRetrieveAETitleOptions) => {\n const [displaySet] = args;\n const seriesMetadata = DicomMetadataStore.getSeries(\n displaySet.StudyInstanceUID,\n displaySet.SeriesInstanceUID\n );\n const [dataSource] = extensionManager.getDataSources(\n seriesMetadata.RetrieveAETitle || defaultDataSourceName\n );\n return dataSource[path](...args);\n};\n\nfunction createMergeDataSourceApi(\n mergeConfig: MergeConfig,\n servicesManager: unknown,\n extensionManager\n) {\n const { seriesMerge } = mergeConfig;\n const { dataSourceNames, defaultDataSourceName } = seriesMerge;\n\n const implementation = {\n initialize: (...args: unknown[]) =>\n callForAllDataSources({\n path: 'initialize',\n args,\n extensionManager,\n dataSourceNames,\n defaultDataSourceName,\n }),\n query: {\n studies: {\n search: (...args: unknown[]) =>\n callForAllDataSourcesAsync({\n mergeMap,\n path: 'query.studies.search',\n args,\n extensionManager,\n dataSourceNames,\n defaultDataSourceName,\n }),\n },\n series: {\n search: (...args: unknown[]) =>\n callForAllDataSourcesAsync({\n mergeMap,\n path: 'query.series.search',\n args,\n extensionManager,\n dataSourceNames,\n defaultDataSourceName,\n }),\n },\n instances: {\n search: (...args: unknown[]) =>\n callForAllDataSourcesAsync({\n mergeMap,\n path: 'query.instances.search',\n args,\n extensionManager,\n dataSourceNames,\n defaultDataSourceName,\n }),\n },\n },\n retrieve: {\n bulkDataURI: (...args: unknown[]) =>\n callForAllDataSourcesAsync({\n mergeMap,\n path: 'retrieve.bulkDataURI',\n args,\n extensionManager,\n dataSourceNames,\n defaultDataSourceName,\n }),\n directURL: (...args: unknown[]) =>\n callForDefaultDataSource({\n path: 'retrieve.directURL',\n args,\n defaultDataSourceName,\n extensionManager,\n }),\n series: {\n metadata: (...args: unknown[]) =>\n callForAllDataSourcesAsync({\n mergeMap,\n path: 'retrieve.series.metadata',\n args,\n extensionManager,\n dataSourceNames,\n defaultDataSourceName,\n }),\n },\n },\n store: {\n dicom: (...args: unknown[]) =>\n callForDefaultDataSource({\n path: 'store.dicom',\n args,\n defaultDataSourceName,\n extensionManager,\n }),\n },\n deleteStudyMetadataPromise: (...args: unknown[]) =>\n callForAllDataSources({\n path: 'deleteStudyMetadataPromise',\n args,\n extensionManager,\n dataSourceNames,\n defaultDataSourceName,\n }),\n getImageIdsForDisplaySet: (...args: unknown[]) =>\n callByRetrieveAETitle({\n path: 'getImageIdsForDisplaySet',\n args,\n defaultDataSourceName,\n extensionManager,\n }),\n getImageIdsForInstance: (...args: unknown[]) =>\n callByRetrieveAETitle({\n path: 'getImageIdsForDisplaySet',\n args,\n defaultDataSourceName,\n extensionManager,\n }),\n getStudyInstanceUIDs: (...args: unknown[]) =>\n callForAllDataSources({\n path: 'getStudyInstanceUIDs',\n args,\n extensionManager,\n dataSourceNames,\n defaultDataSourceName,\n }),\n };\n\n return IWebApiDataSource.create(implementation);\n}\n\nexport { createMergeDataSourceApi };\n","// TODO: Pull in IWebClientApi from @ohif/core\n// TODO: Use constructor to create an instance of IWebClientApi\n// TODO: Use existing DICOMWeb configuration (previously, appConfig, to configure instance)\n\nimport { createDicomWebApi } from './DicomWebDataSource/index.js';\nimport { createDicomJSONApi } from './DicomJSONDataSource/index.js';\nimport { createDicomLocalApi } from './DicomLocalDataSource/index.js';\nimport { createDicomWebProxyApi } from './DicomWebProxyDataSource/index.js';\nimport { createMergeDataSourceApi } from './MergeDataSource/index';\n\n/**\n *\n */\nfunction getDataSourcesModule() {\n return [\n {\n name: 'dicomweb',\n type: 'webApi',\n createDataSource: createDicomWebApi,\n },\n {\n name: 'dicomwebproxy',\n type: 'webApi',\n createDataSource: createDicomWebProxyApi,\n },\n {\n name: 'dicomjson',\n type: 'jsonApi',\n createDataSource: createDicomJSONApi,\n },\n {\n name: 'dicomlocal',\n type: 'localApi',\n createDataSource: createDicomLocalApi,\n },\n {\n name: 'merge',\n type: 'mergeApi',\n createDataSource: createMergeDataSourceApi,\n },\n ];\n}\n\nexport default getDataSourcesModule;\n","import React from 'react';\nimport { Tooltip } from '@ohif/ui';\nimport classnames from 'classnames';\nimport { useToolbar } from '@ohif/core';\n\nexport function Toolbar({ servicesManager, buttonSection = 'primary' }) {\n const { toolbarButtons, onInteraction } = useToolbar({\n servicesManager,\n buttonSection,\n });\n\n if (!toolbarButtons.length) {\n return null;\n }\n\n return (\n <>\n {toolbarButtons.map(toolDef => {\n if (!toolDef) {\n return null;\n }\n\n const { id, Component, componentProps } = toolDef;\n const tool = (\n <Component\n key={id}\n id={id}\n onInteraction={onInteraction}\n servicesManager={servicesManager}\n {...componentProps}\n />\n );\n\n return <div key={id}>{tool}</div>;\n })}\n </>\n );\n}\n","import React from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { useTranslation } from 'react-i18next';\nimport { useLocation } from 'react-router';\n\nimport { ErrorBoundary, UserPreferences, AboutModal, Header, useModal } from '@ohif/ui';\nimport i18n from '@ohif/i18n';\nimport { hotkeys } from '@ohif/core';\nimport { Toolbar } from '../Toolbar/Toolbar';\n\nconst { availableLanguages, defaultLanguage, currentLanguage } = i18n;\n\nfunction ViewerHeader({ hotkeysManager, extensionManager, servicesManager, appConfig }) {\n const navigate = useNavigate();\n const location = useLocation();\n const { FhircastService } = servicesManager.services;\n\n const onClickReturnButton = () => {\n const { pathname } = location;\n const dataSourceIdx = pathname.indexOf('/', 1);\n const query = new URLSearchParams(window.location.search);\n const configUrl = query.get('configUrl');\n\n const dataSourceName = pathname.substring(dataSourceIdx + 1);\n const existingDataSource = extensionManager.getDataSources(dataSourceName);\n\n const searchQuery = new URLSearchParams();\n if (dataSourceIdx !== -1 && existingDataSource) {\n searchQuery.append('datasources', pathname.substring(dataSourceIdx + 1));\n }\n\n if (configUrl) {\n searchQuery.append('configUrl', configUrl);\n }\n\n FhircastService.fhircastPublish({\n timestamp: '',\n id: '',\n event: { 'hub.topic': '', 'hub.event': 'imagingstudy-close', context: [] },\n });\n navigate({\n pathname: '/',\n search: decodeURIComponent(searchQuery.toString()),\n });\n };\n\n const { t } = useTranslation();\n const { show, hide } = useModal();\n const { hotkeyDefinitions, hotkeyDefaults } = hotkeysManager;\n const versionNumber = process.env.VERSION_NUMBER;\n const commitHash = process.env.COMMIT_HASH;\n\n const menuOptions = [\n {\n title: t('Header:About'),\n icon: 'info',\n onClick: () =>\n show({\n content: AboutModal,\n title: t('AboutModal:About OHIF Viewer'),\n contentProps: { versionNumber, commitHash },\n containerDimensions: 'max-w-4xl max-h-4xl',\n }),\n },\n {\n title: t('Header:Preferences'),\n icon: 'settings',\n onClick: () =>\n show({\n title: t('UserPreferencesModal:User preferences'),\n content: UserPreferences,\n contentProps: {\n hotkeyDefaults: hotkeysManager.getValidHotkeyDefinitions(hotkeyDefaults),\n hotkeyDefinitions,\n currentLanguage: currentLanguage(),\n availableLanguages,\n defaultLanguage,\n onCancel: () => {\n hotkeys.stopRecord();\n hotkeys.unpause();\n hide();\n },\n onSubmit: ({ hotkeyDefinitions, language }) => {\n if (language.value !== currentLanguage().value) {\n i18n.changeLanguage(language.value);\n }\n hotkeysManager.setHotkeys(hotkeyDefinitions);\n hide();\n },\n onReset: () => hotkeysManager.restoreDefaultBindings(),\n hotkeysModule: hotkeys,\n },\n }),\n },\n ];\n\n if (appConfig.oidc) {\n menuOptions.push({\n title: t('Header:Logout'),\n icon: 'power-off',\n onClick: async () => {\n navigate(`/logout?redirect_uri=${encodeURIComponent(window.location.href)}`);\n },\n });\n }\n if (appConfig.fhircast) {\n menuOptions.push({\n title: t('Header:FHIRcast'),\n icon: 'power-off',\n onClick: async () => {\n window.open('https://hub-fhircast.azurewebsites.net/', '_blank');\n },\n });\n }\n return (\n <Header\n menuOptions={menuOptions}\n isReturnEnabled={!!appConfig.showStudyList}\n onClickReturnButton={onClickReturnButton}\n WhiteLabeling={appConfig.whiteLabeling}\n showPatientInfo={appConfig.showPatientInfo}\n servicesManager={servicesManager}\n Secondary={\n <Toolbar\n servicesManager={servicesManager}\n buttonSection=\"secondary\"\n />\n }\n appConfig={appConfig}\n >\n <ErrorBoundary context=\"Primary Toolbar\">\n <div className=\"relative flex justify-center gap-[4px]\">\n <Toolbar servicesManager={servicesManager} />\n </div>\n </ErrorBoundary>\n </Header>\n );\n}\n\nexport default ViewerHeader;\n","import React, { useEffect, useState, useCallback } from 'react';\nimport { SidePanel } from '@ohif/ui';\nimport { PanelService, ServicesManager, Types } from '@ohif/core';\n\nexport type SidePanelWithServicesProps = {\n servicesManager: ServicesManager;\n side: 'left' | 'right';\n className: string;\n activeTabIndex: number;\n tabs: any;\n expandedWidth?: number;\n};\n\nconst SidePanelWithServices = ({\n servicesManager,\n side,\n activeTabIndex: activeTabIndexProp,\n tabs: tabsProp,\n expandedWidth,\n ...props\n}: SidePanelWithServicesProps) => {\n const panelService: PanelService = servicesManager?.services?.panelService;\n\n // Tracks whether this SidePanel has been opened at least once since this SidePanel was inserted into the DOM.\n // Thus going to the Study List page and back to the viewer resets this flag for a SidePanel.\n const [hasBeenOpened, setHasBeenOpened] = useState(false);\n const [activeTabIndex, setActiveTabIndex] = useState(activeTabIndexProp);\n const [tabs, setTabs] = useState(tabsProp ?? panelService.getPanels(side));\n\n const handleSidePanelOpen = useCallback(() => {\n setHasBeenOpened(true);\n }, []);\n\n const handleActiveTabIndexChange = useCallback(({ activeTabIndex }) => {\n setActiveTabIndex(activeTabIndex);\n }, []);\n\n /** update the active tab index from outside */\n useEffect(() => {\n setActiveTabIndex(activeTabIndexProp);\n }, [activeTabIndexProp]);\n\n useEffect(() => {\n const { unsubscribe } = panelService.subscribe(\n panelService.EVENTS.PANELS_CHANGED,\n panelChangedEvent => {\n if (panelChangedEvent.position !== side) {\n return;\n }\n\n setTabs(panelService.getPanels(side));\n }\n );\n\n return () => {\n unsubscribe();\n };\n }, [panelService, side]);\n\n useEffect(() => {\n const activatePanelSubscription = panelService.subscribe(\n panelService.EVENTS.ACTIVATE_PANEL,\n (activatePanelEvent: Types.ActivatePanelEvent) => {\n if (!hasBeenOpened || activatePanelEvent.forceActive) {\n const tabIndex = tabs.findIndex(tab => tab.id === activatePanelEvent.panelId);\n if (tabIndex !== -1) {\n setActiveTabIndex(tabIndex);\n }\n }\n }\n );\n\n return () => {\n activatePanelSubscription.unsubscribe();\n };\n }, [tabs, hasBeenOpened, panelService]);\n\n return (\n <SidePanel\n {...props}\n side={side}\n tabs={tabs}\n activeTabIndex={activeTabIndex}\n onOpen={handleSidePanelOpen}\n onActiveTabIndexChange={handleActiveTabIndexChange}\n expandedWidth={expandedWidth}\n ></SidePanel>\n );\n};\n\nexport default SidePanelWithServices;\n","import React, { useEffect, useState, useCallback } from 'react';\nimport PropTypes from 'prop-types';\n\nimport { ErrorBoundary, LoadingIndicatorProgress, InvestigationalUseDialog } from '@ohif/ui';\nimport { ServicesManager, HangingProtocolService, CommandsManager } from '@ohif/core';\nimport { useAppConfig } from '@state';\nimport ViewerHeader from './ViewerHeader';\nimport SidePanelWithServices from '../Components/SidePanelWithServices';\n\nfunction ViewerLayout({\n // From Extension Module Params\n extensionManager,\n servicesManager,\n hotkeysManager,\n commandsManager,\n // From Modes\n viewports,\n ViewportGridComp,\n leftPanelClosed = false,\n rightPanelClosed = false,\n}): React.FunctionComponent {\n const [appConfig] = useAppConfig();\n\n const { panelService, hangingProtocolService } = servicesManager.services;\n const [showLoadingIndicator, setShowLoadingIndicator] = useState(appConfig.showLoadingIndicator);\n\n const hasPanels = useCallback(\n (side): boolean => !!panelService.getPanels(side).length,\n [panelService]\n );\n\n const [hasRightPanels, setHasRightPanels] = useState(hasPanels('right'));\n const [hasLeftPanels, setHasLeftPanels] = useState(hasPanels('left'));\n const [leftPanelClosedState, setLeftPanelClosed] = useState(leftPanelClosed);\n const [rightPanelClosedState, setRightPanelClosed] = useState(rightPanelClosed);\n\n /**\n * Set body classes (tailwindcss) that don't allow vertical\n * or horizontal overflow (no scrolling). Also guarantee window\n * is sized to our viewport.\n */\n useEffect(() => {\n document.body.classList.add('bg-black');\n document.body.classList.add('overflow-hidden');\n return () => {\n document.body.classList.remove('bg-black');\n document.body.classList.remove('overflow-hidden');\n };\n }, []);\n\n const getComponent = id => {\n const entry = extensionManager.getModuleEntry(id);\n\n if (!entry || !entry.component) {\n throw new Error(\n `${id} is not valid for an extension module or no component found from extension ${id}. Please verify your configuration or ensure that the extension is properly registered. It's also possible that your mode is utilizing a module from an extension that hasn't been included in its dependencies (add the extension to the \"extensionDependencies\" array in your mode's index.js file). Check the reference string to the extension in your Mode configuration`\n );\n }\n\n return { entry, content: entry.component };\n };\n\n useEffect(() => {\n const { unsubscribe } = hangingProtocolService.subscribe(\n HangingProtocolService.EVENTS.PROTOCOL_CHANGED,\n\n // Todo: right now to set the loading indicator to false, we need to wait for the\n // hangingProtocolService to finish applying the viewport matching to each viewport,\n // however, this might not be the only approach to set the loading indicator to false. we need to explore this further.\n () => {\n setShowLoadingIndicator(false);\n }\n );\n\n return () => {\n unsubscribe();\n };\n }, [hangingProtocolService]);\n\n const getViewportComponentData = viewportComponent => {\n const { entry } = getComponent(viewportComponent.namespace);\n\n return {\n component: entry.component,\n displaySetsToDisplay: viewportComponent.displaySetsToDisplay,\n };\n };\n\n useEffect(() => {\n const { unsubscribe } = panelService.subscribe(\n panelService.EVENTS.PANELS_CHANGED,\n ({ options }) => {\n setHasLeftPanels(hasPanels('left'));\n setHasRightPanels(hasPanels('right'));\n if (options?.leftPanelClosed !== undefined) {\n setLeftPanelClosed(options.leftPanelClosed);\n }\n if (options?.rightPanelClosed !== undefined) {\n setRightPanelClosed(options.rightPanelClosed);\n }\n }\n );\n\n return () => {\n unsubscribe();\n };\n }, [panelService, hasPanels]);\n\n const viewportComponents = viewports.map(getViewportComponentData);\n\n return (\n <div>\n <ViewerHeader\n hotkeysManager={hotkeysManager}\n extensionManager={extensionManager}\n servicesManager={servicesManager}\n appConfig={appConfig}\n />\n <div\n className=\"relative flex w-full flex-row flex-nowrap items-stretch overflow-hidden bg-black\"\n style={{ height: 'calc(100vh - 52px' }}\n >\n <React.Fragment>\n {showLoadingIndicator && <LoadingIndicatorProgress className=\"h-full w-full bg-black\" />}\n {/* LEFT SIDEPANELS */}\n {hasLeftPanels ? (\n <ErrorBoundary context=\"Left Panel\">\n <SidePanelWithServices\n side=\"left\"\n activeTabIndex={leftPanelClosedState ? null : 0}\n servicesManager={servicesManager}\n />\n </ErrorBoundary>\n ) : null}\n {/* TOOLBAR + GRID */}\n <div className=\"flex h-full flex-1 flex-col\">\n <div className=\"relative flex h-full flex-1 items-center justify-center overflow-hidden bg-black\">\n <ErrorBoundary context=\"Grid\">\n <ViewportGridComp\n servicesManager={servicesManager}\n viewportComponents={viewportComponents}\n commandsManager={commandsManager}\n />\n </ErrorBoundary>\n </div>\n </div>\n {hasRightPanels ? (\n <ErrorBoundary context=\"Right Panel\">\n <SidePanelWithServices\n side=\"right\"\n activeTabIndex={rightPanelClosedState ? null : 0}\n servicesManager={servicesManager}\n />\n </ErrorBoundary>\n ) : null}\n </React.Fragment>\n </div>\n\n <InvestigationalUseDialog dialogConfiguration={appConfig?.investigationalUseDialog} />\n </div>\n );\n}\n\nViewerLayout.propTypes = {\n // From extension module params\n extensionManager: PropTypes.shape({\n getModuleEntry: PropTypes.func.isRequired,\n }).isRequired,\n commandsManager: PropTypes.instanceOf(CommandsManager),\n servicesManager: PropTypes.instanceOf(ServicesManager),\n // From modes\n leftPanels: PropTypes.array,\n rightPanels: PropTypes.array,\n leftPanelClosed: PropTypes.bool.isRequired,\n rightPanelClosed: PropTypes.bool.isRequired,\n /** Responsible for rendering our grid of viewports; provided by consuming application */\n children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired,\n viewports: PropTypes.array,\n};\n\nexport default ViewerLayout;\n","import React, { useState, useEffect, useRef } from 'react';\nimport PropTypes from 'prop-types';\nimport { StudyBrowser, useImageViewer, useViewportGrid } from '@ohif/ui';\nimport { utils } from '@ohif/core';\nimport { useNavigate } from 'react-router-dom';\n\nconst { sortStudyInstances, formatDate } = utils;\n\n/**\n *\n * @param {*} param0\n */\nfunction PanelStudyBrowser({\n servicesManager,\n getImageSrc,\n getStudiesForPatientByMRN,\n requestDisplaySetCreationForStudy,\n dataSource,\n}) {\n const { hangingProtocolService, displaySetService, uiNotificationService } =\n servicesManager.services;\n const navigate = useNavigate();\n\n // Normally you nest the components so the tree isn't so deep, and the data\n // doesn't have to have such an intense shape. This works well enough for now.\n // Tabs --> Studies --> DisplaySets --> Thumbnails\n const { StudyInstanceUIDs } = useImageViewer();\n const [{ activeViewportId, viewports }, viewportGridService] = useViewportGrid();\n const [activeTabName, setActiveTabName] = useState('primary');\n const [expandedStudyInstanceUIDs, setExpandedStudyInstanceUIDs] = useState([\n ...StudyInstanceUIDs,\n ]);\n const [studyDisplayList, setStudyDisplayList] = useState([]);\n const [displaySets, setDisplaySets] = useState([]);\n const [thumbnailImageSrcMap, setThumbnailImageSrcMap] = useState({});\n\n const onDoubleClickThumbnailHandler = displaySetInstanceUID => {\n let updatedViewports = [];\n const viewportId = activeViewportId;\n try {\n updatedViewports = hangingProtocolService.getViewportsRequireUpdate(\n viewportId,\n displaySetInstanceUID\n );\n } catch (error) {\n console.warn(error);\n uiNotificationService.show({\n title: 'Thumbnail Double Click',\n message: 'The selected display sets could not be added to the viewport.',\n type: 'info',\n duration: 3000,\n });\n }\n\n viewportGridService.setDisplaySetsForViewports(updatedViewports);\n };\n\n // ~~ studyDisplayList\n useEffect(() => {\n // Fetch all studies for the patient in each primary study\n async function fetchStudiesForPatient(StudyInstanceUID) {\n // current study qido\n const qidoForStudyUID = await dataSource.query.studies.search({\n studyInstanceUid: StudyInstanceUID,\n });\n\n if (!qidoForStudyUID?.length) {\n navigate('/notfoundstudy', '_self');\n throw new Error('Invalid study URL');\n }\n\n let qidoStudiesForPatient = qidoForStudyUID;\n\n // try to fetch the prior studies based on the patientID if the\n // server can respond.\n try {\n qidoStudiesForPatient = await getStudiesForPatientByMRN(qidoForStudyUID);\n } catch (error) {\n console.warn(error);\n }\n\n const mappedStudies = _mapDataSourceStudies(qidoStudiesForPatient);\n const actuallyMappedStudies = mappedStudies.map(qidoStudy => {\n return {\n studyInstanceUid: qidoStudy.StudyInstanceUID,\n date: formatDate(qidoStudy.StudyDate),\n description: qidoStudy.StudyDescription,\n modalities: qidoStudy.ModalitiesInStudy,\n numInstances: qidoStudy.NumInstances,\n };\n });\n\n setStudyDisplayList(prevArray => {\n const ret = [...prevArray];\n for (const study of actuallyMappedStudies) {\n if (!prevArray.find(it => it.studyInstanceUid === study.studyInstanceUid)) {\n ret.push(study);\n }\n }\n return ret;\n });\n }\n\n StudyInstanceUIDs.forEach(sid => fetchStudiesForPatient(sid));\n }, [StudyInstanceUIDs, dataSource, getStudiesForPatientByMRN, navigate]);\n\n // // ~~ Initial Thumbnails\n useEffect(() => {\n const currentDisplaySets = displaySetService.activeDisplaySets;\n currentDisplaySets.forEach(async dSet => {\n const newImageSrcEntry = {};\n const displaySet = displaySetService.getDisplaySetByUID(dSet.displaySetInstanceUID);\n const imageIds = dataSource.getImageIdsForDisplaySet(displaySet);\n const imageId = imageIds[Math.floor(imageIds.length / 2)];\n\n // TODO: Is it okay that imageIds are not returned here for SR displaySets?\n if (!imageId || displaySet?.unsupported) {\n return;\n }\n // When the image arrives, render it and store the result in the thumbnailImgSrcMap\n newImageSrcEntry[dSet.displaySetInstanceUID] = await getImageSrc(imageId);\n\n setThumbnailImageSrcMap(prevState => {\n return { ...prevState, ...newImageSrcEntry };\n });\n });\n }, [StudyInstanceUIDs, dataSource, displaySetService, getImageSrc]);\n\n // ~~ displaySets\n useEffect(() => {\n // TODO: Are we sure `activeDisplaySets` will always be accurate?\n const currentDisplaySets = displaySetService.activeDisplaySets;\n const mappedDisplaySets = _mapDisplaySets(currentDisplaySets, thumbnailImageSrcMap);\n sortStudyInstances(mappedDisplaySets);\n\n setDisplaySets(mappedDisplaySets);\n }, [StudyInstanceUIDs, thumbnailImageSrcMap, displaySetService]);\n\n // ~~ subscriptions --> displaySets\n useEffect(() => {\n // DISPLAY_SETS_ADDED returns an array of DisplaySets that were added\n const SubscriptionDisplaySetsAdded = displaySetService.subscribe(\n displaySetService.EVENTS.DISPLAY_SETS_ADDED,\n data => {\n const { displaySetsAdded, options } = data;\n displaySetsAdded.forEach(async dSet => {\n const newImageSrcEntry = {};\n const displaySet = displaySetService.getDisplaySetByUID(dSet.displaySetInstanceUID);\n if (displaySet?.unsupported) {\n return;\n }\n\n const imageIds = dataSource.getImageIdsForDisplaySet(displaySet);\n const imageId = imageIds[Math.floor(imageIds.length / 2)];\n\n // TODO: Is it okay that imageIds are not returned here for SR displaysets?\n if (!imageId) {\n return;\n }\n // When the image arrives, render it and store the result in the thumbnailImgSrcMap\n newImageSrcEntry[dSet.displaySetInstanceUID] = await getImageSrc(\n imageId,\n dSet.initialViewport\n );\n\n setThumbnailImageSrcMap(prevState => {\n return { ...prevState, ...newImageSrcEntry };\n });\n });\n }\n );\n\n return () => {\n SubscriptionDisplaySetsAdded.unsubscribe();\n };\n }, [getImageSrc, dataSource, displaySetService]);\n\n useEffect(() => {\n // TODO: Will this always hold _all_ the displaySets we care about?\n // DISPLAY_SETS_CHANGED returns `DisplaySerService.activeDisplaySets`\n const SubscriptionDisplaySetsChanged = displaySetService.subscribe(\n displaySetService.EVENTS.DISPLAY_SETS_CHANGED,\n changedDisplaySets => {\n const mappedDisplaySets = _mapDisplaySets(changedDisplaySets, thumbnailImageSrcMap);\n setDisplaySets(mappedDisplaySets);\n }\n );\n\n const SubscriptionDisplaySetMetaDataInvalidated = displaySetService.subscribe(\n displaySetService.EVENTS.DISPLAY_SET_SERIES_METADATA_INVALIDATED,\n () => {\n const mappedDisplaySets = _mapDisplaySets(\n displaySetService.getActiveDisplaySets(),\n thumbnailImageSrcMap\n );\n\n setDisplaySets(mappedDisplaySets);\n }\n );\n\n return () => {\n SubscriptionDisplaySetsChanged.unsubscribe();\n SubscriptionDisplaySetMetaDataInvalidated.unsubscribe();\n };\n }, [StudyInstanceUIDs, thumbnailImageSrcMap, displaySetService]);\n\n const tabs = _createStudyBrowserTabs(StudyInstanceUIDs, studyDisplayList, displaySets);\n\n // TODO: Should not fire this on \"close\"\n function _handleStudyClick(StudyInstanceUID) {\n const shouldCollapseStudy = expandedStudyInstanceUIDs.includes(StudyInstanceUID);\n const updatedExpandedStudyInstanceUIDs = shouldCollapseStudy\n ? // eslint-disable-next-line prettier/prettier\n [...expandedStudyInstanceUIDs.filter(stdyUid => stdyUid !== StudyInstanceUID)]\n : [...expandedStudyInstanceUIDs, StudyInstanceUID];\n\n setExpandedStudyInstanceUIDs(updatedExpandedStudyInstanceUIDs);\n\n if (!shouldCollapseStudy) {\n const madeInClient = true;\n requestDisplaySetCreationForStudy(displaySetService, StudyInstanceUID, madeInClient);\n }\n }\n\n const activeDisplaySetInstanceUIDs = viewports.get(activeViewportId)?.displaySetInstanceUIDs;\n\n return (\n <StudyBrowser\n tabs={tabs}\n servicesManager={servicesManager}\n activeTabName={activeTabName}\n onDoubleClickThumbnail={onDoubleClickThumbnailHandler}\n activeDisplaySetInstanceUIDs={activeDisplaySetInstanceUIDs}\n expandedStudyInstanceUIDs={expandedStudyInstanceUIDs}\n onClickStudy={_handleStudyClick}\n onClickTab={clickedTabName => {\n setActiveTabName(clickedTabName);\n }}\n />\n );\n}\n\nPanelStudyBrowser.propTypes = {\n servicesManager: PropTypes.object.isRequired,\n dataSource: PropTypes.shape({\n getImageIdsForDisplaySet: PropTypes.func.isRequired,\n }).isRequired,\n getImageSrc: PropTypes.func.isRequired,\n getStudiesForPatientByMRN: PropTypes.func.isRequired,\n requestDisplaySetCreationForStudy: PropTypes.func.isRequired,\n};\n\nexport default PanelStudyBrowser;\n\n/**\n * Maps from the DataSource's format to a naturalized object\n *\n * @param {*} studies\n */\nfunction _mapDataSourceStudies(studies) {\n return studies.map(study => {\n // TODO: Why does the data source return in this format?\n return {\n AccessionNumber: study.accession,\n StudyDate: study.date,\n StudyDescription: study.description,\n NumInstances: study.instances,\n ModalitiesInStudy: study.modalities,\n PatientID: study.mrn,\n PatientName: study.patientName,\n StudyInstanceUID: study.studyInstanceUid,\n StudyTime: study.time,\n };\n });\n}\n\nfunction _mapDisplaySets(displaySets, thumbnailImageSrcMap) {\n const thumbnailDisplaySets = [];\n const thumbnailNoImageDisplaySets = [];\n\n displaySets\n .filter(ds => !ds.excludeFromThumbnailBrowser)\n .forEach(ds => {\n const imageSrc = thumbnailImageSrcMap[ds.displaySetInstanceUID];\n const componentType = _getComponentType(ds);\n\n const array =\n componentType === 'thumbnail' ? thumbnailDisplaySets : thumbnailNoImageDisplaySets;\n\n array.push({\n displaySetInstanceUID: ds.displaySetInstanceUID,\n description: ds.SeriesDescription || '',\n seriesNumber: ds.SeriesNumber,\n modality: ds.Modality,\n seriesDate: ds.SeriesDate,\n seriesTime: ds.SeriesTime,\n numInstances: ds.numImageFrames,\n countIcon: ds.countIcon,\n StudyInstanceUID: ds.StudyInstanceUID,\n messages: ds.messages,\n componentType,\n imageSrc,\n dragData: {\n type: 'displayset',\n displaySetInstanceUID: ds.displaySetInstanceUID,\n // .. Any other data to pass\n },\n isHydratedForDerivedDisplaySet: ds.isHydrated,\n });\n });\n\n return [...thumbnailDisplaySets, ...thumbnailNoImageDisplaySets];\n}\n\nconst thumbnailNoImageModalities = ['SR', 'SEG', 'SM', 'RTSTRUCT', 'RTPLAN', 'RTDOSE'];\n\nfunction _getComponentType(ds) {\n if (thumbnailNoImageModalities.includes(ds.Modality) || ds?.unsupported) {\n // TODO probably others.\n return 'thumbnailNoImage';\n }\n\n return 'thumbnail';\n}\n\n/**\n *\n * @param {string[]} primaryStudyInstanceUIDs\n * @param {object[]} studyDisplayList\n * @param {string} studyDisplayList.studyInstanceUid\n * @param {string} studyDisplayList.date\n * @param {string} studyDisplayList.description\n * @param {string} studyDisplayList.modalities\n * @param {number} studyDisplayList.numInstances\n * @param {object[]} displaySets\n * @returns tabs - The prop object expected by the StudyBrowser component\n */\nfunction _createStudyBrowserTabs(primaryStudyInstanceUIDs, studyDisplayList, displaySets) {\n const primaryStudies = [];\n const recentStudies = [];\n const allStudies = [];\n\n studyDisplayList.forEach(study => {\n const displaySetsForStudy = displaySets.filter(\n ds => ds.StudyInstanceUID === study.studyInstanceUid\n );\n const tabStudy = Object.assign({}, study, {\n displaySets: displaySetsForStudy,\n });\n\n if (primaryStudyInstanceUIDs.includes(study.studyInstanceUid)) {\n primaryStudies.push(tabStudy);\n } else {\n // TODO: Filter allStudies to dates within one year of current date\n recentStudies.push(tabStudy);\n allStudies.push(tabStudy);\n }\n });\n\n const tabs = [\n {\n name: 'primary',\n label: 'Primary',\n studies: primaryStudies,\n },\n {\n name: 'recent',\n label: 'Recent',\n studies: recentStudies,\n },\n {\n name: 'all',\n label: 'All',\n studies: allStudies,\n },\n ];\n\n return tabs;\n}\n","/**\n * @param {*} cornerstone\n * @param {*} imageId\n */\nfunction getImageSrcFromImageId(cornerstone, imageId) {\n return new Promise((resolve, reject) => {\n const canvas = document.createElement('canvas');\n cornerstone.utilities\n .loadImageToCanvas({ canvas, imageId, thumbnail: true })\n .then(imageId => {\n resolve(canvas.toDataURL());\n })\n .catch(reject);\n });\n}\nexport default getImageSrcFromImageId;\n","async function getStudiesForPatientByMRN(dataSource, qidoForStudyUID) {\n if (qidoForStudyUID && qidoForStudyUID.length && qidoForStudyUID[0].mrn) {\n return dataSource.query.studies.search({\n patientId: qidoForStudyUID[0].mrn,\n });\n }\n console.log('No mrn found for', qidoForStudyUID);\n return qidoForStudyUID;\n}\n\nexport default getStudiesForPatientByMRN;\n","function requestDisplaySetCreationForStudy(\n dataSource,\n displaySetService,\n StudyInstanceUID,\n madeInClient\n) {\n // TODO: is this already short-circuited by the map of Retrieve promises?\n if (\n displaySetService.activeDisplaySets.some(\n displaySet => displaySet.StudyInstanceUID === StudyInstanceUID\n )\n ) {\n return;\n }\n\n dataSource.retrieve.series.metadata({ StudyInstanceUID, madeInClient });\n}\n\nexport default requestDisplaySetCreationForStudy;\n","import React, { useCallback } from 'react';\nimport PropTypes from 'prop-types';\n//\nimport PanelStudyBrowser from './PanelStudyBrowser';\nimport getImageSrcFromImageId from './getImageSrcFromImageId';\nimport getStudiesForPatientByMRN from './getStudiesForPatientByMRN';\nimport requestDisplaySetCreationForStudy from './requestDisplaySetCreationForStudy';\n\n/**\n * Wraps the PanelStudyBrowser and provides features afforded by managers/services\n *\n * @param {object} params\n * @param {object} commandsManager\n * @param {object} extensionManager\n */\nfunction WrappedPanelStudyBrowser({ commandsManager, extensionManager, servicesManager }) {\n // TODO: This should be made available a different way; route should have\n // already determined our datasource\n const dataSource = extensionManager.getDataSources()[0];\n const _getStudiesForPatientByMRN = getStudiesForPatientByMRN.bind(null, dataSource);\n const _getImageSrcFromImageId = useCallback(\n _createGetImageSrcFromImageIdFn(extensionManager),\n []\n );\n const _requestDisplaySetCreationForStudy = requestDisplaySetCreationForStudy.bind(\n null,\n dataSource\n );\n\n return (\n <PanelStudyBrowser\n servicesManager={servicesManager}\n dataSource={dataSource}\n getImageSrc={_getImageSrcFromImageId}\n getStudiesForPatientByMRN={_getStudiesForPatientByMRN}\n requestDisplaySetCreationForStudy={_requestDisplaySetCreationForStudy}\n />\n );\n}\n\n/**\n * Grabs cornerstone library reference using a dependent command from\n * the @ohif/extension-cornerstone extension. Then creates a helper function\n * that can take an imageId and return an image src.\n *\n * @param {func} getCommand - CommandManager's getCommand method\n * @returns {func} getImageSrcFromImageId - A utility function powered by\n * cornerstone\n */\nfunction _createGetImageSrcFromImageIdFn(extensionManager) {\n const utilities = extensionManager.getModuleEntry(\n '@ohif/extension-cornerstone.utilityModule.common'\n );\n\n try {\n const { cornerstone } = utilities.exports.getCornerstoneLibraries();\n return getImageSrcFromImageId.bind(null, cornerstone);\n } catch (ex) {\n throw new Error('Required command not found');\n }\n}\n\nWrappedPanelStudyBrowser.propTypes = {\n commandsManager: PropTypes.object.isRequired,\n extensionManager: PropTypes.object.isRequired,\n servicesManager: PropTypes.object.isRequired,\n};\n\nexport default WrappedPanelStudyBrowser;\n","import React from 'react';\n\nimport { ButtonEnums, Dialog, Input, Select } from '@ohif/ui';\n\nexport const CREATE_REPORT_DIALOG_RESPONSE = {\n CANCEL: 0,\n CREATE_REPORT: 1,\n};\n\nexport default function CreateReportDialogPrompt(uiDialogService, { extensionManager }) {\n return new Promise(function (resolve, reject) {\n let dialogId = undefined;\n\n const _handleClose = () => {\n // Dismiss dialog\n uiDialogService.dismiss({ id: dialogId });\n // Notify of cancel action\n resolve({\n action: CREATE_REPORT_DIALOG_RESPONSE.CANCEL,\n value: undefined,\n dataSourceName: undefined,\n });\n };\n\n /**\n *\n * @param {string} param0.action - value of action performed\n * @param {string} param0.value - value from input field\n */\n const _handleFormSubmit = ({ action, value }) => {\n uiDialogService.dismiss({ id: dialogId });\n switch (action.id) {\n case 'save':\n resolve({\n action: CREATE_REPORT_DIALOG_RESPONSE.CREATE_REPORT,\n value: value.label,\n dataSourceName: value.dataSourceName,\n });\n break;\n case 'cancel':\n resolve({\n action: CREATE_REPORT_DIALOG_RESPONSE.CANCEL,\n value: undefined,\n dataSourceName: undefined,\n });\n break;\n }\n };\n\n const dataSourcesOpts = Object.keys(extensionManager.dataSourceMap)\n .filter(ds => {\n const configuration = extensionManager.dataSourceDefs[ds]?.configuration;\n const supportsStow = configuration?.supportsStow ?? configuration?.wadoRoot;\n return supportsStow;\n })\n .map(ds => {\n return {\n value: ds,\n label: ds,\n placeHolder: ds,\n };\n });\n\n dialogId = uiDialogService.create({\n centralize: true,\n isDraggable: false,\n content: Dialog,\n useLastPosition: false,\n showOverlay: true,\n contentProps: {\n title: 'Create Report',\n value: {\n label: '',\n dataSourceName: extensionManager.activeDataSource,\n },\n noCloseButton: true,\n onClose: _handleClose,\n actions: [\n { id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },\n { id: 'save', text: 'Save', type: ButtonEnums.type.primary },\n ],\n // TODO: Should be on button press...\n onSubmit: _handleFormSubmit,\n body: ({ value, setValue }) => {\n const onChangeHandler = event => {\n event.persist();\n setValue(value => ({ ...value, label: event.target.value }));\n };\n const onKeyPressHandler = event => {\n if (event.key === 'Enter') {\n uiDialogService.dismiss({ id: dialogId });\n resolve({\n action: CREATE_REPORT_DIALOG_RESPONSE.CREATE_REPORT,\n value: value.label,\n });\n }\n };\n return (\n <>\n {dataSourcesOpts.length > 1 && window.config?.allowMultiSelectExport && (\n <div>\n <label className=\"text-[14px] leading-[1.2] text-white\">Data Source</label>\n <Select\n closeMenuOnSelect={true}\n className=\"border-primary-main mt-2 bg-black\"\n options={dataSourcesOpts}\n placeholder={\n dataSourcesOpts.find(option => option.value === value.dataSourceName)\n .placeHolder\n }\n value={value.dataSourceName}\n onChange={evt => {\n setValue(v => ({ ...v, dataSourceName: evt.value }));\n }}\n isClearable={false}\n />\n </div>\n )}\n <div className=\"mt-3\">\n <Input\n autoFocus\n label=\"Enter the report name\"\n labelClassName=\"text-white text-[14px] leading-[1.2]\"\n className=\"border-primary-main bg-black\"\n type=\"text\"\n value={value.label}\n onChange={onChangeHandler}\n onKeyPress={onKeyPressHandler}\n required\n />\n </div>\n </>\n );\n },\n },\n });\n });\n}\n","import React from 'react';\nimport { DicomMetadataStore } from '@ohif/core';\n\n/**\n *\n * @param {*} servicesManager\n */\nasync function createReportAsync({ servicesManager, getReport, reportType = 'measurement' }) {\n const { displaySetService, uiNotificationService, uiDialogService } = servicesManager.services;\n const loadingDialogId = uiDialogService.create({\n showOverlay: true,\n isDraggable: false,\n centralize: true,\n content: Loading,\n });\n\n try {\n const naturalizedReport = await getReport();\n\n // The \"Mode\" route listens for DicomMetadataStore changes\n // When a new instance is added, it listens and\n // automatically calls makeDisplaySets\n DicomMetadataStore.addInstances([naturalizedReport], true);\n\n const displaySet = displaySetService.getMostRecentDisplaySet();\n\n const displaySetInstanceUID = displaySet.displaySetInstanceUID;\n\n uiNotificationService.show({\n title: 'Create Report',\n message: `${reportType} saved successfully`,\n type: 'success',\n });\n\n return [displaySetInstanceUID];\n } catch (error) {\n uiNotificationService.show({\n title: 'Create Report',\n message: error.message || `Failed to store ${reportType}`,\n type: 'error',\n });\n } finally {\n uiDialogService.dismiss({ id: loadingDialogId });\n }\n}\n\nfunction Loading() {\n return <div className=\"text-primary-active\">Loading...</div>;\n}\n\nexport default createReportAsync;\n","const MIN_SR_SERIES_NUMBER = 4700;\n\nexport default function getNextSRSeriesNumber(displaySetService) {\n const activeDisplaySets = displaySetService.getActiveDisplaySets();\n const srDisplaySets = activeDisplaySets.filter(ds => ds.Modality === 'SR');\n const srSeriesNumbers = srDisplaySets.map(ds => ds.SeriesNumber);\n const maxSeriesNumber = Math.max(...srSeriesNumbers, MIN_SR_SERIES_NUMBER);\n\n return maxSeriesNumber + 1;\n}\n","import { DisplaySetService, Types } from '@ohif/core';\n\nimport getNextSRSeriesNumber from './getNextSRSeriesNumber';\n\n/**\n * Find an SR having the same series description.\n * This is used by the store service in order to store DICOM SR's having the\n * same Series Description into a single series under consecutive instance numbers\n * That way, they are all organized as a set and could have tools to view\n * \"prior\" SR instances.\n *\n * @param SeriesDescription - is the description to look for\n * @param displaySetService - the display sets to search for DICOM SR in\n * @returns SeriesMetadata from a DICOM SR having the same series description\n */\nexport default function findSRWithSameSeriesDescription(\n SeriesDescription: string,\n displaySetService: DisplaySetService\n): Types.SeriesMetadata {\n const activeDisplaySets = displaySetService.getActiveDisplaySets();\n const srDisplaySets = activeDisplaySets.filter(ds => ds.Modality === 'SR');\n const sameSeries = srDisplaySets.find(ds => ds.SeriesDescription === SeriesDescription);\n if (sameSeries) {\n console.log('Storing to same series', sameSeries);\n const { instance } = sameSeries;\n const { SeriesInstanceUID, SeriesDescription, SeriesDate, SeriesTime, SeriesNumber, Modality } =\n instance;\n return {\n SeriesInstanceUID,\n SeriesDescription,\n SeriesDate,\n SeriesTime,\n SeriesNumber,\n Modality,\n InstanceNumber: sameSeries.instances.length + 1,\n };\n }\n\n const SeriesNumber = getNextSRSeriesNumber(displaySetService);\n return { SeriesDescription, SeriesNumber };\n}\n","import React, { useEffect, useState } from 'react';\nimport PropTypes from 'prop-types';\nimport { useTranslation } from 'react-i18next';\nimport { utils, ServicesManager } from '@ohif/core';\nimport {\n MeasurementTable,\n Dialog,\n Input,\n useViewportGrid,\n ButtonEnums,\n ActionButtons,\n} from '@ohif/ui';\nimport debounce from 'lodash.debounce';\n\nimport createReportDialogPrompt, {\n CREATE_REPORT_DIALOG_RESPONSE,\n} from './createReportDialogPrompt';\nimport createReportAsync from '../Actions/createReportAsync';\nimport findSRWithSameSeriesDescription from '../utils/findSRWithSameSeriesDescription';\n\nconst { downloadCSVReport } = utils;\n\nexport default function PanelMeasurementTable({\n servicesManager,\n commandsManager,\n extensionManager,\n}): React.FunctionComponent {\n const { t } = useTranslation('MeasurementTable');\n\n const [viewportGrid, viewportGridService] = useViewportGrid();\n const { activeViewportId, viewports } = viewportGrid;\n const { measurementService, uiDialogService, uiNotificationService, displaySetService } = (\n servicesManager as ServicesManager\n ).services;\n const [displayMeasurements, setDisplayMeasurements] = useState([]);\n\n useEffect(() => {\n const debouncedSetDisplayMeasurements = debounce(setDisplayMeasurements, 100);\n // ~~ Initial\n setDisplayMeasurements(_getMappedMeasurements(measurementService));\n\n // ~~ Subscription\n const added = measurementService.EVENTS.MEASUREMENT_ADDED;\n const addedRaw = measurementService.EVENTS.RAW_MEASUREMENT_ADDED;\n const updated = measurementService.EVENTS.MEASUREMENT_UPDATED;\n const removed = measurementService.EVENTS.MEASUREMENT_REMOVED;\n const cleared = measurementService.EVENTS.MEASUREMENTS_CLEARED;\n const subscriptions = [];\n\n [added, addedRaw, updated, removed, cleared].forEach(evt => {\n subscriptions.push(\n measurementService.subscribe(evt, () => {\n debouncedSetDisplayMeasurements(_getMappedMeasurements(measurementService));\n }).unsubscribe\n );\n });\n\n return () => {\n subscriptions.forEach(unsub => {\n unsub();\n });\n debouncedSetDisplayMeasurements.cancel();\n };\n }, []);\n\n async function exportReport() {\n const measurements = measurementService.getMeasurements();\n\n downloadCSVReport(measurements, measurementService);\n }\n\n async function clearMeasurements() {\n measurementService.clearMeasurements();\n }\n\n async function createReport(): Promise<any> {\n // filter measurements that are added to the active study\n const activeViewport = viewports.get(activeViewportId);\n const measurements = measurementService.getMeasurements();\n const displaySet = displaySetService.getDisplaySetByUID(\n activeViewport.displaySetInstanceUIDs[0]\n );\n const trackedMeasurements = measurements.filter(\n m => displaySet.StudyInstanceUID === m.referenceStudyUID\n );\n\n if (trackedMeasurements.length <= 0) {\n uiNotificationService.show({\n title: 'No Measurements',\n message: 'No Measurements are added to the current Study.',\n type: 'info',\n duration: 3000,\n });\n return;\n }\n\n const promptResult = await createReportDialogPrompt(uiDialogService, {\n extensionManager,\n });\n\n if (promptResult.action === CREATE_REPORT_DIALOG_RESPONSE.CREATE_REPORT) {\n const dataSources = extensionManager.getDataSources(promptResult.dataSourceName);\n const dataSource = dataSources[0];\n\n const SeriesDescription =\n // isUndefinedOrEmpty\n promptResult.value === undefined || promptResult.value === ''\n ? 'Research Derived Series' // default\n : promptResult.value; // provided value\n\n // Reuse an existing series having the same series description to avoid\n // creating too many series instances.\n const options = findSRWithSameSeriesDescription(SeriesDescription, displaySetService);\n\n const getReport = async () => {\n return commandsManager.runCommand(\n 'storeMeasurements',\n {\n measurementData: trackedMeasurements,\n dataSource,\n additionalFindingTypes: ['ArrowAnnotate'],\n options,\n },\n 'CORNERSTONE_STRUCTURED_REPORT'\n );\n };\n\n return createReportAsync({ servicesManager, getReport });\n }\n }\n\n const jumpToImage = ({ uid, isActive }) => {\n measurementService.jumpToMeasurement(viewportGrid.activeViewportId, uid);\n\n onMeasurementItemClickHandler({ uid, isActive });\n };\n\n const onMeasurementItemEditHandler = ({ uid, isActive }) => {\n const measurement = measurementService.getMeasurement(uid);\n //Todo: why we are jumping to image?\n // jumpToImage({ id, isActive });\n\n const onSubmitHandler = ({ action, value }) => {\n switch (action.id) {\n case 'save': {\n measurementService.update(\n uid,\n {\n ...measurement,\n ...value,\n },\n true\n );\n }\n }\n uiDialogService.dismiss({ id: 'enter-annotation' });\n };\n\n uiDialogService.create({\n id: 'enter-annotation',\n centralize: true,\n isDraggable: false,\n showOverlay: true,\n content: Dialog,\n contentProps: {\n title: 'Annotation',\n noCloseButton: true,\n value: { label: measurement.label || '' },\n body: ({ value, setValue }) => {\n const onChangeHandler = event => {\n event.persist();\n setValue(value => ({ ...value, label: event.target.value }));\n };\n\n const onKeyPressHandler = event => {\n if (event.key === 'Enter') {\n onSubmitHandler({ value, action: { id: 'save' } });\n }\n };\n return (\n <Input\n label=\"Enter your annotation\"\n labelClassName=\"text-white text-[14px] leading-[1.2]\"\n autoFocus\n id=\"annotation\"\n className=\"border-primary-main bg-black\"\n type=\"text\"\n value={value.label}\n onChange={onChangeHandler}\n onKeyPress={onKeyPressHandler}\n />\n );\n },\n actions: [\n { id: 'cancel', text: 'Cancel', type: ButtonEnums.type.secondary },\n { id: 'save', text: 'Save', type: ButtonEnums.type.primary },\n ],\n onSubmit: onSubmitHandler,\n },\n });\n };\n\n const onMeasurementItemClickHandler = ({ uid, isActive }) => {\n if (!isActive) {\n const measurements = [...displayMeasurements];\n const measurement = measurements.find(m => m.uid === uid);\n\n measurements.forEach(m => (m.isActive = m.uid !== uid ? false : true));\n measurement.isActive = true;\n setDisplayMeasurements(measurements);\n }\n };\n\n return (\n <>\n <div\n className=\"ohif-scrollbar overflow-y-auto overflow-x-hidden\"\n data-cy={'measurements-panel'}\n >\n <MeasurementTable\n title={t('Measurements')}\n servicesManager={servicesManager}\n data={displayMeasurements}\n onClick={jumpToImage}\n onEdit={onMeasurementItemEditHandler}\n />\n </div>\n <div className=\"flex justify-center p-4\">\n <ActionButtons\n t={t}\n actions={[\n {\n label: 'Export',\n onClick: exportReport,\n },\n {\n label: 'Create Report',\n onClick: createReport,\n },\n ]}\n />\n </div>\n </>\n );\n}\n\nPanelMeasurementTable.propTypes = {\n servicesManager: PropTypes.instanceOf(ServicesManager).isRequired,\n};\n\nfunction _getMappedMeasurements(measurementService) {\n const measurements = measurementService.getMeasurements();\n\n const mappedMeasurements = measurements.map((m, index) =>\n _mapMeasurementToDisplay(m, index, measurementService.VALUE_TYPES)\n );\n\n return mappedMeasurements;\n}\n\n/**\n * Map the measurements to the display text.\n * Adds finding and site information to the displayText and/or label,\n * and provides as 'displayText' and 'label', while providing the original\n * values as baseDisplayText and baseLabel\n */\nfunction _mapMeasurementToDisplay(measurement, index, types) {\n const {\n displayText: baseDisplayText,\n uid,\n label: baseLabel,\n type,\n selected,\n findingSites,\n finding,\n } = measurement;\n\n const firstSite = findingSites?.[0];\n const label = baseLabel || finding?.text || firstSite?.text || '(empty)';\n let displayText = baseDisplayText || [];\n if (findingSites) {\n const siteText = [];\n findingSites.forEach(site => {\n if (site?.text !== label) {\n siteText.push(site.text);\n }\n });\n displayText = [...siteText, ...displayText];\n }\n if (finding && finding?.text !== label) {\n displayText = [finding.text, ...displayText];\n }\n\n return {\n uid,\n label,\n baseLabel,\n measurementType: type,\n displayText,\n baseDisplayText,\n isActive: selected,\n finding,\n findingSites,\n };\n}\n","import React from 'react';\nimport { WrappedPanelStudyBrowser, PanelMeasurementTable } from './Panels';\nimport i18n from 'i18next';\n\n// TODO:\n// - No loading UI exists yet\n// - cancel promises when component is destroyed\n// - show errors in UI for thumbnails if promise fails\n\nfunction getPanelModule({ commandsManager, extensionManager, servicesManager }) {\n const wrappedMeasurementPanel = () => {\n return (\n <PanelMeasurementTable\n commandsManager={commandsManager}\n servicesManager={servicesManager}\n extensionManager={extensionManager}\n />\n );\n };\n\n return [\n {\n name: 'seriesList',\n iconName: 'tab-studies',\n iconLabel: 'Studies',\n label: i18n.t('SidePanel:Studies'),\n component: WrappedPanelStudyBrowser.bind(null, {\n commandsManager,\n extensionManager,\n servicesManager,\n }),\n },\n {\n name: 'measure',\n iconName: 'tab-linear',\n iconLabel: 'Measure',\n label: i18n.t('SidePanel:Measurements'),\n secondaryLabel: i18n.t('SidePanel:Measurements'),\n component: wrappedMeasurementPanel,\n },\n ];\n}\n\nexport default getPanelModule;\n","import packageJson from '../package.json';\n\nconst id = packageJson.name;\n\nexport { id };\n","import { vec3 } from 'gl-matrix';\nimport toNumber from '@ohif/core/src/utils/toNumber';\nimport { _getPerpendicularDistance } from '@ohif/core/src/utils/isDisplaySetReconstructable';\nimport calculateScanAxisNormal from '../calculateScanAxisNormal';\n\n/**\n * Checks if there is a position shift between consecutive frames\n * @param {*} previousPosition\n * @param {*} actualPosition\n * @param {*} scanAxisNormal\n * @param {*} averageSpacingBetweenFrames\n * @returns\n */\nfunction _checkSeriesPositionShift(\n previousPosition,\n actualPosition,\n scanAxisNormal,\n averageSpacingBetweenFrames\n) {\n // predicted position should be the previous position added by the multiplication\n // of the scanAxisNormal and the average spacing between frames\n const predictedPosition = vec3.scaleAndAdd(\n vec3.create(),\n previousPosition,\n scanAxisNormal,\n averageSpacingBetweenFrames\n );\n return vec3.distance(actualPosition, predictedPosition) > averageSpacingBetweenFrames;\n}\n\n/**\n * Checks if a series has position shifts between consecutive frames\n * @param {*} instances\n * @returns\n */\nexport default function areAllImagePositionsEqual(instances: Array<any>): boolean {\n if (!instances?.length) {\n return false;\n }\n const firstImageOrientationPatient = toNumber(instances[0].ImageOrientationPatient);\n if (!firstImageOrientationPatient) {\n return false;\n }\n const scanAxisNormal = calculateScanAxisNormal(firstImageOrientationPatient);\n const firstImagePositionPatient = toNumber(instances[0].ImagePositionPatient);\n const lastIpp = toNumber(instances[instances.length - 1].ImagePositionPatient);\n\n const averageSpacingBetweenFrames =\n _getPerpendicularDistance(firstImagePositionPatient, lastIpp) / (instances.length - 1);\n\n let previousImagePositionPatient = firstImagePositionPatient;\n for (let i = 1; i < instances.length; i++) {\n const instance = instances[i];\n const imagePositionPatient = toNumber(instance.ImagePositionPatient);\n\n if (\n _checkSeriesPositionShift(\n previousImagePositionPatient,\n imagePositionPatient,\n scanAxisNormal,\n averageSpacingBetweenFrames\n )\n ) {\n return false;\n }\n previousImagePositionPatient = imagePositionPatient;\n }\n return true;\n}\n","import { vec3 } from 'gl-matrix';\n\n/**\n * Calculates the scanAxisNormal based on a image orientation vector extract from a frame\n * @param {*} imageOrientation\n * @returns\n */\nexport default function calculateScanAxisNormal(imageOrientation) {\n const rowCosineVec = vec3.fromValues(\n imageOrientation[0],\n imageOrientation[1],\n imageOrientation[2]\n );\n const colCosineVec = vec3.fromValues(\n imageOrientation[3],\n imageOrientation[4],\n imageOrientation[5]\n );\n return vec3.cross(vec3.create(), rowCosineVec, colCosineVec);\n}\n","import areAllImageDimensionsEqual from './areAllImageDimensionsEqual';\nimport areAllImageComponentsEqual from './areAllImageComponentsEqual';\nimport areAllImageOrientationsEqual from './areAllImageOrientationsEqual';\nimport areAllImagePositionsEqual from './areAllImagePositionsEqual';\nimport areAllImageSpacingEqual from './areAllImageSpacingEqual';\nimport { DisplaySetMessage, DisplaySetMessageList } from '@ohif/core';\n\n/**\n * Runs various checks in a single frame series\n * @param {*} instances\n * @param {*} warnings\n */\nexport default function checkSingleFrames(\n instances: Array<any>,\n messages: DisplaySetMessageList\n): void {\n if (instances.length > 2) {\n if (!areAllImageDimensionsEqual(instances)) {\n messages.addMessage(DisplaySetMessage.CODES.INCONSISTENT_DIMENSIONS);\n }\n\n if (!areAllImageComponentsEqual(instances)) {\n messages.addMessage(DisplaySetMessage.CODES.INCONSISTENT_COMPONENTS);\n }\n\n if (!areAllImageOrientationsEqual(instances)) {\n messages.addMessage(DisplaySetMessage.CODES.INCONSISTENT_ORIENTATIONS);\n }\n\n if (!areAllImagePositionsEqual(instances)) {\n messages.addMessage(DisplaySetMessage.CODES.INCONSISTENT_POSITION_INFORMATION);\n }\n areAllImageSpacingEqual(instances, messages);\n }\n}\n","import toNumber from '@ohif/core/src/utils/toNumber';\n\n/**\n * Check if the frames in a series has different dimensions\n * @param {*} instances\n * @returns\n */\nexport default function areAllImageDimensionsEqual(instances: Array<any>): boolean {\n if (!instances?.length) {\n return false;\n }\n const firstImage = instances[0];\n const firstImageRows = toNumber(firstImage.Rows);\n const firstImageColumns = toNumber(firstImage.Columns);\n\n for (let i = 1; i < instances.length; i++) {\n const instance = instances[i];\n const { Rows, Columns } = instance;\n\n if (Rows !== firstImageRows || Columns !== firstImageColumns) {\n return false;\n }\n }\n return true;\n}\n","import toNumber from '@ohif/core/src/utils/toNumber';\n\n/**\n * Check if all voxels in series images has same number of components (samplesPerPixel)\n * @param {*} instances\n * @returns\n */\nexport default function areAllImageComponentsEqual(instances: Array<any>): boolean {\n if (!instances?.length) {\n return false;\n }\n const firstImage = instances[0];\n const firstImageSamplesPerPixel = toNumber(firstImage.SamplesPerPixel);\n\n for (let i = 1; i < instances.length; i++) {\n const instance = instances[i];\n const { SamplesPerPixel } = instance;\n\n if (SamplesPerPixel !== firstImageSamplesPerPixel) {\n return false;\n }\n }\n return true;\n}\n","import toNumber from '@ohif/core/src/utils/toNumber';\nimport { _isSameOrientation } from '@ohif/core/src/utils/isDisplaySetReconstructable';\n\n/**\n * Check is the series has frames with different orientations\n * @param {*} instances\n * @returns\n */\nexport default function areAllImageOrientationsEqual(instances: Array<any>): boolean {\n if (!instances?.length) {\n return false;\n }\n const firstImage = instances[0];\n const firstImageOrientationPatient = toNumber(firstImage.ImageOrientationPatient);\n\n for (let i = 1; i < instances.length; i++) {\n const instance = instances[i];\n const imageOrientationPatient = toNumber(instance.ImageOrientationPatient);\n\n if (!_isSameOrientation(imageOrientationPatient, firstImageOrientationPatient)) {\n return false;\n }\n }\n return true;\n}\n","import {\n _getPerpendicularDistance,\n _getSpacingIssue,\n reconstructionIssues,\n} from '@ohif/core/src/utils/isDisplaySetReconstructable';\nimport { DisplaySetMessage } from '@ohif/core';\nimport toNumber from '@ohif/core/src/utils/toNumber';\nimport { DisplaySetMessageList } from '@ohif/core';\n\n/**\n * Checks if series has spacing issues\n * @param {*} instances\n * @param {*} warnings\n */\nexport default function areAllImageSpacingEqual(\n instances: Array<any>,\n messages: DisplaySetMessageList\n): void {\n if (!instances?.length) {\n return;\n }\n const firstImagePositionPatient = toNumber(instances[0].ImagePositionPatient);\n if (!firstImagePositionPatient) {\n return;\n }\n const lastIpp = toNumber(instances[instances.length - 1].ImagePositionPatient);\n\n const averageSpacingBetweenFrames =\n _getPerpendicularDistance(firstImagePositionPatient, lastIpp) / (instances.length - 1);\n\n let previousImagePositionPatient = firstImagePositionPatient;\n\n const issuesFound = [];\n for (let i = 1; i < instances.length; i++) {\n const instance = instances[i];\n const imagePositionPatient = toNumber(instance.ImagePositionPatient);\n\n const spacingBetweenFrames = _getPerpendicularDistance(\n imagePositionPatient,\n previousImagePositionPatient\n );\n\n const spacingIssue = _getSpacingIssue(spacingBetweenFrames, averageSpacingBetweenFrames);\n\n if (spacingIssue) {\n const issue = spacingIssue.issue;\n\n // avoid multiple warning of the same thing\n if (!issuesFound.includes(issue)) {\n issuesFound.push(issue);\n if (issue === reconstructionIssues.MISSING_FRAMES) {\n messages.addMessage(DisplaySetMessage.CODES.MISSING_FRAMES);\n } else if (issue === reconstructionIssues.IRREGULAR_SPACING) {\n messages.addMessage(DisplaySetMessage.CODES.IRREGULAR_SPACING);\n }\n }\n // we just want to find issues not how many\n if (issuesFound.length > 1) {\n break;\n }\n }\n previousImagePositionPatient = imagePositionPatient;\n }\n}\n","import sortInstancesByPosition from '@ohif/core/src/utils/sortInstancesByPosition';\nimport { constructableModalities } from '@ohif/core/src/utils/isDisplaySetReconstructable';\nimport { DisplaySetMessage, DisplaySetMessageList } from '@ohif/core';\nimport checkMultiFrame from './utils/validations/checkMultiframe';\nimport checkSingleFrames from './utils/validations/checkSingleFrames';\n/**\n * Checks if a series is reconstructable to a 3D volume.\n *\n * @param {Object[]} instances An array of `OHIFInstanceMetadata` objects.\n */\nexport default function getDisplaySetMessages(\n instances: Array<any>,\n isReconstructable: boolean,\n isDynamicVolume: boolean\n): DisplaySetMessageList {\n const messages = new DisplaySetMessageList();\n\n if (isDynamicVolume) {\n return messages;\n }\n\n if (!instances.length) {\n messages.addMessage(DisplaySetMessage.CODES.NO_VALID_INSTANCES);\n return;\n }\n\n const firstInstance = instances[0];\n const { Modality, ImageType, NumberOfFrames } = firstInstance;\n // Due to current requirements, LOCALIZER series doesn't have any messages\n if (ImageType?.includes('LOCALIZER')) {\n return messages;\n }\n\n if (!constructableModalities.includes(Modality)) {\n return messages;\n }\n\n const isMultiframe = NumberOfFrames > 1;\n // Can't reconstruct if all instances don't have the ImagePositionPatient.\n if (!isMultiframe && !instances.every(instance => instance.ImagePositionPatient)) {\n messages.addMessage(DisplaySetMessage.CODES.NO_POSITION_INFORMATION);\n }\n\n const sortedInstances = sortInstancesByPosition(instances);\n\n isMultiframe\n ? checkMultiFrame(sortedInstances[0], messages)\n : checkSingleFrames(sortedInstances, messages);\n\n if (!isReconstructable) {\n messages.addMessage(DisplaySetMessage.CODES.NOT_RECONSTRUCTABLE);\n }\n return messages;\n}\n","import {\n hasPixelMeasurements,\n hasOrientation,\n hasPosition,\n} from '@ohif/core/src/utils/isDisplaySetReconstructable';\nimport { DisplaySetMessage, DisplaySetMessageList } from '@ohif/core';\n\n/**\n * Check various multi frame issues. It calls OHIF core functions\n * @param {*} multiFrameInstance\n * @param {*} warnings\n */\nexport default function checkMultiFrame(multiFrameInstance, messages: DisplaySetMessageList): void {\n if (!hasPixelMeasurements(multiFrameInstance)) {\n messages.addMessage(DisplaySetMessage.CODES.MULTIFRAME_NO_PIXEL_MEASUREMENTS);\n }\n\n if (!hasOrientation(multiFrameInstance)) {\n messages.addMessage(DisplaySetMessage.CODES.MULTIFRAME_NO_ORIENTATION);\n }\n\n if (!hasPosition(multiFrameInstance)) {\n messages.addMessage(DisplaySetMessage.CODES.MULTIFRAME_NO_POSITION_INFORMATION);\n }\n}\n","import ImageSet from '@ohif/core/src/classes/ImageSet';\nimport { DisplaySetMessage, DisplaySetMessageList } from '@ohif/core';\n/**\n * Default handler for a instance list with an unsupported sopClassUID\n */\nexport default function getDisplaySetsFromUnsupportedSeries(instances) {\n const imageSet = new ImageSet(instances);\n const messages = new DisplaySetMessageList();\n messages.addMessage(DisplaySetMessage.CODES.UNSUPPORTED_DISPLAYSET);\n const instance = instances[0];\n\n imageSet.setAttributes({\n displaySetInstanceUID: imageSet.uid, // create a local alias for the imageSet UID\n SeriesDate: instance.SeriesDate,\n SeriesTime: instance.SeriesTime,\n SeriesInstanceUID: instance.SeriesInstanceUID,\n StudyInstanceUID: instance.StudyInstanceUID,\n SeriesNumber: instance.SeriesNumber || 0,\n FrameRate: instance.FrameTime,\n SOPClassUID: instance.SOPClassUID,\n SeriesDescription: instance.SeriesDescription || '',\n Modality: instance.Modality,\n numImageFrames: instances.length,\n unsupported: true,\n SOPClassHandlerId: 'unsupported',\n isReconstructable: false,\n messages,\n });\n return [imageSet];\n}\n","import { Types, DisplaySetService, utils } from '@ohif/core';\n\nimport { id } from '../id';\n\ntype InstanceMetadata = Types.InstanceMetadata;\n\nconst SOPClassHandlerName = 'chart';\n\nconst CHART_MODALITY = 'CHT';\n\n// Private SOPClassUid for chart data\nconst ChartDataSOPClassUid = '1.9.451.13215.7.3.2.7.6.1';\n\nconst sopClassUids = [ChartDataSOPClassUid];\n\nconst makeChartDataDisplaySet = (instance, sopClassUids) => {\n const {\n StudyInstanceUID,\n SeriesInstanceUID,\n SOPInstanceUID,\n SeriesDescription,\n SeriesNumber,\n SeriesDate,\n SOPClassUID,\n } = instance;\n\n return {\n Modality: CHART_MODALITY,\n loading: false,\n isReconstructable: false,\n displaySetInstanceUID: utils.guid(),\n SeriesDescription,\n SeriesNumber,\n SeriesDate,\n SOPInstanceUID,\n SeriesInstanceUID,\n StudyInstanceUID,\n SOPClassHandlerId: `${id}.sopClassHandlerModule.${SOPClassHandlerName}`,\n SOPClassUID,\n isDerivedDisplaySet: true,\n isLoaded: true,\n sopClassUids,\n instance,\n instances: [instance],\n\n /**\n * Adds instances to the chart displaySet, rather than creating a new one\n * when user moves to a different workflow step and gets back to a step that\n * recreates the chart\n */\n addInstances: function (instances: InstanceMetadata[], _displaySetService: DisplaySetService) {\n this.instances.push(...instances);\n this.instance = this.instances[this.instances.length - 1];\n\n return this;\n },\n };\n};\n\nfunction getSopClassUids(instances) {\n const uniqueSopClassUidsInSeries = new Set();\n instances.forEach(instance => {\n uniqueSopClassUidsInSeries.add(instance.SOPClassUID);\n });\n const sopClassUids = Array.from(uniqueSopClassUidsInSeries);\n\n return sopClassUids;\n}\n\nfunction _getDisplaySetsFromSeries(instances) {\n // If the series has no instances, stop here\n if (!instances || !instances.length) {\n throw new Error('No instances were provided');\n }\n\n const sopClassUids = getSopClassUids(instances);\n const displaySets = instances.map(instance => {\n if (instance.Modality === CHART_MODALITY) {\n return makeChartDataDisplaySet(instance, sopClassUids);\n }\n\n throw new Error('Unsupported modality');\n });\n\n return displaySets;\n}\n\nconst chartHandler = {\n name: SOPClassHandlerName,\n sopClassUids,\n getDisplaySetsFromSeries: instances => {\n return _getDisplaySetsFromSeries(instances);\n },\n};\n\nexport { chartHandler };\n","import { isImage } from '@ohif/core/src/utils/isImage';\nimport sopClassDictionary from '@ohif/core/src/utils/sopClassDictionary';\nimport ImageSet from '@ohif/core/src/classes/ImageSet';\nimport isDisplaySetReconstructable from '@ohif/core/src/utils/isDisplaySetReconstructable';\nimport { id } from './id';\nimport getDisplaySetMessages from './getDisplaySetMessages';\nimport getDisplaySetsFromUnsupportedSeries from './getDisplaySetsFromUnsupportedSeries';\nimport { chartHandler } from './SOPClassHandlers/chartSOPClassHandler';\n\nconst DEFAULT_VOLUME_LOADER_SCHEME = 'cornerstoneStreamingImageVolume';\nconst DYNAMIC_VOLUME_LOADER_SCHEME = 'cornerstoneStreamingDynamicImageVolume';\nconst sopClassHandlerName = 'stack';\nlet appContext = {};\n\nconst getDynamicVolumeInfo = instances => {\n const { extensionManager } = appContext;\n\n if (!extensionManager) {\n throw new Error('extensionManager is not available');\n }\n\n const imageIds = instances.map(({ imageId }) => imageId);\n const volumeLoaderUtility = extensionManager.getModuleEntry(\n '@ohif/extension-cornerstone.utilityModule.volumeLoader'\n );\n const { getDynamicVolumeInfo: csGetDynamicVolumeInfo } = volumeLoaderUtility.exports;\n\n return csGetDynamicVolumeInfo(imageIds);\n};\n\nconst isMultiFrame = instance => {\n return instance.NumberOfFrames > 1;\n};\n\nfunction getDisplaySetInfo(instances) {\n const dynamicVolumeInfo = getDynamicVolumeInfo(instances);\n const { isDynamicVolume, timePoints } = dynamicVolumeInfo;\n let displaySetInfo;\n\n if (isDynamicVolume) {\n const timePoint = timePoints[0];\n const instancesMap = new Map();\n\n // O(n) to convert it into a map and O(1) to find each instance\n instances.forEach(instance => instancesMap.set(instance.imageId, instance));\n\n const firstTimePointInstances = timePoint.map(imageId => instancesMap.get(imageId));\n\n displaySetInfo = isDisplaySetReconstructable(firstTimePointInstances);\n } else {\n displaySetInfo = isDisplaySetReconstructable(instances);\n }\n\n return {\n isDynamicVolume,\n ...displaySetInfo,\n dynamicVolumeInfo,\n };\n}\n\nconst makeDisplaySet = instances => {\n const instance = instances[0];\n const imageSet = new ImageSet(instances);\n\n const {\n isDynamicVolume,\n value: isReconstructable,\n averageSpacingBetweenFrames,\n dynamicVolumeInfo,\n } = getDisplaySetInfo(instances);\n\n const volumeLoaderSchema = isDynamicVolume\n ? DYNAMIC_VOLUME_LOADER_SCHEME\n : DEFAULT_VOLUME_LOADER_SCHEME;\n\n // set appropriate attributes to image set...\n const messages = getDisplaySetMessages(instances, isReconstructable, isDynamicVolume);\n\n imageSet.setAttributes({\n volumeLoaderSchema,\n displaySetInstanceUID: imageSet.uid, // create a local alias for the imageSet UID\n SeriesDate: instance.SeriesDate,\n SeriesTime: instance.SeriesTime,\n SeriesInstanceUID: instance.SeriesInstanceUID,\n StudyInstanceUID: instance.StudyInstanceUID,\n SeriesNumber: instance.SeriesNumber || 0,\n FrameRate: instance.FrameTime,\n SOPClassUID: instance.SOPClassUID,\n SeriesDescription: instance.SeriesDescription || '',\n Modality: instance.Modality,\n isMultiFrame: isMultiFrame(instance),\n countIcon: isReconstructable ? 'icon-mpr' : undefined,\n numImageFrames: instances.length,\n SOPClassHandlerId: `${id}.sopClassHandlerModule.${sopClassHandlerName}`,\n isReconstructable,\n messages,\n averageSpacingBetweenFrames: averageSpacingBetweenFrames || null,\n isDynamicVolume,\n dynamicVolumeInfo,\n });\n\n // Sort the images in this series if needed\n const shallSort = true; //!OHIF.utils.ObjectPath.get(Meteor, 'settings.public.ui.sortSeriesByIncomingOrder');\n if (shallSort) {\n imageSet.sortBy((a, b) => {\n // Sort by InstanceNumber (0020,0013)\n return (parseInt(a.InstanceNumber) || 0) - (parseInt(b.InstanceNumber) || 0);\n });\n }\n\n // Include the first image instance number (after sorted)\n /*imageSet.setAttribute(\n 'instanceNumber',\n imageSet.getImage(0).InstanceNumber\n );*/\n\n /*const isReconstructable = isDisplaySetReconstructable(series, instances);\n\n imageSet.isReconstructable = isReconstructable.value;\n\n if (isReconstructable.missingFrames) {\n // TODO -> This is currently unused, but may be used for reconstructing\n // Volumes with gaps later on.\n imageSet.missingFrames = isReconstructable.missingFrames;\n }*/\n\n return imageSet;\n};\n\nconst isSingleImageModality = modality => {\n return modality === 'CR' || modality === 'MG' || modality === 'DX';\n};\n\nfunction getSopClassUids(instances) {\n const uniqueSopClassUidsInSeries = new Set();\n instances.forEach(instance => {\n uniqueSopClassUidsInSeries.add(instance.SOPClassUID);\n });\n const sopClassUids = Array.from(uniqueSopClassUidsInSeries);\n\n return sopClassUids;\n}\n\n/**\n * Basic SOPClassHandler:\n * - For all Image types that are stackable, create\n * a displaySet with a stack of images\n *\n * @param {SeriesMetadata} series The series metadata object from which the display sets will be created\n * @returns {Array} The list of display sets created for the given series object\n */\nfunction getDisplaySetsFromSeries(instances) {\n // If the series has no instances, stop here\n if (!instances || !instances.length) {\n throw new Error('No instances were provided');\n }\n\n const displaySets = [];\n const sopClassUids = getSopClassUids(instances);\n\n // Search through the instances (InstanceMetadata object) of this series\n // Split Multi-frame instances and Single-image modalities\n // into their own specific display sets. Place the rest of each\n // series into another display set.\n const stackableInstances = [];\n instances.forEach(instance => {\n // All imaging modalities must have a valid value for sopClassUid (x00080016) or rows (x00280010)\n if (!isImage(instance.SOPClassUID) && !instance.Rows) {\n return;\n }\n\n let displaySet;\n\n if (isMultiFrame(instance)) {\n displaySet = makeDisplaySet([instance]);\n\n displaySet.setAttributes({\n sopClassUids,\n isClip: true,\n numImageFrames: instance.NumberOfFrames,\n instanceNumber: instance.InstanceNumber,\n acquisitionDatetime: instance.AcquisitionDateTime,\n });\n displaySets.push(displaySet);\n } else if (isSingleImageModality(instance.Modality)) {\n displaySet = makeDisplaySet([instance]);\n displaySet.setAttributes({\n sopClassUids,\n instanceNumber: instance.InstanceNumber,\n acquisitionDatetime: instance.AcquisitionDateTime,\n });\n displaySets.push(displaySet);\n } else {\n stackableInstances.push(instance);\n }\n });\n\n if (stackableInstances.length) {\n const displaySet = makeDisplaySet(stackableInstances);\n displaySet.setAttribute('studyInstanceUid', instances[0].StudyInstanceUID);\n displaySet.setAttributes({\n sopClassUids,\n });\n displaySets.push(displaySet);\n }\n\n return displaySets;\n}\n\nconst sopClassUids = [\n sopClassDictionary.ComputedRadiographyImageStorage,\n sopClassDictionary.DigitalXRayImageStorageForPresentation,\n sopClassDictionary.DigitalXRayImageStorageForProcessing,\n sopClassDictionary.DigitalMammographyXRayImageStorageForPresentation,\n sopClassDictionary.DigitalMammographyXRayImageStorageForProcessing,\n sopClassDictionary.DigitalIntraOralXRayImageStorageForPresentation,\n sopClassDictionary.DigitalIntraOralXRayImageStorageForProcessing,\n sopClassDictionary.CTImageStorage,\n sopClassDictionary.EnhancedCTImageStorage,\n sopClassDictionary.LegacyConvertedEnhancedCTImageStorage,\n sopClassDictionary.UltrasoundMultiframeImageStorage,\n sopClassDictionary.MRImageStorage,\n sopClassDictionary.EnhancedMRImageStorage,\n sopClassDictionary.EnhancedMRColorImageStorage,\n sopClassDictionary.LegacyConvertedEnhancedMRImageStorage,\n sopClassDictionary.UltrasoundImageStorage,\n sopClassDictionary.UltrasoundImageStorageRET,\n sopClassDictionary.SecondaryCaptureImageStorage,\n sopClassDictionary.MultiframeSingleBitSecondaryCaptureImageStorage,\n sopClassDictionary.MultiframeGrayscaleByteSecondaryCaptureImageStorage,\n sopClassDictionary.MultiframeGrayscaleWordSecondaryCaptureImageStorage,\n sopClassDictionary.MultiframeTrueColorSecondaryCaptureImageStorage,\n sopClassDictionary.XRayAngiographicImageStorage,\n sopClassDictionary.EnhancedXAImageStorage,\n sopClassDictionary.XRayRadiofluoroscopicImageStorage,\n sopClassDictionary.EnhancedXRFImageStorage,\n sopClassDictionary.XRay3DAngiographicImageStorage,\n sopClassDictionary.XRay3DCraniofacialImageStorage,\n sopClassDictionary.BreastTomosynthesisImageStorage,\n sopClassDictionary.BreastProjectionXRayImageStorageForPresentation,\n sopClassDictionary.BreastProjectionXRayImageStorageForProcessing,\n sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForPresentation,\n sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForProcessing,\n sopClassDictionary.NuclearMedicineImageStorage,\n sopClassDictionary.VLEndoscopicImageStorage,\n sopClassDictionary.VideoEndoscopicImageStorage,\n sopClassDictionary.VLMicroscopicImageStorage,\n sopClassDictionary.VideoMicroscopicImageStorage,\n sopClassDictionary.VLSlideCoordinatesMicroscopicImageStorage,\n sopClassDictionary.VLPhotographicImageStorage,\n sopClassDictionary.VideoPhotographicImageStorage,\n sopClassDictionary.OphthalmicPhotography8BitImageStorage,\n sopClassDictionary.OphthalmicPhotography16BitImageStorage,\n sopClassDictionary.OphthalmicTomographyImageStorage,\n sopClassDictionary.VLWholeSlideMicroscopyImageStorage,\n sopClassDictionary.PositronEmissionTomographyImageStorage,\n sopClassDictionary.EnhancedPETImageStorage,\n sopClassDictionary.LegacyConvertedEnhancedPETImageStorage,\n sopClassDictionary.RTImageStorage,\n sopClassDictionary.EnhancedUSVolumeStorage,\n];\n\nfunction getSopClassHandlerModule(appContextParam) {\n appContext = appContextParam;\n\n return [\n {\n name: sopClassHandlerName,\n sopClassUids,\n getDisplaySetsFromSeries,\n },\n {\n name: 'not-supported-display-sets-handler',\n sopClassUids: [],\n getDisplaySetsFromSeries: getDisplaySetsFromUnsupportedSeries,\n },\n {\n name: chartHandler.name,\n sopClassUids: chartHandler.sopClassUids,\n getDisplaySetsFromSeries: chartHandler.getDisplaySetsFromSeries,\n },\n ];\n}\n\nexport default getSopClassHandlerModule;\n","import React from 'react';\n\nexport default function ToolbarDivider() {\n return <span className=\"border-common-dark mx-2 h-8 w-4 self-center border-l\" />;\n}\n","import React, { useEffect, useState, useCallback } from 'react';\nimport PropTypes from 'prop-types';\nimport { LayoutSelector as OHIFLayoutSelector, ToolbarButton, LayoutPreset } from '@ohif/ui';\nimport { ServicesManager } from '@ohif/core';\n\nconst defaultCommonPresets = [\n {\n icon: 'layout-common-1x1',\n commandOptions: {\n numRows: 1,\n numCols: 1,\n },\n },\n {\n icon: 'layout-common-1x2',\n commandOptions: {\n numRows: 1,\n numCols: 2,\n },\n },\n {\n icon: 'layout-common-2x2',\n commandOptions: {\n numRows: 2,\n numCols: 2,\n },\n },\n {\n icon: 'layout-common-2x3',\n commandOptions: {\n numRows: 2,\n numCols: 3,\n },\n },\n];\n\nconst _areSelectorsValid = (hp, displaySets, hangingProtocolService) => {\n if (!hp.displaySetSelectors || Object.values(hp.displaySetSelectors).length === 0) {\n return true;\n }\n\n return hangingProtocolService.areRequiredSelectorsValid(\n Object.values(hp.displaySetSelectors),\n displaySets[0]\n );\n};\n\nconst generateAdvancedPresets = ({ servicesManager }) => {\n const { hangingProtocolService, viewportGridService, displaySetService } =\n servicesManager.services;\n\n const hangingProtocols = Array.from(hangingProtocolService.protocols.values());\n\n const viewportId = viewportGridService.getActiveViewportId();\n\n if (!viewportId) {\n return [];\n }\n const displaySetInsaneUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);\n\n const displaySets = displaySetInsaneUIDs.map(uid => displaySetService.getDisplaySetByUID(uid));\n\n return hangingProtocols\n .map(hp => {\n if (!hp.isPreset) {\n return null;\n }\n\n const areValid = _areSelectorsValid(hp, displaySets, hangingProtocolService);\n\n return {\n icon: hp.icon,\n title: hp.name,\n commandOptions: {\n protocolId: hp.id,\n },\n disabled: !areValid,\n };\n })\n .filter(preset => preset !== null);\n};\n\nfunction ToolbarLayoutSelectorWithServices({ commandsManager, servicesManager, ...props }) {\n const [isDisabled, setIsDisabled] = useState(false);\n\n const handleMouseEnter = () => {\n setIsDisabled(false);\n };\n\n const onSelection = useCallback(props => {\n commandsManager.run({\n commandName: 'setViewportGridLayout',\n commandOptions: { ...props },\n });\n setIsDisabled(true);\n }, []);\n\n const onSelectionPreset = useCallback(props => {\n commandsManager.run({\n commandName: 'setHangingProtocol',\n commandOptions: { ...props },\n });\n setIsDisabled(true);\n }, []);\n\n return (\n <div onMouseEnter={handleMouseEnter}>\n <LayoutSelector\n {...props}\n onSelection={onSelection}\n onSelectionPreset={onSelectionPreset}\n servicesManager={servicesManager}\n tooltipDisabled={isDisabled}\n />\n </div>\n );\n}\n\nfunction LayoutSelector({\n rows,\n columns,\n className,\n onSelection,\n onSelectionPreset,\n servicesManager,\n tooltipDisabled,\n ...rest\n}) {\n const [isOpen, setIsOpen] = useState(false);\n\n const { customizationService } = servicesManager.services;\n const commonPresets = customizationService.get('commonPresets') || defaultCommonPresets;\n const advancedPresets =\n customizationService.get('advancedPresets') || generateAdvancedPresets({ servicesManager });\n\n const closeOnOutsideClick = () => {\n if (isOpen) {\n setIsOpen(false);\n }\n };\n\n useEffect(() => {\n window.addEventListener('click', closeOnOutsideClick);\n return () => {\n window.removeEventListener('click', closeOnOutsideClick);\n };\n }, [isOpen]);\n\n const onInteractionHandler = () => {\n setIsOpen(!isOpen);\n };\n const DropdownContent = isOpen ? OHIFLayoutSelector : null;\n\n return (\n <ToolbarButton\n id=\"Layout\"\n label=\"Layout\"\n icon=\"tool-layout\"\n onInteraction={onInteractionHandler}\n className={className}\n rounded={rest.rounded}\n disableToolTip={tooltipDisabled}\n dropdownContent={\n DropdownContent !== null && (\n <div className=\"flex \">\n <div className=\"bg-secondary-dark flex flex-col gap-2.5 p-2\">\n <div className=\"text-aqua-pale text-xs\">Common</div>\n\n <div className=\"flex gap-4\">\n {commonPresets.map((preset, index) => (\n <LayoutPreset\n key={index}\n classNames=\"hover:bg-primary-dark group p-1 cursor-pointer\"\n icon={preset.icon}\n commandOptions={preset.commandOptions}\n onSelection={onSelection}\n />\n ))}\n </div>\n\n <div className=\"h-[2px] bg-black\"></div>\n\n <div className=\"text-aqua-pale text-xs\">Advanced</div>\n\n <div className=\"flex flex-col gap-2.5\">\n {advancedPresets.map((preset, index) => (\n <LayoutPreset\n key={index + commonPresets.length}\n classNames=\"hover:bg-primary-dark group flex gap-2 p-1 cursor-pointer\"\n icon={preset.icon}\n title={preset.title}\n disabled={preset.disabled}\n commandOptions={preset.commandOptions}\n onSelection={onSelectionPreset}\n />\n ))}\n </div>\n </div>\n\n <div className=\"bg-primary-dark flex flex-col gap-2.5 border-l-2 border-solid border-black p-2\">\n <div className=\"text-aqua-pale text-xs\">Custom</div>\n <DropdownContent\n rows={rows}\n columns={columns}\n onSelection={onSelection}\n />\n <p className=\"text-aqua-pale text-xs leading-tight\">\n Hover to select <br></br>rows and columns <br></br> Click to apply\n </p>\n </div>\n </div>\n )\n }\n isActive={isOpen}\n type=\"toggle\"\n />\n );\n}\n\nLayoutSelector.propTypes = {\n rows: PropTypes.number,\n columns: PropTypes.number,\n onLayoutChange: PropTypes.func,\n servicesManager: PropTypes.instanceOf(ServicesManager),\n};\n\nLayoutSelector.defaultProps = {\n columns: 4,\n rows: 3,\n onLayoutChange: () => {},\n};\n\nexport default ToolbarLayoutSelectorWithServices;\n","import { SplitButton, ToolbarButton } from '@ohif/ui';\nimport React, { useCallback } from 'react';\nimport PropTypes from 'prop-types';\n\nfunction ToolbarSplitButtonWithServices({\n groupId,\n primary,\n secondary,\n items,\n renderer,\n onInteraction,\n servicesManager,\n}) {\n const { toolbarService } = servicesManager?.services;\n\n /* Bubbles up individual item clicks */\n const getSplitButtonItems = useCallback(\n items =>\n items.map((item, index) => ({\n ...item,\n index,\n onClick: () => {\n onInteraction({\n groupId,\n itemId: item.id,\n commands: item.commands,\n });\n },\n })),\n []\n );\n\n const PrimaryButtonComponent =\n toolbarService?.getButtonComponentForUIType(primary.uiType) ?? ToolbarButton;\n\n const listItemRenderer = renderer;\n\n return (\n <SplitButton\n primary={primary}\n secondary={secondary}\n items={getSplitButtonItems(items)}\n groupId={groupId}\n renderer={listItemRenderer}\n onInteraction={onInteraction}\n Component={props => (\n <PrimaryButtonComponent\n {...props}\n servicesManager={servicesManager}\n />\n )}\n />\n );\n}\n\nToolbarSplitButtonWithServices.propTypes = {\n isRadio: PropTypes.bool,\n groupId: PropTypes.string,\n primary: PropTypes.shape({\n id: PropTypes.string.isRequired,\n uiType: PropTypes.string,\n }),\n secondary: PropTypes.shape({\n id: PropTypes.string,\n icon: PropTypes.string.isRequired,\n label: PropTypes.string,\n tooltip: PropTypes.string.isRequired,\n disabled: PropTypes.bool,\n className: PropTypes.string,\n }),\n items: PropTypes.arrayOf(\n PropTypes.shape({\n id: PropTypes.string.isRequired,\n icon: PropTypes.string,\n label: PropTypes.string,\n tooltip: PropTypes.string,\n disabled: PropTypes.bool,\n className: PropTypes.string,\n })\n ),\n renderer: PropTypes.func,\n onInteraction: PropTypes.func.isRequired,\n servicesManager: PropTypes.shape({\n services: PropTypes.shape({\n toolbarService: PropTypes.object,\n }),\n }),\n};\n\nToolbarSplitButtonWithServices.defaultProps = {\n isRadio: false,\n isAction: false,\n};\n\nexport default ToolbarSplitButtonWithServices;\n","import { ToolbarButton, ButtonGroup } from '@ohif/ui';\nimport React, { useCallback } from 'react';\n\nfunction ToolbarButtonGroupWithServices({ groupId, items, onInteraction, size }) {\n const getSplitButtonItems = useCallback(\n items =>\n items.map((item, index) => (\n <ToolbarButton\n key={item.id}\n icon={item.icon}\n label={item.label}\n disabled={item.disabled}\n className={item.className}\n id={item.id}\n size={size}\n onClick={() => {\n onInteraction({\n groupId,\n itemId: item.id,\n commands: item.commands,\n });\n }}\n // Note: this is necessary since tooltip will add\n // default styles to the tooltip container which\n // we don't want for groups\n toolTipClassName=\"\"\n />\n )),\n [onInteraction, groupId]\n );\n\n return <ButtonGroup>{getSplitButtonItems(items)}</ButtonGroup>;\n}\n\nexport default ToolbarButtonGroupWithServices;\n","import React, { useEffect, useState, useCallback, ReactElement } from 'react';\nimport { ServicesManager } from '@ohif/core';\nimport { ProgressDropdown } from '@ohif/ui';\n\nconst workflowStepsToDropdownOptions = (steps = []) =>\n steps.map(step => ({\n label: step.name,\n value: step.id,\n info: step.info,\n activated: false,\n completed: false,\n }));\n\nfunction ProgressDropdownWithService({\n servicesManager,\n}: {\n servicesManager: ServicesManager;\n}): ReactElement {\n const { workflowStepsService } = servicesManager.services;\n const [activeStepId, setActiveStepId] = useState(workflowStepsService.activeWorkflowStep?.id);\n\n const [dropdownOptions, setDropdownOptions] = useState(\n workflowStepsToDropdownOptions(workflowStepsService.workflowSteps)\n );\n\n const setCurrentAndPreviousOptionsAsCompleted = useCallback(currentOption => {\n if (currentOption.completed) {\n return;\n }\n\n setDropdownOptions(prevOptions => {\n const newOptionsState = [...prevOptions];\n const startIndex = newOptionsState.findIndex(option => option.value === currentOption.value);\n\n for (let i = startIndex; i >= 0; i--) {\n const option = newOptionsState[i];\n\n if (option.completed) {\n break;\n }\n\n newOptionsState[i] = {\n ...option,\n completed: true,\n };\n }\n\n return newOptionsState;\n });\n }, []);\n\n const handleDropdownChange = useCallback(\n ({ selectedOption }) => {\n if (!selectedOption) {\n return;\n }\n\n // TODO: Steps should be marked as completed after user has\n // completed some action when required (not implemented)\n setCurrentAndPreviousOptionsAsCompleted(selectedOption);\n setActiveStepId(selectedOption.value);\n },\n [setCurrentAndPreviousOptionsAsCompleted]\n );\n\n useEffect(() => {\n let timeoutId;\n\n if (activeStepId) {\n // We've used setTimeout to give it more time to update the UI since\n // create3DFilterableFromDataArray from Texture.js may take 600+ ms to run\n // when there is a new series to load in the next step but that resulted\n // in the followed React error when updating the content from left/right panels\n // and all component states were being lost:\n // Error: Can't perform a React state update on an unmounted component\n workflowStepsService.setActiveWorkflowStep(activeStepId);\n }\n\n return () => clearTimeout(timeoutId);\n }, [activeStepId, workflowStepsService]);\n\n useEffect(() => {\n const { unsubscribe: unsubStepsChanged } = workflowStepsService.subscribe(\n workflowStepsService.EVENTS.STEPS_CHANGED,\n () => setDropdownOptions(workflowStepsToDropdownOptions(workflowStepsService.workflowSteps))\n );\n\n const { unsubscribe: unsubActiveStepChanged } = workflowStepsService.subscribe(\n workflowStepsService.EVENTS.ACTIVE_STEP_CHANGED,\n\n () => setActiveStepId(workflowStepsService.activeWorkflowStep.id)\n );\n\n return () => {\n unsubStepsChanged();\n unsubActiveStepChanged();\n };\n }, [servicesManager, workflowStepsService]);\n\n return (\n <ProgressDropdown\n options={dropdownOptions}\n value={activeStepId}\n onChange={handleDropdownChange}\n />\n );\n}\n\nexport default ProgressDropdownWithService;\n","import { Types } from '@ohif/ui';\nimport { Menu, SelectorProps, MenuItem, ContextMenuProps } from './types';\n\ntype ContextMenuItem = Types.ContextMenuItem;\n\n/**\n * Finds menu by menu id\n *\n * @returns Menu having the menuId\n */\nexport function findMenuById(menus: Menu[], menuId?: string): Menu {\n if (!menuId) {\n return;\n }\n\n return menus.find(menu => menu.id === menuId);\n}\n\n/**\n * Default finding menu method. This method will go through\n * the list of menus until it finds the first one which\n * has no selector, OR has the selector, when applied to the\n * check props, return true.\n * The selectorProps are a set of provided properties which can be\n * passed into the selector function to determine when to display a menu.\n * For example, a selector function of:\n * `({displayset}) => displaySet?.SeriesDescription?.indexOf?.('Left')!==-1\n * would match series descriptions containing 'Left'.\n *\n * @param {Object[]} menus List of menus\n * @param {*} subProps\n * @returns\n */\nexport function findMenuDefault(menus: Menu[], subProps: Record<string, unknown>): Menu {\n if (!menus) {\n return null;\n }\n return menus.find(menu => !menu.selector || menu.selector(subProps.selectorProps));\n}\n\n/**\n * Finds the menu to be used for different scenarios:\n * This will first look for a subMenu with the specified subMenuId\n * Next it will look for the first menu whose selector returns true.\n *\n * @param menus - List of menus\n * @param props - root props\n * @param menuIdFilter - menu id identifier (to be considered on selection)\n * This is intended to support other types of filtering in the future.\n */\nexport function findMenu(menus: Menu[], props?: Types.IProps, menuIdFilter?: string) {\n const { subMenu } = props;\n\n function* findMenuIterator() {\n yield findMenuById(menus, menuIdFilter || subMenu);\n yield findMenuDefault(menus, props);\n }\n\n const findIt = findMenuIterator();\n\n let current = findIt.next();\n let menu = current.value;\n\n while (!current.done) {\n menu = current.value;\n\n if (menu) {\n findIt.return();\n }\n current = findIt.next();\n }\n\n return menu;\n}\n\n/**\n * Returns the menu from a list of possible menus, based on the actual state of component props and tool data nearby.\n * This uses the findMenu command above to first find the appropriate\n * menu, and then it chooses the actual contents of that menu.\n * A menu item can be optional by implementing the 'selector',\n * which will be called with the selectorProps, and if it does not return true,\n * then the item is excluded.\n *\n * Other menus can be delegated to by setting the delegating value to\n * a string id for another menu. That menu's content will replace the\n * current menu item (only if the item would be included).\n *\n * This allows single id menus to be chosen by id, but have varying contents\n * based on the delegated menus.\n *\n * Finally, for each item, the adaptItem call is made. This allows\n * items to modify themselves before being displayed, such as\n * incorporating additional information from translation sources.\n * See the `test-mode` examples for details.\n *\n * @param selectorProps\n * @param {*} event event that originates the context menu\n * @param {*} menus List of menus\n * @param {*} menuIdFilter\n * @returns\n */\nexport function getMenuItems(\n selectorProps: SelectorProps,\n event: Event,\n menus: Menu[],\n menuIdFilter?: string\n): MenuItem[] | void {\n // Include both the check props and the ...check props as one is used\n // by the child menu and the other used by the selector function\n const subProps = { selectorProps, event };\n\n const menu = findMenu(menus, subProps, menuIdFilter);\n\n if (!menu) {\n return undefined;\n }\n\n if (!menu.items) {\n console.warn('Must define items in menu', menu);\n return [];\n }\n\n let menuItems = [];\n menu.items.forEach(item => {\n const { delegating, selector, subMenu } = item;\n\n if (!selector || selector(selectorProps)) {\n if (delegating) {\n menuItems = [...menuItems, ...getMenuItems(selectorProps, event, menus, subMenu)];\n } else {\n const toAdd = adaptItem(item, subProps);\n menuItems.push(toAdd);\n }\n }\n });\n\n return menuItems;\n}\n\n/**\n * Returns item adapted to be consumed by ContextMenu component\n * and then goes through the item to add action behaviour for clicking the item,\n * making it compatible with the default ContextMenu display.\n *\n * @param {Object} item\n * @param {Object} subProps\n * @returns a MenuItem that is compatible with the base ContextMenu\n * This requires having a label and set of actions to be called.\n */\nexport function adaptItem(item: MenuItem, subProps: ContextMenuProps): ContextMenuItem {\n const newItem: ContextMenuItem = {\n ...item,\n value: subProps.selectorProps?.value,\n };\n\n if (item.actionType === 'ShowSubMenu' && !newItem.iconRight) {\n newItem.iconRight = 'chevron-menu';\n }\n if (!item.action) {\n newItem.action = (itemRef, componentProps) => {\n const { event = {} } = componentProps;\n const { detail = {} } = event;\n newItem.element = detail.element;\n\n componentProps.onClose();\n const action = componentProps[`on${itemRef.actionType || 'Default'}`];\n if (action) {\n action.call(componentProps, newItem, itemRef, subProps);\n } else {\n console.warn('No action defined for', itemRef);\n }\n };\n }\n\n return newItem;\n}\n","import * as ContextMenuItemsBuilder from './ContextMenuItemsBuilder';\nimport ContextMenu from '../../../../platform/ui/src/components/ContextMenu/ContextMenu';\nimport { CommandsManager, ServicesManager, Types } from '@ohif/core';\nimport { annotation as CsAnnotation } from '@cornerstonejs/tools';\nimport { Menu, MenuItem, Point, ContextMenuProps } from './types';\n\n/**\n * The context menu controller is a helper class that knows how\n * to manage context menus based on the UI Customization Service.\n * There are a few parts to this:\n * 1. Basic controls to manage displaying and hiding context menus\n * 2. Menu selection services, which use the UI customization service\n * to choose which menu to display\n * 3. Menu item adapter services to convert menu items into displayable and actionable items.\n *\n * The format for a menu is defined in the exported type MenuItem\n */\nexport default class ContextMenuController {\n commandsManager: CommandsManager;\n services: Types.Services;\n menuItems: Menu[] | MenuItem[];\n\n constructor(servicesManager: ServicesManager, commandsManager: CommandsManager) {\n this.services = servicesManager.services as Obj;\n this.commandsManager = commandsManager;\n }\n\n closeContextMenu() {\n this.services.uiDialogService.dismiss({ id: 'context-menu' });\n }\n\n /**\n * Figures out which context menu is appropriate to display and shows it.\n *\n * @param contextMenuProps - the context menu properties, see ./types.ts\n * @param viewportElement - the DOM element this context menu is related to\n * @param defaultPointsPosition - a default position to show the context menu\n */\n showContextMenu(\n contextMenuProps: ContextMenuProps,\n viewportElement,\n defaultPointsPosition\n ): void {\n if (!this.services.uiDialogService) {\n console.warn('Unable to show dialog; no UI Dialog Service available.');\n return;\n }\n\n const { event, subMenu, menuId, menus, selectorProps } = contextMenuProps;\n\n const annotationManager = CsAnnotation.state.getAnnotationManager();\n const { locking } = CsAnnotation;\n const targetAnnotationId = selectorProps?.nearbyToolData?.annotationUID as string;\n const isLocked = locking.isAnnotationLocked(\n annotationManager.getAnnotation(targetAnnotationId)\n );\n\n if (isLocked) {\n console.warn('Annotation is locked.');\n return;\n }\n\n const items = ContextMenuItemsBuilder.getMenuItems(\n selectorProps || contextMenuProps,\n event,\n menus,\n menuId\n );\n\n this.services.uiDialogService.dismiss({ id: 'context-menu' });\n this.services.uiDialogService.create({\n id: 'context-menu',\n isDraggable: false,\n preservePosition: false,\n preventCutOf: true,\n defaultPosition: ContextMenuController._getDefaultPosition(\n defaultPointsPosition,\n event?.detail,\n viewportElement\n ),\n event,\n content: ContextMenu,\n\n // This naming is part of the uiDialogService convention\n // Clicking outside simply closes the dialog box.\n onClickOutside: () => this.services.uiDialogService.dismiss({ id: 'context-menu' }),\n\n contentProps: {\n items,\n selectorProps,\n menus,\n event,\n subMenu,\n eventData: event?.detail,\n\n onClose: () => {\n this.services.uiDialogService.dismiss({ id: 'context-menu' });\n },\n\n /**\n * Displays a sub-menu, removing this menu\n * @param {*} item\n * @param {*} itemRef\n * @param {*} subProps\n */\n onShowSubMenu: (item, itemRef, subProps) => {\n if (!itemRef.subMenu) {\n console.warn('No submenu defined for', item, itemRef, subProps);\n return;\n }\n this.showContextMenu(\n {\n ...contextMenuProps,\n menuId: itemRef.subMenu,\n },\n viewportElement,\n defaultPointsPosition\n );\n },\n\n // Default is to run the specified commands.\n onDefault: (item, itemRef, subProps) => {\n this.commandsManager.run(item, {\n ...selectorProps,\n ...itemRef,\n subProps,\n });\n },\n },\n });\n }\n\n static getDefaultPosition = (): Point => {\n return {\n x: 0,\n y: 0,\n };\n };\n\n static _getEventDefaultPosition = eventDetail => ({\n x: eventDetail && eventDetail.currentPoints.client[0],\n y: eventDetail && eventDetail.currentPoints.client[1],\n });\n\n static _getElementDefaultPosition = element => {\n if (element) {\n const boundingClientRect = element.getBoundingClientRect();\n return {\n x: boundingClientRect.x,\n y: boundingClientRect.y,\n };\n }\n\n return {\n x: undefined,\n y: undefined,\n };\n };\n\n static _getCanvasPointsPosition = (points = [], element) => {\n const viewerPos = ContextMenuController._getElementDefaultPosition(element);\n\n for (let pointIndex = 0; pointIndex < points.length; pointIndex++) {\n const point = {\n x: points[pointIndex][0] || points[pointIndex]['x'],\n y: points[pointIndex][1] || points[pointIndex]['y'],\n };\n if (\n ContextMenuController._isValidPosition(point) &&\n ContextMenuController._isValidPosition(viewerPos)\n ) {\n return {\n x: point.x + viewerPos.x,\n y: point.y + viewerPos.y,\n };\n }\n }\n };\n\n static _isValidPosition = (source): boolean => {\n return source && typeof source.x === 'number' && typeof source.y === 'number';\n };\n\n /**\n * Returns the context menu default position. It look for the positions of: canvasPoints (got from selected), event that triggers it, current viewport element\n */\n static _getDefaultPosition = (canvasPoints, eventDetail, viewerElement) => {\n function* getPositionIterator() {\n yield ContextMenuController._getCanvasPointsPosition(canvasPoints, viewerElement);\n yield ContextMenuController._getEventDefaultPosition(eventDetail);\n yield ContextMenuController._getElementDefaultPosition(viewerElement);\n yield ContextMenuController.getDefaultPosition();\n }\n\n const positionIterator = getPositionIterator();\n\n let current = positionIterator.next();\n let position = current.value;\n\n while (!current.done) {\n position = current.value;\n\n if (ContextMenuController._isValidPosition(position)) {\n positionIterator.return();\n }\n current = positionIterator.next();\n }\n\n return position;\n };\n}\n","const defaultContextMenu = {\n id: 'measurementsContextMenu',\n customizationType: 'ohif.contextMenu',\n menus: [\n // Get the items from the UI Customization for the menu name (and have a custom name)\n {\n id: 'forExistingMeasurement',\n selector: ({ nearbyToolData }) => !!nearbyToolData,\n items: [\n {\n label: 'Delete measurement',\n commands: [\n {\n commandName: 'deleteMeasurement',\n // we only have support for cornerstoneTools context menu since\n // they are svg based\n context: 'CORNERSTONE',\n },\n ],\n },\n {\n label: 'Add Label',\n commands: [\n {\n commandName: 'setMeasurementLabel',\n },\n ],\n },\n ],\n },\n ],\n};\n\nexport default defaultContextMenu;\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { VariableSizeList as List } from 'react-window';\nimport classNames from 'classnames';\nimport debounce from 'lodash.debounce';\n\nconst lineHeightPx = 20;\nconst lineHeightClassName = `leading-[${lineHeightPx}px]`;\nconst rowVerticalPaddingPx = 10;\nconst rowBottomBorderPx = 1;\nconst rowVerticalPaddingStyle = { padding: `${rowVerticalPaddingPx}px 0` };\nconst rowStyle = {\n borderBottomWidth: `${rowBottomBorderPx}px`,\n ...rowVerticalPaddingStyle,\n};\n\nfunction ColumnHeaders({ tagRef, vrRef, keywordRef, valueRef }) {\n return (\n <div\n className={classNames(\n 'bg-secondary-dark ohif-scrollbar flex w-full flex-row overflow-y-scroll'\n )}\n style={rowVerticalPaddingStyle}\n >\n <div className=\"w-4/24 px-3\">\n <label\n ref={tagRef}\n className=\"flex flex-1 select-none flex-col pl-1 text-lg text-white\"\n >\n <span className=\"flex flex-row items-center focus:outline-none\">Tag</span>\n </label>\n </div>\n <div className=\"w-2/24 px-3\">\n <label\n ref={vrRef}\n className=\"flex flex-1 select-none flex-col pl-1 text-lg text-white\"\n >\n <span className=\"flex flex-row items-center focus:outline-none\">VR</span>\n </label>\n </div>\n <div className=\"w-6/24 px-3\">\n <label\n ref={keywordRef}\n className=\"flex flex-1 select-none flex-col pl-1 text-lg text-white\"\n >\n <span className=\"flex flex-row items-center focus:outline-none\">Keyword</span>\n </label>\n </div>\n <div className=\"w-5/24 grow px-3\">\n <label\n ref={valueRef}\n className=\"flex flex-1 select-none flex-col pl-1 text-lg text-white\"\n >\n <span className=\"flex flex-row items-center focus:outline-none\">Value</span>\n </label>\n </div>\n </div>\n );\n}\n\nfunction DicomTagTable({ rows }) {\n const listRef = useRef();\n const canvasRef = useRef();\n\n const [tagHeaderElem, setTagHeaderElem] = useState(null);\n const [vrHeaderElem, setVrHeaderElem] = useState(null);\n const [keywordHeaderElem, setKeywordHeaderElem] = useState(null);\n const [valueHeaderElem, setValueHeaderElem] = useState(null);\n\n // Here the refs are inturn stored in state to trigger a render of the table.\n // This virtualized table does NOT render until the header is rendered because the header column widths are used to determine the row heights in the table.\n // Therefore whenever the refs change (in particular the first time the refs are set), we want to trigger a render of the table.\n const tagRef = elem => {\n if (elem) {\n setTagHeaderElem(elem);\n }\n };\n const vrRef = elem => {\n if (elem) {\n setVrHeaderElem(elem);\n }\n };\n const keywordRef = elem => {\n if (elem) {\n setKeywordHeaderElem(elem);\n }\n };\n const valueRef = elem => {\n if (elem) {\n setValueHeaderElem(elem);\n }\n };\n\n /**\n * When new rows are set, scroll to the top and reset the virtualization.\n */\n useEffect(() => {\n if (!listRef?.current) {\n return;\n }\n\n listRef.current.scrollTo(0);\n listRef.current.resetAfterIndex(0);\n }, [rows]);\n\n /**\n * When the browser window resizes, update the row virtualization (i.e. row heights)\n */\n useEffect(() => {\n const debouncedResize = debounce(() => listRef.current.resetAfterIndex(0), 100);\n\n window.addEventListener('resize', debouncedResize);\n\n return () => {\n debouncedResize.cancel();\n window.removeEventListener('resize', debouncedResize);\n };\n }, []);\n\n const Row = useCallback(\n ({ index, style }) => {\n const row = rows[index];\n\n return (\n <div\n style={{ ...style, ...rowStyle }}\n className={classNames(\n 'hover:bg-secondary-main border-secondary-light flex w-full flex-row items-center break-all bg-black text-base transition duration-300',\n lineHeightClassName\n )}\n key={`DICOMTagRow-${index}`}\n >\n <div className=\"w-4/24 px-3\">{row[0]}</div>\n <div className=\"w-2/24 px-3\">{row[1]}</div>\n <div className=\"w-6/24 px-3\">{row[2]}</div>\n <div className=\"w-5/24 grow px-3\">{row[3]}</div>\n </div>\n );\n },\n [rows]\n );\n\n /**\n * Whenever any one of the column headers is set, then the header is rendered.\n * Here we chose the tag header.\n */\n const isHeaderRendered = useCallback(() => tagHeaderElem !== null, [tagHeaderElem]);\n\n /**\n * Get the item/row size. We use the header column widths to calculate the various row heights.\n * @param index the row index\n * @returns the row height\n */\n const getItemSize = useCallback(\n index => {\n const headerWidths = [\n tagHeaderElem.offsetWidth,\n vrHeaderElem.offsetWidth,\n keywordHeaderElem.offsetWidth,\n valueHeaderElem.offsetWidth,\n ];\n\n const context = canvasRef.current.getContext('2d');\n context.font = getComputedStyle(canvasRef.current).font;\n\n return rows[index]\n .map((colText, index) => {\n const colOneLineWidth = context.measureText(colText).width;\n const numLines = Math.ceil(colOneLineWidth / headerWidths[index]);\n return numLines * lineHeightPx + 2 * rowVerticalPaddingPx + rowBottomBorderPx;\n })\n .reduce((maxHeight, colHeight) => Math.max(maxHeight, colHeight));\n },\n [rows, keywordHeaderElem, tagHeaderElem, valueHeaderElem, vrHeaderElem]\n );\n\n return (\n <div>\n <canvas\n style={{ visibility: 'hidden', position: 'absolute' }}\n className=\"text-base\"\n ref={canvasRef}\n />\n <ColumnHeaders\n tagRef={tagRef}\n vrRef={vrRef}\n keywordRef={keywordRef}\n valueRef={valueRef}\n />\n <div\n className=\"relative m-auto border-2 border-black bg-black\"\n style={{ height: '32rem' }}\n >\n {isHeaderRendered() && (\n <List\n ref={listRef}\n height={500}\n itemCount={rows.length}\n itemSize={getItemSize}\n width={'100%'}\n className=\"ohif-scrollbar\"\n >\n {Row}\n </List>\n )}\n </div>\n </div>\n );\n}\n\nexport default DicomTagTable;\n","import dcmjs from 'dcmjs';\nimport moment from 'moment';\nimport React, { useState, useMemo, useEffect } from 'react';\nimport { classes } from '@ohif/core';\nimport { InputRange, Select, Typography, InputFilterText } from '@ohif/ui';\nimport debounce from 'lodash.debounce';\n\nimport DicomTagTable from './DicomTagTable';\nimport './DicomTagBrowser.css';\n\nconst { ImageSet } = classes;\nconst { DicomMetaDictionary } = dcmjs.data;\nconst { nameMap } = DicomMetaDictionary;\n\nconst DicomTagBrowser = ({ displaySets, displaySetInstanceUID }) => {\n // The column indices that are to be excluded during a filter of the table.\n // At present the column indices are:\n // 0: DICOM tag\n // 1: VR\n // 2: Keyword\n // 3: Value\n const excludedColumnIndicesForFilter: Set<number> = new Set([1]);\n\n const [selectedDisplaySetInstanceUID, setSelectedDisplaySetInstanceUID] =\n useState(displaySetInstanceUID);\n const [instanceNumber, setInstanceNumber] = useState(1);\n const [filterValue, setFilterValue] = useState('');\n\n const onSelectChange = value => {\n setSelectedDisplaySetInstanceUID(value.value);\n setInstanceNumber(1);\n };\n\n const activeDisplaySet = displaySets.find(\n ds => ds.displaySetInstanceUID === selectedDisplaySetInstanceUID\n );\n\n const isImageStack = _isImageStack(activeDisplaySet);\n const showInstanceList = isImageStack && activeDisplaySet.images.length > 1;\n\n const displaySetList = useMemo(() => {\n displaySets.sort((a, b) => a.SeriesNumber - b.SeriesNumber);\n return displaySets.map(displaySet => {\n const {\n displaySetInstanceUID,\n SeriesDate,\n SeriesTime,\n SeriesNumber,\n SeriesDescription,\n Modality,\n } = displaySet;\n\n /* Map to display representation */\n const dateStr = `${SeriesDate}:${SeriesTime}`.split('.')[0];\n const date = moment(dateStr, 'YYYYMMDD:HHmmss');\n const displayDate = date.format('ddd, MMM Do YYYY');\n\n return {\n value: displaySetInstanceUID,\n label: `${SeriesNumber} (${Modality}): ${SeriesDescription}`,\n description: displayDate,\n };\n });\n }, [displaySets]);\n\n const rows = useMemo(() => {\n let metadata;\n if (isImageStack) {\n metadata = activeDisplaySet.images[instanceNumber - 1];\n } else {\n metadata = activeDisplaySet.instance || activeDisplaySet;\n }\n const tags = getSortedTags(metadata);\n return getFormattedRowsFromTags(tags, metadata);\n }, [instanceNumber, selectedDisplaySetInstanceUID]);\n\n const filteredRows = useMemo(() => {\n if (!filterValue) {\n return rows;\n }\n\n const filterValueLowerCase = filterValue.toLowerCase();\n return rows.filter(row => {\n return row.reduce((keepRow, col, colIndex) => {\n if (keepRow) {\n // We are already keeping the row, why do more work so return now.\n return keepRow;\n }\n\n if (excludedColumnIndicesForFilter.has(colIndex)) {\n return keepRow;\n }\n\n return keepRow || col.toLowerCase().includes(filterValueLowerCase);\n }, false);\n });\n }, [rows, filterValue]);\n\n const debouncedSetFilterValue = useMemo(() => {\n return debounce(setFilterValue, 200);\n }, []);\n\n useEffect(() => {\n return () => {\n debouncedSetFilterValue?.cancel();\n };\n }, []);\n\n return (\n <div className=\"dicom-tag-browser-content\">\n <div className=\"mb-6 flex flex-row items-center pl-1\">\n <div className=\"flex w-1/2 flex-row items-center\">\n <Typography\n variant=\"subtitle\"\n className=\"mr-4\"\n >\n Series\n </Typography>\n <div className=\"mr-8 grow\">\n <Select\n id=\"display-set-selector\"\n isClearable={false}\n onChange={onSelectChange}\n options={displaySetList}\n value={displaySetList.find(ds => ds.value === selectedDisplaySetInstanceUID)}\n className=\"text-white\"\n />\n </div>\n </div>\n <div className=\"flex w-1/2 flex-row items-center\">\n {showInstanceList && (\n <Typography\n variant=\"subtitle\"\n className=\"mr-4\"\n >\n Instance Number\n </Typography>\n )}\n {showInstanceList && (\n <div className=\"grow\">\n <InputRange\n value={instanceNumber}\n key={selectedDisplaySetInstanceUID}\n onChange={value => {\n setInstanceNumber(parseInt(value));\n }}\n minValue={1}\n maxValue={activeDisplaySet.images.length}\n step={1}\n inputClassName=\"w-full\"\n labelPosition=\"left\"\n trackColor={'#3a3f99'}\n />\n </div>\n )}\n </div>\n </div>\n <div className=\"h-1 w-full bg-black\"></div>\n <div className=\"my-3 flex w-1/2 flex-row\">\n <InputFilterText\n className=\"mr-8 block w-full\"\n placeholder=\"Search metadata...\"\n onDebounceChange={setFilterValue}\n ></InputFilterText>\n </div>\n <DicomTagTable rows={filteredRows} />\n </div>\n );\n};\n\nfunction getFormattedRowsFromTags(tags, metadata) {\n const rows = [];\n\n tags.forEach(tagInfo => {\n if (tagInfo.vr === 'SQ') {\n rows.push([`${tagInfo.tagIndent}${tagInfo.tag}`, tagInfo.vr, tagInfo.keyword, '']);\n\n const { values } = tagInfo;\n\n values.forEach((item, index) => {\n const formatedRowsFromTags = getFormattedRowsFromTags(item, metadata);\n\n rows.push([`${item[0].tagIndent}(FFFE,E000)`, '', `Item #${index}`, '']);\n\n rows.push(...formatedRowsFromTags);\n });\n } else {\n if (tagInfo.vr === 'xs') {\n try {\n const tag = dcmjs.data.Tag.fromPString(tagInfo.tag).toCleanString();\n const originalTagInfo = metadata[tag];\n tagInfo.vr = originalTagInfo.vr;\n } catch (error) {\n console.error(`Failed to parse value representation for tag '${tagInfo.keyword}'`);\n }\n }\n rows.push([`${tagInfo.tagIndent}${tagInfo.tag}`, tagInfo.vr, tagInfo.keyword, tagInfo.value]);\n }\n });\n\n return rows;\n}\n\nfunction getSortedTags(metadata) {\n const tagList = getRows(metadata);\n\n // Sort top level tags, sequence groups are sorted when created.\n _sortTagList(tagList);\n\n return tagList;\n}\n\nfunction getRows(metadata, depth = 0) {\n // Tag, Type, Value, Keyword\n\n const keywords = Object.keys(metadata);\n\n let tagIndent = '';\n\n for (let i = 0; i < depth; i++) {\n tagIndent += '>';\n }\n\n if (depth > 0) {\n tagIndent += ' '; // If indented, add a space after the indents.\n }\n\n const rows = [];\n for (let i = 0; i < keywords.length; i++) {\n let keyword = keywords[i];\n\n if (keyword === '_vrMap') {\n continue;\n }\n\n const tagInfo = nameMap[keyword];\n\n let value = metadata[keyword];\n\n if (tagInfo && tagInfo.vr === 'SQ') {\n const sequenceAsArray = toArray(value);\n\n // Push line defining the sequence\n\n const sequence = {\n tag: tagInfo.tag,\n tagIndent,\n vr: tagInfo.vr,\n keyword,\n values: [],\n };\n\n rows.push(sequence);\n\n if (value === null) {\n // Type 2 Sequence\n continue;\n }\n\n sequenceAsArray.forEach(item => {\n const sequenceRows = getRows(item, depth + 1);\n\n if (sequenceRows.length) {\n // Sort the sequence group.\n _sortTagList(sequenceRows);\n sequence.values.push(sequenceRows);\n }\n });\n\n continue;\n }\n\n if (Array.isArray(value)) {\n if (value.length > 0 && typeof value[0] != 'object') {\n value = value.join('\\\\');\n }\n }\n\n if (typeof value === 'number') {\n value = value.toString();\n }\n\n if (typeof value !== 'string') {\n if (value === null) {\n value = ' ';\n } else {\n if (typeof value === 'object') {\n if (value.InlineBinary) {\n value = 'Inline Binary';\n } else if (value.BulkDataURI) {\n value = `Bulk Data URI`; //: ${value.BulkDataURI}`;\n } else if (value.Alphabetic) {\n value = value.Alphabetic;\n } else {\n console.warn(`Unrecognised Value: ${value} for ${keyword}:`);\n console.warn(value);\n value = ' ';\n }\n } else {\n console.warn(`Unrecognised Value: ${value} for ${keyword}:`);\n value = ' ';\n }\n }\n }\n\n // tag / vr/ keyword/ value\n\n // Remove retired tags\n keyword = keyword.replace('RETIRED_', '');\n if (tagInfo) {\n rows.push({\n tag: tagInfo.tag,\n tagIndent,\n vr: tagInfo.vr,\n keyword,\n value,\n });\n } else {\n // skip properties without hex tag numbers\n const regex = /[0-9A-Fa-f]{6}/g;\n if (keyword.match(regex)) {\n const tag = `(${keyword.substring(0, 4)},${keyword.substring(4, 8)})`;\n rows.push({\n tag,\n tagIndent,\n vr: '',\n keyword: 'Private Tag',\n value,\n });\n }\n }\n }\n\n return rows;\n}\n\nfunction _isImageStack(displaySet) {\n return displaySet instanceof ImageSet;\n}\n\nfunction toArray(objectOrArray) {\n return Array.isArray(objectOrArray) ? objectOrArray : [objectOrArray];\n}\n\nfunction _sortTagList(tagList) {\n tagList.sort((a, b) => {\n if (a.tag < b.tag) {\n return -1;\n }\n\n return 1;\n });\n}\n\nexport default DicomTagBrowser;\n","import { HangingProtocolService, StateSyncService, Types } from '@ohif/core';\n\nexport type ReturnType = {\n hangingProtocolStageIndexMap: Record<string, Types.HangingProtocol.HPInfo>;\n viewportGridStore: Record<string, unknown>;\n displaySetSelectorMap: Record<string, string>;\n};\n\n/**\n * Calculates a set of state information for hanging protocols and viewport grid\n * which defines the currently applied hanging protocol state.\n * @param state is the viewport grid state\n * @param syncService is the state sync service to use for getting existing state\n * @returns Set of states that can be applied to the state sync to remember\n * the current view state.\n */\nconst reuseCachedLayout = (\n state,\n hangingProtocolService: HangingProtocolService,\n syncService: StateSyncService\n): ReturnType => {\n const { activeViewportId } = state;\n const { protocol } = hangingProtocolService.getActiveProtocol();\n\n if (!protocol) {\n return;\n }\n\n const hpInfo = hangingProtocolService.getState();\n const { protocolId, stageIndex, activeStudyUID } = hpInfo;\n\n const syncState = syncService.getState();\n const viewportGridStore = { ...syncState.viewportGridStore };\n const displaySetSelectorMap = { ...syncState.displaySetSelectorMap };\n\n const stage = protocol.stages[stageIndex];\n const storeId = `${activeStudyUID}:${protocolId}:${stageIndex}`;\n const cacheId = `${activeStudyUID}:${protocolId}`;\n const hangingProtocolStageIndexMap = {\n ...syncState.hangingProtocolStageIndexMap,\n };\n const { rows, columns } = stage.viewportStructure.properties;\n const custom =\n stage.viewports.length !== state.viewports.size ||\n state.layout.numRows !== rows ||\n state.layout.numCols !== columns;\n\n hangingProtocolStageIndexMap[cacheId] = hpInfo;\n\n if (storeId && custom) {\n viewportGridStore[storeId] = { ...state };\n }\n\n state.viewports.forEach((viewport, viewportId) => {\n const { displaySetOptions, displaySetInstanceUIDs } = viewport;\n if (!displaySetOptions) {\n return;\n }\n for (let i = 0; i < displaySetOptions.length; i++) {\n const displaySetUID = displaySetInstanceUIDs[i];\n if (!displaySetUID) {\n continue;\n }\n if (viewportId === activeViewportId && i === 0) {\n displaySetSelectorMap[`${activeStudyUID}:activeDisplaySet:0`] = displaySetUID;\n }\n if (displaySetOptions[i]?.id) {\n displaySetSelectorMap[\n `${activeStudyUID}:${displaySetOptions[i].id}:${\n displaySetOptions[i].matchedDisplaySetsIndex || 0\n }`\n ] = displaySetUID;\n }\n }\n });\n\n return {\n hangingProtocolStageIndexMap,\n viewportGridStore,\n displaySetSelectorMap,\n };\n};\n\nexport default reuseCachedLayout;\n","import { StateSyncService } from '@ohif/core';\n\n/**\n * This find or create viewport is paired with the reduce results from\n * below, and the action of this viewport is to look for previously filled\n * viewports, and to reuse by position id. If there is no filled viewport,\n * then one can be re-used from the display set if it isn't going to be displayed.\n * @param hangingProtocolService - bound parameter supplied before using this\n * @param viewportsByPosition - bound parameter supplied before using this\n * @param position - the position in the grid to retrieve\n * @param positionId - the current position on screen to retrieve\n * @param options - the set of options used, so that subsequent calls can\n * store state that is reset by the setLayout.\n * This class uses the options to store the already viewed\n * display sets, filling it initially with the pre-existing viewports.\n */\nexport const findOrCreateViewport = (\n hangingProtocolService,\n viewportsByPosition,\n position: number,\n positionId: string,\n options: Record<string, unknown>\n) => {\n const byPositionViewport = viewportsByPosition?.[positionId];\n if (byPositionViewport) {\n return { ...byPositionViewport };\n }\n const { protocolId, stageIndex } = hangingProtocolService.getState();\n\n // Setup the initial in display correctly for initial view/select\n if (!options.inDisplay) {\n options.inDisplay = [...viewportsByPosition.initialInDisplay];\n }\n // See if there is a default viewport for new views.\n const missing = hangingProtocolService.getMissingViewport(protocolId, stageIndex, options);\n if (missing) {\n const displaySetInstanceUIDs = missing.displaySetsInfo.map(it => it.displaySetInstanceUID);\n options.inDisplay.push(...displaySetInstanceUIDs);\n return {\n displaySetInstanceUIDs,\n displaySetOptions: missing.displaySetsInfo.map(it => it.displaySetOptions),\n viewportOptions: {\n ...missing.viewportOptions,\n },\n };\n }\n\n // and lastly if there is no default viewport, then we see if we can grab the\n // viewportsByPosition at the position index and use that\n // const candidate = Object.values(viewportsByPosition)[position];\n\n // // if it has something to display, then we can use it\n // return candidate?.displaySetInstanceUIDs ? candidate : {};\n return {};\n};\n\n/**\n * Records the information on what viewports are displayed in which position.\n * Also records what instances from the existing positions are going to be in\n * view initially.\n * @param state is the viewport grid state\n * @param syncService is the state sync service to use for getting existing state\n * @returns Set of states that can be applied to the state sync to remember\n * the current view state.\n */\nconst findViewportsByPosition = (\n state,\n { numRows, numCols },\n syncService: StateSyncService\n): Record<string, Record<string, unknown>> => {\n const { viewports } = state;\n const syncState = syncService.getState();\n const viewportsByPosition = { ...syncState.viewportsByPosition };\n const initialInDisplay = [];\n\n viewports.forEach(viewport => {\n if (viewport.positionId) {\n const storedViewport = {\n ...viewport,\n viewportOptions: { ...viewport.viewportOptions },\n };\n viewportsByPosition[viewport.positionId] = storedViewport;\n }\n });\n\n for (let row = 0; row < numRows; row++) {\n for (let col = 0; col < numCols; col++) {\n const positionId = `${col}-${row}`;\n const viewport = viewportsByPosition[positionId];\n if (viewport?.displaySetInstanceUIDs) {\n initialInDisplay.push(...viewport.displaySetInstanceUIDs);\n }\n }\n }\n\n // Store the initially displayed elements\n viewportsByPosition.initialInDisplay = initialInDisplay;\n\n return { viewportsByPosition };\n};\n\nexport default findViewportsByPosition;\n","import { ServicesManager, utils, Types } from '@ohif/core';\n\nimport { ContextMenuController, defaultContextMenu } from './CustomizableContextMenu';\nimport DicomTagBrowser from './DicomTagBrowser/DicomTagBrowser';\nimport reuseCachedLayouts from './utils/reuseCachedLayouts';\nimport findViewportsByPosition, {\n findOrCreateViewport as layoutFindOrCreate,\n} from './findViewportsByPosition';\n\nimport { ContextMenuProps } from './CustomizableContextMenu/types';\nimport { NavigateHistory } from './types/commandModuleTypes';\nimport { history } from '@ohif/app';\n\nconst { subscribeToNextViewportGridChange } = utils;\n\nexport type HangingProtocolParams = {\n protocolId?: string;\n stageIndex?: number;\n activeStudyUID?: string;\n stageId?: string;\n reset?: false;\n};\n\nexport type UpdateViewportDisplaySetParams = {\n direction: number;\n excludeNonImageModalities?: boolean;\n};\n\nconst commandsModule = ({\n servicesManager,\n commandsManager,\n}: Types.Extensions.ExtensionParams): Types.Extensions.CommandsModule => {\n const {\n customizationService,\n measurementService,\n hangingProtocolService,\n uiNotificationService,\n viewportGridService,\n displaySetService,\n stateSyncService,\n } = (servicesManager as ServicesManager).services;\n\n // Define a context menu controller for use with any context menus\n const contextMenuController = new ContextMenuController(servicesManager, commandsManager);\n\n const actions = {\n /**\n * Show the context menu.\n * @param options.menuId defines the menu name to lookup, from customizationService\n * @param options.defaultMenu contains the default menu set to use\n * @param options.element is the element to show the menu within\n * @param options.event is the event that caused the context menu\n * @param options.selectorProps is the set of selection properties to use\n */\n showContextMenu: (options: ContextMenuProps) => {\n const {\n menuCustomizationId,\n element,\n event,\n selectorProps,\n defaultPointsPosition = [],\n } = options;\n\n const optionsToUse = { ...options };\n\n if (menuCustomizationId) {\n Object.assign(\n optionsToUse,\n customizationService.get(menuCustomizationId, defaultContextMenu)\n );\n }\n\n // TODO - make the selectorProps richer by including the study metadata and display set.\n const { protocol, stage } = hangingProtocolService.getActiveProtocol();\n optionsToUse.selectorProps = {\n event,\n protocol,\n stage,\n ...selectorProps,\n };\n\n contextMenuController.showContextMenu(optionsToUse, element, defaultPointsPosition);\n },\n\n /** Close a context menu currently displayed */\n closeContextMenu: () => {\n contextMenuController.closeContextMenu();\n },\n\n displayNotification: ({ text, title, type }) => {\n uiNotificationService.show({\n title: title,\n message: text,\n type: type,\n });\n },\n clearMeasurements: () => {\n measurementService.clear();\n },\n\n /**\n * Sets the specified protocol\n * 1. Records any existing state using the viewport grid service\n * 2. Finds the destination state - this can be one of:\n * a. The specified protocol stage\n * b. An alternate (toggled or restored) protocol stage\n * c. A restored custom layout\n * 3. Finds the parameters for the specified state\n * a. Gets the displaySetSelectorMap\n * b. Gets the map by position\n * c. Gets any toggle mapping to map position to/from current view\n * 4. If restore, then sets layout\n * a. Maps viewport position by currently displayed viewport map id\n * b. Uses toggle information to map display set id\n * 5. Else applies the hanging protocol\n * a. HP Service is provided displaySetSelectorMap\n * b. HP Service will throw an exception if it isn't applicable\n * @param options - contains information on the HP to apply\n * @param options.activeStudyUID - the updated study to apply the HP to\n * @param options.protocolId - the protocol ID to change to\n * @param options.stageId - the stageId to apply\n * @param options.stageIndex - the index of the stage to go to.\n * @param options.reset - flag to indicate if the HP should be reset to its original and not restored to a previous state\n */\n setHangingProtocol: ({\n activeStudyUID = '',\n protocolId,\n stageId,\n stageIndex,\n reset = false,\n }: HangingProtocolParams): boolean => {\n try {\n // Stores in the state the display set selector id to displaySetUID mapping\n // Pass in viewportId for the active viewport. This item will get set as\n // the activeViewportId\n const state = viewportGridService.getState();\n const hpInfo = hangingProtocolService.getState();\n const stateSyncReduce = reuseCachedLayouts(state, hangingProtocolService, stateSyncService);\n const { hangingProtocolStageIndexMap, viewportGridStore, displaySetSelectorMap } =\n stateSyncReduce;\n\n if (!protocolId) {\n // Reuse the previous protocol id, and optionally stage\n protocolId = hpInfo.protocolId;\n if (stageId === undefined && stageIndex === undefined) {\n stageIndex = hpInfo.stageIndex;\n }\n } else if (stageIndex === undefined && stageId === undefined) {\n // Re-set the same stage as was previously used\n const hangingId = `${activeStudyUID || hpInfo.activeStudyUID}:${protocolId}`;\n stageIndex = hangingProtocolStageIndexMap[hangingId]?.stageIndex;\n }\n\n const useStageIdx =\n stageIndex ??\n hangingProtocolService.getStageIndex(protocolId, {\n stageId,\n stageIndex,\n });\n\n if (activeStudyUID) {\n hangingProtocolService.setActiveStudyUID(activeStudyUID);\n }\n\n const storedHanging = `${hangingProtocolService.getState().activeStudyUID}:${protocolId}:${\n useStageIdx || 0\n }`;\n\n const restoreProtocol = !reset && viewportGridStore[storedHanging];\n\n if (\n protocolId === hpInfo.protocolId &&\n useStageIdx === hpInfo.stageIndex &&\n !activeStudyUID\n ) {\n // Clear the HP setting to reset them\n hangingProtocolService.setProtocol(protocolId, {\n stageId,\n stageIndex: useStageIdx,\n });\n } else {\n hangingProtocolService.setProtocol(protocolId, {\n displaySetSelectorMap,\n stageId,\n stageIndex: useStageIdx,\n restoreProtocol,\n });\n if (restoreProtocol) {\n viewportGridService.set(viewportGridStore[storedHanging]);\n }\n }\n // Do this after successfully applying the update\n // Note, don't store the active display set - it is only needed while\n // changing display sets. This causes jump to measurement to fail on\n // multi-study display.\n delete displaySetSelectorMap[\n `${activeStudyUID || hpInfo.activeStudyUID}:activeDisplaySet:0`\n ];\n stateSyncService.store(stateSyncReduce);\n return true;\n } catch (e) {\n console.error(e);\n uiNotificationService.show({\n title: 'Apply Hanging Protocol',\n message: 'The hanging protocol could not be applied.',\n type: 'error',\n duration: 3000,\n });\n return false;\n }\n },\n\n toggleHangingProtocol: ({ protocolId, stageIndex }: HangingProtocolParams): boolean => {\n const {\n protocol,\n stageIndex: desiredStageIndex,\n activeStudy,\n } = hangingProtocolService.getActiveProtocol();\n const { toggleHangingProtocol } = stateSyncService.getState();\n const storedHanging = `${activeStudy.StudyInstanceUID}:${protocolId}:${stageIndex | 0}`;\n if (\n protocol.id === protocolId &&\n (stageIndex === undefined || stageIndex === desiredStageIndex)\n ) {\n // Toggling off - restore to previous state\n const previousState = toggleHangingProtocol[storedHanging] || {\n protocolId: 'default',\n };\n return actions.setHangingProtocol(previousState);\n } else {\n stateSyncService.store({\n toggleHangingProtocol: {\n ...toggleHangingProtocol,\n [storedHanging]: {\n protocolId: protocol.id,\n stageIndex: desiredStageIndex,\n },\n },\n });\n return actions.setHangingProtocol({\n protocolId,\n stageIndex,\n reset: true,\n });\n }\n },\n\n deltaStage: ({ direction }) => {\n const { protocolId, stageIndex: oldStageIndex } = hangingProtocolService.getState();\n const { protocol } = hangingProtocolService.getActiveProtocol();\n for (\n let stageIndex = oldStageIndex + direction;\n stageIndex >= 0 && stageIndex < protocol.stages.length;\n stageIndex += direction\n ) {\n if (protocol.stages[stageIndex].status !== 'disabled') {\n return actions.setHangingProtocol({\n protocolId,\n stageIndex,\n });\n }\n }\n uiNotificationService.show({\n title: 'Change Stage',\n message: 'The hanging protocol has no more applicable stages',\n type: 'info',\n duration: 3000,\n });\n },\n\n /**\n * Changes the viewport grid layout in terms of the MxN layout.\n */\n setViewportGridLayout: ({ numRows, numCols, isHangingProtocolLayout = false }) => {\n const { protocol } = hangingProtocolService.getActiveProtocol();\n const onLayoutChange = protocol.callbacks?.onLayoutChange;\n if (commandsManager.run(onLayoutChange, { numRows, numCols }) === false) {\n console.log('setViewportGridLayout running', onLayoutChange, numRows, numCols);\n // Don't apply the layout if the run command returns false\n return;\n }\n\n const completeLayout = () => {\n const state = viewportGridService.getState();\n const stateReduce = findViewportsByPosition(state, { numRows, numCols }, stateSyncService);\n const findOrCreateViewport = layoutFindOrCreate.bind(\n null,\n hangingProtocolService,\n stateReduce.viewportsByPosition\n );\n\n viewportGridService.setLayout({\n numRows,\n numCols,\n findOrCreateViewport,\n isHangingProtocolLayout,\n });\n stateSyncService.store(stateReduce);\n };\n // Need to finish any work in the callback\n window.setTimeout(completeLayout, 0);\n },\n\n toggleOneUp() {\n const viewportGridState = viewportGridService.getState();\n const { activeViewportId, viewports, layout } = viewportGridState;\n const { displaySetInstanceUIDs, displaySetOptions, viewportOptions } =\n viewports.get(activeViewportId);\n\n if (layout.numCols === 1 && layout.numRows === 1) {\n // The viewer is in one-up. Check if there is a state to restore/toggle back to.\n const { toggleOneUpViewportGridStore } = stateSyncService.getState();\n\n if (!toggleOneUpViewportGridStore.layout) {\n return;\n }\n // There is a state to toggle back to. The viewport that was\n // originally toggled to one up was the former active viewport.\n const viewportIdToUpdate = toggleOneUpViewportGridStore.activeViewportId;\n\n // We are restoring the previous layout but taking into the account that\n // the current one up viewport might have a new displaySet dragged and dropped on it.\n // updatedViewportsViaHP below contains the viewports applicable to the HP that existed\n // prior to the toggle to one-up - including the updated viewports if a display\n // set swap were to have occurred.\n const updatedViewportsViaHP =\n displaySetInstanceUIDs.length > 1\n ? []\n : displaySetInstanceUIDs\n .map(displaySetInstanceUID =>\n hangingProtocolService.getViewportsRequireUpdate(\n viewportIdToUpdate,\n displaySetInstanceUID\n )\n )\n .flat();\n\n // findOrCreateViewport returns either one of the updatedViewportsViaHP\n // returned from the HP service OR if there is not one from the HP service then\n // simply returns what was in the previous state for a given position in the layout.\n const findOrCreateViewport = (position: number, positionId: string) => {\n // Find the viewport for the given position prior to the toggle to one-up.\n const preOneUpViewport = Array.from(toggleOneUpViewportGridStore.viewports.values()).find(\n viewport => viewport.positionId === positionId\n );\n\n // Use the viewport id from before the toggle to one-up to find any updates to the viewport.\n const viewport = updatedViewportsViaHP.find(\n viewport => viewport.viewportId === preOneUpViewport.viewportId\n );\n\n return viewport\n ? // Use the applicable viewport from the HP updated viewports\n { viewportOptions, displaySetOptions, ...viewport }\n : // Use the previous viewport for the given position\n preOneUpViewport;\n };\n\n const layoutOptions = viewportGridService.getLayoutOptionsFromState(\n toggleOneUpViewportGridStore\n );\n\n // Restore the previous layout including the active viewport.\n viewportGridService.setLayout({\n numRows: toggleOneUpViewportGridStore.layout.numRows,\n numCols: toggleOneUpViewportGridStore.layout.numCols,\n activeViewportId: viewportIdToUpdate,\n layoutOptions,\n findOrCreateViewport,\n isHangingProtocolLayout: true,\n });\n } else {\n // We are not in one-up, so toggle to one up.\n\n // Store the current viewport grid state so we can toggle it back later.\n stateSyncService.store({\n toggleOneUpViewportGridStore: viewportGridState,\n });\n\n // This findOrCreateViewport only return one viewport - the active\n // one being toggled to one up.\n const findOrCreateViewport = () => {\n return {\n displaySetInstanceUIDs,\n displaySetOptions,\n viewportOptions,\n };\n };\n\n // Set the layout to be 1x1/one-up.\n viewportGridService.setLayout({\n numRows: 1,\n numCols: 1,\n findOrCreateViewport,\n isHangingProtocolLayout: true,\n });\n\n // Subscribe to ANY (i.e. manual and hanging protocol) layout changes so that\n // any grid layout state to toggle to from one up is cleared. This is performed on\n // a timeout to avoid clearing the state for the actual to one up change.\n // Whenever the next layout change event is fired, the subscriptions are unsubscribed.\n const clearToggleOneUpViewportGridStore = () => {\n const toggleOneUpViewportGridStore = {};\n stateSyncService.store({\n toggleOneUpViewportGridStore,\n });\n };\n\n subscribeToNextViewportGridChange(viewportGridService, clearToggleOneUpViewportGridStore);\n }\n },\n\n /**\n * Exposes the browser history navigation used by OHIF. This command can be used to either replace or\n * push a new entry into the browser history. For example, the following will replace the current\n * browser history entry with the specified relative URL which changes the study displayed to the\n * study with study instance UID 1.2.3. Note that as a result of using `options.replace = true`, the\n * page prior to invoking this command cannot be returned to via the browser back button.\n *\n * navigateHistory({\n * to: 'viewer?StudyInstanceUIDs=1.2.3',\n * options: { replace: true },\n * });\n *\n * @param historyArgs - arguments for the history function;\n * the `to` property is the URL;\n * the `options.replace` is a boolean indicating if the current browser history entry\n * should be replaced or a new entry pushed onto the history (stack); the default value\n * for `replace` is false\n */\n navigateHistory(historyArgs: NavigateHistory) {\n history.navigate(historyArgs.to, historyArgs.options);\n },\n\n openDICOMTagViewer() {\n const { activeViewportId, viewports } = viewportGridService.getState();\n const activeViewportSpecificData = viewports.get(activeViewportId);\n const { displaySetInstanceUIDs } = activeViewportSpecificData;\n\n const displaySets = displaySetService.activeDisplaySets;\n const { UIModalService } = servicesManager.services;\n\n const displaySetInstanceUID = displaySetInstanceUIDs[0];\n UIModalService.show({\n content: DicomTagBrowser,\n contentProps: {\n displaySets,\n displaySetInstanceUID,\n onClose: UIModalService.hide,\n },\n containerDimensions: 'max-w-4xl max-h-4xl',\n title: 'DICOM Tag Browser',\n });\n },\n\n /**\n * Toggle viewport overlay (the information panel shown on the four corners\n * of the viewport)\n * @see ViewportOverlay and CustomizableViewportOverlay components\n */\n toggleOverlays: () => {\n const overlays = document.getElementsByClassName('viewport-overlay');\n for (let i = 0; i < overlays.length; i++) {\n overlays.item(i).classList.toggle('hidden');\n }\n },\n\n scrollActiveThumbnailIntoView: () => {\n const { activeViewportId, viewports } = viewportGridService.getState();\n\n const activeViewport = viewports.get(activeViewportId);\n const activeDisplaySetInstanceUID = activeViewport.displaySetInstanceUIDs[0];\n\n const thumbnailList = document.querySelector('#ohif-thumbnail-list');\n\n if (!thumbnailList) {\n return;\n }\n\n const thumbnailListBounds = thumbnailList.getBoundingClientRect();\n\n const thumbnail = document.querySelector(`#thumbnail-${activeDisplaySetInstanceUID}`);\n\n if (!thumbnail) {\n return;\n }\n\n const thumbnailBounds = thumbnail.getBoundingClientRect();\n\n // This only handles a vertical thumbnail list.\n if (\n thumbnailBounds.top >= thumbnailListBounds.top &&\n thumbnailBounds.top <= thumbnailListBounds.bottom\n ) {\n return;\n }\n\n thumbnail.scrollIntoView({ behavior: 'smooth' });\n },\n\n updateViewportDisplaySet: ({\n direction,\n excludeNonImageModalities,\n }: UpdateViewportDisplaySetParams) => {\n const nonImageModalities = ['SR', 'SEG', 'SM', 'RTSTRUCT', 'RTPLAN', 'RTDOSE'];\n\n // Sort the display sets as per the hanging protocol service viewport/display set scoring system.\n // The thumbnail list uses the same sorting.\n const dsSortFn = hangingProtocolService.getDisplaySetSortFunction();\n const currentDisplaySets = [...displaySetService.activeDisplaySets];\n\n currentDisplaySets.sort(dsSortFn);\n\n const { activeViewportId, viewports } = viewportGridService.getState();\n\n const { displaySetInstanceUIDs } = viewports.get(activeViewportId);\n\n const activeDisplaySetIndex = currentDisplaySets.findIndex(displaySet =>\n displaySetInstanceUIDs.includes(displaySet.displaySetInstanceUID)\n );\n\n let displaySetIndexToShow: number;\n\n for (\n displaySetIndexToShow = activeDisplaySetIndex + direction;\n displaySetIndexToShow > -1 && displaySetIndexToShow < currentDisplaySets.length;\n displaySetIndexToShow += direction\n ) {\n if (\n !excludeNonImageModalities ||\n !nonImageModalities.includes(currentDisplaySets[displaySetIndexToShow].Modality)\n ) {\n break;\n }\n }\n\n if (displaySetIndexToShow < 0 || displaySetIndexToShow >= currentDisplaySets.length) {\n return;\n }\n\n const { displaySetInstanceUID } = currentDisplaySets[displaySetIndexToShow];\n\n let updatedViewports = [];\n\n try {\n updatedViewports = hangingProtocolService.getViewportsRequireUpdate(\n activeViewportId,\n displaySetInstanceUID\n );\n } catch (error) {\n console.warn(error);\n uiNotificationService.show({\n title: 'Navigate Viewport Display Set',\n message:\n 'The requested display sets could not be added to the viewport due to a mismatch in the Hanging Protocol rules.',\n type: 'info',\n duration: 3000,\n });\n }\n\n viewportGridService.setDisplaySetsForViewports(updatedViewports);\n\n setTimeout(() => actions.scrollActiveThumbnailIntoView(), 0);\n },\n };\n\n const definitions = {\n showContextMenu: {\n commandFn: actions.showContextMenu,\n },\n closeContextMenu: {\n commandFn: actions.closeContextMenu,\n },\n clearMeasurements: {\n commandFn: actions.clearMeasurements,\n },\n displayNotification: {\n commandFn: actions.displayNotification,\n },\n setHangingProtocol: {\n commandFn: actions.setHangingProtocol,\n },\n toggleHangingProtocol: {\n commandFn: actions.toggleHangingProtocol,\n },\n navigateHistory: {\n commandFn: actions.navigateHistory,\n },\n nextStage: {\n commandFn: actions.deltaStage,\n options: { direction: 1 },\n },\n previousStage: {\n commandFn: actions.deltaStage,\n options: { direction: -1 },\n },\n setViewportGridLayout: {\n commandFn: actions.setViewportGridLayout,\n },\n toggleOneUp: {\n commandFn: actions.toggleOneUp,\n },\n openDICOMTagViewer: {\n commandFn: actions.openDICOMTagViewer,\n },\n updateViewportDisplaySet: {\n commandFn: actions.updateViewportDisplaySet,\n },\n };\n\n return {\n actions,\n definitions,\n defaultContext: 'DEFAULT',\n };\n};\n\nexport default commandsModule;\n","import { Types } from '@ohif/core';\n\n/**\n * This hanging protocol can be activated on the primary mode by directly\n * referencing it in a URL or by directly including it within a mode, e.g.:\n * `&hangingProtocolId=@ohif/mnGrid` added to the viewer URL\n * It is not included in the viewer mode by default.\n */\nconst hpMN: Types.HangingProtocol.Protocol = {\n id: '@ohif/mnGrid',\n description: 'Has various hanging protocol grid layouts',\n name: '2x2',\n protocolMatchingRules: [\n {\n id: 'OneOrMoreSeries',\n weight: 25,\n attribute: 'numberOfDisplaySetsWithImages',\n constraint: {\n greaterThan: 0,\n },\n },\n ],\n toolGroupIds: ['default'],\n displaySetSelectors: {\n defaultDisplaySetId: {\n seriesMatchingRules: [\n {\n attribute: 'numImageFrames',\n constraint: {\n greaterThan: { value: 0 },\n },\n required: true,\n },\n // This display set will select the specified items by preference\n // It has no affect if nothing is specified in the URL.\n {\n attribute: 'isDisplaySetFromUrl',\n weight: 10,\n constraint: {\n equals: true,\n },\n },\n ],\n },\n },\n defaultViewport: {\n viewportOptions: {\n viewportType: 'stack',\n toolGroupId: 'default',\n allowUnmatchedView: true,\n },\n displaySets: [\n {\n id: 'defaultDisplaySetId',\n matchedDisplaySetsIndex: -1,\n },\n ],\n },\n stages: [\n {\n id: '2x2',\n stageActivation: {\n enabled: {\n minViewportsMatched: 4,\n },\n },\n viewportStructure: {\n layoutType: 'grid',\n properties: {\n rows: 2,\n columns: 2,\n },\n },\n viewports: [\n {\n viewportOptions: {\n toolGroupId: 'default',\n allowUnmatchedView: true,\n },\n displaySets: [\n {\n id: 'defaultDisplaySetId',\n },\n ],\n },\n {\n viewportOptions: {\n toolGroupId: 'default',\n allowUnmatchedView: true,\n },\n displaySets: [\n {\n matchedDisplaySetsIndex: 1,\n id: 'defaultDisplaySetId',\n },\n ],\n },\n {\n viewportOptions: {\n toolGroupId: 'default',\n allowUnmatchedView: true,\n },\n displaySets: [\n {\n matchedDisplaySetsIndex: 2,\n id: 'defaultDisplaySetId',\n },\n ],\n },\n {\n viewportOptions: {\n toolGroupId: 'default',\n allowUnmatchedView: true,\n },\n displaySets: [\n {\n matchedDisplaySetsIndex: 3,\n id: 'defaultDisplaySetId',\n },\n ],\n },\n ],\n },\n\n // 3x1 stage\n {\n id: '3x1',\n // Obsolete settings:\n requiredViewports: 1,\n preferredViewports: 3,\n // New equivalent:\n stageActivation: {\n enabled: {\n minViewportsMatched: 3,\n },\n },\n viewportStructure: {\n layoutType: 'grid',\n properties: {\n rows: 1,\n columns: 3,\n },\n },\n viewports: [\n {\n viewportOptions: {\n toolGroupId: 'default',\n allowUnmatchedView: true,\n },\n displaySets: [\n {\n id: 'defaultDisplaySetId',\n },\n ],\n },\n {\n viewportOptions: {\n toolGroupId: 'default',\n allowUnmatchedView: true,\n },\n displaySets: [\n {\n id: 'defaultDisplaySetId',\n matchedDisplaySetsIndex: 1,\n },\n ],\n },\n {\n viewportOptions: {\n toolGroupId: 'default',\n allowUnmatchedView: true,\n },\n displaySets: [\n {\n id: 'defaultDisplaySetId',\n matchedDisplaySetsIndex: 2,\n },\n ],\n },\n ],\n },\n\n // A 2x1 stage\n {\n id: '2x1',\n requiredViewports: 1,\n preferredViewports: 2,\n stageActivation: {\n enabled: {\n minViewportsMatched: 2,\n },\n },\n viewportStructure: {\n layoutType: 'grid',\n properties: {\n rows: 1,\n columns: 2,\n },\n },\n viewports: [\n {\n viewportOptions: {\n toolGroupId: 'default',\n allowUnmatchedView: true,\n },\n displaySets: [\n {\n id: 'defaultDisplaySetId',\n },\n ],\n },\n {\n viewportOptions: {\n toolGroupId: 'default',\n allowUnmatchedView: true,\n },\n displaySets: [\n {\n matchedDisplaySetsIndex: 1,\n id: 'defaultDisplaySetId',\n },\n ],\n },\n ],\n },\n\n // A 1x1 stage - should be automatically activated if there is only 1 viewable instance\n {\n id: '1x1',\n requiredViewports: 1,\n preferredViewports: 1,\n stageActivation: {\n enabled: {\n minViewportsMatched: 1,\n },\n },\n viewportStructure: {\n layoutType: 'grid',\n properties: {\n rows: 1,\n columns: 1,\n },\n },\n viewports: [\n {\n viewportOptions: {\n toolGroupId: 'default',\n allowUnmatchedView: true,\n },\n displaySets: [\n {\n id: 'defaultDisplaySetId',\n },\n ],\n },\n ],\n },\n ],\n numberOfPriorsReferenced: -1,\n};\n\nexport default hpMN;\n","import { Types } from '@ohif/core';\n\nconst defaultDisplaySetSelector = {\n studyMatchingRules: [\n {\n // The priorInstance is a study counter that indicates what position this study is in\n // and the value comes from the options parameter.\n attribute: 'studyInstanceUIDsIndex',\n from: 'options',\n required: true,\n constraint: {\n equals: { value: 0 },\n },\n },\n ],\n seriesMatchingRules: [\n {\n attribute: 'numImageFrames',\n constraint: {\n greaterThan: { value: 0 },\n },\n },\n // This display set will select the specified items by preference\n // It has no affect if nothing is specified in the URL.\n {\n attribute: 'isDisplaySetFromUrl',\n weight: 10,\n constraint: {\n equals: true,\n },\n },\n ],\n};\n\nconst priorDisplaySetSelector = {\n studyMatchingRules: [\n {\n // The priorInstance is a study counter that indicates what position this study is in\n // and the value comes from the options parameter.\n attribute: 'studyInstanceUIDsIndex',\n from: 'options',\n required: true,\n constraint: {\n equals: { value: 1 },\n },\n },\n ],\n seriesMatchingRules: [\n {\n attribute: 'numImageFrames',\n constraint: {\n greaterThan: { value: 0 },\n },\n },\n // This display set will select the specified items by preference\n // It has no affect if nothing is specified in the URL.\n {\n attribute: 'isDisplaySetFromUrl',\n weight: 10,\n constraint: {\n equals: true,\n },\n },\n ],\n};\n\nconst currentDisplaySet = {\n id: 'defaultDisplaySetId',\n};\n\nconst priorDisplaySet = {\n id: 'priorDisplaySetId',\n};\n\nconst currentViewport0 = {\n viewportOptions: {\n toolGroupId: 'default',\n allowUnmatchedView: true,\n },\n displaySets: [currentDisplaySet],\n};\n\nconst currentViewport1 = {\n ...currentViewport0,\n displaySets: [\n {\n ...currentDisplaySet,\n matchedDisplaySetsIndex: 1,\n },\n ],\n};\n\nconst priorViewport0 = {\n ...currentViewport0,\n displaySets: [priorDisplaySet],\n};\n\nconst priorViewport1 = {\n ...priorViewport0,\n displaySets: [\n {\n ...priorDisplaySet,\n matchedDisplaySetsIndex: 1,\n },\n ],\n};\n\n/**\n * This hanging protocol can be activated on the primary mode by directly\n * referencing it in a URL or by directly including it within a mode, e.g.:\n * `&hangingProtocolId=@ohif/mnGrid` added to the viewer URL\n * It is not included in the viewer mode by default.\n */\nconst hpMNCompare: Types.HangingProtocol.Protocol = {\n id: '@ohif/hpCompare',\n description: 'Compare two studies in various layouts',\n name: 'Compare Two Studies',\n numberOfPriorsReferenced: 1,\n protocolMatchingRules: [\n {\n id: 'Two Studies',\n weight: 1000,\n attribute: 'StudyInstanceUID',\n // The 'from' attribute says where to get the 'attribute' value from. In this case\n // prior means the second study in the study list.\n from: 'prior',\n required: true,\n constraint: {\n notNull: true,\n },\n },\n ],\n toolGroupIds: ['default'],\n displaySetSelectors: {\n defaultDisplaySetId: defaultDisplaySetSelector,\n priorDisplaySetId: priorDisplaySetSelector,\n },\n defaultViewport: {\n viewportOptions: {\n viewportType: 'stack',\n toolGroupId: 'default',\n allowUnmatchedView: true,\n },\n displaySets: [\n {\n id: 'defaultDisplaySetId',\n matchedDisplaySetsIndex: -1,\n },\n ],\n },\n stages: [\n {\n name: '2x2',\n stageActivation: {\n enabled: {\n minViewportsMatched: 4,\n },\n },\n viewportStructure: {\n layoutType: 'grid',\n properties: {\n rows: 2,\n columns: 2,\n },\n },\n viewports: [currentViewport0, priorViewport0, currentViewport1, priorViewport1],\n },\n\n {\n name: '2x1',\n stageActivation: {\n enabled: {\n minViewportsMatched: 2,\n },\n },\n viewportStructure: {\n layoutType: 'grid',\n properties: {\n rows: 1,\n columns: 2,\n },\n },\n viewports: [currentViewport0, priorViewport0],\n },\n ],\n};\n\nexport default hpMNCompare;\n","import hpMNGrid from './hpMNGrid';\nimport hpMNCompare from './hpCompare';\n\nconst defaultProtocol = {\n id: 'default',\n locked: true,\n // Don't store this hanging protocol as it applies to the currently active\n // display set by default\n // cacheId: null,\n name: 'Default',\n createdDate: '2021-02-23T19:22:08.894Z',\n modifiedDate: '2023-04-01',\n availableTo: {},\n editableBy: {},\n protocolMatchingRules: [],\n toolGroupIds: ['default'],\n hpInitiationCriteria: { minSeriesLoaded: 1 },\n // -1 would be used to indicate active only, whereas other values are\n // the number of required priors referenced - so 0 means active with\n // 0 or more priors.\n numberOfPriorsReferenced: 0,\n // Default viewport is used to define the viewport when\n // additional viewports are added using the layout tool\n defaultViewport: {\n viewportOptions: {\n viewportType: 'stack',\n toolGroupId: 'default',\n allowUnmatchedView: true,\n },\n displaySets: [\n {\n id: 'defaultDisplaySetId',\n matchedDisplaySetsIndex: -1,\n },\n ],\n },\n displaySetSelectors: {\n defaultDisplaySetId: {\n // Matches displaysets, NOT series\n seriesMatchingRules: [\n // Try to match series with images by default, to prevent weird display\n // on SEG/SR containing studies\n {\n attribute: 'numImageFrames',\n constraint: {\n greaterThan: { value: 0 },\n },\n },\n // This display set will select the specified items by preference\n // It has no affect if nothing is specified in the URL.\n {\n attribute: 'isDisplaySetFromUrl',\n weight: 10,\n constraint: {\n equals: true,\n },\n },\n ],\n // Can be used to select matching studies\n // studyMatchingRules: [],\n },\n },\n stages: [\n {\n name: 'default',\n viewportStructure: {\n layoutType: 'grid',\n properties: {\n rows: 1,\n columns: 1,\n },\n },\n viewports: [\n {\n viewportOptions: {\n viewportType: 'stack',\n viewportId: 'default',\n toolGroupId: 'default',\n // This will specify the initial image options index if it matches in the URL\n // and will otherwise not specify anything.\n initialImageOptions: {\n custom: 'sopInstanceLocation',\n },\n // Other options for initialImageOptions, which can be included in the default\n // custom attribute, or can be provided directly.\n // index: 180,\n // preset: 'middle', // 'first', 'last', 'middle'\n // },\n },\n displaySets: [\n {\n id: 'defaultDisplaySetId',\n },\n ],\n },\n ],\n createdDate: '2021-02-23T18:32:42.850Z',\n },\n ],\n};\n\nfunction getHangingProtocolModule() {\n return [\n {\n name: defaultProtocol.id,\n protocol: defaultProtocol,\n },\n // Create a MxN hanging protocol available by default\n {\n name: hpMNGrid.id,\n protocol: hpMNGrid,\n },\n // Create a MxN comparison hanging protocol available by default\n {\n name: hpMNCompare.id,\n protocol: hpMNCompare,\n },\n ];\n}\n\nexport default getHangingProtocolModule;\n","import React from 'react';\nimport classnames from 'classnames';\nimport { useNavigate } from 'react-router-dom';\nimport { useAppConfig } from '@state';\n\nimport { Button, ButtonEnums } from '@ohif/ui';\n\nfunction DataSourceSelector() {\n const [appConfig] = useAppConfig();\n const navigate = useNavigate();\n\n // This is frowned upon, but the raw config is needed here to provide\n // the selector\n const dsConfigs = appConfig.dataSources;\n\n return (\n <div style={{ width: '100%', height: '100%' }}>\n <div className=\"flex h-screen w-screen items-center justify-center \">\n <div className=\"bg-secondary-dark mx-auto space-y-2 rounded-lg py-8 px-8 drop-shadow-md\">\n <img\n className=\"mx-auto block h-14\"\n src=\"./ohif-logo.svg\"\n alt=\"OHIF\"\n />\n <div className=\"space-y-2 pt-4 text-center\">\n {dsConfigs\n .filter(it => it.sourceName !== 'dicomjson' && it.sourceName !== 'dicomlocal')\n .map(ds => (\n <div key={ds.sourceName}>\n <h1 className=\"text-white\">\n {ds.configuration?.friendlyName || ds.friendlyName}\n </h1>\n <Button\n type={ButtonEnums.type.primary}\n className={classnames('ml-2')}\n onClick={() => {\n navigate({\n pathname: '/',\n search: `datasources=${ds.sourceName}`,\n });\n }}\n >\n {ds.sourceName}\n </Button>\n <br />\n </div>\n ))}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nexport default DataSourceSelector;\n","import classNames from 'classnames';\nimport React, { ReactElement, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Button, Icon, InputFilterText, LoadingIndicatorProgress } from '@ohif/ui';\nimport { Types } from '@ohif/core';\n\ntype ItemListComponentProps = {\n itemLabel: string;\n itemList: Array<Types.BaseDataSourceConfigurationAPIItem>;\n onItemClicked: (item: Types.BaseDataSourceConfigurationAPIItem) => void;\n};\n\nfunction ItemListComponent({\n itemLabel,\n itemList,\n onItemClicked,\n}: ItemListComponentProps): ReactElement {\n const { t } = useTranslation('DataSourceConfiguration');\n const [filterValue, setFilterValue] = useState('');\n\n useEffect(() => {\n setFilterValue('');\n }, [itemList]);\n\n return (\n <div className=\"flex min-h-[1px] grow flex-col gap-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"text-primary-light text-[20px]\">{t(`Select ${itemLabel}`)}</div>\n <InputFilterText\n className=\"max-w-[40%] grow\"\n value={filterValue}\n onDebounceChange={setFilterValue}\n placeholder={t(`Search ${itemLabel} list`)}\n ></InputFilterText>\n </div>\n <div className=\"relative flex min-h-[1px] grow flex-col bg-black text-[14px]\">\n {itemList == null ? (\n <LoadingIndicatorProgress className={'h-full w-full'} />\n ) : itemList.length === 0 ? (\n <div className=\"text-primary-light flex h-full flex-col items-center justify-center px-6 py-4\">\n <Icon\n name=\"magnifier\"\n className=\"mb-4\"\n />\n <span>{t(`No ${itemLabel} available`)}</span>\n </div>\n ) : (\n <>\n <div className=\"bg-secondary-dark px-3 py-1.5 text-white\">{t(itemLabel)}</div>\n <div className=\"ohif-scrollbar overflow-auto\">\n {itemList\n .filter(\n item =>\n !filterValue || item.name.toLowerCase().includes(filterValue.toLowerCase())\n )\n .map(item => {\n const border =\n 'rounded border-transparent border-b-secondary-light border-[1px] hover:border-primary-light';\n return (\n <div\n className={classNames(\n 'hover:text-primary-light hover:bg-primary-dark group mx-2 flex items-center justify-between px-6 py-2',\n border\n )}\n key={item.id}\n >\n <div>{item.name}</div>\n <Button\n onClick={() => onItemClicked(item)}\n className=\"invisible group-hover:visible\"\n endIcon={<Icon name=\"arrow-left\" />}\n >\n {t('Select')}\n </Button>\n </div>\n );\n })}\n </div>\n </>\n )}\n </div>\n </div>\n );\n}\n\nexport default ItemListComponent;\n","import classNames from 'classnames';\nimport React, { ReactElement, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Icon } from '@ohif/ui';\nimport { Types } from '@ohif/core';\nimport ItemListComponent from './ItemListComponent';\n\nconst NO_WRAP_ELLIPSIS_CLASS_NAMES = 'text-ellipsis whitespace-nowrap overflow-hidden';\n\ntype DataSourceConfigurationModalComponentProps = {\n configurationAPI: Types.BaseDataSourceConfigurationAPI;\n configuredItems: Array<Types.BaseDataSourceConfigurationAPIItem>;\n onHide: () => void;\n};\n\nfunction DataSourceConfigurationModalComponent({\n configurationAPI,\n configuredItems,\n onHide,\n}: DataSourceConfigurationModalComponentProps) {\n const { t } = useTranslation('DataSourceConfiguration');\n\n const [itemList, setItemList] = useState<Array<Types.BaseDataSourceConfigurationAPIItem>>();\n\n const [selectedItems, setSelectedItems] = useState(configuredItems);\n\n const [errorMessage, setErrorMessage] = useState<string>();\n\n const [itemLabels] = useState(configurationAPI.getItemLabels());\n\n // Determines whether to show the full/existing configuration for the data source.\n // A full or complete configuration is one where the data source (path) has the\n // maximum/required number of path items. Anything less is considered not complete and\n // the configuration starts from scratch (i.e. as if no items are configured at all).\n // TODO: consider configuration starting from a partial (i.e. non-empty) configuration\n const [showFullConfig, setShowFullConfig] = useState(\n itemLabels.length === configuredItems.length\n );\n\n /**\n * The index of the selected item that is considered current and for which\n * its sub-items should be displayed in the items list component. When the\n * full/existing configuration for a data source is to be shown, the current\n * selected item is the second to last in the `selectedItems` list.\n */\n const currentSelectedItemIndex = showFullConfig\n ? selectedItems.length - 2\n : selectedItems.length - 1;\n\n useEffect(() => {\n let shouldUpdate = true;\n\n setErrorMessage(null);\n\n // Clear out the former/old list while we fetch the next sub item list.\n setItemList(null);\n\n if (selectedItems.length === 0) {\n configurationAPI\n .initialize()\n .then(items => {\n if (shouldUpdate) {\n setItemList(items);\n }\n })\n .catch(error => setErrorMessage(error.message));\n } else if (!showFullConfig && selectedItems.length === itemLabels.length) {\n // The last item to configure the data source (path) has been selected.\n configurationAPI.setCurrentItem(selectedItems[selectedItems.length - 1]);\n // We can hide the modal dialog now.\n onHide();\n } else {\n configurationAPI\n .setCurrentItem(selectedItems[currentSelectedItemIndex])\n .then(items => {\n if (shouldUpdate) {\n setItemList(items);\n }\n })\n .catch(error => setErrorMessage(error.message));\n }\n\n return () => {\n shouldUpdate = false;\n };\n }, [\n selectedItems,\n configurationAPI,\n onHide,\n itemLabels,\n showFullConfig,\n currentSelectedItemIndex,\n ]);\n\n const getSelectedItemCursorClasses = itemIndex =>\n itemIndex !== itemLabels.length - 1 && itemIndex < selectedItems.length\n ? 'cursor-pointer'\n : 'cursor-auto';\n\n const getSelectedItemBackgroundClasses = itemIndex =>\n itemIndex < selectedItems.length\n ? classNames(\n 'bg-black/[.4]',\n itemIndex !== itemLabels.length - 1 ? 'hover:bg-transparent active:bg-secondary-dark' : ''\n )\n : 'bg-transparent';\n\n const getSelectedItemBorderClasses = itemIndex =>\n itemIndex === currentSelectedItemIndex + 1\n ? classNames('border-2', 'border-solid', 'border-primary-light')\n : itemIndex < selectedItems.length\n ? 'border border-solid border-primary-active hover:border-primary-light active:border-white'\n : 'border border-dashed border-secondary-light';\n\n const getSelectedItemTextClasses = itemIndex =>\n itemIndex <= selectedItems.length ? 'text-primary-light' : 'text-primary-active';\n\n const getErrorComponent = (): ReactElement => {\n return (\n <div className=\"flex min-h-[1px] grow flex-col gap-4\">\n <div className=\"text-primary-light text-[20px]\">\n {t(`Error fetching ${itemLabels[selectedItems.length]} list`)}\n </div>\n <div className=\"grow bg-black p-4 text-[14px]\">{errorMessage}</div>\n </div>\n );\n };\n\n const getSelectedItemsComponent = (): ReactElement => {\n return (\n <div className=\"flex gap-4\">\n {itemLabels.map((itemLabel, itemLabelIndex) => {\n return (\n <div\n key={itemLabel}\n className={classNames(\n 'flex min-w-[1px] shrink basis-[200px] flex-col gap-1 rounded-md p-3.5',\n getSelectedItemCursorClasses(itemLabelIndex),\n getSelectedItemBackgroundClasses(itemLabelIndex),\n getSelectedItemBorderClasses(itemLabelIndex),\n getSelectedItemTextClasses(itemLabelIndex)\n )}\n onClick={\n (showFullConfig && itemLabelIndex < currentSelectedItemIndex) ||\n itemLabelIndex <= currentSelectedItemIndex\n ? () => {\n setShowFullConfig(false);\n setSelectedItems(theList => theList.slice(0, itemLabelIndex));\n }\n : undefined\n }\n >\n <div className=\"text- flex items-center gap-2\">\n {itemLabelIndex < selectedItems.length ? (\n <Icon name=\"status-tracked\" />\n ) : (\n <Icon name=\"status-untracked\" />\n )}\n <div className={classNames(NO_WRAP_ELLIPSIS_CLASS_NAMES)}>{t(itemLabel)}</div>\n </div>\n {itemLabelIndex < selectedItems.length ? (\n <div className={classNames('text-[14px] text-white', NO_WRAP_ELLIPSIS_CLASS_NAMES)}>\n {selectedItems[itemLabelIndex].name}\n </div>\n ) : (\n <br></br>\n )}\n </div>\n );\n })}\n </div>\n );\n };\n\n return (\n <div className=\"flex h-[calc(100vh-300px)] select-none flex-col gap-4 pt-0.5\">\n {getSelectedItemsComponent()}\n <div className=\"h-0.5 w-full shrink-0 bg-black\"></div>\n {errorMessage ? (\n getErrorComponent()\n ) : (\n <ItemListComponent\n itemLabel={itemLabels[currentSelectedItemIndex + 1]}\n itemList={itemList}\n onItemClicked={item => {\n setShowFullConfig(false);\n setSelectedItems(theList => [...theList.slice(0, currentSelectedItemIndex + 1), item]);\n }}\n ></ItemListComponent>\n )}\n </div>\n );\n}\n\nexport default DataSourceConfigurationModalComponent;\n","import React, { ReactElement, useCallback, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Icon, useModal } from '@ohif/ui';\nimport { ExtensionManager, ServicesManager, Types } from '@ohif/core';\nimport DataSourceConfigurationModalComponent from './DataSourceConfigurationModalComponent';\n\ntype DataSourceConfigurationComponentProps = {\n servicesManager: ServicesManager;\n extensionManager: ExtensionManager;\n};\n\nfunction DataSourceConfigurationComponent({\n servicesManager,\n extensionManager,\n}: DataSourceConfigurationComponentProps): ReactElement {\n const { t } = useTranslation('DataSourceConfiguration');\n const { show, hide } = useModal();\n\n const { customizationService } = servicesManager.services;\n\n const [configurationAPI, setConfigurationAPI] = useState<Types.BaseDataSourceConfigurationAPI>();\n\n const [configuredItems, setConfiguredItems] =\n useState<Array<Types.BaseDataSourceConfigurationAPIItem>>();\n\n useEffect(() => {\n let shouldUpdate = true;\n\n const dataSourceChangedCallback = async () => {\n const activeDataSourceDef = extensionManager.getActiveDataSourceDefinition();\n\n if (!activeDataSourceDef.configuration.configurationAPI) {\n return;\n }\n\n const { factory: configurationAPIFactory } =\n customizationService.get(activeDataSourceDef.configuration.configurationAPI) ?? {};\n\n if (!configurationAPIFactory) {\n return;\n }\n\n const configAPI = configurationAPIFactory(activeDataSourceDef.sourceName);\n setConfigurationAPI(configAPI);\n\n // New configuration API means that the existing configured items must be cleared.\n setConfiguredItems(null);\n\n configAPI.getConfiguredItems().then(list => {\n if (shouldUpdate) {\n setConfiguredItems(list);\n }\n });\n };\n\n const sub = extensionManager.subscribe(\n extensionManager.EVENTS.ACTIVE_DATA_SOURCE_CHANGED,\n dataSourceChangedCallback\n );\n\n dataSourceChangedCallback();\n\n return () => {\n shouldUpdate = false;\n sub.unsubscribe();\n };\n }, []);\n\n const showConfigurationModal = useCallback(() => {\n show({\n content: DataSourceConfigurationModalComponent,\n title: t('Configure Data Source'),\n contentProps: {\n configurationAPI,\n configuredItems,\n onHide: hide,\n },\n });\n }, [configurationAPI, configuredItems]);\n\n useEffect(() => {\n if (!configurationAPI || !configuredItems) {\n return;\n }\n\n if (configuredItems.length !== configurationAPI.getItemLabels().length) {\n // Not the correct number of configured items, so show the modal to configure the data source.\n showConfigurationModal();\n }\n }, [configurationAPI, configuredItems, showConfigurationModal]);\n\n return configuredItems ? (\n <div className=\"text-aqua-pale flex items-center overflow-hidden\">\n <Icon\n name=\"settings\"\n className=\"mr-2.5 h-3.5 w-3.5 shrink-0 cursor-pointer\"\n onClick={showConfigurationModal}\n ></Icon>\n {configuredItems.map((item, itemIndex) => {\n return (\n <div\n key={itemIndex}\n className=\"flex overflow-hidden\"\n >\n <div\n key={itemIndex}\n className=\"overflow-hidden text-ellipsis whitespace-nowrap\"\n >\n {item.name}\n </div>\n {itemIndex !== configuredItems.length - 1 && <div className=\"px-2.5\">|</div>}\n </div>\n );\n })}\n </div>\n ) : (\n <></>\n );\n}\n\nexport default DataSourceConfigurationComponent;\n","import { ExtensionManager, Types } from '@ohif/core';\n\n/**\n * This file contains the implementations of BaseDataSourceConfigurationAPIItem\n * and BaseDataSourceConfigurationAPI for the Google cloud healthcare API. To\n * better understand this implementation and/or to implement custom implementations,\n * see the platform\\core\\src\\types\\DataSourceConfigurationAPI.ts and its JS doc\n * comments as a guide.\n */\n\n/**\n * The various Google Cloud Healthcare path item types.\n */\nenum ItemType {\n projects = 0,\n locations = 1,\n datasets = 2,\n dicomStores = 3,\n}\n\ninterface NamedItem {\n name: string;\n}\ninterface Project extends NamedItem {\n projectId: string;\n}\n\nconst initialUrl = 'https://cloudresourcemanager.googleapis.com/v1';\nconst baseHealthcareUrl = 'https://healthcare.googleapis.com/v1';\n\nclass GoogleCloudDataSourceConfigurationAPIItem\n implements Types.BaseDataSourceConfigurationAPIItem\n{\n id: string;\n name: string;\n url: string;\n itemType: ItemType;\n}\n\nclass GoogleCloudDataSourceConfigurationAPI implements Types.BaseDataSourceConfigurationAPI {\n private _extensionManager: ExtensionManager;\n private _fetchOptions: { method: string; headers: unknown };\n private _dataSourceName: string;\n\n constructor(dataSourceName, servicesManager, extensionManager) {\n this._dataSourceName = dataSourceName;\n this._extensionManager = extensionManager;\n const userAuthenticationService = servicesManager.services.userAuthenticationService;\n this._fetchOptions = {\n method: 'GET',\n headers: userAuthenticationService.getAuthorizationHeader(),\n };\n }\n\n getItemLabels = () => ['Project', 'Location', 'Data set', 'DICOM store'];\n\n async initialize(): Promise<Types.BaseDataSourceConfigurationAPIItem[]> {\n const url = `${initialUrl}/projects`;\n\n const projects = (await GoogleCloudDataSourceConfigurationAPI._doFetch(\n url,\n ItemType.projects,\n this._fetchOptions\n )) as Array<Project>;\n\n if (!projects?.length) {\n return [];\n }\n\n const projectItems = projects.map(project => {\n return {\n id: project.projectId,\n name: project.name,\n itemType: ItemType.projects,\n url: `${baseHealthcareUrl}/projects/${project.projectId}`,\n };\n });\n\n return projectItems;\n }\n\n async setCurrentItem(\n anItem: Types.BaseDataSourceConfigurationAPIItem\n ): Promise<Types.BaseDataSourceConfigurationAPIItem[]> {\n const googleCloudItem = anItem as GoogleCloudDataSourceConfigurationAPIItem;\n\n if (googleCloudItem.itemType === ItemType.dicomStores) {\n // Last configurable item, so update the data source configuration.\n const url = `${googleCloudItem.url}/dicomWeb`;\n const dataSourceDefCopy = JSON.parse(\n JSON.stringify(this._extensionManager.getDataSourceDefinition(this._dataSourceName))\n );\n dataSourceDefCopy.configuration = {\n ...dataSourceDefCopy.configuration,\n wadoUriRoot: url,\n qidoRoot: url,\n wadoRoot: url,\n };\n\n this._extensionManager.updateDataSourceConfiguration(\n dataSourceDefCopy.sourceName,\n dataSourceDefCopy.configuration\n );\n\n return [];\n }\n\n const subItemType = googleCloudItem.itemType + 1;\n const subItemField = `${ItemType[subItemType]}`;\n\n const url = `${googleCloudItem.url}/${subItemField}`;\n\n const fetchedSubItems = await GoogleCloudDataSourceConfigurationAPI._doFetch(\n url,\n subItemType,\n this._fetchOptions\n );\n\n if (!fetchedSubItems?.length) {\n return [];\n }\n\n const subItems = fetchedSubItems.map(subItem => {\n const nameSplit = subItem.name.split('/');\n return {\n id: subItem.name,\n name: nameSplit[nameSplit.length - 1],\n itemType: subItemType,\n url: `${baseHealthcareUrl}/${subItem.name}`,\n };\n });\n\n return subItems;\n }\n\n async getConfiguredItems(): Promise<Array<GoogleCloudDataSourceConfigurationAPIItem>> {\n const dataSourceDefinition = this._extensionManager.getDataSourceDefinition(\n this._dataSourceName\n );\n\n const url = dataSourceDefinition.configuration.wadoUriRoot;\n const projectsIndex = url.indexOf('projects');\n // Split the configured URL into (essentially) pairs (i.e. item type followed by item)\n // Explicitly: ['projects','aProject','locations','aLocation','datasets','aDataSet','dicomStores','aDicomStore']\n // Note that a partial configuration will have a subset of the above.\n const urlSplit = url.substring(projectsIndex).split('/');\n\n const configuredItems = [];\n\n for (\n let itemType = 0;\n // the number of configured items is either the max (4) or the number extracted from the url split\n itemType < 4 && (itemType + 1) * 2 < urlSplit.length;\n itemType += 1\n ) {\n if (itemType === ItemType.projects) {\n const projectId = urlSplit[1];\n const projectUrl = `${initialUrl}/projects/${projectId}`;\n const data = await GoogleCloudDataSourceConfigurationAPI._doFetch(\n projectUrl,\n ItemType.projects,\n this._fetchOptions\n );\n const project = data[0] as Project;\n configuredItems.push({\n id: project.projectId,\n name: project.name,\n itemType: itemType,\n url: `${baseHealthcareUrl}/projects/${project.projectId}`,\n });\n } else {\n const relativePath = urlSplit.slice(0, itemType * 2 + 2).join('/');\n configuredItems.push({\n id: relativePath,\n name: urlSplit[itemType * 2 + 1],\n itemType: itemType,\n url: `${baseHealthcareUrl}/${relativePath}`,\n });\n }\n }\n\n return configuredItems;\n }\n\n /**\n * Fetches an array of items the specified item type.\n * @param urlStr the fetch url\n * @param fetchItemType the type to fetch\n * @param fetchOptions the header options for the fetch (e.g. authorization header)\n * @param fetchSearchParams any search query params; currently only used for paging results\n * @returns an array of items of the specified type\n */\n private static async _doFetch(\n urlStr: string,\n fetchItemType: ItemType,\n fetchOptions = {},\n fetchSearchParams: Record<string, string> = {}\n ): Promise<Array<Project> | Array<NamedItem>> {\n try {\n const url = new URL(urlStr);\n url.search = new URLSearchParams(fetchSearchParams).toString();\n\n const response = await fetch(url, fetchOptions);\n const data = await response.json();\n if (response.status >= 200 && response.status < 300 && data != null) {\n if (data.nextPageToken != null) {\n fetchSearchParams.pageToken = data.nextPageToken;\n const subPageData = await this._doFetch(\n urlStr,\n fetchItemType,\n fetchOptions,\n fetchSearchParams\n );\n data[ItemType[fetchItemType]] = data[ItemType[fetchItemType]].concat(subPageData);\n }\n if (data[ItemType[fetchItemType]]) {\n return data[ItemType[fetchItemType]];\n } else if (data.name) {\n return [data];\n } else {\n return [];\n }\n } else {\n const message =\n data?.error?.message ||\n `Error returned from Google Cloud Healthcare: ${response.status} - ${response.statusText}`;\n throw new Error(message);\n }\n } catch (err) {\n const message = err?.message || 'Error occurred during fetch request.';\n throw new Error(message);\n }\n }\n}\n\nexport { GoogleCloudDataSourceConfigurationAPI };\n","import React from 'react';\nimport { LineChart } from '@ohif/ui';\n\nconst LineChartViewport = ({ displaySets }) => {\n const displaySet = displaySets[0];\n const { axis: chartAxis, series: chartSeries } = displaySet.instance.chartData;\n\n return (\n <LineChart\n showLegend={true}\n legendWidth={150}\n axis={{\n x: {\n label: chartAxis.x.label,\n indexRef: 0,\n type: 'x',\n range: {\n min: 0,\n },\n },\n y: {\n label: chartAxis.y.label,\n indexRef: 1,\n type: 'y',\n },\n }}\n series={chartSeries}\n />\n );\n};\n\nexport { LineChartViewport as default };\n","import OHIF from '@ohif/core';\n\nimport { InstanceMetadata, PhilipsPETPrivateGroup } from '@cornerstonejs/calculate-suv/src/types';\n\nconst metadataProvider = OHIF.classes.MetadataProvider;\n\nexport default function getPTImageIdInstanceMetadata(imageId: string): InstanceMetadata {\n const dicomMetaData = metadataProvider.get('instance', imageId);\n\n if (!dicomMetaData) {\n throw new Error('dicom metadata are required');\n }\n\n if (\n dicomMetaData.SeriesDate === undefined ||\n dicomMetaData.SeriesTime === undefined ||\n dicomMetaData.CorrectedImage === undefined ||\n dicomMetaData.Units === undefined ||\n !dicomMetaData.RadiopharmaceuticalInformationSequence ||\n dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadionuclideHalfLife === undefined ||\n dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadionuclideTotalDose === undefined ||\n dicomMetaData.DecayCorrection === undefined ||\n dicomMetaData.AcquisitionDate === undefined ||\n dicomMetaData.AcquisitionTime === undefined ||\n (dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadiopharmaceuticalStartDateTime ===\n undefined &&\n dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadiopharmaceuticalStartTime ===\n undefined)\n ) {\n throw new Error('required metadata are missing');\n }\n\n if (dicomMetaData.PatientWeight === undefined) {\n console.warn('PatientWeight missing from PT instance metadata');\n }\n\n const instanceMetadata: InstanceMetadata = {\n CorrectedImage: dicomMetaData.CorrectedImage,\n Units: dicomMetaData.Units,\n RadionuclideHalfLife:\n dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadionuclideHalfLife,\n RadionuclideTotalDose:\n dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadionuclideTotalDose,\n RadiopharmaceuticalStartDateTime:\n dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadiopharmaceuticalStartDateTime,\n RadiopharmaceuticalStartTime:\n dicomMetaData.RadiopharmaceuticalInformationSequence[0].RadiopharmaceuticalStartTime,\n DecayCorrection: dicomMetaData.DecayCorrection,\n PatientWeight: dicomMetaData.PatientWeight,\n SeriesDate: dicomMetaData.SeriesDate,\n SeriesTime: dicomMetaData.SeriesTime,\n AcquisitionDate: dicomMetaData.AcquisitionDate,\n AcquisitionTime: dicomMetaData.AcquisitionTime,\n };\n\n if (\n dicomMetaData['70531000'] ||\n dicomMetaData['70531000'] !== undefined ||\n dicomMetaData['70531009'] ||\n dicomMetaData['70531009'] !== undefined\n ) {\n const philipsPETPrivateGroup: PhilipsPETPrivateGroup = {\n SUVScaleFactor: dicomMetaData['70531000'],\n ActivityConcentrationScaleFactor: dicomMetaData['70531009'],\n };\n instanceMetadata.PhilipsPETPrivateGroup = philipsPETPrivateGroup;\n }\n\n if (dicomMetaData['0009100d'] && dicomMetaData['0009100d'] !== undefined) {\n instanceMetadata.GEPrivatePostInjectionDateTime = dicomMetaData['0009100d'];\n }\n\n if (dicomMetaData.FrameReferenceTime && dicomMetaData.FrameReferenceTime !== undefined) {\n instanceMetadata.FrameReferenceTime = dicomMetaData.FrameReferenceTime;\n }\n\n if (dicomMetaData.ActualFrameDuration && dicomMetaData.ActualFrameDuration !== undefined) {\n instanceMetadata.ActualFrameDuration = dicomMetaData.ActualFrameDuration;\n }\n\n if (dicomMetaData.PatientSex && dicomMetaData.PatientSex !== undefined) {\n instanceMetadata.PatientSex = dicomMetaData.PatientSex;\n }\n\n if (dicomMetaData.PatientSize && dicomMetaData.PatientSize !== undefined) {\n instanceMetadata.PatientSize = dicomMetaData.PatientSize;\n }\n\n return instanceMetadata;\n}\n\nfunction convertInterfaceTimeToString(time): string {\n const hours = `${time.hours || '00'}`.padStart(2, '0');\n const minutes = `${time.minutes || '00'}`.padStart(2, '0');\n const seconds = `${time.seconds || '00'}`.padStart(2, '0');\n\n const fractionalSeconds = `${time.fractionalSeconds || '000000'}`.padEnd(6, '0');\n\n const timeString = `${hours}${minutes}${seconds}.${fractionalSeconds}`;\n return timeString;\n}\n\nfunction convertInterfaceDateToString(date): string {\n const month = `${date.month}`.padStart(2, '0');\n const day = `${date.day}`.padStart(2, '0');\n const dateString = `${date.year}${month}${day}`;\n return dateString;\n}\n\nexport { getPTImageIdInstanceMetadata };\n","import { DicomMetadataStore, classes } from '@ohif/core';\nimport { calculateSUVScalingFactors } from '@cornerstonejs/calculate-suv';\n\nimport getPTImageIdInstanceMetadata from './getPTImageIdInstanceMetadata';\n\nconst metadataProvider = classes.MetadataProvider;\n\n/**\n *\n * @param {Object} servicesManager\n * @param {Object} configuration\n */\nexport default function init({ servicesManager, configuration = {}, commandsManager }): void {\n const { stateSyncService, toolbarService, cineService, viewportGridService } =\n servicesManager.services;\n\n toolbarService.registerEventForToolbarUpdate(cineService, [\n cineService.EVENTS.CINE_STATE_CHANGED,\n ]);\n // Add\n DicomMetadataStore.subscribe(DicomMetadataStore.EVENTS.INSTANCES_ADDED, handlePETImageMetadata);\n\n // If the metadata for PET has changed by the user (e.g. manually changing the PatientWeight)\n // we need to recalculate the SUV Scaling Factors\n DicomMetadataStore.subscribe(DicomMetadataStore.EVENTS.SERIES_UPDATED, handlePETImageMetadata);\n\n // viewportGridStore is a sync state which stores the entire\n // ViewportGridService getState, by the keys `<activeStudyUID>:<protocolId>:<stageIndex>`\n // Used to recover manual changes to the layout of a stage.\n stateSyncService.register('viewportGridStore', { clearOnModeExit: true });\n\n // uiStateStore is a sync state which stores the relevant\n // UI state for the viewer\n stateSyncService.register('uiStateStore', { clearOnModeExit: true });\n\n // displaySetSelectorMap stores a map from\n // `<activeStudyUID>:<displaySetSelectorId>:<matchOffset>` to\n // a displaySetInstanceUID, used to display named display sets in\n // specific spots within a hanging protocol and be able to remember what the\n // user did with those named spots between stages and protocols.\n stateSyncService.register('displaySetSelectorMap', { clearOnModeExit: true });\n\n // Stores a map from `<activeStudyUID>:${protocolId}` to the getHPInfo results\n // in order to recover the correct stage when returning to a Hanging Protocol.\n stateSyncService.register('hangingProtocolStageIndexMap', {\n clearOnModeExit: true,\n });\n\n // Stores a map from the to be applied hanging protocols `<activeStudyUID>:<protocolId>`\n // to the previously applied hanging protocolStageIndexMap key, in order to toggle\n // off the applied protocol and remember the old state.\n stateSyncService.register('toggleHangingProtocol', { clearOnModeExit: true });\n\n // Stores the viewports by `rows-cols` position so that when the layout\n // changes numRows and numCols, the viewports can be remembers and then replaced\n // afterwards.\n stateSyncService.register('viewportsByPosition', { clearOnModeExit: true });\n\n // Function to process and subscribe to events for a given set of commands and listeners\n const subscribeToEvents = listeners => {\n Object.entries(listeners).forEach(([event, commands]) => {\n const supportedEvents = [\n viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED,\n viewportGridService.EVENTS.VIEWPORTS_READY,\n ];\n\n if (supportedEvents.includes(event)) {\n viewportGridService.subscribe(event, eventData => {\n const viewportId = eventData?.viewportId ?? viewportGridService.getActiveViewportId();\n\n commandsManager.run(commands, { viewportId });\n });\n }\n });\n };\n\n toolbarService.subscribe(toolbarService.EVENTS.TOOL_BAR_MODIFIED, state => {\n const { buttons } = state;\n for (const [id, button] of Object.entries(buttons)) {\n const { groupId, items, listeners } = button.props || {};\n\n // Handle group items' listeners\n if (groupId && items) {\n items.forEach(item => {\n if (item.listeners) {\n subscribeToEvents(item.listeners);\n }\n });\n }\n\n // Handle button listeners\n if (listeners) {\n subscribeToEvents(listeners);\n }\n }\n });\n}\n\nconst handlePETImageMetadata = ({ SeriesInstanceUID, StudyInstanceUID }) => {\n const { instances } = DicomMetadataStore.getSeries(StudyInstanceUID, SeriesInstanceUID);\n\n if (!instances?.length) {\n return;\n }\n\n const modality = instances[0].Modality;\n\n if (!modality || modality !== 'PT') {\n return;\n }\n\n const imageIds = instances.map(instance => instance.imageId);\n const instanceMetadataArray = [];\n\n // try except block to prevent errors when the metadata is not correct\n try {\n imageIds.forEach(imageId => {\n const instanceMetadata = getPTImageIdInstanceMetadata(imageId);\n if (instanceMetadata) {\n instanceMetadataArray.push(instanceMetadata);\n }\n });\n\n if (!instanceMetadataArray.length) {\n return;\n }\n\n const suvScalingFactors = calculateSUVScalingFactors(instanceMetadataArray);\n instanceMetadataArray.forEach((instanceMetadata, index) => {\n metadataProvider.addCustomMetadata(\n imageIds[index],\n 'scalingModule',\n suvScalingFactors[index]\n );\n });\n } catch (error) {\n console.log(error);\n }\n};\n","import { Types } from '@ohif/core';\n\nimport getDataSourcesModule from './getDataSourcesModule.js';\nimport getLayoutTemplateModule from './getLayoutTemplateModule.js';\nimport getPanelModule from './getPanelModule';\nimport getSopClassHandlerModule from './getSopClassHandlerModule.js';\nimport getToolbarModule from './getToolbarModule';\nimport getCommandsModule from './commandsModule';\nimport getHangingProtocolModule from './getHangingProtocolModule';\nimport getStudiesForPatientByMRN from './Panels/getStudiesForPatientByMRN';\nimport getCustomizationModule from './getCustomizationModule';\nimport getViewportModule from './getViewportModule';\nimport { id } from './id.js';\nimport preRegistration from './init';\nimport { ContextMenuController, CustomizableContextMenuTypes } from './CustomizableContextMenu';\nimport * as dicomWebUtils from './DicomWebDataSource/utils';\nimport { createReportDialogPrompt } from './Panels';\nimport createReportAsync from './Actions/createReportAsync';\nimport StaticWadoClient from './DicomWebDataSource/utils/StaticWadoClient';\n\nconst defaultExtension: Types.Extensions.Extension = {\n /**\n * Only required property. Should be a unique value across all extensions.\n */\n id,\n preRegistration,\n getDataSourcesModule,\n getViewportModule,\n getLayoutTemplateModule,\n getPanelModule,\n getHangingProtocolModule,\n getSopClassHandlerModule,\n getToolbarModule,\n getCommandsModule,\n getUtilityModule({ servicesManager }) {\n return [\n {\n name: 'common',\n exports: {\n getStudiesForPatientByMRN,\n },\n },\n ];\n },\n\n getCustomizationModule,\n};\n\nexport default defaultExtension;\n\nexport {\n ContextMenuController,\n CustomizableContextMenuTypes,\n getStudiesForPatientByMRN,\n dicomWebUtils,\n createReportDialogPrompt,\n createReportAsync,\n StaticWadoClient,\n};\n","import { ServicesManager, CommandsManager, ExtensionManager } from '@ohif/core';\nimport LineChartViewport from './Components/LineChartViewport/index';\n\nconst getViewportModule = ({\n servicesManager,\n commandsManager,\n extensionManager,\n}: {\n servicesManager: ServicesManager;\n commandsManager: CommandsManager;\n extensionManager: ExtensionManager;\n}) => {\n return [\n {\n name: 'chartViewport',\n component: LineChartViewport,\n },\n ];\n};\n\nexport { getViewportModule as default };\n","import ViewerLayout from './ViewerLayout';\n/*\n- Define layout for the viewer in mode configuration.\n- Pass in the viewport types that can populate the viewer.\n- Init layout based on the displaySets and the objects.\n*/\n\nexport default function ({ servicesManager, extensionManager, commandsManager, hotkeysManager }) {\n function ViewerLayoutWithServices(props) {\n return ViewerLayout({\n servicesManager,\n extensionManager,\n commandsManager,\n hotkeysManager,\n ...props,\n });\n }\n\n return [\n // Layout Template Definition\n // TODO: this is weird naming\n {\n name: 'viewerLayout',\n id: 'viewerLayout',\n component: ViewerLayoutWithServices,\n },\n ];\n}\n","import ToolbarDivider from './Toolbar/ToolbarDivider';\nimport ToolbarLayoutSelectorWithServices from './Toolbar/ToolbarLayoutSelector';\nimport ToolbarSplitButtonWithServices from './Toolbar/ToolbarSplitButtonWithServices';\nimport ToolbarButtonGroupWithServices from './Toolbar/ToolbarButtonGroupWithServices';\nimport { ToolbarButton } from '@ohif/ui';\nimport ProgressDropdownWithService from './components/ProgressDropdownWithService';\n\nconst getClassName = isToggled => {\n return {\n className: isToggled\n ? '!text-primary-active'\n : '!text-common-bright hover:!bg-primary-dark hover:text-primary-light',\n };\n};\n\nexport default function getToolbarModule({ commandsManager, servicesManager }) {\n const { cineService } = servicesManager.services;\n return [\n {\n name: 'ohif.radioGroup',\n defaultComponent: ToolbarButton,\n },\n {\n name: 'ohif.divider',\n defaultComponent: ToolbarDivider,\n },\n {\n name: 'ohif.splitButton',\n defaultComponent: ToolbarSplitButtonWithServices,\n },\n {\n name: 'ohif.layoutSelector',\n defaultComponent: props =>\n ToolbarLayoutSelectorWithServices({ ...props, commandsManager, servicesManager }),\n },\n {\n name: 'ohif.buttonGroup',\n defaultComponent: ToolbarButtonGroupWithServices,\n },\n {\n name: 'ohif.progressDropdown',\n defaultComponent: ProgressDropdownWithService,\n },\n {\n name: 'evaluate.group.promoteToPrimary',\n evaluate: ({ viewportId, button, itemId }) => {\n const { items } = button.props;\n\n if (!itemId) {\n return {\n primary: button.props.primary,\n items,\n };\n }\n\n // other wise we can move the clicked tool to the primary button\n const clickedItemProps = items.find(item => item.id === itemId || item.itemId === itemId);\n\n return {\n primary: clickedItemProps,\n items,\n };\n },\n },\n {\n name: 'evaluate.cine',\n evaluate: () => {\n const isToggled = cineService.getState().isCineEnabled;\n return getClassName(isToggled);\n },\n },\n ];\n}\n","import { CustomizationService } from '@ohif/core';\nimport React from 'react';\nimport DataSourceSelector from './Panels/DataSourceSelector';\nimport ProgressDropdownWithService from './components/ProgressDropdownWithService';\nimport DataSourceConfigurationComponent from './Components/DataSourceConfigurationComponent';\nimport { GoogleCloudDataSourceConfigurationAPI } from './DataSourceConfigurationAPI/GoogleCloudDataSourceConfigurationAPI';\n\n/**\n *\n * Note: this is an example of how the customization module can be used\n * using the customization module. Below, we are adding a new custom route\n * to the application at the path /custom and rendering a custom component\n * Real world use cases of the having a custom route would be to add a\n * custom page for the user to view their profile, or to add a custom\n * page for login etc.\n */\nexport default function getCustomizationModule({ servicesManager, extensionManager }) {\n return [\n {\n name: 'helloPage',\n value: {\n id: 'customRoutes',\n routes: [\n {\n path: '/custom',\n children: () => <h1 style={{ color: 'white' }}>Hello Custom Route</h1>,\n },\n ],\n },\n },\n\n // Example customization to list a set of datasources\n {\n name: 'datasources',\n value: {\n id: 'customRoutes',\n routes: [\n {\n path: '/datasources',\n children: DataSourceSelector,\n },\n ],\n },\n },\n\n {\n name: 'default',\n value: [\n /**\n * Customization Component Type definition for overlay items.\n * Overlay items are texts (or other components) that will be displayed\n * on a Viewport Overlay, which contains the information panels on the\n * four corners of a viewport.\n *\n * @definition of a overlay item using this type\n * The value to be displayed is defined by\n * - setting DICOM image instance's property to this field,\n * - or defining contentF()\n *\n * {\n * id: string - unique id for the overlay item\n * customizationType: string - indicates customization type definition to this\n * label: string - Label, to be displayed for the item\n * title: string - Tooltip, for the item\n * color: string - Color of the text\n * condition: ({ instance }) => boolean - decides whether to display the overlay item or not\n * attribute: string - property name of the DICOM image instance\n * contentF: ({ instance, formatters }) => string | component,\n * }\n *\n * @example\n * {\n * id: 'PatientNameOverlay',\n * customizationType: 'ohif.overlayItem',\n * label: 'PN:',\n * title: 'Patient Name',\n * color: 'yellow',\n * condition: ({ instance }) => instance && instance.PatientName && instance.PatientName.Alphabetic,\n * attribute: 'PatientName',\n * contentF: ({ instance, formatters: { formatPN } }) => `${formatPN(instance.PatientName.Alphabetic)} ${(instance.PatientSex ? '(' + instance.PatientSex + ')' : '')}`,\n * },\n *\n * @see CustomizableViewportOverlay\n */\n {\n id: 'ohif.overlayItem',\n content: function (props) {\n if (this.condition && !this.condition(props)) {\n return null;\n }\n\n const { instance } = props;\n const value =\n instance && this.attribute\n ? instance[this.attribute]\n : this.contentF && typeof this.contentF === 'function'\n ? this.contentF(props)\n : null;\n if (!value) {\n return null;\n }\n\n return (\n <span\n className=\"overlay-item flex flex-row\"\n style={{ color: this.color || undefined }}\n title={this.title || ''}\n >\n {this.label && <span className=\"mr-1 shrink-0\">{this.label}</span>}\n <span className=\"font-light\">{value}</span>\n </span>\n );\n },\n },\n\n {\n id: 'ohif.contextMenu',\n\n /** Applies the customizationType to all the menu items.\n * This function clones the object and child objects to prevent\n * changes to the original customization object.\n */\n transform: function (customizationService: CustomizationService) {\n // Don't modify the children, as those are copied by reference\n const clonedObject = { ...this };\n clonedObject.menus = this.menus.map(menu => ({ ...menu }));\n\n for (const menu of clonedObject.menus) {\n const { items: originalItems } = menu;\n menu.items = [];\n for (const item of originalItems) {\n menu.items.push(customizationService.transform(item));\n }\n }\n return clonedObject;\n },\n },\n\n {\n // the generic GUI component to configure a data source using an instance of a BaseDataSourceConfigurationAPI\n id: 'ohif.dataSourceConfigurationComponent',\n component: DataSourceConfigurationComponent.bind(null, {\n servicesManager,\n extensionManager,\n }),\n },\n\n {\n // The factory for creating an instance of a BaseDataSourceConfigurationAPI for Google Cloud Healthcare\n id: 'ohif.dataSourceConfigurationAPI.google',\n factory: (dataSourceName: string) =>\n new GoogleCloudDataSourceConfigurationAPI(\n dataSourceName,\n servicesManager,\n extensionManager\n ),\n },\n\n {\n id: 'progressDropdownWithServiceComponent',\n component: ProgressDropdownWithService,\n },\n ],\n },\n ];\n}\n"],"names":["getString","getName","getModalities","DICOMWeb","processResults","qidoStudies","length","studies","forEach","qidoStudy","push","studyInstanceUid","date","time","accession","mrn","patientName","utils","formatPN","instances","Number","description","modalities","async","search","dicomWebClient","seriesInstanceUid","queryParameters","searchForStudies","undefined","queryParams","mapParams","params","options","commaSeparatedFields","join","supportsWildcard","withWildcard","value","parameters","PatientName","patientId","AccessionNumber","accessionNumber","StudyDescription","studyDescription","ModalitiesInStudy","modalitiesInStudy","limit","offset","fuzzymatching","supportsFuzzyMatching","includefield","startDate","endDate","StudyDate","today","Date","DD","String","getDate","padStart","MM","getMonth","todayStr","getFullYear","oldDateStr","studyUids","Array","isArray","replace","StudyInstanceUID","final","Object","keys","key","getImageId","instance","frame","config","thumbnail","url","renderingAttr","uri","baseWadoRsUri","SeriesInstanceUID","SOPInstanceUID","wadoRoot","buildInstanceWadoRsUri","buildInstanceFrameWadoRsUri","getWADORSImageId","wadouri","paramString","wadoUriRoot","buildInstanceWadoUrl","imageId","RetrieveMetadataLoader","constructor","client","studyInstanceUID","filters","sortCriteria","sortFunction","this","execLoad","preLoadData","preLoad","loadData","load","posLoad","runLoaders","loaders","result","loader","next","done","Error","configLoad","RetrieveMetadataLoaderSync","getOptions","seriesInstanceUID","getLoaders","retrieveSeriesMetadata","bind","retrieveStudyMetadata","includeField","DeferredPromise","metadata","processFunction","internalPromise","thenFunction","rejectFunction","setMetadata","setProcessFunction","func","getPromise","start","then","reject","RetrieveMetadataLoaderAsync","getPreLoaders","preLoaders","searchForSeries","naturalizeDataset","dcmjs","DicomMetaDictionary","naturalized","map","sortStudySeries","seriesAsyncLoader","seriesInstanceUIDList","freeze","hasNext","shift","promise","makeSeriesAsyncLoader","seriesMetadata","promises","enableStudyLazyLoad","retrieveMetadataLoader","SeriesInstanceUIDs","Promise","resolve","uid","seriesSpecificFilters","assign","RetrieveMetadata","all","results","aggregatedResult","concat","moduleName","StudyMetaDataPromises","Map","dicomWebConfig","promiseId","name","has","get","retrieveMetadataFiltered","data","set","deleteStudyMetadataPromise","delete","checkToken","token","dataOffset","endIndex","i","str","uint","Uint8Array","j","charCodeAt","stringToUint8Array","fixMultipart","arrayData","dashIndex","findIndexOfString","tokenIndex","header","fromCharCode","uint8ArrayToString","boundary","substr","findBoundary","split","slice","buffer","DICOMwebClient","api","anyDicomwebClient","_orig_buildMultipartAcceptHeaderFieldValue","_buildMultipartAcceptHeaderFieldValue","mediaTypes","acceptableTypes","mediaType","endsWith","StaticWadoClient","super","staticWado","retrieveBulkData","shouldFixMultipart","fixBulkdataMultipart","useOptions","retrieveInstanceFrames","searchResult","lowerParams","toLowerParams","filter","study","studyFilterKeys","filterItem","series","seriesFilterKeys","compareValues","desired","actual","find","item","actualItem","Alphabetic","indexOf","substring","compareDateRange","range","dash","end","sourceFilterMap","altKey","testValue","valueElem","vr","Value","entries","toLowerCase","studyinstanceuid","patientname","studydescription","studydate","modalitiesinstudy","accessionnumber","seriesinstanceuid","seriesnumber","modality","getDirectURL","singlepart","tag","defaultPath","defaultType","fetchPart","DirectRetrieveURL","InlineBinary","blob","b64toBlob","URL","createObjectURL","arr","Blob","type","console","warn","BulkDataURI","hasQuery","hasAccept","fixBulkDataURI","startsWith","origin","bulkDataURI","relativeResolution","DicomDict","denaturalizeDataset","ImplementationClassUID","ImplementationVersionName","EXPLICIT_VR_LITTLE_ENDIAN","metadataProvider","classes","MetadataProvider","createDicomWebApi","servicesManager","userAuthenticationService","customizationService","services","dicomWebConfigCopy","qidoConfig","wadoConfig","qidoDicomWebClient","wadoDicomWebClient","getAuthrorizationHeader","generateWadoHeader","implementation","initialize","query","onConfiguration","JSON","parse","stringify","xhrRequestHeaders","authHeaders","getAuthorizationHeader","Authorization","Accept","generateAcceptHeader","acceptHeader","requestTransferSyntaxUID","omitQuotationForMultipartRequest","qidoRoot","headers","errorInterceptor","errorHandler","getHTTPErrorHandler","origParams","mappedParams","qidoSearch","qidoSeries","seriesNumber","seriesDate","formatDate","numSeriesInstances","processSeriesResults","seriesInStudy","call","retrieve","directURL","multipart","val","madeInClient","returnPromises","_retrieveSeriesMetadataAsync","_retrieveSeriesMetadataSync","store","dicom","dataset","request","dicomDict","ArrayBuffer","datasets","storeInstances","effectiveDicomDict","meta","FileMetaInformationVersion","_meta","MediaStorageSOPClassUID","SOPClassUID","MediaStorageSOPInstanceUID","TransferSyntaxUID","denaturalized","defaultDicomDict","dict","write","naturalizedInstancesMetadata","seriesSummaryMetadata","instancesPerSeries","SeriesDescription","SeriesNumber","SeriesTime","ProtocolName","Modality","getImageIdsForInstance","wadoUri","addImageIdToUIDs","values","DicomMetadataStore","addSeriesMetadata","addInstances","seriesPromises","addRetrieveBulkData","enabled","ret","arrayBuffer","byteLength","setSuccessFlag","getStudy","isLoaded","aSeries","seriesDeliveredPromises","naturalizedInstances","getImageIdsForDisplaySet","displaySet","images","imageIds","NumberOfFrames","getConfig","getStudyInstanceUIDs","StudyInstanceUIDs","paramsStudyInstanceUIDs","queryStudyInstanceUIDs","splitComma","getAll","supportsReject","xhr","XMLHttpRequest","open","log","onreadystatechange","readyState","status","responseText","send","IWebApiDataSource","create","OHIF","mappings","_store","urls","studyInstanceUIDMap","wrapSequences","obj","reduce","acc","addAccessors","getMetaDataByURL","metaData","findStudies","aStudy","createDicomJSONApi","dicomJsonConfig","response","fetch","json","naturalizedDicom","param","mappedParam","NumInstances","Modalities","PatientID","StudyTime","customSort","seriesSummary","numberOfSeries","index","EVENTS","END_MODALITIES","SR","SEG","DOC","compareValue","v1","v2","def","seriesA","seriesB","instanceA","instanceB","modalityA","modalityB","isEndA","isEndB","createDicomLocalApi","dicomLocalConfig","numInstances","Set","add","firstInstance","from","SeriesDate","_broadcastEvent","SERIES_ADDED","isMultiframe","frameIndex","INSTANCES_ADDED","naturalizedReport","reportBlob","datasetToBlob","objectUrl","window","location","getInstance","StudyInstanceUIDsAsArray","isStudyInCache","sort","createDicomWebProxyApi","dicomWebProxyConfig","dicomWebDelegate","servers","dicomWeb","configuration","args","studyInstanceUIDs","mergeMap","mergeKey","tagFunc","x","sourceName","RetrieveAETitle","updateSeriesMetadata","callForAllDataSourcesAsync","path","extensionManager","dataSourceNames","defaultDataSourceName","defs","dataSourceDefs","defaultDataSourceDef","unshift","sourceNames","dataSourceDef","includes","dataSource","getDataSources","apply","mergedData","allSettled","uniqBy","flat","callForAllDataSources","callForDefaultDataSource","callByRetrieveAETitle","getSeries","createMergeDataSourceApi","mergeConfig","seriesMerge","createDataSource","Toolbar","buttonSection","toolbarButtons","onInteraction","useToolbar","React","toolDef","id","Component","componentProps","tool","_extends","availableLanguages","defaultLanguage","currentLanguage","i18n","hotkeysManager","appConfig","navigate","useNavigate","useLocation","FhircastService","t","useTranslation","show","hide","useModal","hotkeyDefinitions","hotkeyDefaults","menuOptions","title","icon","onClick","content","AboutModal","contentProps","versionNumber","process","commitHash","containerDimensions","UserPreferences","getValidHotkeyDefinitions","onCancel","hotkeys","stopRecord","unpause","onSubmit","language","changeLanguage","setHotkeys","onReset","restoreDefaultBindings","hotkeysModule","oidc","encodeURIComponent","href","fhircast","Header","isReturnEnabled","showStudyList","onClickReturnButton","pathname","dataSourceIdx","configUrl","URLSearchParams","dataSourceName","existingDataSource","searchQuery","append","fhircastPublish","timestamp","event","context","decodeURIComponent","toString","WhiteLabeling","whiteLabeling","showPatientInfo","Secondary","ErrorBoundary","className","SidePanelWithServices","side","activeTabIndex","activeTabIndexProp","tabs","tabsProp","expandedWidth","props","panelService","hasBeenOpened","setHasBeenOpened","useState","setActiveTabIndex","setTabs","getPanels","handleSidePanelOpen","useCallback","handleActiveTabIndexChange","useEffect","unsubscribe","subscribe","PANELS_CHANGED","panelChangedEvent","position","activatePanelSubscription","ACTIVATE_PANEL","activatePanelEvent","forceActive","tabIndex","findIndex","tab","panelId","SidePanel","onOpen","onActiveTabIndexChange","ViewerLayout","commandsManager","viewports","ViewportGridComp","leftPanelClosed","rightPanelClosed","useAppConfig","hangingProtocolService","showLoadingIndicator","setShowLoadingIndicator","hasPanels","hasRightPanels","setHasRightPanels","hasLeftPanels","setHasLeftPanels","leftPanelClosedState","setLeftPanelClosed","rightPanelClosedState","setRightPanelClosed","document","body","classList","remove","HangingProtocolService","PROTOCOL_CHANGED","viewportComponents","viewportComponent","entry","getModuleEntry","component","getComponent","namespace","displaySetsToDisplay","ViewerHeader","style","height","LoadingIndicatorProgress","InvestigationalUseDialog","dialogConfiguration","investigationalUseDialog","propTypes","PropTypes","isRequired","CommandsManager","ServicesManager","leftPanels","rightPanels","children","sortStudyInstances","PanelStudyBrowser","getImageSrc","getStudiesForPatientByMRN","requestDisplaySetCreationForStudy","displaySetService","uiNotificationService","useImageViewer","activeViewportId","viewportGridService","useViewportGrid","activeTabName","setActiveTabName","expandedStudyInstanceUIDs","setExpandedStudyInstanceUIDs","studyDisplayList","setStudyDisplayList","displaySets","setDisplaySets","thumbnailImageSrcMap","setThumbnailImageSrcMap","sid","qidoForStudyUID","qidoStudiesForPatient","error","actuallyMappedStudies","prevArray","it","fetchStudiesForPatient","activeDisplaySets","newImageSrcEntry","getDisplaySetByUID","dSet","displaySetInstanceUID","Math","floor","unsupported","prevState","mappedDisplaySets","_mapDisplaySets","SubscriptionDisplaySetsAdded","DISPLAY_SETS_ADDED","displaySetsAdded","initialViewport","SubscriptionDisplaySetsChanged","DISPLAY_SETS_CHANGED","changedDisplaySets","SubscriptionDisplaySetMetaDataInvalidated","DISPLAY_SET_SERIES_METADATA_INVALIDATED","getActiveDisplaySets","primaryStudyInstanceUIDs","primaryStudies","recentStudies","allStudies","displaySetsForStudy","ds","tabStudy","label","_createStudyBrowserTabs","activeDisplaySetInstanceUIDs","displaySetInstanceUIDs","StudyBrowser","onDoubleClickThumbnail","updatedViewports","viewportId","getViewportsRequireUpdate","message","duration","setDisplaySetsForViewports","onClickStudy","shouldCollapseStudy","updatedExpandedStudyInstanceUIDs","stdyUid","onClickTab","clickedTabName","thumbnailDisplaySets","thumbnailNoImageDisplaySets","excludeFromThumbnailBrowser","imageSrc","componentType","thumbnailNoImageModalities","_getComponentType","seriesTime","numImageFrames","countIcon","messages","dragData","isHydratedForDerivedDisplaySet","isHydrated","cornerstone","canvas","createElement","utilities","loadImageToCanvas","toDataURL","catch","some","WrappedPanelStudyBrowser","_getStudiesForPatientByMRN","_getImageSrcFromImageId","exports","getCornerstoneLibraries","getImageSrcFromImageId","ex","_createGetImageSrcFromImageIdFn","_requestDisplaySetCreationForStudy","CREATE_REPORT_DIALOG_RESPONSE","CANCEL","CREATE_REPORT","CreateReportDialogPrompt","uiDialogService","dialogId","dataSourcesOpts","dataSourceMap","supportsStow","placeHolder","centralize","isDraggable","Dialog","useLastPosition","showOverlay","activeDataSource","noCloseButton","onClose","_handleClose","dismiss","action","actions","text","ButtonEnums","secondary","primary","_handleFormSubmit","setValue","allowMultiSelectExport","Select","closeMenuOnSelect","placeholder","option","onChange","evt","v","isClearable","Input","autoFocus","labelClassName","persist","target","onKeyPress","required","Loading","getReport","reportType","loadingDialogId","getMostRecentDisplaySet","MIN_SR_SERIES_NUMBER","findSRWithSameSeriesDescription","sameSeries","InstanceNumber","srSeriesNumbers","max","getNextSRSeriesNumber","downloadCSVReport","PanelMeasurementTable","viewportGrid","measurementService","displayMeasurements","setDisplayMeasurements","debouncedSetDisplayMeasurements","debounce","_getMappedMeasurements","added","MEASUREMENT_ADDED","addedRaw","RAW_MEASUREMENT_ADDED","updated","MEASUREMENT_UPDATED","removed","MEASUREMENT_REMOVED","cleared","MEASUREMENTS_CLEARED","subscriptions","unsub","cancel","onMeasurementItemClickHandler","isActive","measurements","measurement","m","MeasurementTable","jumpToImage","jumpToMeasurement","onEdit","onMeasurementItemEditHandler","getMeasurement","onSubmitHandler","update","ActionButtons","getMeasurements","activeViewport","trackedMeasurements","referenceStudyUID","promptResult","createReportDialogPrompt","createReportAsync","runCommand","measurementData","additionalFindingTypes","types","displayText","baseDisplayText","baseLabel","selected","findingSites","finding","firstSite","siteText","site","measurementType","_mapMeasurementToDisplay","VALUE_TYPES","iconName","iconLabel","secondaryLabel","wrappedMeasurementPanel","packageJson","_checkSeriesPositionShift","previousPosition","actualPosition","scanAxisNormal","averageSpacingBetweenFrames","predictedPosition","vec3","areAllImagePositionsEqual","firstImageOrientationPatient","toNumber","ImageOrientationPatient","imageOrientation","rowCosineVec","colCosineVec","calculateScanAxisNormal","firstImagePositionPatient","ImagePositionPatient","lastIpp","_getPerpendicularDistance","previousImagePositionPatient","imagePositionPatient","checkSingleFrames","firstImage","firstImageRows","Rows","firstImageColumns","Columns","areAllImageDimensionsEqual","addMessage","DisplaySetMessage","CODES","INCONSISTENT_DIMENSIONS","firstImageSamplesPerPixel","SamplesPerPixel","areAllImageComponentsEqual","INCONSISTENT_COMPONENTS","imageOrientationPatient","_isSameOrientation","areAllImageOrientationsEqual","INCONSISTENT_ORIENTATIONS","INCONSISTENT_POSITION_INFORMATION","issuesFound","spacingBetweenFrames","spacingIssue","_getSpacingIssue","issue","reconstructionIssues","MISSING_FRAMES","IRREGULAR_SPACING","areAllImageSpacingEqual","getDisplaySetMessages","isReconstructable","isDynamicVolume","DisplaySetMessageList","NO_VALID_INSTANCES","ImageType","constructableModalities","every","NO_POSITION_INFORMATION","sortedInstances","sortInstancesByPosition","multiFrameInstance","hasPixelMeasurements","MULTIFRAME_NO_PIXEL_MEASUREMENTS","hasOrientation","MULTIFRAME_NO_ORIENTATION","hasPosition","MULTIFRAME_NO_POSITION_INFORMATION","checkMultiFrame","NOT_RECONSTRUCTABLE","getDisplaySetsFromUnsupportedSeries","imageSet","ImageSet","UNSUPPORTED_DISPLAYSET","setAttributes","FrameRate","FrameTime","SOPClassHandlerId","SOPClassHandlerName","makeChartDataDisplaySet","sopClassUids","loading","guid","isDerivedDisplaySet","_displaySetService","_getDisplaySetsFromSeries","uniqueSopClassUidsInSeries","getSopClassUids","chartHandler","getDisplaySetsFromSeries","sopClassHandlerName","appContext","isMultiFrame","getDisplaySetInfo","dynamicVolumeInfo","volumeLoaderUtility","getDynamicVolumeInfo","csGetDynamicVolumeInfo","timePoints","displaySetInfo","timePoint","instancesMap","firstTimePointInstances","isDisplaySetReconstructable","makeDisplaySet","volumeLoaderSchema","sortBy","a","b","parseInt","isSingleImageModality","stackableInstances","isImage","isClip","instanceNumber","acquisitionDatetime","AcquisitionDateTime","setAttribute","sopClassDictionary","ComputedRadiographyImageStorage","DigitalXRayImageStorageForPresentation","DigitalXRayImageStorageForProcessing","DigitalMammographyXRayImageStorageForPresentation","DigitalMammographyXRayImageStorageForProcessing","DigitalIntraOralXRayImageStorageForPresentation","DigitalIntraOralXRayImageStorageForProcessing","CTImageStorage","EnhancedCTImageStorage","LegacyConvertedEnhancedCTImageStorage","UltrasoundMultiframeImageStorage","MRImageStorage","EnhancedMRImageStorage","EnhancedMRColorImageStorage","LegacyConvertedEnhancedMRImageStorage","UltrasoundImageStorage","UltrasoundImageStorageRET","SecondaryCaptureImageStorage","MultiframeSingleBitSecondaryCaptureImageStorage","MultiframeGrayscaleByteSecondaryCaptureImageStorage","MultiframeGrayscaleWordSecondaryCaptureImageStorage","MultiframeTrueColorSecondaryCaptureImageStorage","XRayAngiographicImageStorage","EnhancedXAImageStorage","XRayRadiofluoroscopicImageStorage","EnhancedXRFImageStorage","XRay3DAngiographicImageStorage","XRay3DCraniofacialImageStorage","BreastTomosynthesisImageStorage","BreastProjectionXRayImageStorageForPresentation","BreastProjectionXRayImageStorageForProcessing","IntravascularOpticalCoherenceTomographyImageStorageForPresentation","IntravascularOpticalCoherenceTomographyImageStorageForProcessing","NuclearMedicineImageStorage","VLEndoscopicImageStorage","VideoEndoscopicImageStorage","VLMicroscopicImageStorage","VideoMicroscopicImageStorage","VLSlideCoordinatesMicroscopicImageStorage","VLPhotographicImageStorage","VideoPhotographicImageStorage","OphthalmicPhotography8BitImageStorage","OphthalmicPhotography16BitImageStorage","OphthalmicTomographyImageStorage","VLWholeSlideMicroscopyImageStorage","PositronEmissionTomographyImageStorage","EnhancedPETImageStorage","LegacyConvertedEnhancedPETImageStorage","RTImageStorage","EnhancedUSVolumeStorage","appContextParam","ToolbarDivider","defaultCommonPresets","commandOptions","numRows","numCols","generateAdvancedPresets","hangingProtocols","protocols","getActiveViewportId","getDisplaySetsUIDsForViewport","hp","isPreset","areValid","_areSelectorsValid","displaySetSelectors","areRequiredSelectorsValid","protocolId","disabled","preset","LayoutSelector","rows","columns","onSelection","onSelectionPreset","tooltipDisabled","rest","isOpen","setIsOpen","commonPresets","advancedPresets","closeOnOutsideClick","addEventListener","removeEventListener","DropdownContent","OHIFLayoutSelector","ToolbarButton","onInteractionHandler","rounded","disableToolTip","dropdownContent","LayoutPreset","classNames","onLayoutChange","defaultProps","isDisabled","setIsDisabled","run","commandName","onMouseEnter","handleMouseEnter","ToolbarSplitButtonWithServices","groupId","items","renderer","toolbarService","getSplitButtonItems","itemId","commands","PrimaryButtonComponent","getButtonComponentForUIType","uiType","listItemRenderer","SplitButton","isRadio","tooltip","isAction","size","toolTipClassName","ButtonGroup","workflowStepsToDropdownOptions","steps","step","info","activated","completed","workflowStepsService","activeStepId","setActiveStepId","activeWorkflowStep","dropdownOptions","setDropdownOptions","workflowSteps","setCurrentAndPreviousOptionsAsCompleted","currentOption","prevOptions","newOptionsState","handleDropdownChange","selectedOption","setActiveWorkflowStep","clearTimeout","timeoutId","unsubStepsChanged","STEPS_CHANGED","unsubActiveStepChanged","ACTIVE_STEP_CHANGED","ProgressDropdown","getMenuItems","selectorProps","menus","menuIdFilter","subProps","menu","subMenu","findIt","menuId","findMenuById","selector","findMenuDefault","findMenuIterator","current","return","findMenu","menuItems","delegating","toAdd","newItem","actionType","iconRight","itemRef","detail","element","adaptItem","ContextMenuController","closeContextMenu","showContextMenu","contextMenuProps","viewportElement","defaultPointsPosition","annotationManager","CsAnnotation","locking","targetAnnotationId","nearbyToolData","annotationUID","isAnnotationLocked","getAnnotation","ContextMenuItemsBuilder","preservePosition","preventCutOf","defaultPosition","_getDefaultPosition","ContextMenu","onClickOutside","eventData","onShowSubMenu","onDefault","_ContextMenuController","getDefaultPosition","y","_getEventDefaultPosition","eventDetail","currentPoints","_getElementDefaultPosition","boundingClientRect","getBoundingClientRect","_getCanvasPointsPosition","points","viewerPos","pointIndex","point","_isValidPosition","source","canvasPoints","viewerElement","positionIterator","getPositionIterator","customizationType","rowVerticalPaddingStyle","padding","rowStyle","borderBottomWidth","ColumnHeaders","tagRef","vrRef","keywordRef","valueRef","ref","listRef","useRef","canvasRef","tagHeaderElem","setTagHeaderElem","vrHeaderElem","setVrHeaderElem","keywordHeaderElem","setKeywordHeaderElem","valueHeaderElem","setValueHeaderElem","scrollTo","resetAfterIndex","debouncedResize","Row","row","isHeaderRendered","getItemSize","headerWidths","offsetWidth","getContext","font","getComputedStyle","colText","colOneLineWidth","measureText","width","ceil","maxHeight","colHeight","visibility","elem","List","itemCount","itemSize","nameMap","getFormattedRowsFromTags","tags","tagInfo","tagIndent","keyword","formatedRowsFromTags","Tag","fromPString","toCleanString","originalTagInfo","getRows","depth","keywords","sequenceAsArray","objectOrArray","sequence","sequenceRows","_sortTagList","regex","match","tagList","DicomTagBrowser","excludedColumnIndicesForFilter","selectedDisplaySetInstanceUID","setSelectedDisplaySetInstanceUID","setInstanceNumber","filterValue","setFilterValue","activeDisplaySet","isImageStack","showInstanceList","displaySetList","useMemo","dateStr","moment","format","getSortedTags","filteredRows","filterValueLowerCase","keepRow","col","colIndex","debouncedSetFilterValue","Typography","variant","InputRange","minValue","maxValue","inputClassName","labelPosition","trackColor","InputFilterText","onDebounceChange","DicomTagTable","reuseCachedLayout","state","syncService","protocol","getActiveProtocol","hpInfo","getState","stageIndex","activeStudyUID","syncState","viewportGridStore","displaySetSelectorMap","stage","stages","storeId","cacheId","hangingProtocolStageIndexMap","viewportStructure","properties","custom","layout","viewport","displaySetOptions","displaySetUID","matchedDisplaySetsIndex","findOrCreateViewport","viewportsByPosition","positionId","byPositionViewport","inDisplay","initialInDisplay","missing","getMissingViewport","displaySetsInfo","viewportOptions","findViewportsByPosition","storedViewport","subscribeToNextViewportGridChange","commandsModule","stateSyncService","contextMenuController","menuCustomizationId","optionsToUse","defaultContextMenu","displayNotification","clearMeasurements","clear","setHangingProtocol","stageId","reset","stateSyncReduce","reuseCachedLayouts","hangingId","useStageIdx","getStageIndex","setActiveStudyUID","storedHanging","restoreProtocol","setProtocol","e","toggleHangingProtocol","desiredStageIndex","activeStudy","previousState","deltaStage","direction","oldStageIndex","setViewportGridLayout","isHangingProtocolLayout","callbacks","setTimeout","completeLayout","stateReduce","layoutFindOrCreate","setLayout","toggleOneUp","viewportGridState","toggleOneUpViewportGridStore","viewportIdToUpdate","updatedViewportsViaHP","preOneUpViewport","layoutOptions","getLayoutOptionsFromState","clearToggleOneUpViewportGridStore","navigateHistory","historyArgs","history","to","openDICOMTagViewer","activeViewportSpecificData","UIModalService","toggleOverlays","overlays","getElementsByClassName","toggle","scrollActiveThumbnailIntoView","activeDisplaySetInstanceUID","thumbnailList","querySelector","thumbnailListBounds","thumbnailBounds","top","bottom","scrollIntoView","behavior","updateViewportDisplaySet","excludeNonImageModalities","nonImageModalities","dsSortFn","getDisplaySetSortFunction","currentDisplaySets","displaySetIndexToShow","definitions","commandFn","nextStage","previousStage","defaultContext","protocolMatchingRules","weight","attribute","constraint","greaterThan","toolGroupIds","defaultDisplaySetId","seriesMatchingRules","equals","defaultViewport","viewportType","toolGroupId","allowUnmatchedView","stageActivation","minViewportsMatched","layoutType","requiredViewports","preferredViewports","numberOfPriorsReferenced","currentDisplaySet","priorDisplaySet","currentViewport0","currentViewport1","priorViewport0","notNull","studyMatchingRules","priorDisplaySetId","defaultProtocol","locked","createdDate","modifiedDate","availableTo","editableBy","hpInitiationCriteria","minSeriesLoaded","initialImageOptions","hpMNGrid","hpMNCompare","dsConfigs","dataSources","src","alt","friendlyName","Button","classnames","itemLabel","itemList","onItemClicked","Icon","endIcon","NO_WRAP_ELLIPSIS_CLASS_NAMES","configurationAPI","configuredItems","onHide","setItemList","selectedItems","setSelectedItems","errorMessage","setErrorMessage","itemLabels","getItemLabels","showFullConfig","setShowFullConfig","currentSelectedItemIndex","shouldUpdate","setCurrentItem","getSelectedItemBackgroundClasses","itemIndex","getSelectedItemBorderClasses","getSelectedItemTextClasses","itemLabelIndex","theList","ItemListComponent","setConfigurationAPI","setConfiguredItems","dataSourceChangedCallback","activeDataSourceDef","getActiveDataSourceDefinition","factory","configurationAPIFactory","configAPI","getConfiguredItems","list","sub","ACTIVE_DATA_SOURCE_CHANGED","showConfigurationModal","DataSourceConfigurationModalComponent","ItemType","initialUrl","baseHealthcareUrl","GoogleCloudDataSourceConfigurationAPI","_extensionManager","_fetchOptions","_dataSourceName","method","projects","_doFetch","project","projectId","itemType","anItem","googleCloudItem","dicomStores","dataSourceDefCopy","getDataSourceDefinition","updateDataSourceConfiguration","subItemType","subItemField","fetchedSubItems","subItem","nameSplit","projectsIndex","urlSplit","projectUrl","relativePath","urlStr","fetchItemType","fetchOptions","fetchSearchParams","nextPageToken","pageToken","subPageData","statusText","err","LineChartViewport","axis","chartAxis","chartSeries","chartData","LineChart","showLegend","legendWidth","indexRef","min","handlePETImageMetadata","instanceMetadataArray","instanceMetadata","dicomMetaData","CorrectedImage","Units","RadiopharmaceuticalInformationSequence","RadionuclideHalfLife","RadionuclideTotalDose","DecayCorrection","AcquisitionDate","AcquisitionTime","RadiopharmaceuticalStartDateTime","RadiopharmaceuticalStartTime","PatientWeight","philipsPETPrivateGroup","SUVScaleFactor","ActivityConcentrationScaleFactor","PhilipsPETPrivateGroup","GEPrivatePostInjectionDateTime","FrameReferenceTime","ActualFrameDuration","PatientSex","PatientSize","getPTImageIdInstanceMetadata","suvScalingFactors","calculateSUVScalingFactors","addCustomMetadata","defaultExtension","preRegistration","cineService","registerEventForToolbarUpdate","CINE_STATE_CHANGED","SERIES_UPDATED","register","clearOnModeExit","subscribeToEvents","listeners","ACTIVE_VIEWPORT_ID_CHANGED","VIEWPORTS_READY","TOOL_BAR_MODIFIED","buttons","button","getDataSourcesModule","getViewportModule","getLayoutTemplateModule","getPanelModule","getHangingProtocolModule","getSopClassHandlerModule","getToolbarModule","defaultComponent","ToolbarLayoutSelectorWithServices","ToolbarButtonGroupWithServices","ProgressDropdownWithService","evaluate","isToggled","getClassName","isCineEnabled","getCommandsModule","getUtilityModule","getCustomizationModule","routes","color","DataSourceSelector","condition","contentF","transform","clonedObject","originalItems","DataSourceConfigurationComponent"],"sourceRoot":""}