Class MedicalHelper
- java.lang.Object
-
- com.openinventor.medical.helpers.MedicalHelper
-
public class MedicalHelper extends java.lang.Object
Utility class for medical applications using Open Inventor. Open Inventor includes a general purpose 3D graphics core library plus optimized extensions for specific data types and markets, including medical visualization. We recommend using these utility functions (and the Medical utility nodes) to get the best performance and productivity from the Open Inventor Medical utility library.Summary:
-
dicomAdjustVolume()
Call this method to adjust VolumeViz parameters for optimal performance with medical data and to position a DICOM volume correctly in 3D space. -
dicomAdjustDataRange()
Call this method to set the VolumeViz data range based on the Window Center and Window Width tags in a DICOM file. If those tags are not present, automatically sets the data range to the actual range of values in the data. -
dicomSetWindowCenterWidth()
anddicomGetWindowCenterWidth()
In Open Inventor the range of voxel values that map onto the color map are specified as the 'min' and 'max' values of the range (see SoDataRange). These methods provide a convenient way to set and query the data range using the medical convention of 'window center' and 'window width'. -
dicomFindFilesbySeries()
Call this method to build a list of DICOM image files in a directory that belong to the same series as the specified file. This list can be passed to the DICOM volume reader using the setFileList() method. -
orientView()
This method is useful for orienting the camera to view a single image (a slice in VolumeViz jargon) along one of the standard axes (Axial, Coronal or Sagittal). But remember that the volume is always a 3D object to Open Inventor and you must also set the 'axis' field on the SoOrthoSlice node. See the dicomImageViewer example.
- See Also:
DicomInfo
,Gnomon
,Magnifier
,Ruler
,SliceOrientationMarkers
,SliceScaleBar
,TextBox
-
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
MedicalHelper.Axis
Medical axis names.
-
Field Summary
Fields Modifier and Type Field Description static java.lang.String
EXAMPLE_LOGO
static short
WINDOW_HEIGHT
static short
WINDOW_WIDTH
-
Constructor Summary
Constructors Constructor Description MedicalHelper()
-
Method Summary
All Methods Static Methods Concrete Methods Modifier and Type Method Description static SoSeparator
buildSliceAnnotation(SoCamera camera, SoOrthoSlice sliceNode, java.lang.String filename)
Slice viewer annotations.static SoSeparator
buildSliceOrientationMarkers(SoOrthoSlice orthoSlice)
Build a scene graph to display slice orientation markers.static SoSeparator
buildSliceScaleBars(SoCamera camera)
Build a scene graph to display dynamic scale bars for slice viewing.static SoSeparator
createBoundingBox(SbBox3f bbox, SbColor color)
Convenience function to draw a specified bounding box as a wireframestatic SoSeparator
createCube(SbBox3f bbox)
Convenience function to retrieve the cube corresponding to the specified bounding box.static boolean
dicomAdjustDataRange(SoDataRange rangeNode, SoVolumeData volume)
Adjust data range based on values in the DICOM file, i.e.static boolean
dicomAdjustVolume(SoVolumeData volume, boolean useImagePosition)
Optimize volume data node for DICOM volumes.static boolean
dicomAdjustVolume(SoVolumeData volume, SoMatrixTransform imgToPatient)
Similar to dicomAdjustVolume( SoVolumeData, boolean ) above but returns an SoMatrixTransform that can be used to properly locate VolumeData in patient space in case of non axis aligned acquisition:static boolean
dicomCheckMonochrome1(SoTransferFunction cmapNode, SoVolumeData volume, boolean forceReverse)
Automatically adjusts the color map (transferFunction) if the specified volume is a DICOM data set (reader is SoVRDicomFileReader) and the Photometric Interpretation (0028,0004) value is MONOCHROME1.static SbVec3f
dicomGetImagePosition(SoVolumeData volume)
Get the "Image Position (Patient)" attribute (0020,0032) from a DICOM volume.static SbVec2f
dicomGetWindowCenterWidth(SoDataRange dataRange)
Get the window center (level) and width values from an SoDataRange node.static SbVec2f
dicomGetWindowCenterWidth(SoVolumeData volume)
Get the window center (level) and width values from a DICOM volume.static boolean
dicomSetWindowCenterWidth(SoDataRange dataRange, SbVec2f winCW)
Set an SoDataRange node from the window center (level) and width values.static void
dollyZoom(float value, SoCameraInteractor cameraInteractor)
Make the scene appear larger or smaller.static SoNode
exampleDicomAnnotation(java.lang.String filename)
Returns a collection of DicomInfo annotation nodes for Open Inventor medical examples.static <NodeClass extends SoNode>
NodeClassfind(SoNode root, java.lang.Class<NodeClass> nodeClass)
Convenience function to find first specified node in the scene graph.static <NodeClass extends SoNode>
NodeClassfind(SoNode root, java.lang.Class<NodeClass> nodeClass, java.lang.String nodeName)
Convenience function to find first specified node in the scene graph.static SbBox3f
getBoundingBox(SoNode node)
Convenience function to retrieve the bounding box of the specified node.static SoNode
getExampleLogoNode()
Returns the example logo nodestatic MedicalHelper.Axis
MedicalAxisFromViewAxis(Axis viewAxis, SbMatrix orientationMatrix)
static MedicalHelper.Axis
MedicalAxisFromViewAxis(Axis viewAxis, SoVolumeData volData)
static boolean
orientView(MedicalHelper.Axis axis, SoCamera camera, SoVolumeData volume)
Equivalent toorientView(axis, camera, volume, 1.01f)
static boolean
orientView(MedicalHelper.Axis axis, SoCamera camera, SoVolumeData volume, float slack)
Adjusts the camera to view a slice or volume along the specified axis.static SoSeparator
readFile(java.lang.String filename)
Convenience function to read a .iv file and return pointer to the root of the created scene graph.static Axis
ViewAxisFromMedicalAxis(MedicalHelper.Axis medicalAxis, SbMatrix orientationMatrix)
static Axis
ViewAxisFromMedicalAxis(MedicalHelper.Axis medicalAxis, SoVolumeData volData)
-
-
-
Field Detail
-
EXAMPLE_LOGO
public static final java.lang.String EXAMPLE_LOGO
- See Also:
- Constant Field Values
-
WINDOW_HEIGHT
public static final short WINDOW_HEIGHT
- See Also:
- Constant Field Values
-
WINDOW_WIDTH
public static final short WINDOW_WIDTH
- See Also:
- Constant Field Values
-
-
Method Detail
-
exampleDicomAnnotation
public static SoNode exampleDicomAnnotation(java.lang.String filename)
Returns a collection of DicomInfo annotation nodes for Open Inventor medical examples. This method is not important for customer applications, but the technique can be useful for adding annotation text to an application window.- Parameters:
filename
- Path to a DICOM file from which info will be extracted- Returns:
- Root of the annotation scene graph.
-
dollyZoom
public static void dollyZoom(float value, SoCameraInteractor cameraInteractor)
Make the scene appear larger or smaller.Provided as a convenience to simplify application code. Values greater than 1 make the scene appear larger. Values less than 1 make the scene appear smaller. For example a of 2 will make the scene approximately 2 times larger in the rendering window. The specific effect on the camera is a 'dolly' or a 'zoom' depending on the type of camera.
This is often useful after calling viewAll(). That method sets the camera parameters based on a bounding sphere around the scene which often leaves the scene not "filling" the viewport.
Details:
- SoPerspectiveCamera:
changes the camera 'position' field. For example, values greater than 1 move the camera closer to the focal point (divide the camera's distance from the focal point by the given value), which makes the scene appear larger. This is a 'dolly'. - SoOrthographicCamera:
changes the camera 'height' field. For example, values greater than 1 decrease the view volume height (scale the height by the inverse of the given value), which makes the scene appear larger. This is a 'zoom' operation. - No effect if value is <= 0 or camera is null.
Note that the value expected by SoCameraInteractor.dolly is the inverse, which is less intuitive.
- Parameters:
value
- The dolly value (ignored if zero).cameraInteractor
- The interactor used to modify the camera (ignored if null).
- SoPerspectiveCamera:
-
getExampleLogoNode
public static SoNode getExampleLogoNode() throws java.io.FileNotFoundException
Returns the example logo node- Returns:
- Example logo node
- Throws:
java.io.FileNotFoundException
- If the example logo resource is not found
-
dicomAdjustDataRange
public static boolean dicomAdjustDataRange(SoDataRange rangeNode, SoVolumeData volume)
Adjust data range based on values in the DICOM file, i.e. the window center (0028,1050) and window width (0028,1051) values. If there are multiple slices, values are taken from the first slice. Volume is needed to get DICOM attributes, but is not modified.- Returns:
- true if successful. Assigns default values if necessary.
-
dicomCheckMonochrome1
public static boolean dicomCheckMonochrome1(SoTransferFunction cmapNode, SoVolumeData volume, boolean forceReverse)
Automatically adjusts the color map (transferFunction) if the specified volume is a DICOM data set (reader is SoVRDicomFileReader) and the Photometric Interpretation (0028,0004) value is MONOCHROME1. Specifically, if the above conditions are true, this method reverses the values in the current color map. Typically used as a convenience call when rendering slices. For intensity based rendering of slices, set the transfer function to the predefined color map INTENSITY. This is an intensity ramp from black to white that is appropriate for Photometric Interpretation MONOCHROME2 (the most common case). When reversed it is appropriate for P.I. MONOCHROME1. Returns true if change was needed and was successful. Volume is needed to get DICOM attributes, but is not modified. Transfer function is modified if necessary.- Parameters:
cmapNode
- the transfer function to adjustvolume
- volume to get DICOM attributesforceReverse
- if true, reverse the values in the color map even if the volume is not a DICOM data set or Photometric Interpretation is not MONOCHROME1.- Returns:
- true if change was needed and was successful.
-
dicomGetWindowCenterWidth
public static SbVec2f dicomGetWindowCenterWidth(SoVolumeData volume)
Get the window center (level) and width values from a DICOM volume. If the query fails, returns (0, 0).Uses the Window Center (0028,1050) and Window Width (0028,1051) tags from the first image in the stack. If these tags do not exist in the volume, then window center and width are computed from the actual data min and max values. (Note that querying the actual min and max values may take some time because every voxel must be loaded.) This method may be called with a non-DICOM volume. In that case the actual min and max data values are used.
- Returns:
- (0, 0) if the query fails
-
dicomGetWindowCenterWidth
public static SbVec2f dicomGetWindowCenterWidth(SoDataRange dataRange)
Get the window center (level) and width values from an SoDataRange node. Convenient for displaying data range in medical terms.- Parameters:
dataRange
- the SoDataRange node- Returns:
- the window center (level) and width values or (0, 0) on failure
-
dicomSetWindowCenterWidth
public static boolean dicomSetWindowCenterWidth(SoDataRange dataRange, SbVec2f winCW)
Set an SoDataRange node from the window center (level) and width values. Convenient for converting from medical user interface to data range.- Parameters:
dataRange
- the SoDataRange node to setwinCW
- the window center (level) and width values- Returns:
- true if successful
-
buildSliceOrientationMarkers
public static SoSeparator buildSliceOrientationMarkers(SoOrthoSlice orthoSlice)
Build a scene graph to display slice orientation markers. This is just a convenience method and helps keep the demo/example programs consistent. Applications can use SliceOrientationMarkers directly.
-
buildSliceScaleBars
public static SoSeparator buildSliceScaleBars(SoCamera camera)
Build a scene graph to display dynamic scale bars for slice viewing.This is just a convenience method and helps keep the demo/example programs consistent. Applications can use SliceScaleBar directly.
Note that a typical length, 10 cm, is assumed.
-
buildSliceAnnotation
public static SoSeparator buildSliceAnnotation(SoCamera camera, SoOrthoSlice sliceNode, java.lang.String filename)
Slice viewer annotations. This is just a convenience method and helps keep the demo/example programs consistent. Applications can use SliceScaleBar (etc) directly.
-
dicomAdjustVolume
public static boolean dicomAdjustVolume(SoVolumeData volume, boolean useImagePosition)
Optimize volume data node for DICOM volumes.The volume properties are modified (but not the data values). Do not call this method before setting the volume data node's fileName field or calling setReader.
- First, adjusts the LDM tile size to optimize data loading. Note this adjustment is valid for any data format that is not already tiled, i.e. most formats except .lda and .ldm.
- Second, adjusts the volume extent in 3D to be the actual physical extent of the data set measured from outside edge to outside edge of the voxels. This is a DICOM specific adjustment.
- Third, if 'useImagePosition' is true, adjusts the volume extent so the center of the first voxel is positioned at the coordinates specified in the data set's "Image position" (0020,0032) attribute. By default the DICOM volume reader sets the volume extent so the center of the volume is positioned at 0,0,0 in 3D space. This is a DICOM specific adjustment.
- Returns:
- true if successful
-
dicomAdjustVolume
public static boolean dicomAdjustVolume(SoVolumeData volume, SoMatrixTransform imgToPatient)
Similar to dicomAdjustVolume( SoVolumeData, boolean ) above but returns an SoMatrixTransform that can be used to properly locate VolumeData in patient space in case of non axis aligned acquisition:... SoMatrixTransform matrixTransform = new SoMatrixTransfrom(); dicomAdjustVolume(volumeData, matrixTransfrom) root.addChild(matrixTransform); root.addChild(volumeData); ...
The computed matrix embeds the image position and image orientation as described here: https://dicom.innolitics.com/ciods/ct-image/image-plane/00200037 Scaling part is embedded in VolumeData extent.If SoVolumeData is not a DICOM volume, imgToPatient will be set to identity.
- Returns:
- true if successful
-
dicomGetImagePosition
public static SbVec3f dicomGetImagePosition(SoVolumeData volume)
Get the "Image Position (Patient)" attribute (0020,0032) from a DICOM volume.DICOM calls this the upper left hand corner of the image, but more precisely it's the center of the first voxel, in millimeters (mm). For VolumeViz the upper left hand corner of the image is literally the corner of the voxel, one-half voxel different from Image Position.
Note the SoVRDicomData getPosition() method does not return the value of the Image Position attribute. It returns a value computed from Image Position. If there are multiple slices, value is taken from the first slice.
- Returns:
- 0,0,0 if not successful.
-
createBoundingBox
public static SoSeparator createBoundingBox(SbBox3f bbox, SbColor color)
Convenience function to draw a specified bounding box as a wireframe
-
getBoundingBox
public static SbBox3f getBoundingBox(SoNode node)
Convenience function to retrieve the bounding box of the specified node. If node contains SoVolumeData, use SoVolumeData extent.
-
createCube
public static SoSeparator createCube(SbBox3f bbox)
Convenience function to retrieve the cube corresponding to the specified bounding box.
-
orientView
public static boolean orientView(MedicalHelper.Axis axis, SoCamera camera, SoVolumeData volume)
Equivalent toorientView(axis, camera, volume, 1.01f)
-
orientView
public static boolean orientView(MedicalHelper.Axis axis, SoCamera camera, SoVolumeData volume, float slack)
Adjusts the camera to view a slice or volume along the specified axis.The camera is rotated to give the conventional orientation for the specified axis. If the volume data is specified, then viewAll() is called to center the volume in the view volume.
If the camera is an SoOrthographicCamera (the usual case for viewing a slice) and the volume data node is specified, then the camera (specifically the view volume height) is adjusted to make the slice image fill the viewport. This is convenient because the viewAll() method gives a very loose fit around the slice image.
If the camera is an SoPerspectiveCamera (commonly used for viewing a 3D volume) or the volume data node is specified, then viewAll() is called, but no additional adjustment is done to the camera. 'slack' is ignored in this case.
Axial -> "Feet" view. Coronal -> "Anterior" view. Sagittal -> "Left" view.
- Parameters:
axis
- Axial, Coronal or Sagittalcamera
- The camera node that will be modified (fails if null).volume
- The data volume that is being viewed (used to compute view volume, not modified)slack
- Values greater than 1 will leave additional space between image and window edge.- Returns:
- true if the operation succeeded.
-
MedicalAxisFromViewAxis
public static MedicalHelper.Axis MedicalAxisFromViewAxis(Axis viewAxis, SbMatrix orientationMatrix)
-
MedicalAxisFromViewAxis
public static MedicalHelper.Axis MedicalAxisFromViewAxis(Axis viewAxis, SoVolumeData volData)
-
ViewAxisFromMedicalAxis
public static Axis ViewAxisFromMedicalAxis(MedicalHelper.Axis medicalAxis, SbMatrix orientationMatrix)
-
ViewAxisFromMedicalAxis
public static Axis ViewAxisFromMedicalAxis(MedicalHelper.Axis medicalAxis, SoVolumeData volData)
-
find
public static <NodeClass extends SoNode> NodeClass find(SoNode root, java.lang.Class<NodeClass> nodeClass, java.lang.String nodeName)
Convenience function to find first specified node in the scene graph.- Parameters:
root
- root of scene graph you want to searchnodeClass
- class of the node you want to findnodeName
- Name of the node you want to find- Returns:
- The found node or null if nothing found
-
find
public static <NodeClass extends SoNode> NodeClass find(SoNode root, java.lang.Class<NodeClass> nodeClass)
Convenience function to find first specified node in the scene graph.- Parameters:
root
- root of scene graph you want to searchnodeClass
- class of the node you want to find- Returns:
- The found node or null if nothing found
-
readFile
public static SoSeparator readFile(java.lang.String filename)
Convenience function to read a .iv file and return pointer to the root of the created scene graph.- Parameters:
filename
- of file containing a scene graph.- Returns:
- Root of the read scene graph or null if the file cannot be read.
-
-