Examples¶
The following programs are provided as standalone compilable examples in the
src/ directory of the companion manuscript repository. Each can be built
with pixi run -e cxx build-src. See src/CMakeLists.txt for the
CMake configuration.
Example 1: Reading a TRX File and Inspecting Metadata¶
This program opens a TRX file, prints summary statistics, and lists all named
groups, DPS fields, and DPV fields. It demonstrates the basic reader pipeline
and the enumeration API on TrxStreamlineData.
#include "itkTrxFileReader.h"
#include "itkTrxStreamlineData.h"
#include <iostream>
int main(int argc, char * argv[])
{
if (argc < 2)
{
std::cerr << "Usage: TrxReadInfo <input.trx>\n";
return EXIT_FAILURE;
}
auto reader = itk::TrxFileReader::New();
reader->SetFileName(argv[1]);
reader->Update();
auto data = reader->GetOutput();
std::cout << "Streamlines : " << data->GetNumberOfStreamlines() << "\n";
std::cout << "Vertices : " << data->GetNumberOfVertices() << "\n";
if (data->HasGroups())
{
for (const auto & name : data->GetGroupNames())
{
auto group = data->GetGroup(name);
std::cout << " group '" << name << "': "
<< group->GetStreamlineIndices().size()
<< " streamlines\n";
}
}
for (const auto & f : data->GetDpsFieldNames())
std::cout << " DPS field: " << f << "\n";
for (const auto & f : data->GetDpvFieldNames())
std::cout << " DPV field: " << f << "\n";
return EXIT_SUCCESS;
}
Example 2: Spatial Query with an Axis-Aligned Bounding Box¶
QueryAabb() selects streamlines whose bounding boxes intersect a region
of interest specified in LPS+ coordinates and returns the matching streamlines
as a new TrxStreamlineData. The result can be written directly to a new
TRX file using Save().
#include "itkTrxFileReader.h"
#include "itkTrxStreamlineData.h"
#include <iostream>
int main(int argc, char * argv[])
{
// argv[1] input, argv[2] output,
// argv[3-5] min LPS corner, argv[6-8] max LPS corner
if (argc < 9) { return EXIT_FAILURE; }
auto reader = itk::TrxFileReader::New();
reader->SetFileName(argv[1]);
reader->Update();
auto data = reader->GetOutput();
itk::TrxStreamlineData::PointType minCorner, maxCorner;
for (int i = 0; i < 3; ++i)
{
minCorner[i] = std::stod(argv[3 + i]);
maxCorner[i] = std::stod(argv[6 + i]);
}
auto subset = data->QueryAabb(minCorner, maxCorner);
std::cout << "Found " << subset->GetNumberOfStreamlines()
<< " / " << data->GetNumberOfStreamlines()
<< " streamlines in ROI\n";
subset->Save(argv[2], /*useCompression=*/true);
return EXIT_SUCCESS;
}
Example 3: Streaming Writer with DPS and DPV Fields¶
TrxStreamWriter is designed for pipelines that generate streamlines
incrementally. Fields must be declared before the first PushStreamline()
call to ensure that all arrays in the output archive have matching lengths.
#include "itkTrxStreamWriter.h"
#include "itkPoint.h"
#include <vector>
#include <iostream>
int main(int argc, char * argv[])
{
if (argc < 2) { return EXIT_FAILURE; }
using PointType = itk::Point<double, 3>;
auto writer = itk::TrxStreamWriter::New();
writer->SetFileName(argv[1]);
writer->UseCompressionOn();
// Declare fields before pushing any streamlines
writer->RegisterDpsField("mean_fa", "float32");
writer->RegisterDpvField("fa", "float32");
for (int s = 0; s < 10; ++s)
{
std::vector<PointType> pts;
std::vector<double> faPerVertex;
for (int v = 0; v < 50; ++v)
{
PointType p;
p[0] = static_cast<double>(v);
p[1] = static_cast<double>(s);
p[2] = 0.0;
pts.push_back(p);
faPerVertex.push_back(0.6 + 0.004 * v);
}
writer->PushStreamline(pts,
/*dps=*/{ { "mean_fa", 0.65 } },
/*dpv=*/{ { "fa", faPerVertex } });
}
writer->Finalize();
std::cout << "Wrote " << argv[1] << "\n";
return EXIT_SUCCESS;
}
Example 4: Working with Named Groups¶
Groups represent named anatomical bundles. Group membership is loaded lazily;
data->GetGroup("CST_left") caches the index list on first access.
Underlying streamline positions are fetched only when GetStreamlines() is
called.
#include "itkTrxFileReader.h"
#include "itkTrxStreamlineData.h"
#include <iostream>
int main(int argc, char * argv[])
{
// argv[1] input, argv[2] output bundle file, argv[3] group name
if (argc < 4) { return EXIT_FAILURE; }
auto reader = itk::TrxFileReader::New();
reader->SetFileName(argv[1]);
reader->Update();
auto data = reader->GetOutput();
auto group = data->GetGroup(argv[3]);
if (!group)
{
std::cerr << "Group '" << argv[3] << "' not found\n";
return EXIT_FAILURE;
}
std::cout << argv[3] << ": "
<< group->GetStreamlineIndices().size()
<< " streamlines\n";
// Lazy subset — no position data is copied
auto bundle = group->GetStreamlines(data.GetPointer());
// Iterate point-by-point in LPS+ (default)
for (itk::SizeValueType i = 0; i < bundle->GetNumberOfStreamlines(); ++i)
{
for (const auto & pt : bundle->GetStreamlineRange(i))
{
(void)pt; // use pt[0], pt[1], pt[2] ...
}
}
bundle->Save(argv[2], /*useCompression=*/true);
return EXIT_SUCCESS;
}