Weasis Documentation

repository·master·Indexed 23 days ago

https://github.com/nroduit/weasis

An open-source DICOM viewer for standalone desktop use and web-based integration. It supports integration with PACS, VNA, and EHR systems via DICOMweb, DIMSE, and WADO-URI. The documentation covers installation via Maven archetypes, custom plug-in development, memory management architecture (JVM heap, OpenCV native heap, and GPU/VRAM), and the Dicomizer module for converting non-DICOM media.

Tokens
17.4K
Snippets
21
Records
83
Agent score
79%

What's inside Weasis

  1. Differentiate between volume-space and canvas-space crosshair positions

    master

    When working with MPR, you must distinguish between two types of crosshair position methods to avoid rendering or interaction errors:

    getCrossHairPosition() (No arguments)

    • Purpose: Returns the raw volume-space center.
    • Usage: Used by the rendering pipeline (e.g., VolImageIO.getImageFragment(), MprAxis.updateRotation()) to sample the 3D volume.
    • Constraint: It must not apply any canvas projection. It represents a true 3D coordinate in the volume.

    getCrossHairPosition(MprAxis axis)

    • Purpose: Returns the center projected onto a specific view's 2D canvas.
    • Usage: Used for UI and interaction (e.g., mouseMoved() for hit-testing, addCrossline() for drawing graphics, mouseDragged() for computing new positions).
    • Constraint: It must apply the full inverse rotation (viewRotation⁻¹) to correctly project the 3D center onto the 2D plane.
  2. Understand the MPR rotation system layers

    master

    The Multi-Planar Reconstruction (MPR) rotation system uses three distinct layers to manage how views are oriented relative to the 3D volume and how user interactions (like tilting crosshairs) affect the display:

    1. Base Plane Rotations: Fixed rotations that orient each plane relative to the volume axes.

      • AXIAL: Identity (Canvas XY = Volume XY).
      • CORONAL: Rx(-90°) with a Y-flip S(1, -1, 1) for anatomical orientation.
      • SAGITTAL: Ry(90°) · Rz(90°).
    2. Global Rotation: An accumulated rotation applied when a user tilts the crosshair on any view. This affects all views.

    3. Per-Plane Rotation Offset: A local offset used to cancel out the globalRotation for the specific view being tilted. This ensures that if you tilt the crosshair on the AXIAL view, the AXIAL view itself remains unchanged while the CORONAL and SAGITTAL views reflect the tilt.

    // Example of how global rotation is updated during a tilt:
    // In rotateAroundAxis():
    Vector3d axis = plane.getDirection();          // (0,0,1) for AXIAL
    Quaterniond q = Quaterniond().fromAxisAngleRad(axis, planeAngle);
    globalRotation.mul(q);
  3. Maintain Rotation Consistency in MPR

    master

    When implementing custom transformations or rotation logic, the forward transform (display to texture) and the inverse transform (texture to display) must use matching rotations to ensure coordinate integrity.

    • Forward Transform: R(viewRot) · basePlaneRot (used in getDisplayPointToTexturePointMatrix)
    • Inverse Transform: basePlaneRot⁻¹ · R(viewRot)⁻¹ (used in getCenterForCanvas or applyRotationMatrix)

    If you modify the rotation logic for one, you must update the other to maintain consistency.

  4. Understand the MPR coordinate space pipeline

    master

    The Multi-Planar Reconstruction (MPR) system in Weasis uses a four-stage pipeline to transform raw voxel data into a viewable screen image. Understanding this flow is essential for implementing custom rendering or coordinate transformations:

    1. Voxel Index Space: The raw 3D integer grid defined by Volume.size.
    2. VR-Space (Voxel-Ratio-Scaled Space): An "isotropised" space where equal distances correspond to equal physical distances, compensating for anisotropic voxel spacing.
    3. Isotropic Slice Space (Working Space): The 2D/3D space where user interactions (crosshairs, mouse clicks, panning, zooming) occur. It uses a square pixel grid where each pixel represents the smallest physical spacing (min(pixelRatio)).
    4. Screen / Viewport Space: The final 2D projection on the user's monitor.

    This pipeline ensures that even if the original volume is anisotropic (e.g., thick CT slices), the user interacts with a visually consistent, isotropic representation.

    Voxel Index Space           [0, size.i)
          │
          │  × voxelRatio (per-component)
          ▼
    VR-Space                    [0, volSize.i)       ← getRealVolumeTransformation output
          │
          │  (conversion only in getRealVolumeTransformation)
          ▼
    Isotropic Slice Space       [0, sliceSize]²      ← AxesControl.center, crosshair, mouse
          │
          │  view transform (pan, zoom)
          ▼
    Screen / Viewport Space
  5. Configure Grow and Shrink Weights in MigLayoutModel

    master

    Weights control how space is distributed when the container resizes.

    Grow Weight (Default: 100)

    Controls space distribution when the container expands.

    • Higher weight: Receives more extra space.
    • Weight 0: Fixed size (won't grow beyond preferred size).
    • Proportionality: Weights are relative (e.g., a 1:2:1 ratio is implemented as 100, 200, 100).

    Shrink Weight (Default: 100)

    Controls space reduction when the container shrinks.

    • Higher weight: Loses more space when the container shrinks.
    • Weight 0: Won't shrink below preferred size.
    • Independence: Grow and shrink weights are independent; a component can be configured to grow but not shrink, or vice versa.

    Fill Property

    Determines if a component expands to occupy the entire cell.

    • true: Component fills the cell.
    • false: Component uses its preferred size and alignment.
    // Three columns growing in 1:2:1 ratio
    double[] columnWeights = {100, 200, 100};
    model.setColumnWeights(columnWeights);
    
    // First column shrinks slowly, second shrinks quickly
    double[] growWeights = {100, 100};
    double[] shrinkWeights = {25, 100};
    model.setColumnWeights(growWeights, shrinkWeights);
  6. Understand Weasis memory management architecture

    master

    Weasis manages memory across three distinct 'arenas' because DICOM pixel data is often too large for the JVM heap and is allocated via native code (OpenCV) or the GPU. Understanding these boundaries is critical for debugging memory issues:

    ArenaContentReclaimed ByBounded By
    JVM heapSwing UI, DICOM metadata, Java pixel copiesGarbage collector-Xmx or -XX:MaxRAMPercentage
    OpenCV native heapDecoded image pixel buffers (org.opencv.core.Mat)Explicit release(), driven by image cachesThe native-memory budget
    GPU and native staging3D volume textures in VRAM; off-heap FFM Arena stagingGL driver; explicit Arena closeVRAM; the volume staging chunk size

    Note: Runtime.getRuntime().maxMemory() only describes the JVM heap. Weasis calculates its native memory budget based on physical RAM to avoid competing with the OS and the heap.

  7. How the MPR system works in Weasis

    master

    The Multi-Planar Reconstruction (MPR) system reconstructs three orthogonal slice views (Axial, Coronal, and Sagittal) from a 3D volume. It allows users to navigate the volume by moving a crosshair, rotating (tilting) the crosshair to view oblique slices, scrolling along the slice normal, and adjusting Maximum Intensity Projection (MIP) thickness.

    Component Architecture

    • MprContainer: The top-level container.
    • MprView: Three instances (AXIAL, CORONAL, SAGITTAL) that display the reconstructed slices.
    • MprController: A central controller that handles mouse input and crosshair interactions across all views.
    • AxesControl: Manages the global state of the crosshair system (position and rotation).
    • Volume<?,?>: The underlying 3D voxel data.
    ┌────────────────────────────────────────────────────────┐
    │                     MprContainer                       │
    │  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  │
    │  │  MprView     │  │  MprView     │  │  MprView     │  │
    │  │  (AXIAL)     │  │  (CORONAL)   │  │  (SAGITTAL)  │  │
    │  │              │  │              │  │              │  │
    │  │  MprAxis ◄───┼──┼── MprAxis ◄──┼──┼── MprAxis    │  │
    │  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘  │
    │         │                 │                 │          │
    │         └────────┬────────┴────────┬────────┘          │
    │                  │                 │                   │
    │           MprController       AxesControl              │
    │            (mouse input)    (center, rotation)         │
    │                  │                 │                   │
    │                  └────────┬────────┘                   │
    │                           │                            │
    │                      Volume<?,?>                       │
    │                     (voxel data)                       │
    └────────────────────────────────────────────────────────┘
  8. Distinguish between Volume Center and Canvas Projection

    master

    When working with MPR (Multi-Planar Reconstruction), you must distinguish between the 3D position in the volume and its 2D representation on the screen to avoid coordinate errors.

    • Volume center (axesControl.getCenter()): Represents the 3D position in isotropic slice-space. Use this for rendering operations and volume-based calculations.
    • Canvas projection (getCenterForCanvas(view)): Represents the 2D projection onto a specific view. Use this for UI display, hit-testing, and handling mouse interactions.
  9. Understand the MPR rendering pipeline for slice generation

    master

    The MPR rendering pipeline generates slice images by sampling the 3D volume at the current crosshair position.

    The Process:

    1. MprAxis.updateImage() is triggered.
    2. VolImageIO.getImageFragment() is called using the volume-space crosshair position.
    3. A transformation matrix is calculated via getRealVolumeTransformation(rotation, center) to map slice pixels to VR-space.
    4. For each pixel (px, py) in the slice:
      • Calculate the VR-space point: vrPoint = transformation × (px, py, 0).
      • Convert to voxel coordinates: voxel = vrPoint / voxelRatio.
      • Sample the value using trilinear interpolation.

    Note on MIP (Maximum Intensity Projection): The pipeline can also render multiple slices and combine them using max, min, or average functions.

  10. How MigLayoutModel works

    master

    MigLayoutModel is a grid-based layout management system used by Weasis viewer or editor plugins. It leverages a constraint-based approach to create responsive UIs.

    Key components include:

    • Rows: Horizontal divisions configured with row constraints.
    • Columns: Vertical divisions configured with column constraints.
    • Cells: Individual spaces where components are placed.

    Developers use it to define how components grow, shrink, and fill space within a grid, allowing for complex layouts that respond to container resizing.

  11. Understand MPR rotation components

    master

    MPR transformations rely on two types of rotations:

    1. getViewRotation(plane) (Full per-view rotation): This is the accumulated user tilt. When a user tilts the crosshair on a specific view, the globalRotation changes for all views, but a rotationOffset is applied to that specific view to cancel the effect, making its viewRot identity while other views become non-identity.

    2. getRotationForSlice(plane) (Base plane orientation): These are fixed rotations that orient each anatomical plane relative to the volume. They map 2D canvas axes (u, v) to 3D volume axes:

    PlaneQuaternion
    AXIALIdentity
    CORONALRx(-90°)
    SAGITTALRy(90°) · Rz(90°)
  12. Understand Linux glibc compatibility constraints

    master

    The effective minimum glibc version required for Weasis Linux packages is GLIBC_2.17.

    This floor is determined by the prebuilt native binaries bundled with the application (specifically jogamp's libgluegen_rt.so), not by the operating system used to build the package. Even though the build environment uses a modern glibc (e.g., 2.43 in the Ubuntu 26.04 Docker image), the resulting .deb or .rpm packages remain compatible with Linux distributions from approximately 2012 onwards (e.g., RHEL/CentOS 7, Ubuntu 14.04+).

    Key takeaway: Bumping the Docker base image version will not change the glibc compatibility floor of the shipped packages.