# DKI project: PR#1 Simulations to test DKI #582

Merged
merged 26 commits into from Jun 8, 2015

## Conversation

Projects
None yet
4 participants
Contributor

### RafaelNH commented Mar 1, 2015

 I add some functions on dipy.sims.voxel module for DKI simulations (multi_tensor_dki, compute_Wijkl, single_diffkurt_tensors, dki_design_matrix). This PR was discussed to be the first milestone of the DKI project. To see how to use the functions please give a look to the added script on doc/examples/simulations_dki.py. Basically, the objective of the new functions is to produce ground truth DT and KT tensors to test diffusion fits (you can simulate tensors for any single voxel crossing fiber configuration ;) ). DW signals are also simulated from the computed tensors using the DKI model. Future steps on the DKI project can use these simulations to check if the DKI implementation is correct. DKI simulations modules are also relevant for DKI fit comparison studies. Implementation was done according to PEP 8 standards and the nomenclature is consistent to previous dipy functions. However, I notice that the order of DT elements is different from previous dipy modules (as dipy.reconst.dti.py), I decided to keep this order since I notice that they are consistent to the in progress DKI implementations. Perhaps is better to transform all new functions to dipy assumed format - Dxx Dxy Dyy Dxz Dyz Dzz. What do you thing? Please let me know if you need help doing this on the submitted changes after its revision. Enjoy, R Neto Henriques

### arokem reviewed Mar 1, 2015

 # kurtosis tensor - Impact on the development of robust tractography # procedures and novel biomarkers", NeuroImage, 2015; 111:85-99. # diffusion_tensor = np.array([1638e-6, 444e-6, 444e-6, 0, 0, 0])

#### arokem Mar 1, 2015

Member

Would it be OK to use the same diffusion evals as the ones just above (on L16)? It's starting to get crowded in this namespace...

#### RafaelNH Mar 2, 2015

Contributor

Can we instead change the evals? The parameters diffusion_tensor and kurtosis_tensor are the defaults for a voxel of well aligned fibers and assuming the multi-compartmental model's parameters on Table 1 of Neto Henriques et al. (2015), so I want to keep then consistent to each other. Another option is to remove these global variables at all, and require users always giving the DT and KT as input of function single_diffkurt_tensors.

### arokem reviewed Mar 1, 2015

 diffusion_tensor = np.array([1638e-6, 444e-6, 444e-6, 0, 0, 0]) kurtosis_tensor = np.array([1.7068, 0.8010, 0.8010, 0, 0, 0, 0, 0, 0, 0.3897, 0.3897, 0.2670, 0, 0, 0])

#### arokem Mar 1, 2015

Member

Just for my own understanding: are the kurtosis elements of similar units to the DT evals? Why are they 3 orders of magnitude different?

#### RafaelNH Mar 2, 2015

Contributor

Kurtosis don't have the same units of DT evals! Actually kurtosis is dimensionless - it is an statistical measure quantifying deviations of the water diffusion propagation function from gaussian. Typical values of kurtosis are on the range of [0 3].

### arokem reviewed Mar 1, 2015

 def multi_tensor_dki(gtab, mevals, S0=100, angles=[(0., 0.), (90., 0.)], fractions=[50, 50], snr=20): r"""Simulate the elements of the diffusion and diffusion kurtosis tensor as

#### arokem Mar 1, 2015

Member

Possible typo, Should this be: "...the diffusion tensor and diffusion kurtosis tensor..."?

#### arokem Mar 1, 2015

Member

Would be nice to have a one-line summary at the top, and then a more expansive explanation.

#### RafaelNH Mar 2, 2015

Contributor

Yes, you are right it should be diffusion tensor

### arokem reviewed Mar 1, 2015

 r"""Simulate the elements of the diffusion and diffusion kurtosis tensor as well as the diffusion signal S based on the DKI model (i.e. taylor accumulante larger than the fourth order are ignored). Simulations are

#### arokem Mar 1, 2015

Member

"Taylor expansion"?

#### RafaelNH Mar 2, 2015

Contributor

Perhaps is better to say 'Taylor expansion coefficients larger than ...'.

