This Application is written in Rust and the GUI is based on egui and bevy.
A sample scan of a THz time-domain 2D imaging system can be found in the sample_data
directory.
- Features
- Installation
- Usage
- Custom Filters
- PSF File Generation
- Tested Platforms
- Community Guidelines
- Cross-platform (Linux, macOS, Windows)
- Interactive 2D and 3D visualization
- Meta data editing
- Region of Interest (ROI) selection and comparison
- Reference dataset support
- Extensible with custom filters
Binary bundles are available for Linux, macOS, and Windows.
If you see the message "THz Image Explorer is damaged and cannot be opened."
, run:
xattr -rd com.apple.quarantine THz\ Image\ Explorer.app
Install dependencies:
sudo apt-get install libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxkbcommon-dev libssl-dev libasound2-dev libxkbcommon-x11-0 libx11-dev
- Install Rust and Cargo.
- Install Cmake.
- Install dependencies (Linux only):
Note: For Fedora and other distributions consult bevy and egui documentation for the required dependencies.
sudo apt-get install libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxkbcommon-dev libssl-dev pkg-config libx11-dev libasound2-dev libudev-dev libxkbcommon-x11-0
- Install bundling tools:
- Linux/macOS:
cargo install cargo-bundle
- Windows:
cargo install cargo-wix
- Linux/macOS:
- Build:
- Linux/macOS:
cargo bundle --release
- Windows:
cargo wix -p thz-image-explorer
- Linux/macOS:
Note: cargo-bundle only supports Linux and macOS. For Windows, use cargo-wix.
The DotTHzQLExtension.appex
plugin is installed in THz Image Explorer.app/Contents/PlugIns
.
Source: DotTHzQL
Requires HDF5 to be installed system-wide.
Example data is available in the sample_data
directory of this repository.
The window is structured with the time domain trace and frequency domain spectrum for the selected pixel (default is
0,0) in the center panel. A different tab showing the optical properties (refractive index and absorption coefficient)
can be selected, as
well as a tab containing an interactive 3D viewer.
The left side-panel contains the intensity plot of the 2D scan along with the meta-data editor. The right
side-panel contains the possible filters with configuration settings.
A pixel can be (de-)selected by clicking inside the intensity plot.
For large scans, it is recommended to down-scale the image. This will average the pixel values in a
THz Image Explorer is able to load scans in the .thz
(dotTHz) format, which are based on the HDF5 standard.
This allows the files to also contain meta-data, which will also be displayed by the THz Image Explorer. The meta-data
is shown in the file opening dialog on Linux and Windows, and using QuickView on macOS, allowing to easily
browse through directories containing multiple scans.
THz Image Explorer supports drag & drop of .thz
, .thzimg
and .thzswp
files.
To comply with the dotTHz standard, the .thzimg
file needs to contain two datasets:
- time axis: 1D, shape
(n_t,)
- data: 3D, shape
(n_x, n_y, n_t)
The file should also contain at least the mandatory fields of the meta-data (e.g. user, date, thickness etc.).
The 3D structure can be exported as a .vtu
file for further analysis.
A reference file (standard .thz
) can be loaded, which is used to compute the optical properties of the sample. The
first
entry will be used.
The meta-data editor allows the user to edit the meta-data of the loaded scan. The meta-data is stored in the .thz
(or
.thzimg
, or .thzswp
)
file. Certain fields are mandatory as per the dotTHz standard, and cannot be deleted. But any further
attributes can be added, modified and deleted.
By holding the Shift key and selecting pixels, a region of interest (ROI) can be selected. This ROI is a convex polygon, which is closed if the last corner is selected reasonably close to the first one (< 5 % of width/height of the image). This ROI can then be saved in the meta-data of the dotTHz file for future analysis. The full averaged scan as well as the averages of all selected ROIs can be displayed in the center plot.
The filtering process is a simple linear pipeline, where the output of one filter is the input of the next filter.
Before applying the Fast-Fourier-Transform (FFT), a tilt-compensation can be applied to the time domain trace to
compensate any misalignment along the
To reduce artefacts in frequency domain, a window is multiplied to the time domain signal before applying the Fast-Fourier-Transform (FFT). By default, an adapted Blackman window is applied, but the user can also select other windows:
- Adapted Blackman (default)
- Blackman
- Hanning
- Hamming
- FlatTop
The adapted Blackman window is a modified version of the Blackman window, where most of the signal is preserved and only the first and last couple of datapoints are modified.
All windows are defined in math_tools.rs
.
A simple band-pass filter can be applied in fourier space to only display certain frequency bands.
The inverse FFT is applied to convert the data from frequency domain back to time domain.
After converting back to time domain, another band-pass filter can be applied to the time traces.
The deconvolution filter is an implementation of the Frequency-dependent Richardson-Lucy algorithm.
Extend the codebase with custom filters:
- Create a file in
src/filters
with a struct implementing theFilter
trait. - Attach the file to
mod.rs
insrc/filters
. - Implement the required functions (
config
,filter
,ui
, etc.). - Derive
Clone
,Debug
, andCopyStaticFields
. - Add the
#[register_filter]
macro to your struct.
Loops requiring heavy computation can be parallelized using the rayon
crate. Use the cancellable_loops
crate for
abortable computations.
Example:
use crate::filters::filter::Filter;
use crate::data_container::ScannedImageFilterData;
use crate::gui::application::GuiSettingsContainer;
#[register_filter]
#[derive(Clone, Debug, CopyStaticFields)]
struct ExampleFilter;
impl Filter for ExampleFilter {
fn new() -> Self { ExampleFilter }
fn reset(&mut self, time: &Array1<f32>, shape: &[usize]) {
// Reset any internal state if necessary
}
fn show_data(&mut self, data: &ScannedImageFilterData) {
// Display any data in the GUI if needed
}
fn filter(
&mut self,
input_data: &ScannedImageFilterData,
gui_settings: &mut GuiSettingsContainer,
progress_lock: &mut Arc<RwLock<Option<f32>>>,
abort_flag: &Arc<AtomicBool>,
) -> ScannedImageFilterData {
// Apply filter logic here
input_data.clone() // Placeholder, replace with actual filtering logic
}
fn config(&self) -> FilterConfig {
FilterConfig {
name: "Example Filter".to_string(),
description: "Description of the example filter.".to_string(),
hyperlink: None, // Optional DOI or reference link
domain: FilterDomain::TimeBeforeFFT, // Specify the domain of the filter
}
}
fn ui(
&mut self,
ui: &mut egui::Ui,
thread_communication: &mut ThreadCommunication,
panel_width: f32,
) -> egui::Response {
// Render filter configuration UI here
}
}
To run the deconvolution filter, a point spread function (PSF) file is required.
-
Perform a knife-edge scan and create a
.thz
file (seesample_data/example_beam_width/
). -
Run:
python scripts/generate_psf.py \ --path_x sample_data/example_beam_width/measurement_x/data/1750085285.8557956_data.thz \ --path_y sample_data/example_beam_width/measurement_y/data/1750163177.929295_data.thz
This generates a psf.npz
file for deblurring in THz Image Explorer.
After regions of interest (ROIs) have been selected, they can be saved in the meta-data of the dotTHz file. The coordinates are saved for each ROI with label "ROI {i}" as a list, e.g.:
"ROI 1": [[27.57,34.72],[37.96,23.65],[40.35,32.06],[35.06,37.92]]
while the label of the ROI is saved in the "ROI Labels" meta-data field as a comma-separated list.
The file can then be opened with Python using the pydotthz
package
to further process the data.
A Python code snipped for ROI extraction and the PSF generation script can be found in the scripts
directory of the
repository.
- macOS 12.4 Monterey x86
- macOS 10.14.6 Mojave x86
- Debian 12 (Testing) x86
- Windows 10 x86
We welcome contributions and feedback from the community! Please follow these guidelines:
-
Contributing to the Software
- Fork the repository and submit pull requests for new features, bug fixes, or improvements.
- Please ensure your code follows the existing style and includes relevant documentation.
- For major changes, open an issue first to discuss your proposal.
-
Reporting Issues or Problems
- Use the GitHub Issues page to report bugs, request features, or suggest improvements.
- Provide as much detail as possible, including steps to reproduce, screenshots, and your operating system.
-
Seeking Support
- For general questions or help, open a discussion in the GitHub Discussions section.
- You may also contact the maintainers via email listed in the relevant publication.
Thank you for helping us improve THz Image Explorer!