fix: jump to measurement forever (#4867)
This commit is contained in:
1 parent
eafa2efda5
commit
d7bd36544a
39 files changed
+731
-448
No files matched your search
@@ -670,8 +670,11 @@ class MeasurementService extends PubSubService {
|
||||
measurement,
|
||||
});
|
||||
|
||||
this._broadcastEvent(EVENTS.JUMP_TO_MEASUREMENT_VIEWPORT, consumableEvent);
|
||||
// Important: we should broadcast the layout event first, since
|
||||
// in the layout there might be a viewport that we can match and choose
|
||||
// and jump in it before we decide on changing the orientation of different viewports
|
||||
this._broadcastEvent(EVENTS.JUMP_TO_MEASUREMENT_LAYOUT, consumableEvent);
|
||||
this._broadcastEvent(EVENTS.JUMP_TO_MEASUREMENT_VIEWPORT, consumableEvent);
|
||||
}
|
||||
|
||||
_getSourceUID(name, version) {
|
||||
|
||||
@@ -38,6 +38,10 @@ class ViewportGridService extends PubSubService {
|
||||
this.presentationIdProviders.set(id, provider);
|
||||
}
|
||||
|
||||
public setIsReferenceViewable(viewportId: string, isReferenceViewable: boolean): void {
|
||||
this.serviceImplementation._setIsReferenceViewable(viewportId, isReferenceViewable);
|
||||
}
|
||||
|
||||
public getPresentationId(id: string, viewportId: string): string | null {
|
||||
const state = this.getState();
|
||||
const viewport = state.viewports.get(viewportId);
|
||||
@@ -93,7 +97,12 @@ class ViewportGridService extends PubSubService {
|
||||
set: setImplementation,
|
||||
getNumViewportPanes: getNumViewportPanesImplementation,
|
||||
setViewportIsReady: setViewportIsReadyImplementation,
|
||||
setIsReferenceViewable: setIsReferenceViewableImplementation,
|
||||
getViewportState: getViewportStateImplementation,
|
||||
}): void {
|
||||
if (getViewportStateImplementation) {
|
||||
this.serviceImplementation._getViewportState = getViewportStateImplementation;
|
||||
}
|
||||
if (getStateImplementation) {
|
||||
this.serviceImplementation._getState = getStateImplementation;
|
||||
}
|
||||
@@ -123,6 +132,9 @@ class ViewportGridService extends PubSubService {
|
||||
if (setViewportIsReadyImplementation) {
|
||||
this.serviceImplementation._setViewportIsReady = setViewportIsReadyImplementation;
|
||||
}
|
||||
if (setIsReferenceViewableImplementation) {
|
||||
this.serviceImplementation._setIsReferenceViewable = setIsReferenceViewableImplementation;
|
||||
}
|
||||
}
|
||||
|
||||
public publishViewportsReady() {
|
||||
@@ -148,8 +160,7 @@ class ViewportGridService extends PubSubService {
|
||||
}
|
||||
|
||||
public getViewportState(viewportId: string) {
|
||||
const state = this.getState();
|
||||
return state.viewports.get(viewportId);
|
||||
return this.serviceImplementation._getViewportState(viewportId);
|
||||
}
|
||||
|
||||
public setViewportIsReady(viewportId, callback) {
|
||||
|
||||
@@ -45,6 +45,10 @@ export interface ViewportGridState {
|
||||
activeViewportId: string | null;
|
||||
layout: Layout;
|
||||
isHangingProtocolLayout: boolean;
|
||||
isReferenceViewable: (props: {
|
||||
viewportId: string;
|
||||
reference: Record<string, unknown>;
|
||||
}) => boolean;
|
||||
viewports: GridViewports;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { vec3 } from 'gl-matrix';
|
||||
|
||||
/**
|
||||
* Get the plane (orientation) to which the ImageOrientationPatient is most closely aligned
|
||||
*
|
||||
* @param displaySetService
|
||||
* @param displaySetInstanceUID
|
||||
* @returns orientation
|
||||
*/
|
||||
export default function getClosestOrientationFromIOP(displaySetService, displaySetInstanceUID) {
|
||||
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
||||
const imageOrientationPatient = displaySet.instances[0].ImageOrientationPatient as Array<number>;
|
||||
// ImageOrientationPatient must be an array of length 6.
|
||||
if (imageOrientationPatient?.length !== 6) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Take cross product to get vector coming "out" of image plane
|
||||
const rowCosineVec = vec3.fromValues(
|
||||
imageOrientationPatient[0],
|
||||
imageOrientationPatient[1],
|
||||
imageOrientationPatient[2]
|
||||
);
|
||||
const colCosineVec = vec3.fromValues(
|
||||
imageOrientationPatient[3],
|
||||
imageOrientationPatient[4],
|
||||
imageOrientationPatient[5]
|
||||
);
|
||||
const scanAxisNormal = vec3.cross(vec3.create(), rowCosineVec, colCosineVec);
|
||||
|
||||
// Define the reference vectors for axial, coronal, and sagittal planes
|
||||
const unitVectors = {
|
||||
axial: vec3.fromValues(0, 0, 1),
|
||||
coronal: vec3.fromValues(0, 1, 0),
|
||||
sagittal: vec3.fromValues(1, 0, 0),
|
||||
};
|
||||
|
||||
// Compute dot products for each reference plane
|
||||
// Because all vectors are normalized, dot product is bounded between -1 and 1
|
||||
let maxDot = 0;
|
||||
let maxOrientation: string = '';
|
||||
for (const [k, v] of Object.entries(unitVectors)) {
|
||||
// Absolute value of dot product because we only care about alignment with the axis
|
||||
// For example, dot product of -1 for a given axis means perfect alignment
|
||||
// but the image is pointing in the "opposite" direction
|
||||
const res = Math.abs(vec3.dot(scanAxisNormal, v));
|
||||
if (res > maxDot) {
|
||||
maxDot = res;
|
||||
maxOrientation = k;
|
||||
}
|
||||
}
|
||||
|
||||
return maxOrientation;
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import * as utils from './index';
|
||||
|
||||
describe('Top level exports', () => {
|
||||
test('should export the modules ', () => {
|
||||
const expectedExports = [
|
||||
'guid',
|
||||
'ObjectPath',
|
||||
'absoluteUrl',
|
||||
'seriesSortCriteria',
|
||||
'sortBy',
|
||||
'sortStudy',
|
||||
'sortBySeriesDate',
|
||||
'sortStudyInstances',
|
||||
'sortStudySeries',
|
||||
'sortingCriteria',
|
||||
'splitComma',
|
||||
'getSplitParam',
|
||||
'isLowPriorityModality',
|
||||
'writeScript',
|
||||
'debounce',
|
||||
'downloadCSVReport',
|
||||
'imageIdToURI',
|
||||
'roundNumber',
|
||||
'b64toBlob',
|
||||
'sopClassDictionary',
|
||||
'createStudyBrowserTabs',
|
||||
'formatDate',
|
||||
'formatTime',
|
||||
'formatPN',
|
||||
'generateAcceptHeader',
|
||||
'isEqualWithin',
|
||||
//'loadAndCacheDerivedDisplaySets',
|
||||
'isDisplaySetReconstructable',
|
||||
'isImage',
|
||||
'urlUtil',
|
||||
'makeDeferred',
|
||||
'makeCancelable',
|
||||
'hotkeys',
|
||||
'Queue',
|
||||
'isDicomUid',
|
||||
'resolveObjectPath',
|
||||
'hierarchicalListUtils',
|
||||
'progressTrackingUtils',
|
||||
'uuidv4',
|
||||
'addAccessors',
|
||||
'MeasurementFilters',
|
||||
].sort();
|
||||
|
||||
const exports = Object.keys(utils.default).sort();
|
||||
|
||||
expect(exports).toEqual(expectedExports);
|
||||
});
|
||||
});
|
||||
@@ -40,7 +40,7 @@ import { splitComma, getSplitParam } from './splitComma';
|
||||
import { createStudyBrowserTabs } from './createStudyBrowserTabs';
|
||||
import { sopClassDictionary } from './sopClassDictionary';
|
||||
import * as MeasurementFilters from './measurementFilters';
|
||||
|
||||
import getClosestOrientationFromIOP from './getClosestOrientationFromIOP';
|
||||
// Commented out unused functionality.
|
||||
// Need to implement new mechanism for derived displaySets using the displaySetManager.
|
||||
|
||||
@@ -86,6 +86,7 @@ const utils = {
|
||||
generateAcceptHeader,
|
||||
createStudyBrowserTabs,
|
||||
MeasurementFilters,
|
||||
getClosestOrientationFromIOP,
|
||||
};
|
||||
|
||||
export {
|
||||
@@ -120,6 +121,7 @@ export {
|
||||
generateAcceptHeader,
|
||||
createStudyBrowserTabs,
|
||||
MeasurementFilters,
|
||||
getClosestOrientationFromIOP,
|
||||
};
|
||||
|
||||
export default utils;
|
||||
Reference in new issue
Block a user