🚀 Get started with with Tractography.jl
This tutorial will introduce you to the functionalities for computing streamlines.
Basic use
In this example, we sample Nmc streamlines from a Model model.
using Tractography
const TG = Tractography
model = Model(Δt = 0.125f0,
foddata = FODData((@__DIR__) * "/../../examples/fod-FC.nii.gz"),
)
Nmc = 10
seeds = rand(Float32, 6, Nmc)
alg = Probabilistic()
streamlines, tract_length = sample(model, alg, seeds);
size(streamlines)(3, 1000, 10)Step 1: Define a Model
We define a Tractography Markov Chain (Model) model as follows:
model = Model(Δt = 0.125f0,
foddata = FODData((@__DIR__) * "/../../examples/fod-FC.nii.gz"),
)Model with elype Float32
├─ Δt = 0.125
├─ minimal probability = 0.0
├─ cone = Cone{Float32}(90.0f0)
├─ mollifier = max_mollifier
├─ evaluation of the basis = PreComputeAllFOD()
└─ data : (lmax = 8)
Step 2: Define the seeds
seeds is a 6 x Nmc matrix. Each column stores:
seeds[1:3, i]: initial position(x, y, z)in native spaceseeds[4:6, i]: initial direction(u1, u2, u3)
Nmc = 10 # Monte Carlo sample
seeds = rand(Float32, 6, Nmc)6×10 Matrix{Float32}:
0.958727 0.732877 0.972953 0.106595 … 0.647098 0.64341 0.486739
0.284568 0.794337 0.0587938 0.834071 0.912675 0.149684 0.780145
0.813771 0.54531 0.407041 0.779897 0.184815 0.890609 0.559893
0.979626 0.14715 0.739527 0.889523 0.394945 0.421846 0.385374
0.59004 0.0707152 0.567951 0.850859 0.876543 0.155006 0.318012
0.0167293 0.88054 0.152792 0.0702036 … 0.268925 0.153168 0.402905Step 3: Choose a sampling algorithm
alg = Probabilistic()Probabilistic()Step 4: Sample the streamlines
streamlines, tract_length = sample(model, alg, seeds);(Float32[0.9587271 1.0367229 … 1.0760609 1.0760609; 0.28456777 0.35634938 … -1.5205965 -1.5205965; 0.8137715 0.74752146 … 1.6512716 1.6512716;;; 0.7328775 0.6464846 … -1.5124451 -1.5124451; 0.7943368 0.7637382 … -1.3866397 -1.3866397; 0.5453104 0.63031036 … 3.067185 3.067185;;; 0.9729532 0.9857268 … -0.6417298 -0.6417298; 0.058793843 0.11557364 … 2.9777167 2.9777167; 0.40704125 0.5176662 … -1.541709 -1.541709;;; 0.10659522 0.1498922 … -1.5378102 -1.5378102; 0.834071 0.8435897 … -1.2157539 -1.2157539; 0.7798966 0.8967716 … 3.6611466 3.6611466;;; 0.78961754 0.8703191 … 3.6800435 3.6800435; 0.07483721 -0.0086684 … -1.5166051 -1.5166051; 0.31199408 0.35824406 … 0.3351197 0.3351197;;; 0.497927 0.605739 … 0.13399333 0.13399333; 0.5730119 0.6244104 … -1.5001765 -1.5001765; 0.9473256 0.9104506 … 0.96732557 0.96732557;;; 0.091783345 0.19959533 … 0.52727395 0.52727395; 0.80801666 0.8594152 … 3.4576056 3.4576056; 0.588063 0.551188 … -1.5131872 -1.5131872;;; 0.6470983 0.5504283 … 2.175899 2.175899; 0.9126755 0.99060667 … 2.1313498 2.1313498; 0.18481529 0.19919029 … -1.5683095 -1.5683095;;; 0.64341044 0.7214062 … 1.5481051 1.5481051; 0.14968371 0.22146532 … -1.5661538 -1.5661538; 0.8906089 0.8243589 … 0.3487339 0.3487339;;; 0.48673928 0.5590347 … -1.6206806 -1.6206806; 0.7801454 0.86718625 … 3.4691792 3.4691792; 0.5598935 0.50676847 … 0.25176847 0.25176847], UInt32[0x00000020, 0x00000051, 0x0000008c, 0x000000f8, 0x0000011a, 0x0000004a, 0x000000a6, 0x0000007b, 0x00000034, 0x00000076])Optimal use
When computing multiple batches for the same model, it is more efficient to precompute a cache once and reuse it.
model = Model(Δt = 0.125f0,
foddata = FODData((@__DIR__) * "/../../examples/fod-FC.nii.gz"),
)
Nmc = 10
seeds = rand(Float32, 6, Nmc)
streamlines = zeros(Float32, 6, 20, Nmc)
tract_length = zeros(UInt32, Nmc)
alg = Probabilistic()
cache = TG.init(model, alg)
# this can be called repeatedly after updating seeds for example
TG.sample!(streamlines, tract_length, model, cache, alg, seeds);
size(streamlines)(6, 20, 10)