### arokem reviewed Mar 1, 2015

 r"""Simulate the elements of the diffusion and diffusion kurtosis tensor as well as the diffusion signal S based on the DKI model (i.e. taylor accumulante larger than the fourth order are ignored). Simulations are based on multicompartmental models which assumes that tissue are described

#### arokem Mar 1, 2015

Member

"tissue is described" or "tissue compartments are described"

#### RafaelNH Mar 2, 2015

Contributor

tissue is described

### arokem reviewed Mar 1, 2015

 gtab : GradientTable mevals : array (K, 3) eigenvalues of the diffusion tensor for each individual compartment S0 : float

#### arokem Mar 1, 2015

Member

Mark optional arguments as "(optional)" and tell us what the default values are.

Contributor

ok, will do

#### arokem May 25, 2015

Member

This is still needed

### arokem reviewed Mar 1, 2015

 sticks = np.array(sticks) # computing a 3D matrice containing the individual DT components mD=np.zeros((len(fractions),3,3))

#### arokem Mar 1, 2015

Member

PEP8: spaces around operators and after comma:

mD = np.zeros((len(fractions, 3, 3))


### arokem reviewed Mar 1, 2015

 mD[i] = dot(dot(R, np.diag(mevals[i])), R.T) # compute DT D=np.zeros((3,3))

Member

PEP8

### arokem reviewed Mar 1, 2015

 # compute DT D=np.zeros((3,3)) for i in range(len(fractions)): D=D+fractions[i]*mD[i]

Member

PEP8

### arokem reviewed Mar 1, 2015

 return dt, kt, S def compute_Wijkl(Dc,frac,i,j,k,el,DT=None): r""" # function that computes the elements of KT by especifying their

#### arokem Mar 1, 2015

Member

You can remove the '#' at the beginning. Also: "especifying" => "specifying"

### arokem reviewed Mar 1, 2015

 def compute_Wijkl(Dc,frac,i,j,k,el,DT=None): r""" # function that computes the elements of KT by especifying their four indexes i, j, k and el. Each index can be equal to x, y or z which are codified respectively by 0, 1 and 2. Simulations are based on

#### arokem Mar 1, 2015

Member

I am not sure I understand the sentence: "x, y, or z which are codified by 0, 1, and 2". Does this have to do with the principal orientation of the kurtosis tensor in 3D space?

#### RafaelNH Mar 2, 2015

Contributor

Unfortunately, defining a principal orientation of KT is not trivial (and what will this principal orientation mean on KT? - don't forget that KT is not an ellipsoid). KT have 15 elements: Wxxxx Wyyyy Wzzzz Wxxxy Wxxxz Wxyyy Wyyyz Wxzzz Wyzzz Wxxyy Wxxzz Wyyzz Wxxyz Wxyyz Wxyzz - what I wanted to say for codifying each element I use 0 for x, 1 for y and 2 for z.

### arokem reviewed Mar 1, 2015

 wijkl=(wijkl- DT[i][j]*DT[k][el]-DT[i][k]*DT[j][el]-DT[i][el]*DT[j][k])/(MD**2) return wijkl

#### arokem Mar 1, 2015

Member

PEP8 in this entire function: space around operators and around =. Make sure to break lines into 80 characters when you add those spaces.

### arokem reviewed Mar 1, 2015

 Returns -------- S : (N,) ndarray Simulated signal based on the DKI model S=S0*exp(-b*D+1/6*b**2*D**2*K)

#### arokem Mar 1, 2015

Member

You might want to render the equation with the latex engine, by adding $ signs around it, so: Simulated signal based on the DKI model:$S=S0e^{-b D+\frac{1}{6} b^2 D^2 K}\$


### arokem reviewed Mar 1, 2015

 Elements of the diffusion kurtosis tensor. snr : float Signal to noise ratio, assuming Rician noise. None implies no noise.

#### arokem Mar 1, 2015

Member

Again: optional arguments and their default values.

### arokem reviewed Mar 1, 2015

 A=dki_design_matrix(gtab) # define vector of DKI parameters MD=sum(dt[0:3])/3

#### arokem Mar 1, 2015

Member

Is this also MD when the last 3 elements are non-zero?

#### RafaelNH Mar 2, 2015

Contributor

Yup! This is a matrix trace propriety - trace is invariant to tensor rotations, thus MD=trace(DT)/3=(Dxx+Dyy+Dzz)/3=(e0 + e1 + e2)/3.

### arokem reviewed Mar 1, 2015

 # define vector of DKI parameters MD=sum(dt[0:3])/3 X=np.concatenate((dt,kt*MD*MD,np.array([np.log(S0)])),axis=0)

#### arokem Mar 1, 2015

Member

How is b**2 factored into this equation for the KT?

#### RafaelNH Mar 2, 2015

Contributor

b**2 is factorized on dki design matrix - see function dki_design_matrix

### arokem reviewed Mar 1, 2015

 return S def dki_design_matrix(gtab):

#### arokem Mar 1, 2015

Member

It's fine to put this here for now, but we'll eventually need to have just one implementation of this, preferably in the reconst/dki.py file (which doesn't exist yet on this branch...), so we need to remember to remove this from here, and import it from there when we start working on merging these things together.

Contributor

I agree

### arokem reviewed Mar 1, 2015

 def dki_design_matrix(gtab): r""" Constructs B design matrix for DKI

