Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(brush): update data only once when Brush interaction is done #762

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion common/reviews/api/core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export abstract class BaseVolumeViewport extends Viewport implements IVolumeView
// (undocumented)
setOrientation(orientation: OrientationAxis, immediate?: boolean): void;
// (undocumented)
setProperties({ voiRange, VOILUTFunction, invert, colormap, preset, }?: VolumeViewportProperties, volumeId?: string, suppressEvents?: boolean): void;
setProperties({ voiRange, VOILUTFunction, invert, colormap, preset, interpolationType, }?: VolumeViewportProperties, volumeId?: string, suppressEvents?: boolean): void;
// (undocumented)
abstract setSlabThickness(slabThickness: number, filterActorUIDs?: Array<string>): void;
// (undocumented)
Expand Down Expand Up @@ -2738,6 +2738,7 @@ type ViewportProperties = {
voiRange?: VOIRange;
VOILUTFunction?: VOILUTFunctionType;
invert?: boolean;
interpolationType?: InterpolationType;
};

// @public (undocumented)
Expand Down
2 changes: 2 additions & 0 deletions common/reviews/api/streaming-image-volume-loader.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1343,6 +1343,7 @@ interface IVolumeViewport extends IViewport {
// (undocumented)
useCPURendering: boolean;
worldToCanvas: (worldPos: Point3) => Point2;

}

// @public
Expand Down Expand Up @@ -1611,6 +1612,7 @@ type ViewportProperties = {
voiRange?: VOIRange;
VOILUTFunction?: VOILUTFunctionType;
invert?: boolean;
interpolationType?: InterpolationType;
};

