{"version":3,"file":"342.bundle.4e4dcc176d6c2f7851a6.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/retrieveStudyMetadata.js","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/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/ActionButtons.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/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/ToolbarButtonWithServices.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/getPTImageIdInstanceMetadata.ts","webpack:///../../../extensions/default/src/init.ts","webpack:///../../../extensions/default/src/index.ts","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} - 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} [filter.seriesInstanceUID] - series instance uid to filter results against\n * @param {Function} [sortSeries] - Custom sort function for series\n */\n constructor(client, studyInstanceUID, filters = {}, sortCriteria, sortFunction) {\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\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 try {\n result = await loader();\n if (result && result.length) {\n break; // closes iterator in case data is retrieved successfully\n }\n } catch (e) {\n throw e;\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, sortingCriteria } from '@ohif/core/src/utils/sortStudy';\nimport RetrieveMetadataLoader from './retrieveMetadataLoader';\n\n/**\n * Creates an immutable series loader object which loads each series sequentially using the iterator interface\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 * @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 async next() {\n const seriesInstanceUID = seriesInstanceUIDList.shift();\n return client.retrieveSeriesMetadata({\n studyInstanceUID,\n seriesInstanceUID,\n });\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 if (seriesInstanceUID) {\n const options = {\n studyInstanceUID,\n queryParams: { SeriesInstanceUID: seriesInstanceUID },\n };\n preLoaders.push(client.searchForSeries.bind(client, options));\n }\n // Fallback preloader\n preLoaders.push(client.searchForSeries.bind(client, { studyInstanceUID }));\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(\n naturalized,\n sortCriteria || sortingCriteria.seriesSortCriteria.seriesInfoSortingCriteria,\n sortFunction\n );\n }\n\n async load(preLoadData) {\n const { client, studyInstanceUID } = this;\n\n const seriesInstanceUIDs = preLoadData.map(s => s.SeriesInstanceUID);\n\n const seriesAsyncLoader = makeSeriesAsyncLoader(client, studyInstanceUID, seriesInstanceUIDs);\n\n const promises = [];\n\n while (seriesAsyncLoader.hasNext()) {\n promises.push(seriesAsyncLoader.next());\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 {Object} dicomWebClient The dicomweb-client.\n * @param {string} studyInstanceUid The Study Instance UID of the study which needs to be loaded\n * @param {Object} [filters] - Object containing filters to be applied on retrieve metadata process\n * @param {string} [filter.seriesInstanceUID] - series instance uid to filter results against\n * @returns {Object} A 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.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} server Object with server configuration parameters\n * @param {string} StudyInstanceUID The UID of the Study to be retrieved\n * @param {boolean} enabledStudyLazyLoad Whether the study metadata should be loaded asynchronously.\n * @param {function} storeInstancesCallback A callback used to store the retrieved instance metadata.\n * @param {Object} [filters] - Object containing filters to be applied on retrieve metadata process\n * @param {string} [filter.seriesInstanceUID] - series instance uid to filter results against\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) {\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 // Already waiting on result? Return cached promise\n if (StudyMetaDataPromises.has(StudyInstanceUID)) {\n return StudyMetaDataPromises.get(StudyInstanceUID);\n }\n\n // Create a promise to handle the data retrieval\n const 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 // Store the promise in cache\n StudyMetaDataPromises.set(StudyInstanceUID, 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 *\n */\nexport function deleteStudyMetadataPromise(StudyInstanceUID) {\n if (StudyMetaDataPromises.has(StudyInstanceUID)) {\n StudyMetaDataPromises.delete(StudyInstanceUID);\n }\n}\n","import { api } from 'dicomweb-client';\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 */\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 constructor(qidoConfig) {\n super(qidoConfig);\n this.staticWado = qidoConfig.staticWado;\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): Record {\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 * @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 } = params;\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 return value.retrieveBulkData().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 *\n * @param {string} name - Data source name\n * @param {string} wadoUriRoot - Legacy? (potentially unused/replaced)\n * @param {string} qidoRoot - Base URL to use for QIDO requests\n * @param {string} wadoRoot - Base URL to use for WADO requests\n * @param {boolean} qidoSupportsIncludeField - Whether QIDO supports the \"Include\" option to request additional fields in response\n * @param {string} imageRengering - wadors | ? (unsure of where/how this is used)\n * @param {string} thumbnailRendering - wadors | ? (unsure of where/how this is used)\n * @param {bool} supportsReject - Whether the server supports reject calls (i.e. DCM4CHEE)\n * @param {bool} lazyLoadStudy - \"enableStudyLazyLoad\"; Request series meta async instead of blocking\n * @param {string|bool} singlepart - indicates of the retrieves can fetch singlepart. Options are bulkdata, video, image or boolean true\n */\nfunction createDicomWebApi(dicomWebConfig, userAuthenticationService) {\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 qidoSearch.call(undefined, qidoDicomWebClient, studyInstanceUid, null, queryParameters);\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 } = {}) => {\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 );\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) => {\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 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 dicomDict = new DicomDict(denaturalized);\n\n dicomDict.dict = denaturalizeDataset(dataset);\n\n const part10Buffer = dicomDict.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 );\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\n _retrieveSeriesMetadataAsync: async (\n StudyInstanceUID,\n filters,\n sortCriteria,\n sortFunction,\n madeInClient = 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 );\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 = () => {\n // handle the scenarios where bulkDataURI is relative path\n fixBulkDataURI(value, naturalized, dicomWebConfig);\n\n const options = {\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 };\n // Todo: this needs to be from wado dicom web client\n return qidoDicomWebClient.retrieveBulkData(options).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, index) => {\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, madeInClient);\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 promise.then(instances => {\n storeInstances(instances);\n })\n );\n await Promise.all(seriesDeliveredPromises);\n setSuccessFlag();\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 }) {\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\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(wadoRoot, 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 const obj = {\n ...instance.metadata,\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, UserAuthenticationService) {\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 UserAuthenticationService\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","// 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';\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}\n\nexport default getDataSourcesModule;\n","import React, { useEffect, useState, useCallback } from 'react';\nimport classnames from 'classnames';\n\nexport default function Toolbar({ servicesManager }) {\n const { toolbarService } = servicesManager.services;\n const [toolbarButtons, setToolbarButtons] = useState([]);\n\n useEffect(() => {\n const { unsubscribe } = toolbarService.subscribe(toolbarService.EVENTS.TOOL_BAR_MODIFIED, () =>\n setToolbarButtons(toolbarService.getButtonSection('primary'))\n );\n\n return () => {\n unsubscribe();\n };\n }, [toolbarService]);\n\n const onInteraction = useCallback(\n args => toolbarService.recordInteraction(args),\n [toolbarService]\n );\n\n return (\n <>\n {toolbarButtons.map(toolDef => {\n const { id, Component, componentProps } = toolDef;\n return (\n // The margin for separating the tools on the toolbar should go here and NOT in each individual component (button) item.\n // This allows for the individual items to be included in other UI components where perhaps alternative margins are desired.\n \n \n \n );\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 { useAppConfig } from '@state';\nimport Toolbar from '../Toolbar/Toolbar';\n\nconst { availableLanguages, defaultLanguage, currentLanguage } = i18n;\n\nfunction ViewerHeader({ hotkeysManager, extensionManager, servicesManager }) {\n const [appConfig] = useAppConfig();\n const navigate = useNavigate();\n const location = useLocation();\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 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: 'About OHIF Viewer',\n contentProps: { versionNumber, commitHash },\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\n return (\n \n \n
\n \n
\n
\n \n );\n}\n\nexport default ViewerHeader;\n","import React, { useEffect, useState } from 'react';\nimport { SidePanel } from '@ohif/ui';\nimport { PanelService, ServicesManager } from '@ohif/core';\n\nexport type SidePanelWithServicesProps = {\n servicesManager: ServicesManager;\n side: 'left' | 'right';\n className: string;\n activeTabIndex: number;\n tabs: any;\n};\n\nconst SidePanelWithServices = ({\n servicesManager,\n side,\n className,\n activeTabIndex: activeTabIndexProp,\n tabs,\n}) => {\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\n useEffect(() => {\n if (panelService) {\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 }\n }, [tabs, hasBeenOpened, panelService]);\n\n return (\n {\n setHasBeenOpened(true);\n }}\n >\n );\n};\n\nexport default SidePanelWithServices;\n","import React, { useEffect, useState } from 'react';\nimport PropTypes from 'prop-types';\n\nimport { SidePanel, ErrorBoundary, LoadingIndicatorProgress } 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 leftPanels = [],\n rightPanels = [],\n leftPanelDefaultClosed = false,\n rightPanelDefaultClosed = false,\n}): React.FunctionComponent {\n const [appConfig] = useAppConfig();\n\n const { hangingProtocolService } = servicesManager.services;\n const [showLoadingIndicator, setShowLoadingIndicator] = useState(appConfig.showLoadingIndicator);\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) {\n throw new Error(\n `${id} is not valid for an extension module. 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)`\n );\n }\n\n let content;\n if (entry && entry.component) {\n content = entry.component;\n } else {\n throw new Error(\n `No component found from extension ${id}. Check the reference string to the extension in your Mode configuration`\n );\n }\n\n return { entry, content };\n };\n\n const getPanelData = id => {\n const { content, entry } = getComponent(id);\n\n return {\n id: entry.id,\n iconName: entry.iconName,\n iconLabel: entry.iconLabel,\n label: entry.label,\n name: entry.name,\n content,\n };\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 const leftPanelComponents = leftPanels.map(getPanelData);\n const rightPanelComponents = rightPanels.map(getPanelData);\n const viewportComponents = viewports.map(getViewportComponentData);\n\n return (\n
\n \n \n \n {showLoadingIndicator && }\n {/* LEFT SIDEPANELS */}\n {leftPanelComponents.length ? (\n \n \n \n ) : null}\n {/* TOOLBAR + GRID */}\n
\n
\n \n \n \n
\n
\n {rightPanelComponents.length ? (\n \n \n \n ) : null}\n
\n
\n \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 leftPanelDefaultClosed: PropTypes.bool.isRequired,\n rightPanelDefaultClosed: 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 {\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 })\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 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 = _createGetImageSrcFromImageIdFn(extensionManager);\n const _requestDisplaySetCreationForStudy = requestDisplaySetCreationForStudy.bind(\n null,\n dataSource\n );\n\n return (\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';\nimport PropTypes from 'prop-types';\nimport { useTranslation } from 'react-i18next';\n\nimport { LegacyButton, LegacyButtonGroup } from '@ohif/ui';\n\nfunction ActionButtons({ onExportClick, onCreateReportClick }) {\n const { t } = useTranslation('MeasurementTable');\n\n return (\n \n \n {/* TODO Revisit design of LegacyButtonGroup later - for now use LegacyButton for its children.*/}\n \n {t('Export CSV')}\n \n \n {t('Create Report')}\n \n \n \n );\n}\n\nActionButtons.propTypes = {\n onExportClick: PropTypes.func,\n onCreateReportClick: PropTypes.func,\n};\n\nActionButtons.defaultProps = {\n onExportClick: () => alert('Export'),\n onCreateReportClick: () => alert('Create Report'),\n};\n\nexport default ActionButtons;\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
\n \n 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
\n )}\n
\n \n
\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
Loading...
;\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 { utils, ServicesManager } from '@ohif/core';\nimport { MeasurementTable, Dialog, Input, useViewportGrid, ButtonEnums } from '@ohif/ui';\nimport ActionButtons from './ActionButtons';\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 [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 {\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 \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 \n \n \n
\n \n
\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';\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 \n );\n };\n\n return [\n {\n name: 'seriesList',\n iconName: 'tab-studies',\n iconLabel: 'Studies',\n label: '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: 'Measurements',\n secondaryLabel: '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): 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,\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): 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): 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): 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,\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,\n isReconstructable: boolean\n): DisplaySetMessageList {\n const messages = new DisplaySetMessageList();\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 { 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';\n\nconst sopClassHandlerName = 'stack';\n\nconst isMultiFrame = instance => {\n return instance.NumberOfFrames > 1;\n};\n\nconst makeDisplaySet = instances => {\n const instance = instances[0];\n const imageSet = new ImageSet(instances);\n\n const { value: isReconstructable, averageSpacingBetweenFrames } =\n isDisplaySetReconstructable(instances);\n // set appropriate attributes to image set...\n const messages = getDisplaySetMessages(instances, isReconstructable);\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 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 });\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 {Array} sopClassHandlerModules List of SOP Class Modules\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() {\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}\n\nexport default getSopClassHandlerModule;\n","import React from 'react';\n\nexport default function ToolbarDivider() {\n return ;\n}\n","import React, { useEffect, useState, useCallback } from 'react';\nimport PropTypes from 'prop-types';\nimport { LayoutSelector as OHIFLayoutSelector, ToolbarButton } from '@ohif/ui';\nimport { ServicesManager } from '@ohif/core';\n\nfunction ToolbarLayoutSelectorWithServices({ servicesManager, ...props }) {\n const { toolbarService } = servicesManager.services;\n\n const onSelection = useCallback(\n props => {\n toolbarService.recordInteraction({\n interactionType: 'action',\n commands: [\n {\n commandName: 'setViewportGridLayout',\n commandOptions: { ...props },\n context: 'DEFAULT',\n },\n ],\n });\n },\n [toolbarService]\n );\n\n return (\n \n );\n}\n\nfunction LayoutSelector({ rows, columns, className, onSelection, ...rest }) {\n const [isOpen, setIsOpen] = useState(false);\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 = () => setIsOpen(!isOpen);\n const DropdownContent = isOpen ? OHIFLayoutSelector : null;\n\n return (\n \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 rows: 3,\n columns: 3,\n onLayoutChange: () => {},\n};\n\nexport default ToolbarLayoutSelectorWithServices;\n","import { SplitButton, Icon, ToolbarButton } from '@ohif/ui';\nimport React, { useEffect, useState } from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\n\nfunction ToolbarSplitButtonWithServices({\n isRadio,\n isAction,\n groupId,\n primary,\n secondary,\n items,\n renderer,\n onInteraction,\n servicesManager,\n}) {\n const { toolbarService } = servicesManager?.services;\n\n const handleItemClick = (item, index) => {\n const { id, type, commands } = item;\n onInteraction({\n groupId,\n itemId: id,\n interactionType: type,\n commands,\n });\n\n setState(state => ({\n ...state,\n primary: !isAction && isRadio ? { ...item, index } : state.primary,\n isExpanded: false,\n items: getSplitButtonItems(items).filter(item =>\n isRadio && !isAction ? item.index !== index : true\n ),\n }));\n };\n\n /* Bubbles up individual item clicks */\n const getSplitButtonItems = items =>\n items.map((item, index) => ({\n ...item,\n index,\n onClick: () => handleItemClick(item, index),\n }));\n\n const [buttonsState, setButtonState] = useState({\n primaryToolId: '',\n toggles: {},\n groups: {},\n });\n\n const [state, setState] = useState({\n primary,\n items: getSplitButtonItems(items).filter(item =>\n isRadio && !isAction ? item.id !== primary.id : true\n ),\n });\n\n const { primaryToolId, toggles } = buttonsState;\n\n const isPrimaryToggle = state.primary.type === 'toggle';\n\n const isPrimaryActive =\n (state.primary.type === 'tool' && primaryToolId === state.primary.id) ||\n (isPrimaryToggle && toggles[state.primary.id] === true);\n\n const PrimaryButtonComponent =\n toolbarService?.getButtonComponentForUIType(state.primary.uiType) ?? ToolbarButton;\n\n useEffect(() => {\n const { unsubscribe } = toolbarService.subscribe(\n toolbarService.EVENTS.TOOL_BAR_STATE_MODIFIED,\n state => {\n setButtonState({ ...state });\n }\n );\n\n return () => {\n unsubscribe();\n };\n }, [toolbarService]);\n\n const updatedItems = state.items.map(item => {\n const isActive = item.type === 'tool' && primaryToolId === item.id;\n\n // We could have added the\n // item.type === 'toggle' && toggles[item.id] === true\n // too but that makes the button active when the toggle is active under it\n // which feels weird\n return {\n ...item,\n isActive,\n };\n });\n\n const DefaultListItemRenderer = ({ type, icon, label, t, id }) => {\n const isActive = type === 'toggle' && toggles[id] === true;\n\n return (\n \n {icon && (\n \n \n \n )}\n {t(label)}\n \n );\n };\n\n const listItemRenderer = renderer || DefaultListItemRenderer;\n\n return (\n item.isActive)}\n isToggle={isPrimaryToggle}\n onInteraction={onInteraction}\n Component={props => (\n \n )}\n />\n );\n}\n\nToolbarSplitButtonWithServices.propTypes = {\n isRadio: PropTypes.bool,\n isAction: PropTypes.bool,\n groupId: PropTypes.string,\n primary: PropTypes.shape({\n id: PropTypes.string.isRequired,\n type: PropTypes.oneOf(['tool', 'action', 'toggle']).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 isActive: PropTypes.bool,\n }),\n items: PropTypes.arrayOf(\n PropTypes.shape({\n id: PropTypes.string.isRequired,\n type: PropTypes.oneOf(['tool', 'action', 'toggle']).isRequired,\n icon: PropTypes.string,\n label: PropTypes.string,\n tooltip: 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 } from '@ohif/ui';\nimport React, { useEffect, useState } from 'react';\nimport PropTypes from 'prop-types';\n\nfunction ToolbarButtonWithServices({\n id,\n type,\n commands,\n onInteraction,\n servicesManager,\n ...props\n}) {\n const { toolbarService } = servicesManager?.services || {};\n\n const [buttonsState, setButtonState] = useState({\n primaryToolId: '',\n toggles: {},\n groups: {},\n });\n const { primaryToolId } = buttonsState;\n\n const isActive =\n (type === 'tool' && id === primaryToolId) ||\n (type === 'toggle' && buttonsState.toggles[id] === true);\n\n useEffect(() => {\n const { unsubscribe } = toolbarService.subscribe(\n toolbarService.EVENTS.TOOL_BAR_STATE_MODIFIED,\n state => {\n setButtonState({ ...state });\n }\n );\n\n return () => {\n unsubscribe();\n };\n }, [toolbarService]);\n\n return (\n \n );\n}\n\nToolbarButtonWithServices.propTypes = {\n id: PropTypes.string.isRequired,\n type: PropTypes.oneOf(['tool', 'action', 'toggle']).isRequired,\n commands: PropTypes.arrayOf(\n PropTypes.shape({\n commandName: PropTypes.string.isRequired,\n context: PropTypes.string,\n })\n ),\n onInteraction: PropTypes.func.isRequired,\n servicesManager: PropTypes.shape({\n services: PropTypes.shape({\n toolbarService: PropTypes.shape({\n subscribe: PropTypes.func.isRequired,\n state: PropTypes.shape({\n primaryToolId: PropTypes.string,\n toggles: PropTypes.objectOf(PropTypes.bool),\n groups: PropTypes.objectOf(PropTypes.object),\n }).isRequired,\n }).isRequired,\n }).isRequired,\n }).isRequired,\n};\n\nexport default ToolbarButtonWithServices;\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): 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 console.log('Menu chosen', menu?.id || 'NONE');\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 { 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 console.log('Getting items from', menus);\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 },\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 \n
\n \n Tag\n \n
\n
\n \n VR\n \n
\n
\n \n Keyword\n \n
\n
\n \n Value\n \n
\n \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 \n
{row[0]}
\n
{row[1]}
\n
{row[2]}
\n
{row[3]}
\n \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
\n \n \n \n {isHeaderRendered() && (\n \n {Row}\n \n )}\n
\n \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 = 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
\n
\n
\n \n Series\n \n
\n ds.value === selectedDisplaySetInstanceUID)}\n className=\"text-white\"\n />\n
\n
\n
\n {showInstanceList && (\n \n Instance Number\n \n )}\n {showInstanceList && (\n
\n {\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
\n )}\n
\n
\n
\n
\n \n
\n \n
\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;\n viewportGridStore: Record;\n displaySetSelectorMap: Record;\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 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\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 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> => {\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};\n\nexport type UpdateViewportDisplaySetParams = {\n direction: number;\n excludeNonImageModalities?: boolean;\n};\n\n/**\n * Determine if a command is a hanging protocol one.\n * For now, just use the two hanging protocol commands that are in this\n * commands module, but if others get added elsewhere this may need enhancing.\n */\nconst isHangingProtocolCommand = command =>\n command &&\n (command.commandName === 'setHangingProtocol' || command.commandName === 'toggleHangingProtocol');\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 toolbarService,\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 * Toggles off all tools which contain a commandName of setHangingProtocol\n * or toggleHangingProtocol, and which match/don't match the protocol id/stage\n */\n toggleHpTools: () => {\n const {\n protocol,\n stageIndex: toggleStageIndex,\n stage,\n } = hangingProtocolService.getActiveProtocol();\n const enableListener = button => {\n if (!button.id) {\n return;\n }\n const { commands, items } = button.props || button;\n if (items) {\n items.forEach(enableListener);\n }\n const hpCommand = commands?.find?.(isHangingProtocolCommand);\n if (!hpCommand) {\n return;\n }\n const { protocolId, stageIndex, stageId } = hpCommand.commandOptions;\n const isActive =\n (!protocolId || protocolId === protocol.id) &&\n (stageIndex === undefined || stageIndex === toggleStageIndex) &&\n (!stageId || stageId === stage.id);\n toolbarService.setToggled(button.id, isActive);\n };\n Object.values(toolbarService.getButtons()).forEach(enableListener);\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 const primaryToolBeforeHPChange = toolbarService.getActivePrimaryTool();\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 { protocol: oldProtocol } = hangingProtocolService.getActiveProtocol();\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 // This is a default action applied\n const { protocol } = hangingProtocolService.getActiveProtocol();\n actions.toggleHpTools();\n\n // try to use the same tool in the new hanging protocol stage\n const primaryButton = toolbarService.getButton(primaryToolBeforeHPChange);\n if (primaryButton) {\n // is there any type of interaction on this button, if not it might be in the\n // items. This is a bit of a hack, but it works for now.\n\n let interactionType = primaryButton.props?.interactionType;\n\n if (!interactionType && primaryButton.props?.items) {\n const firstItem = primaryButton.props.items[0];\n interactionType = firstItem.props?.interactionType || firstItem.props?.type;\n }\n\n if (interactionType) {\n toolbarService.recordInteraction({\n interactionType,\n ...primaryButton.props,\n });\n }\n }\n\n // Send the notification about updating the state\n if (protocolId !== hpInfo.protocolId) {\n // The old protocol callbacks are used for turning off things\n // like crosshairs when moving to the new HP\n commandsManager.run(oldProtocol.callbacks?.onProtocolExit);\n // The new protocol callback is used for things like\n // activating modes etc.\n }\n commandsManager.run(protocol.callbacks?.onProtocolEnter);\n return true;\n } catch (e) {\n console.error(e);\n actions.toggleHpTools();\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 }) => {\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 });\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 });\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 });\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 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 storeContexts: [],\n options: {},\n },\n displayNotification: {\n commandFn: actions.displayNotification,\n storeContexts: [],\n options: {},\n },\n setHangingProtocol: {\n commandFn: actions.setHangingProtocol,\n storeContexts: [],\n options: {},\n },\n toggleHangingProtocol: {\n commandFn: actions.toggleHangingProtocol,\n storeContexts: [],\n options: {},\n },\n navigateHistory: {\n commandFn: actions.navigateHistory,\n storeContexts: [],\n options: {},\n },\n nextStage: {\n commandFn: actions.deltaStage,\n storeContexts: [],\n options: { direction: 1 },\n },\n previousStage: {\n commandFn: actions.deltaStage,\n storeContexts: [],\n options: { direction: -1 },\n },\n setViewportGridLayout: {\n commandFn: actions.setViewportGridLayout,\n storeContexts: [],\n options: {},\n },\n toggleOneUp: {\n commandFn: actions.toggleOneUp,\n storeContexts: [],\n options: {},\n },\n openDICOMTagViewer: {\n commandFn: actions.openDICOMTagViewer,\n },\n updateViewportDisplaySet: {\n commandFn: actions.updateViewportDisplaySet,\n storeContexts: [],\n options: {},\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 // -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
\n
\n
\n \n
\n {dsConfigs\n .filter(it => it.sourceName !== 'dicomjson' && it.sourceName !== 'dicomlocal')\n .map(ds => (\n
\n

\n {ds.configuration?.friendlyName || ds.friendlyName}\n

\n {\n navigate({\n pathname: '/',\n search: `datasources=${ds.sourceName}`,\n });\n }}\n >\n {ds.sourceName}\n \n
\n
\n ))}\n
\n
\n
\n
\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;\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
\n
\n
{t(`Select ${itemLabel}`)}
\n \n
\n
\n {itemList == null ? (\n \n ) : itemList.length === 0 ? (\n
\n \n {t(`No ${itemLabel} available`)}\n
\n ) : (\n <>\n
{t(itemLabel)}
\n
\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 \n
{item.name}
\n onItemClicked(item)}\n className=\"invisible group-hover:visible\"\n endIcon={}\n >\n {t('Select')}\n \n
\n );\n })}\n
\n \n )}\n
\n \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;\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>();\n\n const [selectedItems, setSelectedItems] = useState(configuredItems);\n\n const [errorMessage, setErrorMessage] = useState();\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
\n
\n {t(`Error fetching ${itemLabels[selectedItems.length]} list`)}\n
\n
{errorMessage}
\n
\n );\n };\n\n const getSelectedItemsComponent = (): ReactElement => {\n return (\n
\n {itemLabels.map((itemLabel, itemLabelIndex) => {\n return (\n {\n setShowFullConfig(false);\n setSelectedItems(theList => theList.slice(0, itemLabelIndex));\n }\n : undefined\n }\n >\n
\n {itemLabelIndex < selectedItems.length ? (\n \n ) : (\n \n )}\n
{t(itemLabel)}
\n
\n {itemLabelIndex < selectedItems.length ? (\n
\n {selectedItems[itemLabelIndex].name}\n
\n ) : (\n

\n )}\n
\n );\n })}\n \n );\n };\n\n return (\n
\n {getSelectedItemsComponent()}\n
\n {errorMessage ? (\n getErrorComponent()\n ) : (\n {\n setShowFullConfig(false);\n setSelectedItems(theList => [...theList.slice(0, currentSelectedItemIndex + 1), item]);\n }}\n >\n )}\n
\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();\n\n const [configuredItems, setConfiguredItems] =\n useState>();\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
\n \n {configuredItems.map((item, itemIndex) => {\n return (\n \n \n {item.name}\n
\n {itemIndex !== configuredItems.length - 1 &&
|
}\n \n );\n })}\n \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 {\n const url = `${initialUrl}/projects`;\n\n const projects = (await GoogleCloudDataSourceConfigurationAPI._doFetch(\n url,\n ItemType.projects,\n this._fetchOptions\n )) as Array;\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 {\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> {\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 = {}\n ): Promise | Array> {\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 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 = {} }): void {\n const { stateSyncService } = servicesManager.services;\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 `::`\n // Used to recover manual changes to the layout of a stage.\n stateSyncService.register('viewportGridStore', { clearOnModeExit: true });\n\n // displaySetSelectorMap stores a map from\n // `::` 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 `:${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 `:`\n // to the previously applied hanging protolStageIndexMap 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\nconst handlePETImageMetadata = ({ SeriesInstanceUID, StudyInstanceUID }) => {\n const { instances } = DicomMetadataStore.getSeries(StudyInstanceUID, SeriesInstanceUID);\n\n const modality = instances[0].Modality;\n if (modality !== 'PT') {\n return;\n }\n const imageIds = instances.map(instance => instance.imageId);\n const instanceMetadataArray = [];\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 // try except block to prevent errors when the metadata is not correct\n let suvScalingFactors;\n try {\n suvScalingFactors = calculateSUVScalingFactors(instanceMetadataArray);\n } catch (error) {\n console.log(error);\n }\n\n if (!suvScalingFactors) {\n return;\n }\n\n instanceMetadataArray.forEach((instanceMetadata, index) => {\n metadataProvider.addCustomMetadata(imageIds[index], 'scalingModule', suvScalingFactors[index]);\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 { 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';\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 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};\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 ToolbarButtonWithServices from './Toolbar/ToolbarButtonWithServices';\n\nexport default function getToolbarModule({ commandsManager, servicesManager }) {\n return [\n {\n name: 'ohif.divider',\n defaultComponent: ToolbarDivider,\n clickHandler: () => {},\n },\n {\n name: 'ohif.action',\n defaultComponent: ToolbarButtonWithServices,\n clickHandler: () => {},\n },\n {\n name: 'ohif.radioGroup',\n defaultComponent: ToolbarButtonWithServices,\n clickHandler: () => {},\n },\n {\n name: 'ohif.splitButton',\n defaultComponent: ToolbarSplitButtonWithServices,\n clickHandler: () => {},\n },\n {\n name: 'ohif.layoutSelector',\n defaultComponent: ToolbarLayoutSelectorWithServices,\n clickHandler: (evt, clickedBtn, btnSectionName) => {},\n },\n {\n name: 'ohif.toggle',\n defaultComponent: ToolbarButtonWithServices,\n clickHandler: () => {},\n },\n ];\n}\n","import { CustomizationService } from '@ohif/core';\nimport React from 'react';\nimport DataSourceSelector from './Panels/DataSourceSelector';\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: () =>

Hello Custom Route

,\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 \n {this.label && {this.label}}\n {value}\n
\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 ];\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","arguments","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","_ref","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","e","next","done","Error","configLoad","RetrieveMetadataLoaderSync","getOptions","seriesInstanceUID","getLoaders","retrieveSeriesMetadata","bind","retrieveStudyMetadata","RetrieveMetadataLoaderAsync","getPreLoaders","preLoaders","searchForSeries","naturalizeDataset","dcmjs","DicomMetaDictionary","naturalized","map","sortStudySeries","sortingCriteria","seriesSortCriteria","seriesInfoSortingCriteria","seriesAsyncLoader","seriesInstanceUIDList","freeze","hasNext","shift","makeSeriesAsyncLoader","s","promises","enableStudyLazyLoad","retrieveMetadataLoader","moduleName","StudyMetaDataPromises","Map","has","get","promise","Promise","resolve","reject","RetrieveMetadata","then","data","set","deleteStudyMetadataPromise","delete","StaticWadoClient","api","DICOMwebClient","qidoConfig","super","staticWado","searchResult","lowerParams","toLowerParams","filter","study","studyFilterKeys","filterItem","series","seriesFilterKeys","compareValues","desired","actual","find","item","actualItem","Alphabetic","indexOf","substring","compareDateRange","range","dash","start","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","retrieveBulkData","arr","Blob","type","console","warn","BulkDataURI","hasQuery","hasAccept","fixBulkDataURI","dicomWebConfig","startsWith","origin","bulkDataURI","relativeResolution","DicomDict","denaturalizeDataset","ImplementationClassUID","ImplementationVersionName","EXPLICIT_VR_LITTLE_ENDIAN","metadataProvider","classes","MetadataProvider","createDicomWebApi","userAuthenticationService","dicomWebConfigCopy","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","_ref2","multipart","val","metadata","madeInClient","_retrieveSeriesMetadataAsync","_retrieveSeriesMetadataSync","store","dicom","dataset","request","ArrayBuffer","datasets","storeInstances","meta","FileMetaInformationVersion","_meta","MediaStorageSOPClassUID","SOPClassUID","MediaStorageSOPInstanceUID","TransferSyntaxUID","denaturalized","dicomDict","dict","write","naturalizedInstancesMetadata","seriesSummaryMetadata","instancesPerSeries","SeriesDescription","SeriesNumber","SeriesTime","ProtocolName","Modality","getImageIdsForInstance","wadoUri","addImageIdToUIDs","seriesMetadata","values","DicomMetadataStore","addSeriesMetadata","addInstances","seriesPromises","addRetrieveBulkData","enabled","ret","arrayBuffer","byteLength","aSeries","seriesDeliveredPromises","naturalizedInstances","index","all","getStudy","isLoaded","getImageIdsForDisplaySet","displaySet","images","imageIds","NumberOfFrames","_ref3","getConfig","getStudyInstanceUIDs","_ref4","StudyInstanceUIDs","paramsStudyInstanceUIDs","queryStudyInstanceUIDs","splitComma","getAll","supportsReject","xhr","XMLHttpRequest","open","log","onreadystatechange","readyState","status","responseText","send","IWebApiDataSource","create","OHIF","mappings","_store","urls","studyInstanceUIDMap","getMetaDataByURL","metaData","findStudies","aStudy","createDicomJSONApi","dicomJsonConfig","response","fetch","json","naturalizedDicom","param","mappedParam","NumInstances","Modalities","PatientID","StudyTime","customSort","seriesSummary","numberOfSeries","obj","i","EVENTS","END_MODALITIES","SR","SEG","DOC","compareValue","v1","v2","seriesA","seriesB","instanceA","instanceB","modalityA","modalityB","isEndA","isEndB","createDicomLocalApi","dicomLocalConfig","name","numInstances","Set","add","firstInstance","from","SeriesDate","_broadcastEvent","SERIES_ADDED","isMultiframe","frameIndex","INSTANCES_ADDED","naturalizedReport","reportBlob","datasetToBlob","objectUrl","window","location","assign","getInstance","StudyInstanceUIDsAsArray","isStudyInCache","sort","createDicomWebProxyApi","dicomWebProxyConfig","UserAuthenticationService","dicomWebDelegate","servers","dicomWeb","configuration","studyInstanceUIDs","split","createDataSource","Toolbar","servicesManager","toolbarService","services","toolbarButtons","setToolbarButtons","useState","useEffect","unsubscribe","subscribe","TOOL_BAR_MODIFIED","getButtonSection","onInteraction","useCallback","args","recordInteraction","React","toolDef","id","Component","componentProps","className","classnames","_extends","availableLanguages","defaultLanguage","currentLanguage","i18n","hotkeysManager","extensionManager","appConfig","useAppConfig","navigate","useNavigate","useLocation","t","useTranslation","show","hide","useModal","hotkeyDefinitions","hotkeyDefaults","menuOptions","title","icon","onClick","content","AboutModal","contentProps","versionNumber","process","commitHash","UserPreferences","getValidHotkeyDefinitions","onCancel","hotkeys","stopRecord","unpause","onSubmit","language","changeLanguage","setHotkeys","onReset","restoreDefaultBindings","hotkeysModule","oidc","encodeURIComponent","href","Header","isReturnEnabled","showStudyList","onClickReturnButton","pathname","dataSourceIdx","configUrl","URLSearchParams","dataSourceName","existingDataSource","getDataSources","searchQuery","append","decodeURIComponent","toString","WhiteLabeling","whiteLabeling","ErrorBoundary","context","side","activeTabIndex","activeTabIndexProp","tabs","panelService","hasBeenOpened","setHasBeenOpened","setActiveTabIndex","activatePanelSubscription","ACTIVATE_PANEL","activatePanelEvent","forceActive","tabIndex","findIndex","tab","panelId","SidePanel","onOpen","ViewerLayout","commandsManager","viewports","ViewportGridComp","leftPanels","rightPanels","leftPanelDefaultClosed","rightPanelDefaultClosed","hangingProtocolService","showLoadingIndicator","setShowLoadingIndicator","document","body","classList","remove","getComponent","entry","getModuleEntry","component","getPanelData","iconName","iconLabel","label","HangingProtocolService","PROTOCOL_CHANGED","leftPanelComponents","rightPanelComponents","viewportComponents","viewportComponent","namespace","displaySetsToDisplay","ViewerHeader","style","height","LoadingIndicatorProgress","SidePanelWithServices","propTypes","PropTypes","isRequired","CommandsManager","ServicesManager","children","sortStudyInstances","PanelStudyBrowser","getImageSrc","getStudiesForPatientByMRN","requestDisplaySetCreationForStudy","dataSource","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","includes","_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","ActionButtons","onExportClick","onCreateReportClick","LegacyButtonGroup","color","size","LegacyButton","defaultProps","alert","CREATE_REPORT_DIALOG_RESPONSE","CANCEL","CREATE_REPORT","CreateReportDialogPrompt","uiDialogService","dialogId","dataSourcesOpts","dataSourceMap","dataSourceDefs","supportsStow","placeHolder","centralize","isDraggable","Dialog","useLastPosition","showOverlay","activeDataSource","noCloseButton","onClose","_handleClose","dismiss","action","actions","text","ButtonEnums","secondary","primary","setValue","allowMultiSelectExport","Select","closeMenuOnSelect","placeholder","option","onChange","evt","v","isClearable","Input","autoFocus","labelClassName","event","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","_ref6","uid","isActive","measurements","measurement","m","MeasurementTable","jumpToMeasurement","onEdit","getMeasurement","onSubmitHandler","update","_ref5","getMeasurements","onClearMeasurementsClick","clearMeasurements","activeViewport","trackedMeasurements","referenceStudyUID","promptResult","createReportDialogPrompt","createReportAsync","runCommand","measurementData","additionalFindingTypes","types","displayText","baseDisplayText","baseLabel","selected","findingSites","finding","firstSite","siteText","site","measurementType","_mapMeasurementToDisplay","VALUE_TYPES","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","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","isMultiFrame","makeDisplaySet","isDisplaySetReconstructable","sortBy","a","b","parseInt","isSingleImageModality","getDisplaySetsFromSeries","sopClassUids","uniqueSopClassUidsInSeries","getSopClassUids","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","ToolbarDivider","LayoutSelector","rows","columns","onSelection","rest","isOpen","setIsOpen","closeOnOutsideClick","addEventListener","removeEventListener","DropdownContent","OHIFLayoutSelector","ToolbarButton","onInteractionHandler","rounded","dropdownContent","onLayoutChange","props","interactionType","commands","commandName","commandOptions","ToolbarSplitButtonWithServices","isRadio","isAction","groupId","items","renderer","handleItemClick","itemId","setState","state","isExpanded","getSplitButtonItems","buttonsState","setButtonState","primaryToolId","toggles","groups","isPrimaryToggle","isPrimaryActive","PrimaryButtonComponent","getButtonComponentForUIType","uiType","TOOL_BAR_STATE_MODIFIED","updatedItems","listItemRenderer","classNames","Icon","SplitButton","isToggle","tooltip","ToolbarButtonWithServices","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","ContextMenuItemsBuilder","preservePosition","preventCutOf","defaultPosition","_getDefaultPosition","ContextMenu","onClickOutside","eventData","onShowSubMenu","onDefault","run","getDefaultPosition","x","y","_getEventDefaultPosition","eventDetail","currentPoints","_getElementDefaultPosition","boundingClientRect","getBoundingClientRect","_getCanvasPointsPosition","points","viewerPos","pointIndex","point","_isValidPosition","source","canvasPoints","viewerElement","positionIterator","getPositionIterator","position","customizationType","nearbyToolData","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","reduce","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","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","step","inputClassName","labelPosition","trackColor","InputFilterText","onDebounceChange","DicomTagTable","reuseCachedLayout","syncService","protocol","getActiveProtocol","hpInfo","getState","protocolId","stageIndex","activeStudyUID","syncState","viewportGridStore","displaySetSelectorMap","stage","stages","storeId","cacheId","hangingProtocolStageIndexMap","viewportStructure","properties","custom","layout","numRows","numCols","viewport","displaySetOptions","displaySetUID","matchedDisplaySetsIndex","findOrCreateViewport","viewportsByPosition","positionId","byPositionViewport","inDisplay","initialInDisplay","missing","getMissingViewport","displaySetsInfo","viewportOptions","findViewportsByPosition","storedViewport","subscribeToNextViewportGridChange","isHangingProtocolCommand","command","customizationService","stateSyncService","contextMenuController","menuCustomizationId","optionsToUse","defaultContextMenu","displayNotification","clear","toggleHpTools","toggleStageIndex","enableListener","button","hpCommand","stageId","setToggled","getButtons","setHangingProtocol","reset","primaryToolBeforeHPChange","getActivePrimaryTool","oldProtocol","stateSyncReduce","reuseCachedLayouts","hangingId","useStageIdx","getStageIndex","setActiveStudyUID","storedHanging","restoreProtocol","setProtocol","primaryButton","getButton","firstItem","callbacks","onProtocolExit","onProtocolEnter","toggleHangingProtocol","desiredStageIndex","activeStudy","previousState","deltaStage","direction","oldStageIndex","setViewportGridLayout","setTimeout","completeLayout","stateReduce","layoutFindOrCreate","setLayout","toggleOneUp","viewportGridState","toggleOneUpViewportGridStore","viewportIdToUpdate","updatedViewportsViaHP","flat","preOneUpViewport","layoutOptions","getLayoutOptionsFromState","clearToggleOneUpViewportGridStore","navigateHistory","historyArgs","history","to","openDICOMTagViewer","activeViewportSpecificData","UIModalService","DicomTagBrowser","toggleOverlays","overlays","getElementsByClassName","toggle","scrollActiveThumbnailIntoView","activeDisplaySetInstanceUID","thumbnailList","querySelector","thumbnailListBounds","thumbnailBounds","top","bottom","scrollIntoView","behavior","updateViewportDisplaySet","_ref7","excludeNonImageModalities","nonImageModalities","dsSortFn","getDisplaySetSortFunction","currentDisplaySets","displaySetIndexToShow","definitions","commandFn","storeContexts","nextStage","previousStage","defaultContext","protocolMatchingRules","weight","attribute","constraint","greaterThan","toolGroupIds","displaySetSelectors","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","initialImageOptions","hpMNGrid","hpMNCompare","dsConfigs","dataSources","src","alt","sourceName","friendlyName","Button","itemLabel","itemList","onItemClicked","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","slice","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","concat","statusText","err","handlePETImageMetadata","getSeries","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","preRegistration","SERIES_UPDATED","register","clearOnModeExit","getDataSourcesModule","getLayoutTemplateModule","getPanelModule","getHangingProtocolModule","getSopClassHandlerModule","getToolbarModule","defaultComponent","clickHandler","ToolbarLayoutSelectorWithServices","clickedBtn","btnSectionName","getCommandsModule","getUtilityModule","getCustomizationModule","routes","path","DataSourceSelector","condition","contentF","transform","clonedObject","originalItems","DataSourceConfigurationComponent"],"sourceRoot":""}