1 /*
2 Teem: Tools to process and visualize scientific data and images .
3 Copyright (C) 2012, 2011, 2010, 2009 University of Chicago
4 Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann
5 Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public License
9 (LGPL) as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11 The terms of redistributing and/or modifying this software also
12 include exceptions to the LGPL that facilitate static linking.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with this library; if not, write to Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #include "ten.h"
25 #include "privateTen.h"
26
27 /* NOTE: this model is a single 2nd-order tensor, not a two-tensor model */
28
29 #define PARM_NUM 7
30 /* 1/sqrt(2) */
31 #define OST 0.70710678118654752440
32 static const tenModelParmDesc
33 parmDesc[] = {
34 /* 0 */ {"B0", 0.0, TEN_MODEL_B0_MAX, AIR_FALSE, AIR_FALSE, 0},
35 /* 1 */ {"Dxx", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, AIR_FALSE, 0},
36 /* 2 */ {"Dxy", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, AIR_FALSE, 0},
37 /* 3 */ {"Dxz", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, AIR_FALSE, 0},
38 /* 4 */ {"Dyy", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, AIR_FALSE, 0},
39 /* 5 */ {"Dyz", -TEN_MODEL_DIFF_MAX*OST, TEN_MODEL_DIFF_MAX*OST, AIR_FALSE, AIR_FALSE, 0},
40 /* 6 */ {"Dzz", -TEN_MODEL_DIFF_MAX, TEN_MODEL_DIFF_MAX, AIR_FALSE, AIR_FALSE, 0}
41 };
42
43 static void
simulate(double * dwiSim,const double * parm,const tenExperSpec * espec)44 simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) {
45 unsigned int ii;
46 double b0;
47
48 b0 = parm[0];
49 for (ii=0; ii<espec->imgNum; ii++) {
50 double adc, bb;
51 bb = espec->bval[ii];
52 /* safe because TEN_T3V_CONTR never looks at parm[0] */
53 adc = TEN_T3V_CONTR(parm, espec->grad + 3*ii);
54 dwiSim[ii] = b0*exp(-bb*adc);
55 }
56 return;
57 }
58
59 static char *
parmSprint(char str[AIR_STRLEN_MED],const double * parm)60 parmSprint(char str[AIR_STRLEN_MED], const double *parm) {
61 sprintf(str, "(%g) [%g %g %g; %g %g; %g]", parm[0],
62 parm[1], parm[2], parm[3],
63 parm[4], parm[5],
64 parm[6]);
65 return str;
66 }
67
68 _TEN_PARM_ALLOC
69 _TEN_PARM_RAND
70 _TEN_PARM_STEP
71 _TEN_PARM_DIST
72 _TEN_PARM_COPY
73
74 static int
parmConvert(double * parmDst,const double * parmSrc,const tenModel * modelSrc)75 parmConvert(double *parmDst, const double *parmSrc,
76 const tenModel *modelSrc) {
77 int ret;
78
79 if (modelSrc == tenModelBall) {
80 TEN_T_SET(parmDst, parmSrc[0],
81 parmSrc[1], 0, 0,
82 parmSrc[1], 0,
83 parmSrc[1]);
84 ret = 0;
85 } else if (modelSrc == tenModel1Stick) {
86 double ten[7];
87 TEN_T3V_OUTER(ten, parmSrc + 2);
88 TEN_T_SCALE(parmDst, parmSrc[1], ten);
89 parmDst[0] = parmSrc[0];
90 ret = 0;
91 } else if (modelSrc == tenModelBall1Stick) {
92 double stick[7], ball[7], diff, frac;
93 diff = parmSrc[1];
94 frac = parmSrc[2];
95 TEN_T3V_OUTER(stick, parmSrc + 3);
96 TEN_T_SCALE(stick, diff, stick);
97 TEN_T_SET(ball, 1, diff, 0, 0, diff, 0, diff);
98 TEN_T_LERP(parmDst, frac, ball, stick);
99 parmDst[0] = parmSrc[0];
100 ret = 1;
101 } else if (modelSrc == tenModel1Cylinder) {
102 double stick[7], ball[7], len, rad;
103 len = parmSrc[1];
104 rad = parmSrc[2];
105 TEN_T3V_OUTER(stick, parmSrc + 3);
106 TEN_T_SCALE(stick, len-rad, stick);
107 TEN_T_SET(ball, 1, rad, 0, 0, rad, 0, rad);
108 TEN_T_ADD(parmDst, ball, stick);
109 parmDst[0] = parmSrc[0];
110 ret = 0;
111 } else if (modelSrc == tenModel1Tensor2) {
112 parmCopy(parmDst, parmSrc);
113 ret = 0;
114 } else {
115 unsigned int ii;
116 for (ii=0; ii<PARM_NUM; ii++) {
117 parmDst[ii] = AIR_NAN;
118 }
119 ret = 2;
120 }
121 return ret;
122 }
123
124 _TEN_SQE
125 _TEN_SQE_GRAD_CENTDIFF
126 _TEN_SQE_FIT(tenModel1Tensor2)
127
128 _TEN_NLL
129 _TEN_NLL_GRAD_STUB
130 _TEN_NLL_FIT_STUB
131
132 tenModel
133 _tenModel1Tensor2 = {
134 TEN_MODEL_STR_1TENSOR2,
135 _TEN_MODEL_FIELDS
136 };
137 const tenModel *const tenModel1Tensor2 = &_tenModel1Tensor2;
138