@@ -42,7 +42,12 @@ void usage ()
4242 + Option (" fa" ,
4343 " compute the fractional anisotropy (FA) of the diffusion tensor." )
4444 + Argument (" image" ).type_image_out ()
45-
45+ + Option (" na" ,
46+ " compute the norm of anistropy (NA) of the diffusion tensor." )
47+ + Argument (" image" ).type_image_out ()
48+ + Option (" mo" ,
49+ " compute the mode of anisotropy (MO) of the diffusion tensor." )
50+ + Argument (" image" ).type_image_out ()
4651 + Option (" ad" ,
4752 " compute the axial diffusivity (AD) of the diffusion tensor. "
4853 " (equivalent to the principal eigenvalue)" )
@@ -102,13 +107,19 @@ void usage ()
102107 + " Westin, C. F.; Peled, S.; Gudbjartsson, H.; Kikinis, R. & Jolesz, F. A. "
103108 " Geometrical diffusion measures for MRI from tensor basis analysis. "
104109 " Proc Intl Soc Mag Reson Med, 1997, 5, 1742" ;
110+ +
111+ " Ennis, D. B., & Kindlmann, G. (2006). Orthogonal tensor invariants and"
112+ " the analysis of diffusion tensor magnetic resonance images."
113+ " Magnetic resonance in medicine, 55(1), 136–146." ;
105114}
106115
107116class Processor { MEMALIGN(Processor)
108117 public:
109118 Processor (Image<bool >& mask_img,
110119 Image<value_type>& adc_img,
111120 Image<value_type>& fa_img,
121+ Image<value_type>& mo_img,
122+ Image<value_type>& na_img,
112123 Image<value_type>& ad_img,
113124 Image<value_type>& rd_img,
114125 Image<value_type>& cl_img,
@@ -121,6 +132,8 @@ class Processor { MEMALIGN(Processor)
121132 mask_img (mask_img),
122133 adc_img (adc_img),
123134 fa_img (fa_img),
135+ mo_img (mo_img),
136+ na_img (na_img),
124137 ad_img (ad_img),
125138 rd_img (rd_img),
126139 cl_img (cl_img),
@@ -164,7 +177,7 @@ class Processor { MEMALIGN(Processor)
164177 fa_img.value () = fa;
165178 }
166179
167- bool need_eigenvalues = value_img.valid () || vector_img.valid () || ad_img.valid () || rd_img.valid () || cl_img.valid () || cp_img.valid () || cs_img.valid ();
180+ bool need_eigenvalues = value_img.valid () || vector_img.valid () || ad_img.valid () || na_img. valid () || mo_img. valid () || rd_img.valid () || cl_img.valid () || cp_img.valid () || cs_img.valid ();
168181
169182 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> es;
170183 if (need_eigenvalues || vector_img.valid ()) {
@@ -178,6 +191,7 @@ class Processor { MEMALIGN(Processor)
178191 es = Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d>(M, vector_img.valid () ? Eigen::ComputeEigenvectors : Eigen::EigenvaluesOnly);
179192 }
180193
194+
181195 Eigen::Vector3d eigval;
182196 ssize_t ith_eig[3 ] = { 2 , 1 , 0 };
183197 if (need_eigenvalues) {
@@ -187,6 +201,37 @@ class Processor { MEMALIGN(Processor)
187201 [&eigval](size_t a, size_t b) { return abs (eigval[a]) > abs (eigval[b]); });
188202 }
189203
204+ // new section added here
205+ double mo = 0.0 ;
206+ if (mo_img.valid () || (vector_img.valid () )) {
207+ const double l1 = eigval (0 );
208+ const double l2 = eigval (1 );
209+ const double l3 = eigval (2 );
210+
211+
212+ mo = DWI::eigen2MO (l1,l2,l3);
213+ // std::cout << "mo: " << mo << std::endl;
214+ }
215+ /* output mo */
216+ if (mo_img.valid ()) {
217+ assign_pos_of (dt_img, 0 , 3 ).to (mo_img);
218+ mo_img.value () = mo;
219+ }
220+
221+ double na = 0.0 ;
222+ if (na_img.valid () || (vector_img.valid () )) {
223+ const double l1 = eigval (0 );
224+ const double l2 = eigval (1 );
225+ const double l3 = eigval (2 );
226+
227+ na = DWI::eigen2NA (l1,l2,l3);
228+ }
229+ /* output na */
230+ if (na_img.valid ()) {
231+ assign_pos_of (dt_img, 0 , 3 ).to (na_img);
232+ na_img.value () = na;
233+ }
234+
190235 /* output value */
191236 if (value_img.valid ()) {
192237 assign_pos_of (dt_img, 0 , 3 ).to (value_img);
@@ -253,6 +298,8 @@ class Processor { MEMALIGN(Processor)
253298 Image<bool > mask_img;
254299 Image<value_type> adc_img;
255300 Image<value_type> fa_img;
301+ Image<value_type> mo_img;
302+ Image<value_type> na_img;
256303 Image<value_type> ad_img;
257304 Image<value_type> rd_img;
258305 Image<value_type> cl_img;
@@ -266,11 +313,6 @@ class Processor { MEMALIGN(Processor)
266313
267314
268315
269-
270-
271-
272-
273-
274316void run ()
275317{
276318 auto dt_img = Image<value_type>::open (argument[0 ]);
@@ -304,6 +346,22 @@ void run ()
304346 metric_count++;
305347 }
306348
349+ auto mo_img = Image<value_type>();
350+ opt = get_options (" mo" );
351+ if (opt.size ()) {
352+ header.ndim () = 3 ;
353+ mo_img = Image<value_type>::create (opt[0 ][0 ], header);
354+ metric_count++;
355+ }
356+
357+ auto na_img = Image<value_type>();
358+ opt = get_options (" na" );
359+ if (opt.size ()) {
360+ header.ndim () = 3 ;
361+ na_img = Image<value_type>::create (opt[0 ][0 ], header);
362+ metric_count++;
363+ }
364+
307365 auto ad_img = Image<value_type>();
308366 opt = get_options (" ad" );
309367 if (opt.size ()) {
@@ -382,5 +440,5 @@ void run ()
382440 throw Exception (" No output specified; must request at least one metric of interest using the available command-line options" );
383441
384442 ThreadedLoop (std::string (" computing metric" ) + (metric_count > 1 ? " s" : " " ), dt_img, 0 , 3 )
385- .run (Processor (mask_img, adc_img, fa_img, ad_img, rd_img, cl_img, cp_img, cs_img, value_img, vector_img, vals, modulate), dt_img);
443+ .run (Processor (mask_img, adc_img, fa_img, mo_img, na_img, ad_img, rd_img, cl_img, cp_img, cs_img, value_img, vector_img, vals, modulate), dt_img);
386444}
0 commit comments