fix tool import
This commit is contained in:
+155
-117
@@ -1073,132 +1073,152 @@ function App() {
|
|||||||
}
|
}
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Export the current viewer state as JSON
|
// Export the current viewer state as JSON
|
||||||
window.exportViewerState = () => {
|
window.exportViewerState = () => {
|
||||||
const numActive = viewportGrid.rows * viewportGrid.cols;
|
const numActive = viewportGrid.rows * viewportGrid.cols;
|
||||||
const modes = viewportModes.slice(0, numActive);
|
const modes = viewportModes.slice(0, numActive);
|
||||||
const stackIdx = selectedStackIdx.slice(0, numActive);
|
const stackIdx = selectedStackIdx.slice(0, numActive);
|
||||||
const stacks = availableStacks.map(s => ({
|
const stacks = availableStacks.map(s => ({
|
||||||
i: s.imageIds, // imageIds
|
i: s.imageIds, // imageIds
|
||||||
u: s.studyInstanceUID // studyInstanceUID
|
u: s.studyInstanceUID // studyInstanceUID
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Only keep minimal properties
|
// Only keep minimal properties
|
||||||
const renderingEngine = renderingEngineRef.current;
|
|
||||||
const props: any[] = [];
|
|
||||||
const stackPos: number[] = [];
|
|
||||||
const cam: any[] = [];
|
|
||||||
for (let i = 0; i < numActive; i++) {
|
|
||||||
let p = null, s = null, c = null;
|
|
||||||
if (renderingEngine) {
|
|
||||||
const viewportId = `CT_${i}`;
|
|
||||||
const viewport = renderingEngine.getViewport(viewportId);
|
|
||||||
if (viewport) {
|
|
||||||
if (typeof viewport.getProperties === "function") {
|
|
||||||
const { voiRange, invert, interpolationType, VOILUTFunction, colormap } = viewport.getProperties();
|
|
||||||
p = { voiRange, invert, interpolationType, VOILUTFunction, colormap };
|
|
||||||
}
|
|
||||||
if (typeof viewport.getCurrentImageIdIndex === "function") {
|
|
||||||
s = viewport.getCurrentImageIdIndex();
|
|
||||||
}
|
|
||||||
if (typeof viewport.getCamera === "function") {
|
|
||||||
c = viewport.getCamera();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
props.push(p);
|
|
||||||
stackPos.push(s);
|
|
||||||
cam.push(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use short keys for compactness
|
|
||||||
const state = {
|
|
||||||
grid: viewportGrid,
|
|
||||||
modes,
|
|
||||||
stacks,
|
|
||||||
stackIdx,
|
|
||||||
stackPos,
|
|
||||||
props,
|
|
||||||
cam,
|
|
||||||
};
|
|
||||||
return JSON.stringify(state);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Import and restore a viewer state from JSON (using stack indices)
|
|
||||||
window.importViewerState = (json: string) => {
|
|
||||||
try {
|
|
||||||
restoringStateRef.current = true;
|
|
||||||
const state = typeof json === "string" ? JSON.parse(json) : json;
|
|
||||||
if (state.grid) setViewportGrid(state.grid);
|
|
||||||
if (state.modes) setViewportModes(state.modes);
|
|
||||||
if (state.stacks) setAvailableStacks(state.stacks.map((s: any) => ({
|
|
||||||
imageIds: s.i,
|
|
||||||
studyInstanceUID: s.u,
|
|
||||||
})));
|
|
||||||
if (state.stackIdx && state.stacks) {
|
|
||||||
const reconstructed = state.stackIdx.map(
|
|
||||||
(idx: number) => state.stacks[idx]?.i || []
|
|
||||||
);
|
|
||||||
setViewportImageIds(reconstructed);
|
|
||||||
setSelectedStackIdx(state.stackIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
const renderingEngine = renderingEngineRef.current;
|
const renderingEngine = renderingEngineRef.current;
|
||||||
if (!renderingEngine) {
|
const props: any[] = [];
|
||||||
restoringStateRef.current = false;
|
const stackPos: number[] = [];
|
||||||
return;
|
const cam: any[] = [];
|
||||||
}
|
|
||||||
const numActive = state.grid?.rows * state.grid?.cols || 1;
|
|
||||||
for (let i = 0; i < numActive; i++) {
|
for (let i = 0; i < numActive; i++) {
|
||||||
const viewportId = `CT_${i}`;
|
let p = null, s = null, c = null;
|
||||||
const viewport = renderingEngine.getViewport(viewportId);
|
if (renderingEngine) {
|
||||||
if (!viewport) continue;
|
const viewportId = `CT_${i}`;
|
||||||
|
const viewport = renderingEngine.getViewport(viewportId);
|
||||||
// Restore stack position
|
if (viewport) {
|
||||||
if (
|
if (typeof viewport.getProperties === "function") {
|
||||||
state.stackPos &&
|
const { voiRange, invert, interpolationType, VOILUTFunction, colormap } = viewport.getProperties();
|
||||||
typeof state.stackPos[i] === "number" &&
|
p = { voiRange, invert, interpolationType, VOILUTFunction, colormap };
|
||||||
typeof viewport.setImageIdIndex === "function"
|
}
|
||||||
) {
|
if (typeof viewport.getCurrentImageIdIndex === "function") {
|
||||||
if (csUtilities && csUtilities.jumpToSlice) {
|
s = viewport.getCurrentImageIdIndex();
|
||||||
csUtilities.jumpToSlice(viewport.element, { imageIndex: state.stackPos[i] });
|
}
|
||||||
} else {
|
if (typeof viewport.getCamera === "function") {
|
||||||
viewport.setImageIdIndex(state.stackPos[i]);
|
c = viewport.getCamera();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
props.push(p);
|
||||||
// Restore properties
|
stackPos.push(s);
|
||||||
if (
|
cam.push(c);
|
||||||
state.props &&
|
|
||||||
state.props[i] &&
|
|
||||||
typeof viewport.setProperties === "function"
|
|
||||||
) {
|
|
||||||
viewport.setProperties(state.props[i]);
|
|
||||||
viewport.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore camera
|
|
||||||
if (
|
|
||||||
state.cam &&
|
|
||||||
state.cam[i] &&
|
|
||||||
typeof viewport.setCamera === "function"
|
|
||||||
) {
|
|
||||||
viewport.setCamera(state.cam[i]);
|
|
||||||
viewport.render();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
restoringStateRef.current = false;
|
|
||||||
}, 300);
|
// Use short keys for compactness
|
||||||
} catch (e) {
|
const state = {
|
||||||
restoringStateRef.current = false;
|
grid: viewportGrid,
|
||||||
alert("Failed to import viewer state: " + e);
|
modes,
|
||||||
}
|
stacks,
|
||||||
};
|
stackIdx,
|
||||||
|
stackPos,
|
||||||
|
props,
|
||||||
|
cam,
|
||||||
|
};
|
||||||
|
return JSON.stringify(state);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Import and restore a viewer state from JSON (using stack indices)
|
||||||
|
window.importViewerState = (json: string) => {
|
||||||
|
try {
|
||||||
|
restoringStateRef.current = true;
|
||||||
|
const state = typeof json === "string" ? JSON.parse(json) : json;
|
||||||
|
if (state.grid) setViewportGrid(state.grid);
|
||||||
|
if (state.modes) setViewportModes(state.modes);
|
||||||
|
if (state.stacks) setAvailableStacks(state.stacks.map((s: any) => ({
|
||||||
|
imageIds: s.i,
|
||||||
|
studyInstanceUID: s.u,
|
||||||
|
})));
|
||||||
|
if (state.stackIdx && state.stacks) {
|
||||||
|
const reconstructed = state.stackIdx.map(
|
||||||
|
(idx: number) => state.stacks[idx]?.i || []
|
||||||
|
);
|
||||||
|
setViewportImageIds(reconstructed);
|
||||||
|
setSelectedStackIdx(state.stackIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const renderingEngine = renderingEngineRef.current;
|
||||||
|
if (!renderingEngine) {
|
||||||
|
restoringStateRef.current = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const numActive = state.grid?.rows * state.grid?.cols || 1;
|
||||||
|
for (let i = 0; i < numActive; i++) {
|
||||||
|
const viewportId = `CT_${i}`;
|
||||||
|
const viewport = renderingEngine.getViewport(viewportId);
|
||||||
|
if (!viewport) continue;
|
||||||
|
|
||||||
|
// Restore stack position
|
||||||
|
if (
|
||||||
|
state.stackPos &&
|
||||||
|
typeof state.stackPos[i] === "number" &&
|
||||||
|
typeof viewport.setImageIdIndex === "function"
|
||||||
|
) {
|
||||||
|
if (csUtilities && csUtilities.jumpToSlice) {
|
||||||
|
csUtilities.jumpToSlice(viewport.element, { imageIndex: state.stackPos[i] });
|
||||||
|
} else {
|
||||||
|
viewport.setImageIdIndex(state.stackPos[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore properties
|
||||||
|
if (
|
||||||
|
state.props &&
|
||||||
|
state.props[i] &&
|
||||||
|
typeof viewport.setProperties === "function"
|
||||||
|
) {
|
||||||
|
viewport.setProperties(state.props[i]);
|
||||||
|
viewport.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore camera
|
||||||
|
if (
|
||||||
|
state.cam &&
|
||||||
|
state.cam[i] &&
|
||||||
|
typeof viewport.setCamera === "function"
|
||||||
|
) {
|
||||||
|
viewport.setCamera(state.cam[i]);
|
||||||
|
viewport.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
restoringStateRef.current = false;
|
||||||
|
}, 300);
|
||||||
|
} catch (e) {
|
||||||
|
restoringStateRef.current = false;
|
||||||
|
alert("Failed to import viewer state: " + e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Export all annotations using cornerstoneTools.annotation.state.getAllAnnotations()
|
// Export all annotations using cornerstoneTools.annotation.state.getAllAnnotations()
|
||||||
window.exportAnnotations = () => {
|
window.exportAnnotations = () => {
|
||||||
try {
|
try {
|
||||||
const allAnnotations = cornerstoneTools.annotation.state.getAllAnnotations();
|
let allAnnotations = cornerstoneTools.annotation.state.getAllAnnotations();
|
||||||
|
console.log("Exporting annotations:", allAnnotations);
|
||||||
|
// Remove ReferenceLines annotations (toolName may be 'ReferenceLines')
|
||||||
|
if (Array.isArray(allAnnotations)) {
|
||||||
|
// Only keep annotations with toolName in the allowed list
|
||||||
|
const allowedTools = [
|
||||||
|
LengthTool.toolName,
|
||||||
|
ArrowAnnotateTool.toolName,
|
||||||
|
RectangleROITool.toolName,
|
||||||
|
EllipticalROITool.toolName,
|
||||||
|
PlanarFreehandROITool.toolName,
|
||||||
|
PlanarFreehandContourSegmentationTool.toolName,
|
||||||
|
ProbeTool.toolName,
|
||||||
|
SculptorTool.toolName,
|
||||||
|
];
|
||||||
|
allAnnotations = allAnnotations.filter(
|
||||||
|
ann => allowedTools.includes(ann.metadata.toolName)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return "{}"; // If no annotations found, return empty object
|
||||||
|
}
|
||||||
return JSON.stringify(allAnnotations, null, 2);
|
return JSON.stringify(allAnnotations, null, 2);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert("Failed to export annotations: " + e);
|
alert("Failed to export annotations: " + e);
|
||||||
@@ -1210,7 +1230,25 @@ window.importViewerState = (json: string) => {
|
|||||||
window.importAnnotations = (json: string) => {
|
window.importAnnotations = (json: string) => {
|
||||||
try {
|
try {
|
||||||
const annotationData = typeof json === "string" ? JSON.parse(json) : json;
|
const annotationData = typeof json === "string" ? JSON.parse(json) : json;
|
||||||
cornerstoneTools.annotation.state.restoreAnnotations(annotationData);
|
// Remove all existing annotations if needed
|
||||||
|
if (cornerstoneTools.annotation.state.removeAllAnnotations) {
|
||||||
|
cornerstoneTools.annotation.state.removeAllAnnotations();
|
||||||
|
}
|
||||||
|
// Add each annotation from the imported data
|
||||||
|
if (Array.isArray(annotationData)) {
|
||||||
|
annotationData.forEach(ann => {
|
||||||
|
cornerstoneTools.annotation.state.addAnnotation(ann);
|
||||||
|
});
|
||||||
|
} else if (annotationData && typeof annotationData === "object") {
|
||||||
|
// If the data is an object with tool types as keys
|
||||||
|
Object.values(annotationData).forEach((anns: any) => {
|
||||||
|
if (Array.isArray(anns)) {
|
||||||
|
anns.forEach(ann => {
|
||||||
|
cornerstoneTools.annotation.state.addAnnotation(ann);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
if (renderingEngineRef.current) {
|
if (renderingEngineRef.current) {
|
||||||
renderingEngineRef.current.render();
|
renderingEngineRef.current.render();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user