TRX-cpp is a C++11 library for reading, writing, and memory-mapping the TRX tractography file format (zip archives or on-disk directories of memmaps).
Required:
- C++11 compiler and CMake (>= 3.10)
- libzip
- Eigen3
Optional:
- GTest (for building tests)
cmake -S . -B build
cmake --build build
cmake -S . -B build \
-DTRX_BUILD_TESTS=ON \
-DGTest_DIR=/path/to/GTestConfig.cmake
cmake --build build
ctest --test-dir build --output-on-failure
This repo includes .clang-tidy and .clang-format at the root, plus
MRtrix-inspired helper scripts for formatting and style checks.
clang-formatavailable onPATH- macOS (Homebrew):
brew install llvm(orllvm@17) and ensureclang-formatis onPATH - Ubuntu:
sudo apt-get install clang-format
- macOS (Homebrew):
- For
check_syntaxon macOS, GNU grep is required (brew install grep, then it will useggrep).
Run the formatter across repo sources:
./clang-format-all
You can target a specific clang-format binary:
./clang-format-all --executable /path/to/clang-format
Run the MRtrix-style checks against the C++ sources:
./check_syntax
Results are written to syntax.log when issues are found.
Generate a build with compile commands, then run clang-tidy (matches CI):
cmake -S . -B build \
-DTRX_USE_CONAN=OFF \
-DTRX_BUILD_EXAMPLES=ON \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
run-clang-tidy -p build $(git ls-files '*.cpp' '*.h' '*.hpp' '*.tpp' ':!third_party/**')
To run clang-tidy automatically during builds:
cmake -S . -B build -DTRX_ENABLE_CLANG_TIDY=ON
cmake --build build
If you have run-clang-tidy installed (LLVM extras), you can lint everything
tracked by the repo (excluding third_party), which matches CI.
mioby Martin Andreyel (https://github.com/mandreyel/mio) is vendored inthird_party/mio. Seethird_party/mio/LICENSEfor the license text.json11by Dropbox (https://github.com/dropbox/json11) is vendored inthird_party/json11. Seethird_party/json11/LICENSEfor the license text.clang-format-allandcheck_syntaxare adapted from MRtrix3 (https://github.com/MRtrix3/mrtrix3) and retain their original copyright notices under the Mozilla Public License 2.0.
All examples assume:
#include <trx/trx.h>
using namespace trxmmap;
TrxFile<half> *trx = load_from_zip<half>("tracks.trx");
// Access streamlines: vertices are stored as an Eigen matrix
const auto num_vertices = trx->streamlines->_data.size() / 3;
const auto num_streamlines = trx->streamlines->_offsets.size() - 1;
std::cout << "Vertices: " << num_vertices << "\n";
std::cout << "Streamlines: " << num_streamlines << "\n";
std::cout << "First vertex (x,y,z): "
<< trx->streamlines->_data(0, 0) << ","
<< trx->streamlines->_data(0, 1) << ","
<< trx->streamlines->_data(0, 2) << "\n";
// Data-per-streamline and data-per-vertex are stored in maps
for (const auto &kv : trx->data_per_streamline) {
std::cout << "DPS '" << kv.first << "' elements: "
<< kv.second->_matrix.size() << "\n";
}
for (const auto &kv : trx->data_per_vertex) {
std::cout << "DPV '" << kv.first << "' elements: "
<< kv.second->_data.size() << "\n";
}
trx->close(); // cleans up temporary on-disk data
delete trx;
TrxFile<float> *trx = load_from_directory<float>("/path/to/trx_dir");
std::cout << "Header JSON:\n" << trx->header.dump() << "\n";
trx->close();
delete trx;
You can modify a loaded TrxFile and save it to a new archive:
TrxFile<half> *trx = load_from_zip<half>("tracks.trx");
// Example: update header metadata
auto header_obj = trx->header.object_items();
header_obj["COMMENT"] = "saved by trx-cpp";
trx->header = json(header_obj);
// Save with no compression (ZIP_CM_STORE) or another libzip compression level
save(*trx, "tracks_copy.trx", ZIP_CM_STORE);
trx->close();
delete trx;
TrxFile uses memory-mapped arrays under the hood for large datasets. The
close() method cleans up any temporary folders created during zip extraction.
If you skip close(), temporary directories may be left behind.