Skip to content

Commit 9a6aea1

Browse files
committed
resolve merge conflicts
1 parent 8b3d398 commit 9a6aea1

File tree

2 files changed

+79
-8
lines changed

2 files changed

+79
-8
lines changed

cmd/tensor2metric.cpp

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

107116
class 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-
274316
void 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
}

src/dwi/tensor.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,19 @@ namespace MR
103103
T (0.0);
104104
}
105105

106+
template <class Scalar> inline Scalar eigen2MO (const Scalar l1, const Scalar l2, const Scalar l3)
107+
{
108+
const Scalar md = (l1+l2+l3)/3.0;
109+
const Scalar na = std::sqrt((l1-md)*(l1-md)+(l2-md)*(l2-md)+(l3-md)*(l3-md));
110+
111+
return 3.0*std::sqrt(6.0)*((l1-md)*(l2-md)*(l3-md)/(na*na*na));
112+
}
113+
114+
template <class Scalar> inline Scalar eigen2NA (const Scalar l1, const Scalar l2, const Scalar l3)
115+
{
116+
const Scalar md = (l1+l2+l3)/3.0;
117+
return std::sqrt((l1-md)*(l1-md)+(l2-md)*(l2-md)+(l3-md)*(l3-md));
118+
}
106119

107120
template <class VectorType> inline typename VectorType::Scalar tensor2RA (const VectorType& dt)
108121
{

0 commit comments

Comments
 (0)