Gradient scaling of dirgen output

I am attempting to make my own diffusionvectors.txt file for multishell dwi on a Trio.
I am using the output of dirgen for the vector directions, but I need to scale the output for the lower b value shells. If bmax is the outer shell and the value input to the scanner card, for the lesser b values (bnew), I thought the scaling factor would be sqrt(bnew/bmax).
So if the output of dirgen is 0.4326302799 -0.8109177734 0.394009398 and I wanted a b=1000 with a bmax of 3000 I would multipy the 3 numbers by sqrt(1000/3000).
This simple formula seems to work with the diffusion vectors generator on the DSI studio web site, but not so well with dirgen. The bvalues are incorrect and varied.
I would appreciate if anyone could give me a tip on where I am going wrong.


1 Like


What you are doing sounds absolutely right. Not sure what is going wrong…

Could you provide a minimal example including the original dirgen output and your scaled version? Also check if the output vectors of dirgen have norm one. Also, how do you check the resulting b-values are wrong?


I agree with @bjeurissen : this is correct. I double checked the example vector you provided, and it also has (correctly) an L2 norm of 1.

See for more information also this quote (and the full post that it links to):

and this one just to confirm (comes from the same original thread):

I’ve never had problems creating multi-shell protocols for Siemens scanners in this fashion, always using (combinations of) direction sets from dirgen… Maybe copy paste the text of your problematic scheme here, so we could have a look what could’ve gone wrong.

I an using matlab to produce the text file.

bvals=[1000 2000 3000];
bdir=[12 24 60];

% add inital comments and text

fprintf(fileID,'# diffusion directions generated by dirgen in MRtrix package\n');
fprintf(fileID,'# Referances for dirgen are\n');
fprintf(fileID,'# Jones, D.; Horsfield, M. & Simmons, A Magnetic Resonance in Medicine, 1999, 42: 515-525\n');
fprintf(fileID,'# Papadakis, N. G.; Murrills, C. D.; Hall, L. D.; Huang, C. L.-H. & Adrian Carpenter, T. Magnetic Resonance Imaging, 2000, 18: 671-679\n');

fprintf(fileID,['[directions=' num2str(totaldir) ']\n']);
% add B0
for cd=0:numb0-1
    string=['Vector[' num2str(cd) '] = ( 0.0000000000, 0.0000000000, 0.0000000000 )'];
    fprintf(fileID, '%s\n', string);

% now for the diffusion gradients


for c=1:numbval
    com=['/opt/mrtrix3/release/bin/dirgen -cartesian -force ' num2str(numdir) ' graddir.txt'];
    disp(['b value of ' num2str(bval) ' with ' num2str(numdir) ' directions and scaling of ' num2str(scale)]);
    for cdir =1:bdir(c)
        string=['Vector[' num2str(cd) '] = ( ' num2str(ts(cdir,1),16) ', ' num2str(ts(cdir,2),16) ', ' num2str(ts(cdir,1),16) ' )'];
        fprintf(fileID, '%s\n', string);


% have a look at the text file to confirm all went well
system('gedit DiffusionVectors.txt')

Thanks for your help

Ooops, I think I found the problem
I was stepping through the output to help debug when I found the problem.
Typo , sorry guys I was putting the wrong number for the third column
I have checked it on the scanner and all bvalues are now correct (within numerical error anyway)

While I have your attention.
Theoretically we need 45 directions for CSD, but for single shell we do 60 for SNR reasons.
With multishell, can we now get just as good a result with the 45 direction at b=3000?

Thanks again, sorry about my incompetence.


No worries, we’ve all been there…

45 is the minimum for an unconstrained lmax=8 fit. I’d be more comfortable increasing that number just a little bit, maybe to 48 or 50, just to make sure the fit is not too sensitive to minor imperfections in the uniformity of your gradient directions.

Just to illustrate the point, you can use dirgen to generate uniformly-distributed directions sets from 45 to 50 directions, and use dirstats to report on the condition number of the SH fits:

$ for n in {45..50}; do dirgen -force -quiet $n dirs${n}.txt && dirstat dirs${n}.txt | grep condition; done
    condition numbers for lmax = 2 -> 8: 1.01124 1.03813 1.13936 5.28054
    condition numbers for lmax = 2 -> 8: 1.01014 1.03676 1.11522 2.46214
    condition numbers for lmax = 2 -> 8: 1.00703 1.03294 1.12717 2.08703
    condition numbers for lmax = 2 -> 8: 1.00173 1.02278 1.05102 1.35388
    condition numbers for lmax = 2 -> 8: 1.00684 1.02245 1.04241 1.29193
    condition numbers for lmax = 2 -> 8: 1.00796 1.02301 1.05343 1.32483

You can see that the condition number for that lmax=8 fit (the last number on each line) reduces markedly from ~5 to ~1.3 just by adding 3 more directions (ideal condition number is 1). I think it would be a good idea to go for at least 48 directions for that reason alone…