#### arokem Mar 1, 2015

Member

What's B?

#### RafaelNH Mar 2, 2015

Contributor

As for DTI, in DKI framework you can define the b-values or the B matrix. This function is computing the B matrix for DKI.

### arokem reviewed Mar 1, 2015

 ------- design_matrix : array (N,22) Design matrix or B matrix for the DKI model design_matrix[j, :] = (Bxx, Byy, Bzz, Bxy, Bxz, Byz,

#### arokem Mar 1, 2015

Member

Maybe write this in latex?

### arokem reviewed Mar 1, 2015

 BlogS0) """ b=gtab.bvals bvec=gtab.bvecs

#### arokem Mar 1, 2015

Member

PEP8: spaces around = in these two lines.

Member

### arokem commented Mar 1, 2015

 Did you mean to push the Thumbs.db file into this PR?

### arokem reviewed Mar 1, 2015

 In this example we show how someone can simulate the diffusion tensor, diffusion kurtosis tensor and signals of a single voxel by taking into account different cellular media using a multi-compartment simulatations. Simulations

#### arokem Mar 1, 2015

Member

typo =:> "using a multi-compartment simulation".

### arokem reviewed Mar 1, 2015

 In this example we show how someone can simulate the diffusion tensor, diffusion kurtosis tensor and signals of a single voxel by taking into account different cellular media using a multi-compartment simulatations. Simulations are preformed according to:

Member

=> "performed"

### arokem reviewed Mar 1, 2015

 Here we use the one we created in :ref:example_gradients_spheres. """ from gradients_spheres import gtab

#### arokem Mar 1, 2015

Member

This will run the gradients_spheres example. Is it very fast?

#### RafaelNH Mar 2, 2015

Contributor

Yes. I use this example also to keep consistency to the simulations shown in simulate.py.

### arokem reviewed Mar 1, 2015

 """ In mevals we save the eigenvalues of each tensor. To simulate crossing fibers with two different media (representing intra and extra-cellular media) 4 tissue components are taken in to account (the first two compartments

#### arokem Mar 1, 2015

Member

"in to" => "into" (no space).

### arokem reviewed Mar 1, 2015

 In mevals we save the eigenvalues of each tensor. To simulate crossing fibers with two different media (representing intra and extra-cellular media) 4 tissue components are taken in to account (the first two compartments correspond to the intra and extra cellular media for the first fiber population

#### arokem Mar 1, 2015

Member

=> "...intra- and extra-cellular medium..."

### arokem reviewed Mar 1, 2015

 """ In angles we save in polar coordinates (:math:\theta, \phi) the principal axis of each compartment tensor. To simulate crossing fibres at 70 degrees

#### arokem Mar 1, 2015

Member

Let's go with the US spelling everywhere: "fibers".

Contributor

Ok

### arokem reviewed Mar 1, 2015

 """ In angles we save in polar coordinates (:math:\theta, \phi) the principal axis of each compartment tensor. To simulate crossing fibres at 70 degrees the compartments corresponding to the first fibre are aligned to the x-axis

Member

Same here.

### arokem reviewed Mar 1, 2015

 In angles we save in polar coordinates (:math:\theta, \phi) the principal axis of each compartment tensor. To simulate crossing fibres at 70 degrees the compartments corresponding to the first fibre are aligned to the x-axis while the compartments corresponding to the second fibre are aligned to the

Member

Likewise.

### arokem reviewed Mar 1, 2015

 """ In fractions we save the percentage of the contribution of each tensor, which is computed by multipling the percentage of contribution of each fiber

Member

=> "multiplying"

### RafaelNH added some commits May 13, 2015

 STYLE: comments on functions compute_Wijkl and single_diffkurt_tensor… 
…s were improved, formulas are now latex compatible
 5b0ac2e 
 STYLE: PEP8 is now happy with dipy.sims.voxel and doc.examples.simula… 
…te_dki.py
 05dcf9d 
 DOC: improving comments and correcting misspellings in voxel.py and s… 
…imulate_dki.py
 236ce16 
 BW: remove some unnecessary defaut values on DKI simulates and remove… 
… unnecessary inputs of function compute_Wijkl (dipy/sims/voxel.py)
 9282384 
 BW: rename the inputs i,j,k, and el of function compute_Wijkl to avoi… 
…d future bugs, note that the added for inside the function has index i as well (dipy/sims/voxel.py)
 ca65d65 
 RF: adding an helpers function to check if ground truth directions ar… 
…e in the write format. Before this, code was repeated in each type of simulations, thus now the codes are much more easy to read. This helper function will be tested on test modules
 e38f893 
 STYLE: PEP8 is more happy - spaces around operators (dipy.sims.voxel.py) 
 afacd28 
 Test: testing helpers function to check if ground truth directions of… 
