Bug Summary

File:src/ten/tendEstim.c
Location:line 329, column 5
Description:Value stored to 'EE' is never read

Annotated Source Code

1/*
2 Teem: Tools to process and visualize scientific data and images .
3 Copyright (C) 2013, 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#define INFO"Estimate tensors from a set of DW images" "Estimate tensors from a set of DW images"
28static const char *_tend_estimInfoL =
29 (INFO"Estimate tensors from a set of DW images"
30 ". The tensor coefficient weightings associated with "
31 "each of the DWIs, the B-matrix, is given either as a separate array, "
32 "(see \"tend bmat\" usage info for details), or by the key-value pairs "
33 "in the DWI nrrd header. A \"confidence\" value is computed with the "
34 "tensor, based on a soft thresholding of the sum of all the DWIs, "
35 "according to the threshold and softness parameters. ");
36
37int
38tend_estimMain(int argc, const char **argv, const char *me,
39 hestParm *hparm) {
40 int pret;
41 hestOpt *hopt = NULL((void*)0);
42 char *perr, *err;
43 airArray *mop;
44
45 Nrrd **nin, *nin4d, *nbmat, *nterr, *nB0, *nout;
46 char *outS, *terrS, *bmatS, *eb0S;
47 float soft, scale, sigma;
48 int dwiax, EE, knownB0, oldstuff, estmeth, verbose, fixneg;
49 unsigned int ninLen, axmap[4], wlsi, *skip, skipNum, skipIdx;
50 double valueMin, thresh;
51
52 Nrrd *ngradKVP=NULL((void*)0), *nbmatKVP=NULL((void*)0);
53 double bKVP, bval;
54
55 tenEstimateContext *tec;
56
57 hestOptAdd(&hopt, "old", NULL((void*)0), airTypeInt, 0, 0, &oldstuff, NULL((void*)0),
58 "instead of the new tenEstimateContext code, use "
59 "the old tenEstimateLinear code");
60 hestOptAdd(&hopt, "sigma", "sigma", airTypeFloat, 1, 1, &sigma, "nan",
61 "Rician noise parameter");
62 hestOptAdd(&hopt, "v", "verbose", airTypeInt, 1, 1, &verbose, "0",
63 "verbosity level");
64 hestOptAdd(&hopt, "est", "estimate method", airTypeEnum, 1, 1, &estmeth,
65 "lls",
66 "estimation method to use. \"lls\": linear-least squares",
67 NULL((void*)0), tenEstimate1Method);
68 hestOptAdd(&hopt, "wlsi", "WLS iters", airTypeUInt, 1, 1, &wlsi, "1",
69 "when using weighted-least-squares (\"-est wls\"), how "
70 "many iterations to do after the initial weighted fit.");
71 hestOptAdd(&hopt, "fixneg", NULL((void*)0), airTypeInt, 0, 0, &fixneg, NULL((void*)0),
72 "after estimating the tensor, ensure that there are no negative "
73 "eigenvalues by adding (to all eigenvalues) the amount by which "
74 "the smallest is negative (corresponding to increasing the "
75 "non-DWI image value).");
76 hestOptAdd(&hopt, "ee", "filename", airTypeString, 1, 1, &terrS, "",
77 "Giving a filename here allows you to save out the tensor "
78 "estimation error: a value which measures how much error there "
79 "is between the tensor model and the given diffusion weighted "
80 "measurements for each sample. By default, no such error "
81 "calculation is saved.");
82 hestOptAdd(&hopt, "eb", "filename", airTypeString, 1, 1, &eb0S, "",
83 "In those cases where there is no B=0 reference image given "
84 "(\"-knownB0 false\"), "
85 "giving a filename here allows you to save out the B=0 image "
86 "which is estimated from the data. By default, this image value "
87 "is estimated but not saved.");
88 hestOptAdd(&hopt, "t", "thresh", airTypeDouble, 1, 1, &thresh, "nan",
89 "value at which to threshold the mean DWI value per pixel "
90 "in order to generate the \"confidence\" mask. By default, "
91 "the threshold value is calculated automatically, based on "
92 "histogram analysis.");
93 hestOptAdd(&hopt, "soft", "soft", airTypeFloat, 1, 1, &soft, "0",
94 "how fuzzy the confidence boundary should be. By default, "
95 "confidence boundary is perfectly sharp");
96 hestOptAdd(&hopt, "scale", "scale", airTypeFloat, 1, 1, &scale, "1",
97 "After estimating the tensor, scale all of its elements "
98 "(but not the confidence value) by this amount. Can help with "
99 "downstream numerical precision if values are very large "
100 "or small.");
101 hestOptAdd(&hopt, "mv", "min val", airTypeDouble, 1, 1, &valueMin, "1.0",
102 "minimum plausible value (especially important for linear "
103 "least squares estimation)");
104 hestOptAdd(&hopt, "B", "B-list", airTypeString, 1, 1, &bmatS, NULL((void*)0),
105 "6-by-N list of B-matrices characterizing "
106 "the diffusion weighting for each "
107 "image. \"tend bmat\" is one source for such a matrix; see "
108 "its usage info for specifics on how the coefficients of "
109 "the B-matrix are ordered. "
110 "An unadorned plain text file is a great way to "
111 "specify the B-matrix.\n **OR**\n "
112 "Can say just \"-B kvp\" to try to learn B matrices from "
113 "key/value pair information in input images.");
114 hestOptAdd(&hopt, "b", "b", airTypeDouble, 1, 1, &bval, "nan",
115 "\"b\" diffusion-weighting factor (units of sec/mm^2)");
116 hestOptAdd(&hopt, "knownB0", "bool", airTypeBool, 1, 1, &knownB0, NULL((void*)0),
117 "Indicates if the B=0 non-diffusion-weighted reference image "
118 "is known, or if it has to be estimated along with the tensor "
119 "elements.\n "
120 "\b\bo if \"true\": in the given list of diffusion gradients or "
121 "B-matrices, there are one or more with zero norm, which are "
122 "simply averaged to find the B=0 reference image value\n "
123 "\b\bo if \"false\": there may or may not be diffusion-weighted "
124 "images among the input; the B=0 image value is going to be "
125 "estimated along with the diffusion model");
126 hestOptAdd(&hopt, "i", "dwi0 dwi1", airTypeOther, 1, -1, &nin, "-",
127 "all the diffusion-weighted images (DWIs), as separate 3D nrrds, "
128 "**OR**: One 4D nrrd of all DWIs stacked along axis 0",
129 &ninLen, NULL((void*)0), nrrdHestNrrd);
130 hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-",
131 "output tensor volume");
132
133 mop = airMopNew();
134 airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
135 USAGE(_tend_estimInfoL)if (!argc) { hestInfo(__stdoutp, me, (_tend_estimInfoL), hparm
); hestUsage(__stdoutp, hopt, me, hparm); hestGlossary(__stdoutp
, hopt, hparm); airMopError(mop); return 0; }
;
136 JUSTPARSE()if ((pret=hestParse(hopt, argc, argv, &perr, hparm))) { if
(1 == pret) { fprintf(__stderrp, "%s: %s\n", me, perr); free
(perr); hestUsage(__stderrp, hopt, me, hparm); airMopError(mop
); return 2; } else { exit(1); } }
;
137 airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);
138
139 nout = nrrdNew();
140 airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
141 nbmat = nrrdNew();
142 airMopAdd(mop, nbmat, (airMopper)nrrdNuke, airMopAlways);
143
144 /* figure out B-matrix */
145 if (strcmp("kvp", airToLower(bmatS))) {
146 /* its NOT coming from key/value pairs */
147 if (!AIR_EXISTS(bval)(((int)(!((bval) - (bval)))))) {
148 fprintf(stderr__stderrp, "%s: need to specify scalar b-value\n", me);
149 airMopError(mop); return 1;
150 }
151 if (nrrdLoad(nbmat, bmatS, NULL((void*)0))) {
152 airMopAdd(mop, err=biffGetDone(NRRDnrrdBiffKey), airFree, airMopAlways);
153 fprintf(stderr__stderrp, "%s: trouble loading B-matrix:\n%s\n", me, err);
154 airMopError(mop); return 1;
155 }
156 nin4d = nin[0];
157 skip = NULL((void*)0);
158 skipNum = 0;
159 } else {
160 /* it IS coming from key/value pairs */
161 if (1 != ninLen) {
162 fprintf(stderr__stderrp, "%s: require a single 4-D DWI volume for "
163 "key/value pair based calculation of B-matrix\n", me);
164 airMopError(mop); return 1;
165 }
166 if (oldstuff) {
167 if (knownB0) {
168 fprintf(stderr__stderrp, "%s: sorry, key/value-based DWI info not compatible "
169 "with older implementation of knownB0\n", me);
170 airMopError(mop); return 1;
171 }
172 }
173 if (tenDWMRIKeyValueParse(&ngradKVP, &nbmatKVP, &bKVP,
174 &skip, &skipNum, nin[0])) {
175 airMopAdd(mop, err=biffGetDone(TENtenBiffKey), airFree, airMopAlways);
176 fprintf(stderr__stderrp, "%s: trouble parsing DWI info:\n%s\n", me, err);
177 airMopError(mop); return 1;
178 }
179 if (AIR_EXISTS(bval)(((int)(!((bval) - (bval)))))) {
180 fprintf(stderr__stderrp, "%s: WARNING: key/value pair derived b-value %g "
181 "over-riding %g from command-line", me, bKVP, bval);
182 }
183 bval = bKVP;
184 if (ngradKVP) {
185 airMopAdd(mop, ngradKVP, (airMopper)nrrdNuke, airMopAlways);
186 if (tenBMatrixCalc(nbmat, ngradKVP)) {
187 airMopAdd(mop, err=biffGetDone(TENtenBiffKey), airFree, airMopAlways);
188 fprintf(stderr__stderrp, "%s: trouble finding B-matrix:\n%s\n", me, err);
189 airMopError(mop); return 1;
190 }
191 } else {
192 airMopAdd(mop, nbmatKVP, (airMopper)nrrdNuke, airMopAlways);
193 if (nrrdConvert(nbmat, nbmatKVP, nrrdTypeDouble)) {
194 airMopAdd(mop, err=biffGetDone(NRRDnrrdBiffKey), airFree, airMopAlways);
195 fprintf(stderr__stderrp, "%s: trouble converting B-matrix:\n%s\n", me, err);
196 airMopError(mop); return 1;
197 }
198 }
199 /* this will work because of the impositions of tenDWMRIKeyValueParse */
200 dwiax = ((nrrdKindList == nin[0]->axis[0].kind ||
201 nrrdKindVector == nin[0]->axis[0].kind)
202 ? 0
203 : ((nrrdKindList == nin[0]->axis[1].kind ||
204 nrrdKindVector == nin[0]->axis[1].kind)
205 ? 1
206 : ((nrrdKindList == nin[0]->axis[2].kind ||
207 nrrdKindVector == nin[0]->axis[2].kind)
208 ? 2
209 : 3)));
210 if (0 == dwiax) {
211 nin4d = nin[0];
212 } else {
213 axmap[0] = dwiax;
214 axmap[1] = 1 > dwiax ? 1 : 0;
215 axmap[2] = 2 > dwiax ? 2 : 1;
216 axmap[3] = 3 > dwiax ? 3 : 2;
217 nin4d = nrrdNew();
218 airMopAdd(mop, nin4d, (airMopper)nrrdNuke, airMopAlways);
219 if (nrrdAxesPermute(nin4d, nin[0], axmap)) {
220 airMopAdd(mop, err=biffGetDone(NRRDnrrdBiffKey), airFree, airMopAlways);
221 fprintf(stderr__stderrp, "%s: trouble creating DWI volume:\n%s\n", me, err);
222 airMopError(mop); return 1;
223 }
224 }
225 }
226
227 nterr = NULL((void*)0);
228 nB0 = NULL((void*)0);
229 if (!oldstuff) {
230 if (1 != ninLen) {
231 fprintf(stderr__stderrp, "%s: sorry, currently need single 4D volume "
232 "for new implementation\n", me);
233 airMopError(mop); return 1;
234 }
235 if (!AIR_EXISTS(thresh)(((int)(!((thresh) - (thresh)))))) {
236 unsigned char *isB0 = NULL((void*)0);
237 double bten[7], bnorm, *bmat;
238 unsigned int sl;
239 /* from nbmat, create an array that indicates B0 images */
240 if (tenBMatrixCheck(nbmat, nrrdTypeDouble, 6)) {
241 biffAddf(TENtenBiffKey, "%s: problem within given b-matrix", me);
242 airMopError(mop); return 1;
243 }
244 isB0 = AIR_CAST(unsigned char *, malloc(nbmat->axis[1].size))((unsigned char *)(malloc(nbmat->axis[1].size)));
245 airMopAdd(mop, isB0, airFree, airMopAlways);
246 bmat = (double*) nbmat->data;
247 for (sl=0; sl<nbmat->axis[1].size; sl++) {
248 TEN_T_SET(bten, 1.0,( (bten)[0] = (1.0), (bten)[1] = (bmat[0]), (bten)[2] = (bmat
[1]), (bten)[3] = (bmat[2]), (bten)[4] = (bmat[3]), (bten)[5]
= (bmat[4]), (bten)[6] = (bmat[5]) )
249 bmat[0], bmat[1], bmat[2],( (bten)[0] = (1.0), (bten)[1] = (bmat[0]), (bten)[2] = (bmat
[1]), (bten)[3] = (bmat[2]), (bten)[4] = (bmat[3]), (bten)[5]
= (bmat[4]), (bten)[6] = (bmat[5]) )
250 bmat[3], bmat[4],( (bten)[0] = (1.0), (bten)[1] = (bmat[0]), (bten)[2] = (bmat
[1]), (bten)[3] = (bmat[2]), (bten)[4] = (bmat[3]), (bten)[5]
= (bmat[4]), (bten)[6] = (bmat[5]) )
251 bmat[5])( (bten)[0] = (1.0), (bten)[1] = (bmat[0]), (bten)[2] = (bmat
[1]), (bten)[3] = (bmat[2]), (bten)[4] = (bmat[3]), (bten)[5]
= (bmat[4]), (bten)[6] = (bmat[5]) )
;
252 bnorm = TEN_T_NORM(bten)(sqrt(( (bten)[1]*(bten)[1] + 2*(bten)[2]*(bten)[2] + 2*(bten
)[3]*(bten)[3] + (bten)[4]*(bten)[4] + 2*(bten)[5]*(bten)[5] +
(bten)[6]*(bten)[6] )))
;
253 isB0[sl]=(bnorm==0.0);
254 bmat+=6;
255 }
256 if (tenEstimateThresholdFind(&thresh, isB0, nin4d)) {
257 airMopAdd(mop, err=biffGetDone(TENtenBiffKey), airFree, airMopAlways);
258 fprintf(stderr__stderrp, "%s: trouble finding threshold:\n%s\n", me, err);
259 airMopError(mop); return 1;
260 }
261 /* HACK to lower threshold a titch */
262 thresh *= 0.93;
263 fprintf(stderr__stderrp, "%s: using mean DWI threshold %g\n", me, thresh);
264 }
265 tec = tenEstimateContextNew();
266 tec->progress = AIR_TRUE1;
267 airMopAdd(mop, tec, (airMopper)tenEstimateContextNix, airMopAlways);
268 EE = 0;
269 if (!EE) tenEstimateVerboseSet(tec, verbose);
270 if (!EE) tenEstimateNegEvalShiftSet(tec, fixneg);
271 if (!EE) EE |= tenEstimateMethodSet(tec, estmeth);
272 if (!EE) EE |= tenEstimateBMatricesSet(tec, nbmat, bval, !knownB0);
273 if (!EE) EE |= tenEstimateValueMinSet(tec, valueMin);
274 for (skipIdx=0; skipIdx<skipNum; skipIdx++) {
275 /* fprintf(stderr, "%s: skipping %u\n", me, skip[skipIdx]); */
276 if (!EE) EE |= tenEstimateSkipSet(tec, skip[skipIdx], AIR_TRUE1);
277 }
278 switch(estmeth) {
279 case tenEstimate1MethodLLS:
280 if (airStrlen(terrS)) {
281 tec->recordErrorLogDwi = AIR_TRUE1;
282 /* tec->recordErrorDwi = AIR_TRUE; */
283 }
284 break;
285 case tenEstimate1MethodNLS:
286 if (airStrlen(terrS)) {
287 tec->recordErrorDwi = AIR_TRUE1;
288 }
289 break;
290 case tenEstimate1MethodWLS:
291 if (!EE) tec->WLSIterNum = wlsi;
292 if (airStrlen(terrS)) {
293 tec->recordErrorDwi = AIR_TRUE1;
294 }
295 break;
296 case tenEstimate1MethodMLE:
297 if (!(AIR_EXISTS(sigma)(((int)(!((sigma) - (sigma))))) && sigma > 0.0)) {
298 fprintf(stderr__stderrp, "%s: can't do %s w/out sigma > 0 (not %g)\n",
299 me, airEnumStr(tenEstimate1Method, tenEstimate1MethodMLE),
300 sigma);
301 airMopError(mop); return 1;
302 }
303 if (!EE) EE |= tenEstimateSigmaSet(tec, sigma);
304 if (airStrlen(terrS)) {
305 tec->recordLikelihoodDwi = AIR_TRUE1;
306 }
307 break;
308 }
309 if (!EE) EE |= tenEstimateThresholdSet(tec, thresh, soft);
310 if (!EE) EE |= tenEstimateUpdate(tec);
311 if (EE) {
312 airMopAdd(mop, err=biffGetDone(TENtenBiffKey), airFree, airMopAlways);
313 fprintf(stderr__stderrp, "%s: trouble setting up estimation:\n%s\n", me, err);
314 airMopError(mop); return 1;
315 }
316 if (tenEstimate1TensorVolume4D(tec, nout, &nB0,
317 airStrlen(terrS)
318 ? &nterr
319 : NULL((void*)0),
320 nin4d, nrrdTypeFloat)) {
321 airMopAdd(mop, err=biffGetDone(TENtenBiffKey), airFree, airMopAlways);
322 fprintf(stderr__stderrp, "%s: trouble doing estimation:\n%s\n", me, err);
323 airMopError(mop); return 1;
324 }
325 if (airStrlen(terrS)) {
326 airMopAdd(mop, nterr, (airMopper)nrrdNuke, airMopAlways);
327 }
328 } else {
329 EE = 0;
Value stored to 'EE' is never read
330 if (1 == ninLen) {
331 EE = tenEstimateLinear4D(nout, airStrlen(terrS) ? &nterr : NULL((void*)0), &nB0,
332 nin4d, nbmat, knownB0, thresh, soft, bval);
333 } else {
334 EE = tenEstimateLinear3D(nout, airStrlen(terrS) ? &nterr : NULL((void*)0), &nB0,
335 (const Nrrd*const*)nin, ninLen, nbmat,
336 knownB0, thresh, soft, bval);
337 }
338 if (EE) {
339 airMopAdd(mop, err=biffGetDone(TENtenBiffKey), airFree, airMopAlways);
340 fprintf(stderr__stderrp, "%s: trouble making tensor volume:\n%s\n", me, err);
341 airMopError(mop); return 1;
342 }
343 }
344 if (nterr) {
345 /* it was allocated by tenEstimate*, we have to clean it up */
346 airMopAdd(mop, nterr, (airMopper)nrrdNuke, airMopAlways);
347 }
348 if (nB0) {
349 /* it was allocated by tenEstimate*, we have to clean it up */
350 airMopAdd(mop, nB0, (airMopper)nrrdNuke, airMopAlways);
351 }
352 if (1 != scale) {
353 if (tenSizeScale(nout, nout, scale)) {
354 airMopAdd(mop, err=biffGetDone(TENtenBiffKey), airFree, airMopAlways);
355 fprintf(stderr__stderrp, "%s: trouble doing scaling:\n%s\n", me, err);
356 airMopError(mop); return 1;
357 }
358 }
359 if (nterr) {
360 if (nrrdSave(terrS, nterr, NULL((void*)0))) {
361 airMopAdd(mop, err=biffGetDone(NRRDnrrdBiffKey), airFree, airMopAlways);
362 fprintf(stderr__stderrp, "%s: trouble writing error image:\n%s\n", me, err);
363 airMopError(mop); return 1;
364 }
365 }
366 if (!knownB0 && airStrlen(eb0S)) {
367 if (nrrdSave(eb0S, nB0, NULL((void*)0))) {
368 airMopAdd(mop, err=biffGetDone(NRRDnrrdBiffKey), airFree, airMopAlways);
369 fprintf(stderr__stderrp, "%s: trouble writing estimated B=0 image:\n%s\n",
370 me, err);
371 airMopError(mop); return 1;
372 }
373 }
374
375 if (nrrdSave(outS, nout, NULL((void*)0))) {
376 airMopAdd(mop, err=biffGetDone(NRRDnrrdBiffKey), airFree, airMopAlways);
377 fprintf(stderr__stderrp, "%s: trouble writing:\n%s\n", me, err);
378 airMopError(mop); return 1;
379 }
380
381 airMopOkay(mop);
382 return 0;
383}
384TEND_CMD(estim, INFO)unrrduCmd tend_estimCmd = { "estim", "Estimate tensors from a set of DW images"
, tend_estimMain, 0 }
;