Move files around to confuse James and Erik

This commit is contained in:
dannyrb 2020-05-21 16:24:35 -04:00
parent b5070dd518
commit 715377c565
21 changed files with 122 additions and 101 deletions

View File

@ -6,7 +6,7 @@ import {
processResults, processResults,
processSeriesResults, processSeriesResults,
} from './qido.js'; } from './qido.js';
import { dicomMetadataStore, IWebApiDataSource, utils } from '@ohif/core'; import { DicomMetadataStore, IWebApiDataSource, utils } from '@ohif/core';
import getImageId from './utils/getImageId'; import getImageId from './utils/getImageId';
import * as dcmjs from 'dcmjs'; import * as dcmjs from 'dcmjs';
@ -89,7 +89,7 @@ function createDicomWebApi(dicomWebConfig) {
series: { series: {
// TODO: change queryParams to `StudyInstanceUID` for now? // TODO: change queryParams to `StudyInstanceUID` for now?
// Conduct query, return a promise like others // Conduct query, return a promise like others
// Await this call and add to dicomMetadataStore after receiving result // Await this call and add to DicomMetadataStore after receiving result
metadata: (queryParams, callback) => { metadata: (queryParams, callback) => {
let { StudyInstanceUIDs } = urlUtil.parse(queryParams, true); let { StudyInstanceUIDs } = urlUtil.parse(queryParams, true);
@ -104,7 +104,7 @@ function createDicomWebApi(dicomWebConfig) {
const storeInstances = instances => { const storeInstances = instances => {
const naturalizedInstances = instances.map(naturalizeDataset); const naturalizedInstances = instances.map(naturalizeDataset);
dicomMetadataStore.addInstances(naturalizedInstances); DicomMetadataStore.addInstances(naturalizedInstances);
callback(naturalizedInstances); callback(naturalizedInstances);
}; };
@ -146,7 +146,7 @@ function createDicomWebApi(dicomWebConfig) {
function storeInstances(instances) { function storeInstances(instances) {
const naturalizedInstances = instances.map(naturalizeDataset); const naturalizedInstances = instances.map(naturalizeDataset);
dicomMetadataStore.addInstances(naturalizedInstances); DicomMetadataStore.addInstances(naturalizedInstances);
} }
seriesPromises.forEach(async seriesPromise => { seriesPromises.forEach(async seriesPromise => {

View File

@ -1,10 +1,6 @@
import RetrieveMetadataLoader from './retrieveMetadataLoader'; import RetrieveMetadataLoader from './retrieveMetadataLoader';
//import { sortStudySeries, sortingCriteria } from '../../sortStudy'; //import { sortStudySeries, sortingCriteria } from '../../sortStudy';
import getSeriesInfo from './utils/getSeriesInfo'; import getSeriesInfo from './utils/getSeriesInfo';
// import {
// createStudyFromSOPInstanceList,
// addInstancesToStudy,
// } from './studyInstanceHelpers';
/** /**
* Map seriesList to an array of seriesInstanceUid * Map seriesList to an array of seriesInstanceUid
@ -15,19 +11,6 @@ function mapStudySeries(seriesList) {
return seriesList.map(series => getSeriesInfo(series).seriesInstanceUid); return seriesList.map(series => getSeriesInfo(series).seriesInstanceUid);
} }
// function attachSeriesLoader(server, study, seriesLoader) {
// study.seriesLoader = Object.freeze({
// hasNext() {
// return seriesLoader.hasNext();
// },
// async next() {
// const series = await seriesLoader.next();
// await addInstancesToStudy(server, study, series.sopInstances);
// return study.seriesMap[series.seriesInstanceUID];
// },
// });
// }
/** /**
* Creates an immutable series loader object which loads each series sequentially using the iterator interface * Creates an immutable series loader object which loads each series sequentially using the iterator interface
* @param {DICOMWebClient} dicomWebClient The DICOMWebClient instance to be used for series load * @param {DICOMWebClient} dicomWebClient The DICOMWebClient instance to be used for series load

View File

@ -2,7 +2,7 @@ import React, { useState, useEffect, useCallback } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
// //
import { StudyBrowser, useImageViewer } from '@ohif/ui'; import { StudyBrowser, useImageViewer } from '@ohif/ui';
import { dicomMetadataStore } from '@ohif/core'; import { DicomMetadataStore } from '@ohif/core';
// This has to import from somewhere else... // This has to import from somewhere else...
function PanelStudyBrowser({ function PanelStudyBrowser({
@ -46,8 +46,10 @@ function PanelStudyBrowser({
} }
StudyInstanceUIDs.forEach(sid => fetchStudiesForPatient(sid)); StudyInstanceUIDs.forEach(sid => fetchStudiesForPatient(sid));
}, [StudyInstanceUIDs, getStudiesForPatientByStudyInstanceUID]); }, [
StudyInstanceUIDs,
getStudiesForPatientByStudyInstanceUID,
]);
const updateThumbnailMap = (displaySetInstanceUID, imageSrc) => { const updateThumbnailMap = (displaySetInstanceUID, imageSrc) => {
setThumbnailImageSrcMap( setThumbnailImageSrcMap(

View File

@ -2,7 +2,7 @@ async function getStudiesForPatientByStudyInstanceUID(
dataSource, dataSource,
StudyInstanceUID StudyInstanceUID
) { ) {
// TODO: The `dicomMetadataStore` should short-circuit both of these requests // TODO: The `DicomMetadataStore` should short-circuit both of these requests
// Data _could_ be here from route query, or if using JSON data source // Data _could_ be here from route query, or if using JSON data source
// We could also force this to "await" these values being available in the DICOMStore? // We could also force this to "await" these values being available in the DICOMStore?
// Kind of like promise fulfillment in cornerstone-wado-image-loader when there are multiple // Kind of like promise fulfillment in cornerstone-wado-image-loader when there are multiple
@ -18,6 +18,6 @@ async function getStudiesForPatientByStudyInstanceUID(
patientId: getStudyResult[0].mrn, patientId: getStudyResult[0].mrn,
}); });
} }
}; }
export default getStudiesForPatientByStudyInstanceUID; export default getStudiesForPatientByStudyInstanceUID;

View File

@ -77,7 +77,6 @@ function ViewerLayout({
label: tool.label, label: tool.label,
type: 'setToolActive', type: 'setToolActive',
onClick: () => { onClick: () => {
debugger;
commandsManager.runCommand(tool.commandName, commandOptions); commandsManager.runCommand(tool.commandName, commandOptions);
}, },
}); });
@ -104,8 +103,6 @@ function ViewerLayout({
// } // }
}); });
debugger;
setToolBarLayout(toolBarLayout); setToolBarLayout(toolBarLayout);
}; };
@ -134,7 +131,7 @@ function ViewerLayout({
moreTools={toolBarLayout[0].moreTools} moreTools={toolBarLayout[0].moreTools}
/> />
<div <div
className="flex flex-row flex-no-wrap items-stretch overflow-hidden w-full" className="flex flex-row flex-no-wrap items-stretch w-full overflow-hidden"
style={{ height: 'calc(100vh - 57px' }} style={{ height: 'calc(100vh - 57px' }}
> >
{/* LEFT SIDEPANELS */} {/* LEFT SIDEPANELS */}
@ -145,10 +142,10 @@ function ViewerLayout({
/> />
{/* TOOLBAR + GRID */} {/* TOOLBAR + GRID */}
<div className="flex flex-col flex-1 h-full"> <div className="flex flex-col flex-1 h-full">
<div className="flex flex-2 w-100 border-b border-transparent h-12"> <div className="flex h-12 border-b border-transparent flex-2 w-100">
<Toolbar type="secondary" tools={toolBarLayout[1].tools} /> <Toolbar type="secondary" tools={toolBarLayout[1].tools} />
</div> </div>
<div className="flex flex-1 h-full overflow-hidden bg-black items-center justify-center pb-2 pt-1"> <div className="flex items-center justify-center flex-1 h-full pt-1 pb-2 overflow-hidden bg-black">
<ViewportGridComp <ViewportGridComp
servicesManager={servicesManager} servicesManager={servicesManager}
viewportComponents={viewportComponents} viewportComponents={viewportComponents}

View File

@ -1,4 +1,6 @@
import { dicomMetadataStore } from '@ohif/core'; import { DicomMetadataStore } from '@ohif/core';
// TODO: Use above to inject so dependent datasources don't need to import or
// depend on @ohif/core?
/** /**
* Factory function that creates a new "Web API" data source. * Factory function that creates a new "Web API" data source.
@ -10,7 +12,12 @@ import { dicomMetadataStore } from '@ohif/core';
* It's worth noting that a single implementation of this interface * It's worth noting that a single implementation of this interface
* can define different underlying sources for "read" and "write" operations. * can define different underlying sources for "read" and "write" operations.
*/ */
function create({ query, retrieve, getImageIdsForDisplaySet }) { function create({
query,
retrieve,
retrieveSeriesMetadata,
getImageIdsForDisplaySet,
}) {
const defaultQuery = { const defaultQuery = {
studies: { studies: {
/** /**
@ -41,6 +48,7 @@ function create({ query, retrieve, getImageIdsForDisplaySet }) {
query: query || defaultQuery, query: query || defaultQuery,
retrieve: retrieve || defaultRetrieve, retrieve: retrieve || defaultRetrieve,
getImageIdsForDisplaySet, getImageIdsForDisplaySet,
retrieveSeriesMetadata,
// then go get all series level metadata. // then go get all series level metadata.
// Store this in the DICOM MetadataStore. // Store this in the DICOM MetadataStore.
}; };

View File

@ -4,7 +4,7 @@ import dicomParser from 'dicom-parser';
import getPixelSpacingInformation from '../utils/metadataProvider/getPixelSpacingInformation'; import getPixelSpacingInformation from '../utils/metadataProvider/getPixelSpacingInformation';
import fetchPaletteColorLookupTableData from '../utils/metadataProvider/fetchPaletteColorLookupTableData'; import fetchPaletteColorLookupTableData from '../utils/metadataProvider/fetchPaletteColorLookupTableData';
import fetchOverlayData from '../utils/metadataProvider/fetchOverlayData'; import fetchOverlayData from '../utils/metadataProvider/fetchOverlayData';
import dicomMetadataStore from '../dicomMetadataStore'; import DicomMetadataStore from '../services/DicomMetadataStore';
class MetadataProvider { class MetadataProvider {
constructor() { constructor() {
@ -123,7 +123,7 @@ class MetadataProvider {
const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = uids; const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = uids;
return dicomMetadataStore.getInstance( return DicomMetadataStore.getInstance(
StudyInstanceUID, StudyInstanceUID,
SeriesInstanceUID, SeriesInstanceUID,
SOPInstanceUID SOPInstanceUID

View File

@ -19,18 +19,19 @@ import string from './string.js';
import studies from './studies/'; import studies from './studies/';
import ui from './ui'; import ui from './ui';
import user from './user.js'; import user from './user.js';
import dicomMetadataStore from './dicomMetadataStore';
import { ViewModelProvider, useViewModel } from './ViewModelContext'; import { ViewModelProvider, useViewModel } from './ViewModelContext';
import utils, { hotkeys } from './utils/'; import utils, { hotkeys } from './utils/';
import { import {
MeasurementService,
UIDialogService, UIDialogService,
UIModalService, UIModalService,
UINotificationService, UINotificationService,
UIViewportDialogService, UIViewportDialogService,
//
DicomMetadataStore,
DisplaySetService, DisplaySetService,
ToolBarSerivce, ToolBarSerivce,
MeasurementService,
} from './services'; } from './services';
import IWebApiDataSource from './DataSources/IWebApiDataSource'; import IWebApiDataSource from './DataSources/IWebApiDataSource';
@ -71,7 +72,7 @@ const OHIF = {
MeasurementService, MeasurementService,
ToolBarSerivce, ToolBarSerivce,
IWebApiDataSource, IWebApiDataSource,
dicomMetadataStore, DicomMetadataStore,
// //
ViewModelProvider, ViewModelProvider,
useViewModel, useViewModel,
@ -112,7 +113,7 @@ export {
MeasurementService, MeasurementService,
ToolBarSerivce, ToolBarSerivce,
IWebApiDataSource, IWebApiDataSource,
dicomMetadataStore, DicomMetadataStore,
ViewModelProvider, ViewModelProvider,
useViewModel, useViewModel,
}; };

View File

@ -1,26 +1,6 @@
import { import pubSubServiceInterface from '../_shared/pubSubServiceInterface';
createStudyFromSOPInstanceList, import StudyMetadata from './StudyMetadata';
addInstancesToStudy, import EVENTS from './EVENTS';
} from './studies/services/wado/studyInstanceHelpers';
class StudyMetadata {
constructor(StudyInstanceUID) {
this.StudyInstanceUID = StudyInstanceUID;
this.series = [];
}
addSeries(instances) {
this.series.push(new SeriesMetadata(instances));
}
}
class SeriesMetadata {
constructor(instances) {
const { SeriesInstanceUID } = instances[0];
this.SeriesInstanceUID = SeriesInstanceUID;
this.instances = instances;
}
}
const _model = { const _model = {
studies: [], studies: [],
@ -74,7 +54,9 @@ function _getInstance(StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID) {
); );
} }
const dicomMetadataStore = { const BaseImplementation = {
EVENTS,
listeners: {},
addInstances(instances) { addInstances(instances) {
const { StudyInstanceUID } = instances[0]; const { StudyInstanceUID } = instances[0];
@ -116,10 +98,14 @@ const dicomMetadataStore = {
getInstance: _getInstance, getInstance: _getInstance,
}; };
// const DicomMetadataStore = Object.assign(
{},
BaseImplementation,
pubSubServiceInterface
);
// TODO => Add instances // TODO => Add instances
//_addInstance(input) // arraybuffer, or other stuff //_addInstance(input) // arraybuffer, or other stuff
export { dicomMetadataStore }; export { DicomMetadataStore };
export default dicomMetadataStore; export default DicomMetadataStore;

View File

@ -0,0 +1,6 @@
const EVENTS = {
DISPLAY_SETS_ADDED: 'event::displaySetService:displaySetsAdded',
DISPLAY_SETS_CHANGED: 'event::displaySetService:displaySetsChanged',
};
export default EVENTS;

View File

@ -0,0 +1,9 @@
class SeriesMetadata {
constructor(instances) {
const { SeriesInstanceUID } = instances[0];
this.SeriesInstanceUID = SeriesInstanceUID;
this.instances = instances;
}
}
export default SeriesMetadata;

View File

@ -0,0 +1,14 @@
import SeriesMetadata from './SeriesMetadata';
class StudyMetadata {
constructor(StudyInstanceUID) {
this.StudyInstanceUID = StudyInstanceUID;
this.series = [];
}
addSeries(instances) {
this.series.push(new SeriesMetadata(instances));
}
}
export default StudyMetadata;

View File

@ -0,0 +1,4 @@
import DicomMetadataStore from './DicomMetadataStore';
export { DicomMetadataStore };
export default DicomMetadataStore;

View File

@ -1,17 +1,13 @@
import pubSubServiceInterface from '../pubSubServiceInterface'; import pubSubServiceInterface from '../_shared/pubSubServiceInterface';
import EVENTS from './EVENTS';
const EVENTS = {
DISPLAY_SETS_ADDED: 'event::displaySetService:displaySetsAdded',
DISPLAY_SETS_CHANGED: 'event::displaySetService:displaySetsChanged',
};
const displaySetCache = []; const displaySetCache = [];
export default class DisplaySetService { export default class DisplaySetService {
constructor() { constructor() {
this.displaySets = {}; this.displaySets = {};
this.EVENTS = EVENTS;
this.listeners = {}; this.listeners = {};
this.EVENTS = EVENTS;
Object.assign(this, pubSubServiceInterface); Object.assign(this, pubSubServiceInterface);
} }
@ -50,27 +46,11 @@ export default class DisplaySetService {
* @param {string} displaySetInstanceUID * @param {string} displaySetInstanceUID
* @returns {object} displaySet * @returns {object} displaySet
*/ */
getDisplaySetByUID = displaySetInstanceUid => displaySetCache.find( getDisplaySetByUID = displaySetInstanceUid =>
displaySetCache.find(
displaySet => displaySet.displaySetInstanceUID === displaySetInstanceUid displaySet => displaySet.displaySetInstanceUID === displaySetInstanceUid
); );
/**
* Broadcasts displaySetService changes.
*
* @param {string} eventName The event name
* @return void
*/
_broadcastChange = (eventName, callbackProps) => {
const hasListeners = Object.keys(this.listeners).length > 0;
const hasCallbacks = Array.isArray(this.listeners[eventName]);
if (hasListeners && hasCallbacks) {
this.listeners[eventName].forEach(listener => {
listener.callback(callbackProps);
});
}
};
makeDisplaySets = (input, batch = false) => { makeDisplaySets = (input, batch = false) => {
if (!input || !input.length) { if (!input || !input.length) {
throw new Error('No instances were provided.'); throw new Error('No instances were provided.');
@ -98,12 +78,9 @@ export default class DisplaySetService {
} }
if (displaySetsAdded && displaySetsAdded.length) { if (displaySetsAdded && displaySetsAdded.length) {
this._broadcastChange(EVENTS.DISPLAY_SETS_ADDED, displaySetsAdded); this._broadcastEvent(EVENTS.DISPLAY_SETS_ADDED, displaySetsAdded);
this._broadcastChange( this._broadcastEvent(EVENTS.DISPLAY_SETS_CHANGED, this.activeDisplaySets);
EVENTS.DISPLAY_SETS_CHANGED,
this.activeDisplaySets
);
} }
}; };

View File

@ -0,0 +1,6 @@
const EVENTS = {
DISPLAY_SETS_ADDED: 'event::displaySetService:displaySetsAdded',
DISPLAY_SETS_CHANGED: 'event::displaySetService:displaySetsChanged',
};
export default EVENTS;

View File

@ -1,6 +1,6 @@
import log from '../../log'; import log from '../../log';
import guid from '../../utils/guid'; import guid from '../../utils/guid';
import pubSubServiceInterface from '../pubSubServiceInterface'; import pubSubServiceInterface from '../_shared/pubSubServiceInterface';
/** /**
* Measurement source schema * Measurement source schema

View File

@ -1,4 +1,4 @@
import pubSubServiceInterface from '../pubSubServiceInterface'; import pubSubServiceInterface from '../_shared/pubSubServiceInterface';
const EVENTS = { const EVENTS = {
TOOL_BAR_MODIFIED: 'event::toolBarService:toolBarModified', TOOL_BAR_MODIFIED: 'event::toolBarService:toolBarModified',

View File

@ -0,0 +1,3 @@
import pubSubServiceInterface from './pubSubServiceInterface';
export { pubSubServiceInterface };

View File

@ -1,7 +1,13 @@
import guid from '../../utils/guid'; import guid from '../../utils/guid';
/**
* Consumer must implement:
* this.listeners = {}
* this.EVENTS = { "EVENT_KEY": "EVENT_VALUE" }
*/
export default { export default {
subscribe, subscribe,
_broadcastEvent,
_unsubscribe, _unsubscribe,
_isValidEvent, _isValidEvent,
}; };
@ -62,3 +68,21 @@ function _unsubscribe(eventName, listenerId) {
function _isValidEvent(eventName) { function _isValidEvent(eventName) {
return Object.values(this.EVENTS).includes(eventName); return Object.values(this.EVENTS).includes(eventName);
} }
/**
* Broadcasts displaySetService changes.
*
* @param {string} eventName - The event name
* @param {func} callbackProps - Properties to pass callback
* @return void
*/
function _broadcastEvent(eventName, callbackProps) {
const hasListeners = Object.keys(this.listeners).length > 0;
const hasCallbacks = Array.isArray(this.listeners[eventName]);
if (hasListeners && hasCallbacks) {
this.listeners[eventName].forEach(listener => {
listener.callback(callbackProps);
});
}
}

View File

@ -4,6 +4,7 @@ import UIDialogService from './UIDialogService';
import UIModalService from './UIModalService'; import UIModalService from './UIModalService';
import UINotificationService from './UINotificationService'; import UINotificationService from './UINotificationService';
import UIViewportDialogService from './UIViewportDialogService'; import UIViewportDialogService from './UIViewportDialogService';
import DicomMetadataStore from './DicomMetadataStore';
import DisplaySetService from './DisplaySetService'; import DisplaySetService from './DisplaySetService';
import ToolBarSerivce from './ToolBarService'; import ToolBarSerivce from './ToolBarService';
@ -14,6 +15,7 @@ export {
UIModalService, UIModalService,
UINotificationService, UINotificationService,
UIViewportDialogService, UIViewportDialogService,
DicomMetadataStore,
DisplaySetService, DisplaySetService,
ToolBarSerivce, ToolBarSerivce,
}; };

View File

@ -38,6 +38,7 @@ function DataSourceWrapper(props) {
const firstAppConfigDataSource = appConfig.dataSources[0]; const firstAppConfigDataSource = appConfig.dataSources[0];
const dataSourceConfig = firstAppConfigDataSource.configuration; const dataSourceConfig = firstAppConfigDataSource.configuration;
const firstWebApiDataSource = webApiDataSources[0]; const firstWebApiDataSource = webApiDataSources[0];
debugger;
const dataSource = firstWebApiDataSource.createDataSource(dataSourceConfig); const dataSource = firstWebApiDataSource.createDataSource(dataSourceConfig);
// Route props --> studies.mapParams // Route props --> studies.mapParams
@ -48,7 +49,6 @@ function DataSourceWrapper(props) {
// Or no data fetching here, and just hand down my source // Or no data fetching here, and just hand down my source
const [data, setData] = useState(); const [data, setData] = useState();
useEffect(() => { useEffect(() => {
// 204: no content // 204: no content
async function getData() { async function getData() {
const searchResults = await dataSource.query.studies.search( const searchResults = await dataSource.query.studies.search(
@ -61,7 +61,6 @@ function DataSourceWrapper(props) {
getData(); getData();
} catch (ex) { } catch (ex) {
console.warn(ex); console.warn(ex);
} }
console.log('DataSourceWrapper: useEffect'); console.log('DataSourceWrapper: useEffect');
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps