-
Notifications
You must be signed in to change notification settings - Fork 385
fix CircleROI tool for wsi #1940
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
base: main
Are you sure you want to change the base?
Conversation
❌ Deploy Preview for cornerstone-3d-docs failed. Why did it fail? →
|
@@ -919,7 +919,10 @@ class CircleROITool extends AnnotationTool { | |||
// Check if one of the indexes are inside the volume, this then gives us | |||
// Some area to do stats over. | |||
|
|||
if (this._isInsideVolume(pos1Index, pos2Index, dimensions)) { | |||
if ( | |||
this._isInsideVolume(pos1Index, pos2Index, dimensions) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you make the isInsideVolume work for WSI as well? I'd rather not have a viewport.type==='whileSlide' anywhere inside the tools.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be necessary to improve the WSIViewport with better mapping functions, or perhaps the transformWorldToIndex mapping functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, wsiviewport worldToCanvas returns negative values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can make it work by changing wsiviewport 'getTransform' but I dont know what else it impacts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That impacts too much right now - @pedrokohler is working on a fix for that separately, so lets leave this as is for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes the CircleROI tool so that it properly handles whole slide (wsi) viewports by skipping stats that require the voxel manager. Key changes include:
- Extending the conditional check to include viewport type "wholeSlide" for stats calculation.
- Wrapping the voxel manager-based points collection in a condition that bypasses the process for whole slide viewports.
Comments suppressed due to low confidence (1)
packages/tools/src/tools/annotation/CircleROITool.ts:924
- [nitpick] Consider replacing the magic string 'wholeSlide' with a named constant to improve maintainability.
viewport.type === 'wholeSlide'
…and improve handling of finite values in statistics
…pe and improve null checks
Can you ensure the tests pas[s - I think those are real issues |
…arData length for pointsInShape calculation
…sInShape calculation
…nd Elliptical ROI tools in the tools list
…ornerstone3D into fix-circleroi-wsi
@@ -244,7 +254,7 @@ class WSIViewport extends Viewport { | |||
getDirection: () => metadata.direction, | |||
getDimensions: () => metadata.dimensions, | |||
getRange: () => [0, 255], | |||
getScalarData: () => this.getScalarData(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a viewReference to the getter as an optional? I know we don't pass it in yet, but we need to start thinking about it as the getScalarData for whole slide imaging won't be able to return the entire scalar data.
// Return an empty CanvasScalarData object | ||
const emptyData = new Uint8ClampedArray() as CanvasScalarData; | ||
emptyData.getRange = () => [0, 255]; | ||
emptyData.frameNumber = -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add an emptyData.region that is a rectangle of the enclosing region, and a scale parameter? The region should be zero sized for now, and the scale can be 1, but again I'd like to start thinking about the future.
@@ -1028,6 +1030,14 @@ class CircleROITool extends AnnotationTool { | |||
}; | |||
|
|||
_isInsideVolume = (index1, index2, dimensions) => { | |||
// for wsiViewport | |||
if (index1[1] < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you put this fix into the WSIViewport itself?
@@ -615,12 +627,16 @@ class WSIViewport extends Viewport { | |||
protected canvasToIndex = (canvasPos: Point2): Point2 => { | |||
const transform = this.getTransform(); | |||
transform.invert(); | |||
return transform.transformPoint(canvasPos); | |||
return transform.transformPoint( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use Math.abs on the result here - I think that will get us close to the right value, or on initial setup, figure out which attribute is negative and store a negative multiplier for it.
}; | ||
|
||
protected indexToCanvas = (indexPos: Point2): Point2 => { | ||
const transform = this.getTransform(); | ||
return transform.transformPoint(indexPos); | ||
return transform |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will need to convert back to negative values, so if you on initial setup store an index of which values are negative and multiple by that vector you should get the right sign.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple of small remaining changes, hopefully merge this today.
…in _getScalarData method
* @param n - array of numbers or a simple number | ||
* @returns True if n or the first element of n is finite and not NaN | ||
*/ | ||
public static isNumber(n: number[] | number): boolean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is already a isNumber in packages/core/src/utilities/isEqual.ts , adapt that for your use
@@ -968,6 +968,14 @@ class RectangleROITool extends AnnotationTool { | |||
}; | |||
|
|||
_isInsideVolume = (index1, index2, dimensions) => { | |||
// for wsiViewport | |||
if (index1[1] < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look good. Could you please check if the viewport type is WSI before proceeding? I imagine this might disrupt other types of viewports.
// for wsiViewport | ||
if (index1[1] < 0) { | ||
index1[1] = -index1[1]; | ||
} | ||
if (index2[1] < 0) { | ||
index2[1] = -index2[1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look good. Could you please check if the viewport type is WSI before proceeding? I imagine this might disrupt other types of viewports.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please see my comments
Context
CircleROI and other ROI tools were not generating stats for wsi viewport.
Changes & Results
This PR fixes the CircleROI, RectangleROI, EllipseROI and FreehandROI tool for whole slide (wsi) viewports by skipping statistics calculation that require the voxel manager.
Key changes include:
Changing wsiViewport so that getScalarData returns an empty CanvasScalarData object instead of null.
Wrapping the voxel manager-based points collection of each tool in a condition that bypasses the process when the scalarData is empty.