// @public (undocumented)
Expand Down
37 changes: 31 additions & 6 deletions common/reviews/api/tools.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -562,24 +562,46 @@ declare namespace boundingBox {
type BoundsIJK = [Types_2.Point2, Types_2.Point2, Types_2.Point2];

// @public (undocumented)
export class BrushTool extends BaseTool {
interface BrushCursor extends Annotation {
// (undocumented)
data: {
handles: {
points: [Types_2.Point3];
};
};
}

// @public (undocumented)
export class BrushTool extends AnnotationTool {
constructor(toolProps?: PublicToolProps, defaultToolProps?: ToolProps);
// (undocumented)
addNewAnnotation: (evt: EventTypes_2.MouseDownActivateEventType) => BrushCursor;
// (undocumented)
cancel: () => void;
// (undocumented)
handleSelectedCallback: () => void;
// (undocumented)
invalidateBrushCursor(): void;
// (undocumented)
mouseMoveCallback: (evt: EventTypes_2.InteractionEventType) => void;
isPointNearTool(): boolean;
// (undocumented)
mouseMoveCallback: (evt: EventTypes_2.MouseMoveEventType) => boolean;
// (undocumented)
onSetConfiguration: () => void;
// (undocumented)
onSetToolActive: () => void;
// (undocumented)
onSetToolDisabled: () => void;
// (undocumented)
onSetToolEnabled: () => void;
// (undocumented)
onSetToolPassive: () => void;
// (undocumented)
preMouseDownCallback: (evt: EventTypes_2.MouseDownActivateEventType) => boolean;
// (undocumented)
renderAnnotation(enabledElement: Types_2.IEnabledElement, svgDrawingHelper: SVGDrawingHelper): void;
renderAnnotation(enabledElement: Types_2.IEnabledElement, svgDrawingHelper: SVGDrawingHelper): boolean;
// (undocumented)
static toolName: any;
// (undocumented)
toolSelectedCallback: () => void;
}

// @public (undocumented)
Expand Down Expand Up @@ -3163,6 +3185,7 @@ interface IVolumeViewport extends IViewport {
// (undocumented)
useCPURendering: boolean;
worldToCanvas: (worldPos: Point3) => Point2;

}

// @public (undocumented)
Expand Down Expand Up @@ -5143,7 +5166,8 @@ declare namespace ToolSpecificAnnotationTypes {
AngleAnnotation,
ReferenceCursor,
ReferenceLineAnnotation,
ScaleOverlayAnnotation
ScaleOverlayAnnotation,
BrushCursor
}
}

Expand Down Expand Up @@ -5449,6 +5473,7 @@ type ViewportProperties = {
voiRange?: VOIRange;
VOILUTFunction?: VOILUTFunctionType;
invert?: boolean;
interpolationType?: InterpolationType;
};

declare namespace visibility {
Expand Down
19 changes: 10 additions & 9 deletions packages/adapters/examples/segmentationExport/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import {
createImageIdsAndCacheMetaData
} from "../../../../utils/demo/helpers";
import * as cornerstoneTools from "@cornerstonejs/tools";
import { adaptersSEG } from "@cornerstonejs/adapters";
import { adaptersSEG, helpers } from "@cornerstonejs/adapters";
import dcmjs from "dcmjs";

const { downloadDICOMData } = helpers;

// This is for debugging purposes
console.warn(
"Click on index.ts to open source code for this example --------->"
Expand Down Expand Up @@ -130,15 +132,14 @@ addButtonToToolbar({
labelmapObj.metadata[segmentIndex] = segmentMetadata;
});

const segBlob = Cornerstone3D.Segmentation.generateSegmentation(
images,
labelmapObj,
metaData
);
const generatedSegmentation =
Cornerstone3D.Segmentation.generateSegmentation(
images,
labelmapObj,
metaData
);

//Create a URL for the binary.
const objectUrl = URL.createObjectURL(segBlob);
window.open(objectUrl);
downloadDICOMData(generatedSegmentation.dataset, "mySEG.dcm");
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,7 @@ function fillSegmentation(segmentation, inputLabelmaps3D, userOptions = {}) {
segmentation.bitPackPixelData();
}

const buffer = Buffer.from(datasetToDict(segmentation.dataset).write());
const segBlob = new Blob([buffer], { type: "application/dicom" });

return segBlob;
return segmentation;
sedghi marked this conversation as resolved.
Show resolved Hide resolved
}

function _getLabelmapsFromReferencedFrameIndicies(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const { Segmentation: SegmentationDerivation } = derivations;
* @param images - An array of the cornerstone image objects, which includes imageId and metadata
* @param labelmaps - An array of the 3D Volumes that contain the segmentation data.
*/
function generateSegmentation(images, labelmaps, metadata, options) {
function generateSegmentation(images, labelmaps, metadata, options = {}) {
const segmentation = _createMultiframeSegmentationFromReferencedImages(
images,
metadata,
Expand Down Expand Up @@ -41,8 +41,8 @@ function _createMultiframeSegmentationFromReferencedImages(
...image,
...instance,
// Todo: move to dcmjs tag style
SOPClassUID: instance.SopClassUID,
SOPInstanceUID: instance.SopInstanceUID,
SOPClassUID: instance.SopClassUID || instance.SOPClassUID,
SOPInstanceUID: instance.SopInstanceUID || instance.SOPInstanceUID,
PixelData: image.getPixelData(),
_vrMap: {
PixelData: "OW"
Expand Down
35 changes: 35 additions & 0 deletions packages/adapters/src/adapters/helpers/downloadDICOMData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { data } from "dcmjs";
import { Buffer } from "buffer";
const { datasetToDict } = data;

interface DicomDataset {
_meta?: any;
// other properties
}

/**
* Trigger file download from an array buffer
* @param bufferOrDataset - ArrayBuffer or DicomDataset
* @param filename - name of the file to download
*/
export function downloadDICOMData(
bufferOrDataset: ArrayBuffer | DicomDataset,
filename: string
) {
let blob;
if (bufferOrDataset instanceof ArrayBuffer) {
blob = new Blob([bufferOrDataset], { type: "application/dicom" });
} else {
if (!bufferOrDataset._meta) {
throw new Error("Dataset must have a _meta property");
}

const buffer = Buffer.from(datasetToDict(bufferOrDataset).write());
blob = new Blob([buffer], { type: "application/dicom" });
}

const link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
link.download = filename;
link.click();
}
3 changes: 2 additions & 1 deletion packages/adapters/src/adapters/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { toArray } from "./toArray";
import { codeMeaningEquals } from "./codeMeaningEquals";
import { graphicTypeEquals } from "./graphicTypeEquals";
import { downloadDICOMData } from "./downloadDICOMData";

export { toArray, codeMeaningEquals, graphicTypeEquals };
export { toArray, codeMeaningEquals, graphicTypeEquals, downloadDICOMData };
23 changes: 23 additions & 0 deletions packages/core/src/RenderingEngine/BaseVolumeViewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import {
BlendModes,
Events,
InterpolationType,
OrientationAxis,
ViewportStatus,
VOILUTFunctionType,
Expand Down Expand Up @@ -367,6 +368,23 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
return newRGBTransferFunction;
}

private setInterpolationType(
interpolationType: InterpolationType,
volumeId?: string
) {
const applicableVolumeActorInfo = this._getApplicableVolumeActor(volumeId);

if (!applicableVolumeActorInfo) {
return;
}

const { volumeActor } = applicableVolumeActorInfo;
const volumeProperty = volumeActor.getProperty();

// @ts-ignore
volumeProperty.setInterpolationType(interpolationType);
}

/**
* Sets the properties for the volume viewport on the volume
* (if fusion, it sets it for the first volume in the fusion)
Expand Down Expand Up @@ -449,6 +467,7 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
invert,
colormap,
preset,
interpolationType,
}: VolumeViewportProperties = {},
volumeId?: string,
suppressEvents = false
Expand All @@ -467,6 +486,10 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
this.setVOI(voiRange, volumeId, suppressEvents);
}

if (typeof interpolationType !== 'undefined') {
this.setInterpolationType(interpolationType);
}

if (VOILUTFunction !== undefined) {
this.setVOILUTFunction(VOILUTFunction, volumeId, suppressEvents);
}
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/types/ViewportProperties.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { VOILUTFunctionType } from '../enums';
import { InterpolationType, VOILUTFunctionType } from '../enums';
import { VOIRange } from './voi';

/**
Expand All @@ -11,6 +11,8 @@ type ViewportProperties = {
VOILUTFunction?: VOILUTFunctionType;
/** invert flag - whether the image is inverted */
invert?: boolean;
/** interpolation type */
interpolationType?: InterpolationType;
};

export type { ViewportProperties };
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ async function _convertStackToVolumeViewport(

const { id, element } = viewport;

const prevCamera = viewport.getCamera();

let imageIds = viewport.getImageIds();
imageIds = imageIds.map((imageId) => {
const imageURI = utilities.imageIdToURI(imageId);
Expand All @@ -78,7 +80,6 @@ async function _convertStackToVolumeViewport(
type: ViewportType.ORTHOGRAPHIC,
element,
defaultOptions: {
orientation: Enums.OrientationAxis.SAGITTAL,
background: <Types.Point3>[0.2, 0.4, 0.2],
},
},
Expand All @@ -98,11 +99,27 @@ async function _convertStackToVolumeViewport(

// Set the volume to load
volume.load();
const volumeViewport = <Types.IVolumeViewport>renderingEngine.getViewport(id);

setVolumesForViewports(renderingEngine, [{ volumeId }], [id]);
setVolumesForViewports(
renderingEngine,
[
{
volumeId,
},
],
[id]
);

// preserve the slice location when switching from stack to volume
element.addEventListener(Enums.Events.VOLUME_VIEWPORT_NEW_VOLUME, () => {
volumeViewport.setCamera({
focalPoint: prevCamera.focalPoint,
});
volumeViewport.render();
});

// Render the image
renderingEngine.renderViewports([id]);
volumeViewport.render();
}

export { _convertStackToVolumeViewport, _convertVolumeToStackViewport };
14 changes: 13 additions & 1 deletion packages/tools/src/drawingSvg/drawCircle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,23 @@ function drawCircle(
options = {},
dataId = ''
): void {
const { color, fill, width, lineWidth, lineDash } = Object.assign(
const {
color,
fill,
width,
lineWidth,
lineDash,
fillOpacity,
strokeOpacity,
} = Object.assign(
{
color: 'dodgerblue',
fill: 'transparent',
width: '2',
lineDash: undefined,
lineWidth: undefined,
strokeOpacity: 1,
fillOpacity: 1,
},
options
);
Expand All @@ -42,6 +52,8 @@ function drawCircle(
fill,
'stroke-width': strokeWidth,
'stroke-dasharray': lineDash,
'fill-opacity': fillOpacity, // setting fill opacity
'stroke-opacity': strokeOpacity, // setting stroke opacity
};

if (existingCircleElement) {
Expand Down
Loading