Class 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() and dicomGetWindowCenterWidth()
      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
    • Constructor Detail

      • MedicalHelper

        public MedicalHelper()
    • 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).
      • 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 adjust
        volume - volume to get DICOM attributes
        forceReverse - 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 set
        winCW - 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,
                                         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 Sagittal
        camera - 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.
      • 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 search
        nodeClass - class of the node you want to find
        nodeName - 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 search
        nodeClass - 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.