Asclepios DICOM Viewer

repository·master·Indexed 42 days ago

https://github.com/gavrilovicieduard/asclepios-dicom-viewer

A C++ medical imaging application using Qt and VTK for 2D and 3D visualization of DICOM datasets. It features Volume Rendering, Multiplanar Reconstruction (MPR) via the MPRMaker class, and a structured data hierarchy managed by CoreRepository, DicomReader, and the Patient, Study, Series, and Image classes. The application integrates DCMTK for DICOM file handling and network protocols.

Tokens
7.6K
Snippets
15
Records
29
Agent score
53%

What's inside Asclepios DICOM Viewer

  1. Capabilities of Asclepios DICOM Viewer

    master

    The viewer supports several key medical imaging workflows:

    2D Viewing

    Provides an intuitive layout system for displaying 2D DICOM images obtained from different imaging modalities.

    3D Post-Processing

    Includes state-of-the-art post-processing techniques:

    • 3D Rendering: Supports techniques such as Maximum Intensity Projection (MIP) and Volume Rendering.
    • Multiplanar Reconstruction (MPR): Allows for reconstruction of multiple anatomical planes from volumetric data.
  2. Dependencies and Libraries used by Asclepios DICOM Viewer

    master

    Asclepios DICOM Viewer is built upon the following libraries:

    • Qt: For the user interface and application framework.
    • Visualization Toolkit (VTK): For advanced 3D visualization and rendering.
    • DCMTK (DICOM Toolkit): For handling DICOM file formats and network protocols.
    • DICOM for VTK: For integrating DICOM data into the VTK pipeline.
    • Qt-Nice-Frameless-Window: For custom window decorations in the Qt UI.
  3. DicomReader Public API Reference

    master

    The asclepios::core::DicomReader class provides the following public interface for interacting with DICOM data:

    MethodReturn TypeDescription
    readFile(const std::string& t_filePath)voidLoads a DICOM file from the specified file path.
    getReadPatient()std::unique_ptr<Patient>Returns a unique pointer to the parsed Patient object.
    getReadStudy()std::unique_ptr<Study>Returns a unique pointer to the parsed Study object.
    getReadSeries()std::unique_ptr<Series>Returns a unique pointer to the parsed Series object.
    getReadImage()std::unique_ptr<Image>Returns a unique pointer to the parsed Image object.
    dataSetExists()boolReturns true if the DICOM dataset was successfully loaded and is not null.
  4. Navigate image sequences in a Series

    master

    When working with single-frame images within a Series, you can navigate the sequence using the following methods:

    • getNextSingleFrameImage(Image* t_image): Returns the next image in the sequence after the provided image.
    • getPreviousSingleFrameImage(Image* t_image): Returns the previous image in the sequence before the provided image.
    • getSingleFrameImageByIndex(const int& t_index): Returns the image at a specific index.
  5. Use the Series class to manage DICOM images

    master

    The asclepios::core::Series class is a data model used to group and manage DICOM images within a specific series. It distinguishes between singleFrameImages and multiFrameImages. You can use it to retrieve metadata, navigate through image sequences, and manage the relationship between a series and its parent Study.

    #include "src/core/series.h"
    
    asclepios::core::Series series;
    
    // Set basic DICOM metadata
    series.setUID("1.2.3.4.5.6");
    series.setDescription("Axial T2");
    series.setDate("20230101");
    
    // Add images to the series
    bool isNew = false;
    auto imagePtr = series.addSingleFrameImage(std::move(myUniqueImage), isNew);
    
    // Access images
    auto images = series.getSinlgeFrameImages();
    // Navigate sequence
    Image* nextImage = series.getNextSingleFrameImage(currentImage);
  6. Configure volume rendering transfer functions with TransferFunction

    master

    The asclepios::gui::TransferFunction class manages the visual properties of volume rendering, including window/level settings, lighting (shading), and the mapping of intensity values to colors and opacity.

    Lighting and Window/Level

    You can control the appearance of the rendered volume using:

    • Window/Level: Controls the intensity range displayed.
    • Shading: Toggles shading on/off via setHasShade and configures lighting parameters like setAmbient, setDiffuse, setSpecular, and setSpecularPower.

    Color and Opacity Mapping

    The class manages two types of transfer functions:

    1. Color Transfer Function: Maps intensity values to RGB colors. It uses vtkColorTransferFunction internally.
    2. Opacity Transfer Function: Maps intensity values to alpha (transparency) values. It uses vtkPiecewiseFunction internally.

    Data Loading

    • File Loading: Use loadFilterFromFile(const QString& t_fileName) to load transfer function configurations from a file.
    • JSON Integration: The class provides internal methods extractColorFunctionInfo and extractOpacityFunctionInfo to populate transfer functions from QJsonArray data structures.
    #include "src/gui/transferfunction.h"
    
    asclepios::gui::TransferFunction tf;
    
    // Configure window/level
    tf.setWindow(400);
    tf.setLevel(40);
    
    // Configure shading/lighting
    tf.setHasShade(true);
    tf.setAmbient(0.2);
    tf.setSpecular(0.8);
    
    // Access underlying VTK functions for advanced manipulation
    auto* colorFunc = tf.getColorFunction();
    auto* opacityFunc = tf.getOpacityFunction();
  7. Manage 2D and 3D view tabs with TabWidget

    master

    The TabWidget class is a UI component used to manage different types of DICOM view tabs (2D and 3D/MPR). It acts as a container for WidgetBase objects and provides methods to create, reset, and manipulate these view tabs.

    Creating View Tabs

    • Use createWidget2D() to instantiate a 2D viewer tab.
    • Use createWidgetMPR3D(WidgetBase::WidgetType t_type) to instantiate a 3D/Multiplanar Reconstruction tab. The type of 3D widget is determined by the WidgetBase::WidgetType provided.
    • Use resetWidget() to clear the current tab content.

    Tab Manipulation

    • setTabTitle(int t_index, const QString& t_name): Sets the display name for a specific tab index.
    • closeWidget(int t_index): Closes the tab at the specified index.
    • onMaximize(): A slot to trigger the maximization of the current tab view.

    State Inspection

    • getWidgetType(): Returns the current WidgetBase::WidgetType of the active tab.
    • getTabbedWidget(): Returns the pointer to the underlying WidgetBase instance.
    • getActiveTabbedWidget(): Returns the WidgetBase currently being viewed.
    • getIsActive(): Returns whether the tab widget is currently active.
    • getIsMaximized(): Returns whether the tab view is in maximized mode.
    // Example conceptual usage of TabWidget methods
    asclepios::gui::TabWidget* tabWidget = new asclepios::gui::TabWidget(parent);
    
    // Create a 2D view
    tabWidget->createWidget2D();
    
    // Create a specific 3D MPR view
    tabWidget->createWidgetMPR3D(WidgetBase::WidgetType::MPR);
    
    // Set a custom title for the first tab
    tabWidget->setTabTitle(0, "Axial View");
    
    // Check current state
    if (tabWidget->getIsMaximized()) {
        // handle maximized state
    }
  8. Control MPR view state and generation

    master

    Once MPRMaker is configured, use the following methods to manage the reconstruction and view state:

    • createMPR(): Triggers the generation of the Multiplanar Reconstruction views.
    • create3DMatrix(): Generates the necessary 3D transformation matrices.
    • resetMatrixesToInitialPosition(): Resets the transformation matrices to their default orientation.
    • resetWindowLevel(): Resets the window and level settings to the values provided via setInitialWindow and setInitialLevel.
  9. Use the StudyList UI component

    master

    The asclepios::gui::StudyList class is a QListWidget based component used to display and manage a list of DICOM studies and series. It allows developers to associate a specific core::Patient and core::Study with the list view and provides methods to populate the list with series and image data.

    Key Functionalities:

    • Data Association: Link the list to a specific patient or study using setPatient() and setStudy().
    • Populating Content: Use insertNewSeries() to add new series and image information to the list.
    • Concurrency Tracking: Access active background tasks via getFutures() to monitor loading or processing states.
    • Signals: The finishConcurrent() signal is emitted when concurrent operations associated with the list have completed.
    // Example usage of StudyList
    #include "src/gui/studylist.h"
    
    asclepios::gui::StudyList* studyList = new asclepios::gui::StudyList(parent);
    
    // Associate with data
    studyList->setPatient(myPatientPointer);
    studyList->setStudy(myStudyPointer);
    
    // Add content
    studyList->insertNewSeries(mySeriesPointer, myImagePointer);
    
    // Monitor background tasks
    std::vector<QFuture<void>> tasks = studyList->getFutures();
    
    // Connect to completion signal
    connect(studyList, &asclepios::gui::StudyList::finishConcurrent, []() {
        // Handle completion
    });
  10. Add thumbnails to the ThumbnailsWidget

    master

    The ThumbnailsWidget class provides a slot addThumbnail to populate the UI with DICOM image thumbnails. To add an entry, you must provide pointers to the corresponding core::Patient, core::Study, core::Series, and core::Image objects. This method handles the hierarchical organization of the thumbnails within the widget.

    // Assuming you have pointers to the core DICOM objects
    asclepios::gui::ThumbnailsWidget* thumbnailsWidget = ...;
    
    thumbnailsWidget->addThumbnail(
        patient_ptr, 
        study_ptr, 
        series_ptr, 
        image_ptr
    );
  11. Manage application data with CoreRepository

    master

    The CoreRepository class serves as the central repository for managing the hierarchy of DICOM data within the application. It manages the lifecycle and ownership of Patient, Study, Series, and Image objects.

    Data Hierarchy and Ownership

    • Ownership: The repository owns the Patient objects via std::unique_ptr. Other entities like Study, Series, and Image are managed via raw pointers (Patient*, Study*, etc.) which are updated as the user navigates the DICOM hierarchy.
    • Navigation State: The repository tracks the 'last' accessed entity at each level of the hierarchy (getLastPatient(), getLastStudy(), getLastSeries(), and getLastImage()).
    • Change Tracking: You can check if new data has been added to the current context using newSeriesAdded() and newImageAdded().
    #include "src/core/corerepository.h"
    
    asclepios::core::CoreRepository repo;
    
    // Adding data
    repo.addPatient(std::make_unique<Patient>(...));
    
    // Accessing current state
    asclepios::core::Patient* currentPatient = repo.getLastPatient();
    if (repo.newSeriesAdded()) {
        // Handle new series logic
    }
    
    // Deleting data
    repo.deletePatient(currentPatient);
    // or
    repo.deleteAllPatients();