… simulations are in the right format (dipy.sims.test.test_voxel.py). Starting dki simulation tests
 b297fc7 
 TEST: Continuing the work on the test for DKI simulations (work still… 
… in progress)
 5de64bf 
 TESTS: Tests for DKI simulations complete. Three test are added: test… 
…_compute_Wijkl, test_DKI_simulations_aligned_fibers, test_DKI_crossing_fibers_simulations
 1aa2af9 
 DOC, BW: Minor changes on dipy.sims.voxels.py: 1) Insert new example … 
…of the use of function multi_tensor_dki (DOC); 2) insure that dt and kt are arrays in function single_diffkurt_tensors (BW)
 1d258a0 
 RF: Add two inputs in function compute_Wijkl (dipy/sims/voxel.py), no… 
…w total DT and MD can given as input, this can be usefull for applications that need to use compute_Wijkl many times (e.g. if simulations need to be repeated several times)
 23a46bd 
 DOC, STYLE: (dipy.sims.voxel.py)Rename some variables and functions t… 
…o something more meanfull. Functions compute_Wijkl and single_diffkurt_tensor are know namedkurtosis_element and DKI_signal. Variables Dc and mD are named D_comps standingfor Diffusion tensors for individual COMPartmentS. Added documentation for check_directions.
 b268ea0 
 BW, TEST: Rename dipy.sims.tests.test_voxel functions according to ch… 
…anges at dipy.sims.voxel. Adding test for testing kurtosis_elements optional inputs. Remove test_dki which is useless
 ff83a51 
 BF: I had forgotten to rename a variable which cases a bug in dipy.si… 
…ms.voxel. Now this was sorted
 832b961 
 DOC: Improve documentation. Files dipy/sims/voxel.py and dipy/doc/exa… 
…mples/simulate_dki.py
 aff3a74 
 BW, DOC: Change the gradient table used on DKI simulation example (th… 
…is update reduces computing time and clarifies DKI requirements). Added also a figure directive
 7587430 
 DOC: Figure directive corrected 
 ffd5156 
 BW: Rewrite tensors from format Dxx Dyy Dzz Dxy Dxz Dyz to thestandar… 
…d dipy's format Dxx Dxy Dyy Dxz Dyz Dzz
 4b2cdc3 
 BF: Fixed an error in computing individual DT on DKI multicompartment… 
…al simulations (dipy/sims/voxel.py). A change on all_tensor_evecs outputon the master branch caused an bug on line 385 of voxel.py. Matrices are now multiplied in the right order
 9d9885a 
 NF: Adding the signal simulated from only the dt components and compa… 
…ring this to the signals obtain from the dki simulations in DKI simulation example
 4d58048 
 BW: Output of all_tensor_evecs returns eigenvectors column-wese. dipy… 
….sims.voxel and respective tests were updated
 1e11d08 

Contributor

### RafaelNH commented Jun 8, 2015

 I just add the example comparing DKI simulations with a simulation using only DTI components. I also add a small paragraph explaining the differences. Please let me know if everything is clear. I fix the function all_tensor_evecs to return the eigenvectors in column-wise and made the necessary changes on the parts of voxel.py that were calling this function.
Contributor

### RafaelNH commented Jun 8, 2015

 PS: Having the eigenvectors column-wise is also consistent to numpy (np.linalg.eigh).

### arokem reviewed Jun 8, 2015

 In this example we show how to simulate the diffusion kurtosis imaging (DKI) data of a single voxel. DKI captures information about the non-Gaussian properties of water diffusion which is a consequence of the existence of tissue barriers and compartments. In this simulations compartmental heterogeneity is

#### arokem Jun 8, 2015

Member

typo: "this simulations" => "these simulations"

#### arokem Jun 8, 2015

Member

or "this simulation", if you want the singular

### arokem reviewed Jun 8, 2015

 gaussian water diffusion. This feature can be shown from the figure above, since signals simulated from the DKI models reveals larger DW signal intensities than the signals obtained only from the diffusion tensor components.

Member

Great!

Member

### arokem commented Jun 8, 2015

 OK - this is ready to go! I'll fix the typo in the example in a subsequent commit, once I merge this one in. Congratulations @RafaelNH on your first PR! On to DKI fitting!

### arokem added a commit that referenced this pull request Jun 8, 2015

 Merge pull request #582 from RafaelNH/DKI_PR1_test_simulations_RNH 
DKI project: PR#1 Simulations to test DKI
 d9999dd 

### arokem merged commit d9999dd into nipy:master Jun 8, 2015 1 check passed

#### 1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details