/OCTSharp

Open Source C# Software for OCT

Primary LanguageC#OtherNOASSERTION

OCTSharp

With the advance of hardware technology, imaging speed of Optical Coherence Tomography (OCT) has reached hundreds of kHz for spectral domain OCT (SD-OCT) and it even breaks into MHz territory for swept source OCT. High-speed imaging demands massive computation power for high throughput data acquisition, processing, and visualization. Commercial OCT software provided with the OCT devices is convenient, but users usually cannot access the source code to tailor the software for specific applications nor modify the hardware. For independent research groups, a significant amount of effort is often spent on developing OCT software for real-time imaging, especially for clinical applications. On the other hand, developing software that accommodates different hardware is often challenging. Virtual processing plugin in C++ (https://github.com/spectralcode/OCTproZ) and OCT software development library in C++ (https://www.vortex-oct.dev/) are being explored. However, developing or maintaining C++ based OCT software is often challenging for non-professional software developers due to its complexity of low-level memory management and the steep learning curve of C++ programming. In this project, OCTSharp is developed as open-source software that aims to significantly lower the programming complexity and development cycle for an interactive, intuitive, and high-performance OCT developmental solution.

Programming Structure

OCTSharp is a muti-threads C# Windows form application that provides hardware control, data acquisition, real-time data processing, and image visualization. The frontend User Interface (UI) is developed with native .NET framework, and the backend is consisted of two fundamental layers: the hardware control layer developed with the C# SDK from Teledyne SaperaLT and National Instrument, and the processing layer that is built with ManagedCuda (Fig. 1). ManagedCuda is an open-source C# Application Program Interface (API) that allow CUDA usage in C#. All CUDA kernels are pre-compiled and accessed in real-time during parallel CUDA processing pipeline.

Figure 1. Programming Structure. ManagedCuda is open-source and avaliable at https://github.com/kunzmi/managedCuda

Figure 2. Software Architecture.

Programming Dependencies

  • .NET Framework 4.6.2
  • NVIDIA CUDA 11.1
  • ManagedCUDA 11.1

Hardware Configuration

Figure 3 shows the current hardware configuration. The C# .NET layer was developed using the Software Development Kit (SDK) from Teledyne Dalsa and National Instrument. Therefore, any image acquisition card (IMAQ) from Teledyne Dalsa and data acquisition card (DAQ) from National Instrument are compatible with OCTSharp. In this project, we tested mutiple IMAQ cards, including Xtium-CL MX4 and Xcelera-CL LX1; DAQ cards including PCIe 6361and PCI 6221. Four linear cameras have been also tested independently, which works as expected, including Dalsa Octoplus, AVIIVA SM2 4010 CL, Basler spL 2048 70km, and Sensor Unlimited GL 2048R. User can use any linear camera in OCTSharp as long as the camera file is configured appropriately. Galvanometer scanner can be modified freely as well, where the scanning distance can be adjusted via voltage parameters setting on UI. DAQ is mainly responsible for hardware synchronization and scanner control. DAQs from other vendors can be used as long as C# SDK is provided and the corresponding analog and digital hardware functions are modified accordingly. The master clock of the system is supplied as a strobe signal by a user-specified internal frequency from the Teledyne Dalsa IMAQ card, in the vendor software: CamExpert. Using this master clock, OCTSharp synchronizes the camera with the galvanometer scanner. In addition, the camera runs on external trigger mode based on the acquisition clock, which is generated from master clock and it is adjustable by the user.

Figure 3. OCTSharp hardware configuration. AO0, AO1 are analog output channels on PCIe-6361; CTR0 and TRIG 1 are trigger channels on the PCIe-6361, which are acquisition trigger for camera and master clock respectively; J4 I/O is the general Input & Output ports on the Xtium CL MX4; Two medium CameraLink cables are used to achieve 250kHz image acquisition with Dalsa OCTOPLUS camera at 10-bit 8TAP mode and 85MHz pixel clock. MX-4 has a bandwidth of 1.4GB/s on PCIe Gen.2x4 connection

Environment Preparation

Set Camera hardware parameters with manufacture's software

  • For example, Dalsa Teledyne OCTOPUS Camera is configured with CommCam.exe
  • Set camera parameters, such as: Line Acquisition Rate, Externel Trigger, CameraLink Tap Config, Image Bit Rate, etc.. (These settings need to be consistent with the parameters in camera files, otherwise OCTSharp won't perform properly)

Configure .ccf Camera File

  1. Download SaperaLT SDK that includes the Camera File Configuration Tool: CamExpert (https://www.teledynedalsa.com/en/products/imaging/vision-software/sapera-lt/)
  2. Open CamExpert
  3. Create New .ccf File and set Camera settings

CamExpert Camera Settings example: 250kHz Dalsa Teledyne OCTOPUS (more avaliable in Camera files folder)

  • Basic Timing

* Advance Control

* Externel Trigger

* Image Buffer and ROI

Get Started to image with OCTSharp

  1. Download Zip
  2. Extract all files
  3. Open OCTSharp.exe (at \bin\x64\Release)

Figure 4. OCTSharp GUI.

  1. Adjust Scanner Voltage (sacaning distance)
  2. Load the corresponding .ccf file
  3. Load 3rd Calibration Curve as excel file if needed
  4. Set OCT parameters as needed
  • ANum: number of Linear Camera's pixels
  • BNum: number of A-Scans
  • CNum: number of B-Scans
  • FNum: number of frames for each B-Scans
  • RNum: number of A-Scans for scanner return
  1. Enable display features (Warning: Enable mutiple plotting charts may cause GUI freeze, see Garbage Collection benchmark below for detail)
  2. Click "Scan" button to perform Imaging
  3. Click "Stop" to exit imaging section
  4. Click "Save" button to perform one time scan and save raw data to the pre-defined directory (if Save is enabled with directory)

OCT Display options

Figure 5. Different visualization features in OCTSharp showing the newt anterior chamber of eye. (A) B-Scan (2048x2048) of a Newt eye; (B) An average B-Scan consists of 10 B-Scans at the same scanning position as A’s (B); (C) A Speckle Variant map that shows the blood vessels location in A; (D) An enface image of a newt’s eye; (E) An Volumetric C-Scan generated from data collected in OCTSharp; (F) The angiography display function of OCTSharp that shows the enface blood vessels of (D)..

Software Performance

Two different PC configurations were tested (Tab 1). The highest A-Scan acquisition rate is 250kHz ( this is the limit set by the camera speed but does not represent the maximum acquisition speed of OCTSharp, and it can be upgraded by using a faster linear camera), and A-Scan processing speed can reach up to 350 kHz. The limitation for current processing speed is the data I/O between CPU memory and GPU memory, as it takes up about 50% of the CPU resource.

Table 1. Software Performance w/ different PC Configurations.

Garbage Colletion

The auto garbage collection (GC) mechanism reduces the requirement for memory management but it is one of the major concerns for using C# in real-time application. GC event occurs when physical memory is low or there are dead objects. This mechanism can be effectively reduced by an efficient memory structure, such as recycled memory and reusable objects.

Plot charting at the User Interface (UI) triggers the most GC events during real-time imaging (Fig. 6). GC event has 3 different depths, Gen 0, Gen1 and Gen 2, where Gen 2 GC is known as a full GC that suspends all other threads. We shown that the native C# charting function generates lots of unintentional GC events during rapid charting update (Fig. 6 – blue bar). However, most of these GC event occurs at the Gen 0 and 1 depth which does not suspend other threads’ activities. During a 1-hour continuous imaging section, the C# native charting function leads to 1.13% of blocking time from all threads combined. However, those GC events could be reduced by using a more efficient charting functions. For example, we use SaperLT SDK to plot the chart by displaying a binary image (Fig. 6 –orange bar). This method substantially reduces the GC time down to 0.0488% of the imaging time, which is close to the 0.0401% total blocking time at no charting condition (Fig. 6-gray).

Figure 6. The time spent in GC during real-time image acquisition.

Compile/Debug with Visual Studio

  • Visual Studio 2017/2019 Community

Compile your own CUDA processing file

OCTProz is an Open-source OCT project in C++ (https://github.com/spectralcode/OCTproZ) that provides a set of OCT processing functions in CUDA C. Therefore their CUDA file provides a great reference for OCTSharp CUDA processing pipeline. v1.4.8 version currently provides basic OCT processing functions, including DC removal, 3rd calibration, FFT and modulus calculation (see display feature for other processing options). More processing functions will be added in the future. User can also refer to OCTProz's repository and compile your own CUDA file.

  • CUDA Compile steps
    1.TBA

Version History

  • v1.4.8: First release version

Road Map

⬜ Alternative Processing buffers to optimize GPU performance
⬜ OpenTK Integration for real-time 3D C-Scan display
⬜ Bidirectional scanner pattern to optimize acquisition speed
⬜ Flat GUI update

Known Bugs

License

This project is licensed under the Attribution-NonCommercial-ShareAlike 4.0 International. Check LICENSE.md file for details https://creativecommons.org/licenses/by-nc-sa/4.0/