GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/pull/infoPull.c Lines: 0 218 0.0 %
Date: 2017-05-26 Branches: 0 119 0.0 %

Line Branch Exec Source
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 "pull.h"
25
#include "privatePull.h"
26
27
/* --------------------------------------------- */
28
29
unsigned int
30
_pullInfoLen[PULL_INFO_MAX+1] = {
31
  0, /* pullInfoUnknown */
32
  7, /* pullInfoTensor */
33
  7, /* pullInfoTensorInverse */
34
  9, /* pullInfoHessian */
35
  1, /* pullInfoInside */
36
  3, /* pullInfoInsideGradient */
37
  1, /* pullInfoHeight */
38
  3, /* pullInfoHeightGradient */
39
  9, /* pullInfoHeightHessian */
40
  1, /* pullInfoHeightLaplacian */
41
  1, /* pullInfoSeedPreThresh */
42
  1, /* pullInfoSeedThresh */
43
  1, /* pullInfoLiveThresh */
44
  1, /* pullInfoLiveThresh2 */
45
  1, /* pullInfoLiveThresh3 */
46
  3, /* pullInfoTangent1 */
47
  3, /* pullInfoTangent2 */
48
  3, /* pullInfoNegativeTangent1 */
49
  3, /* pullInfoNegativeTangent2 */
50
  1, /* pullInfoIsovalue */
51
  3, /* pullInfoIsovalueGradient */
52
  9, /* pullInfoIsovalueHessian */
53
  1, /* pullInfoStrength */
54
  1, /* pullInfoQuality */
55
};
56
57
unsigned int
58
pullInfoLen(int info) {
59
  unsigned int ret;
60
61
  if (!airEnumValCheck(pullInfo, info)) {
62
    ret = _pullInfoLen[info];
63
  } else {
64
    ret = 0;
65
  }
66
  return ret;
67
}
68
69
unsigned int
70
pullPropLen(int prop) {
71
  unsigned int ret;
72
73
  switch (prop) {
74
  case pullPropIdtag:
75
  case pullPropIdCC:
76
  case pullPropEnergy:
77
  case pullPropStepEnergy:
78
  case pullPropStepConstr:
79
  case pullPropStuck:
80
  case pullPropNeighDistMean:
81
  case pullPropScale:
82
  case pullPropStability:
83
    ret = 1;
84
    break;
85
  case pullPropPosition:
86
  case pullPropForce:
87
    ret = 4;
88
    break;
89
  case pullPropNeighCovar:
90
    ret = 10;
91
    break;
92
  case pullPropNeighCovar7Ten:
93
    ret = 7;
94
    break;
95
  case pullPropNeighTanCovar:
96
    ret = 6;
97
    break;
98
  default:
99
    ret = 0;
100
    break;
101
  }
102
  return ret;
103
}
104
105
pullInfoSpec *
106
pullInfoSpecNew(void) {
107
  pullInfoSpec *ispec;
108
109
  ispec = AIR_CAST(pullInfoSpec *, calloc(1, sizeof(pullInfoSpec)));
110
  if (ispec) {
111
    ispec->info = pullInfoUnknown;
112
    ispec->source = pullSourceUnknown;
113
    ispec->volName = NULL;
114
    ispec->item = 0;  /* should be the unknown item for any kind */
115
    ispec->prop = pullPropUnknown;
116
    ispec->scale = AIR_NAN;
117
    ispec->zero = AIR_NAN;
118
    ispec->constraint = AIR_FALSE;
119
    ispec->volIdx = UINT_MAX;
120
  }
121
  return ispec;
122
}
123
124
pullInfoSpec *
125
pullInfoSpecNix(pullInfoSpec *ispec) {
126
127
  if (ispec) {
128
    airFree(ispec->volName);
129
    airFree(ispec);
130
  }
131
  return NULL;
132
}
133
134
int
135
pullInfoSpecAdd(pullContext *pctx, pullInfoSpec *ispec) {
136
  static const char me[]="pullInfoSpecAdd";
137
  unsigned int ii, vi, haveLen, needLen;
138
  const gageKind *kind;
139
140
  if (!( pctx && ispec )) {
141
    biffAddf(PULL, "%s: got NULL pointer", me);
142
    return 1;
143
  }
144
  if (airEnumValCheck(pullInfo, ispec->info)) {
145
    biffAddf(PULL, "%s: %d not a valid %s value", me,
146
             ispec->info, pullInfo->name);
147
    return 1;
148
  }
149
  if (airEnumValCheck(pullSource, ispec->source)) {
150
    biffAddf(PULL, "%s: %d not a valid %s value", me,
151
             ispec->source, pullSource->name);
152
    return 1;
153
  }
154
  if (pctx->ispec[ispec->info]) {
155
    biffAddf(PULL, "%s: already set info %s (%d)", me,
156
             airEnumStr(pullInfo, ispec->info), ispec->info);
157
    return 1;
158
  }
159
  for (ii=0; ii<=PULL_INFO_MAX; ii++) {
160
    if (pctx->ispec[ii] == ispec) {
161
      biffAddf(PULL, "%s(%s): already got ispec %p as ispec[%u]", me,
162
               airEnumStr(pullInfo, ispec->info), AIR_VOIDP(ispec), ii);
163
      return 1;
164
    }
165
  }
166
  if (pctx->verbose) {
167
    printf("%s: ispec %s from vol %s\n", me,
168
           airEnumStr(pullInfo, ispec->info), ispec->volName);
169
  }
170
  needLen = pullInfoLen(ispec->info);
171
  if (pullSourceGage == ispec->source) {
172
    vi = _pullVolumeIndex(pctx, ispec->volName);
173
    if (UINT_MAX == vi) {
174
      biffAddf(PULL, "%s(%s): no volume has name \"%s\"", me,
175
               airEnumStr(pullInfo, ispec->info), ispec->volName);
176
      return 1;
177
    }
178
    kind = pctx->vol[vi]->kind;
179
    if (airEnumValCheck(kind->enm, ispec->item)) {
180
      biffAddf(PULL, "%s(%s): %d not a valid \"%s\" item", me,
181
               airEnumStr(pullInfo, ispec->info), ispec->item, kind->name);
182
      return 1;
183
    }
184
    haveLen = kind->table[ispec->item].answerLength;
185
    if (needLen != haveLen) {
186
      biffAddf(PULL, "%s(%s): need len %u, but \"%s\" item \"%s\" has len %u",
187
               me, airEnumStr(pullInfo, ispec->info), needLen,
188
               kind->name, airEnumStr(kind->enm, ispec->item), haveLen);
189
      return 1;
190
    }
191
    /* very tricky: seedOnly is initialized to true for everything */
192
    if (pullInfoSeedThresh != ispec->info
193
        && pullInfoSeedPreThresh != ispec->info) {
194
      /* if the info is neither seedthresh nor seedprethresh, then the
195
         volume will have to be probed after the first iter, so turn
196
         *off* seedOnly */
197
      pctx->vol[vi]->seedOnly = AIR_FALSE;
198
    }
199
    /* less tricky: turn on forSeedPreThresh as needed;
200
       its initialized to false */
201
    if (pullInfoSeedPreThresh == ispec->info) {
202
      pctx->vol[vi]->forSeedPreThresh = AIR_TRUE;
203
      if (pctx->verbose) {
204
        printf("%s: volume %u %s used for %s\n", me, vi, pctx->vol[vi]->name,
205
               airEnumStr(pullInfo, pullInfoSeedPreThresh));
206
      }
207
    }
208
    /* now set item in gage query */
209
    if (gageQueryItemOn(pctx->vol[vi]->gctx, pctx->vol[vi]->gpvl,
210
                        ispec->item)) {
211
      biffMovef(PULL, GAGE, "%s: trouble adding item %u to vol %u", me,
212
                ispec->item, vi);
213
      return 1;
214
    }
215
    ispec->volIdx = vi;
216
  } else if (pullSourceProp == ispec->source) {
217
    haveLen = pullPropLen(ispec->prop);
218
    if (needLen != haveLen) {
219
      biffAddf(PULL, "%s: need len %u, but \"%s\" \"%s\" has len %u",
220
               me, needLen, pullProp->name,
221
               airEnumStr(pullProp, ispec->prop), haveLen);
222
      return 1;
223
    }
224
225
  } else {
226
    biffAddf(PULL, "%s: sorry, source %s unsupported", me,
227
             airEnumStr(pullSource, ispec->source));
228
    return 1;
229
  }
230
  if (haveLen > 9) {
231
    biffAddf(PULL, "%s: sorry, answer length (%u) > 9 unsupported", me,
232
             haveLen);
233
    return 1;
234
  }
235
236
  pctx->ispec[ispec->info] = ispec;
237
238
  return 0;
239
}
240
241
/*
242
** sets:
243
** pctx->infoIdx[]
244
** pctx->infoTotalLen
245
** pctx->constraint
246
** pctx->constraintDim
247
** pctx->targetDim (non-trivial logic for scale-space!)
248
*/
249
int
250
_pullInfoSetup(pullContext *pctx) {
251
  static const char me[]="_pullInfoSetup";
252
  unsigned int ii;
253
254
  pctx->infoTotalLen = 0;
255
  pctx->constraint = 0;
256
  pctx->constraintDim = 0;
257
  for (ii=0; ii<=PULL_INFO_MAX; ii++) {
258
    if (pctx->ispec[ii]) {
259
      pctx->infoIdx[ii] = pctx->infoTotalLen;
260
      if (pctx->verbose) {
261
        printf("!%s: infoIdx[%u] (%s) = %u\n", me,
262
               ii, airEnumStr(pullInfo, ii), pctx->infoIdx[ii]);
263
      }
264
      pctx->infoTotalLen += pullInfoLen(ii);
265
      if (!pullInfoLen(ii)) {
266
        biffAddf(PULL, "%s: got zero-length answer for ispec[%u]", me, ii);
267
        return 1;
268
      }
269
      if (pctx->ispec[ii]->constraint) {
270
        /* pullVolume *cvol; */
271
        pctx->constraint = ii;
272
        /* cvol = pctx->vol[pctx->ispec[ii]->volIdx]; */
273
      }
274
    }
275
  }
276
  if (pctx->constraint) {
277
    pctx->constraintDim = _pullConstraintDim(pctx);
278
    if (-1 == pctx->constraintDim) {
279
      biffAddf(PULL, "%s: problem learning constraint dimension", me);
280
      return 1;
281
    }
282
    if (!pctx->flag.allowCodimension3Constraints && !pctx->constraintDim) {
283
      biffAddf(PULL, "%s: got constr dim 0 but co-dim 3 not allowed", me);
284
      return 1;
285
    }
286
    if (pctx->haveScale) {
287
      double *parmS, denS,
288
        (*evalS)(double *, double, const double parm[PULL_ENERGY_PARM_NUM]);
289
      switch (pctx->interType) {
290
      case pullInterTypeUnivariate:
291
        pctx->targetDim = 1 + pctx->constraintDim;
292
        break;
293
      case pullInterTypeSeparable:
294
        /* HEY! need to check if this is true given enr and ens! */
295
        pctx->targetDim = pctx->constraintDim;
296
        break;
297
      case pullInterTypeAdditive:
298
        parmS = pctx->energySpecS->parm;
299
        evalS = pctx->energySpecS->energy->eval;
300
        evalS(&denS, _PULL_TARGET_DIM_S_PROBE, parmS);
301
        if (denS > 0) {
302
          /* at small positive s, derivative was positive ==> attractive */
303
          pctx->targetDim = pctx->constraintDim;
304
        } else {
305
          /* derivative was negative ==> repulsive */
306
          pctx->targetDim = 1 + pctx->constraintDim;
307
        }
308
        break;
309
      default:
310
        biffAddf(PULL, "%s: sorry, intertype %s not handled here", me,
311
                 airEnumStr(pullInterType, pctx->interType));
312
        break;
313
      }
314
    } else {
315
      pctx->targetDim = pctx->constraintDim;
316
    }
317
  } else {
318
    pctx->constraintDim = 0;
319
    pctx->targetDim = 0;
320
  }
321
  if (pctx->verbose) {
322
    printf("!%s: infoTotalLen=%u, constr=%d, constr,targetDim = %d,%d\n",
323
           me, pctx->infoTotalLen, pctx->constraint,
324
           pctx->constraintDim, pctx->targetDim);
325
  }
326
  return 0;
327
}
328
329
static void
330
_infoCopy1(double *dst, const double *src) {
331
  dst[0] = src[0];
332
}
333
334
static void
335
_infoCopy2(double *dst, const double *src) {
336
  dst[0] = src[0]; dst[1] = src[1];
337
}
338
339
static void
340
_infoCopy3(double *dst, const double *src) {
341
  dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2];
342
}
343
344
static void
345
_infoCopy4(double *dst, const double *src) {
346
  dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; dst[3] = src[3];
347
}
348
349
static void
350
_infoCopy5(double *dst, const double *src) {
351
  dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; dst[3] = src[3];
352
  dst[4] = src[4];
353
}
354
355
static void
356
_infoCopy6(double *dst, const double *src) {
357
  dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; dst[3] = src[3];
358
  dst[4] = src[4]; dst[5] = src[5];
359
}
360
361
static void
362
_infoCopy7(double *dst, const double *src) {
363
  dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; dst[3] = src[3];
364
  dst[4] = src[4]; dst[5] = src[5]; dst[6] = src[6];
365
}
366
367
static void
368
_infoCopy8(double *dst, const double *src) {
369
  dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; dst[3] = src[3];
370
  dst[4] = src[4]; dst[5] = src[5]; dst[6] = src[6]; dst[7] = src[7];
371
}
372
373
static void
374
_infoCopy9(double *dst, const double *src) {
375
  dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; dst[3] = src[3];
376
  dst[4] = src[4]; dst[5] = src[5]; dst[6] = src[6]; dst[7] = src[7];
377
  dst[8] = src[8];
378
}
379
380
void (*_pullInfoCopy[10])(double *, const double *) = {
381
  NULL,
382
  _infoCopy1,
383
  _infoCopy2,
384
  _infoCopy3,
385
  _infoCopy4,
386
  _infoCopy5,
387
  _infoCopy6,
388
  _infoCopy7,
389
  _infoCopy8,
390
  _infoCopy9
391
};
392
393
int
394
pullInfoGet(Nrrd *ninfo, int info, pullContext *pctx) {
395
  static const char me[]="pullInfoGet";
396
  size_t size[2];
397
  unsigned int dim, pointNum, pointIdx, binIdx, outIdx, alen, aidx;
398
  double *out_d;
399
  pullBin *bin;
400
  pullPoint *point;
401
402
  if (airEnumValCheck(pullInfo, info)) {
403
    biffAddf(PULL, "%s: info %d not valid", me, info);
404
    return 1;
405
  }
406
  pointNum = pullPointNumber(pctx);
407
  alen = pullInfoLen(info);
408
  aidx = pctx->infoIdx[info];
409
  if (1 == alen) {
410
    dim = 1;
411
    size[0] = pointNum;
412
  } else {
413
    dim = 2;
414
    size[0] = alen;
415
    size[1] = pointNum;
416
  }
417
  if (nrrdMaybeAlloc_nva(ninfo, nrrdTypeDouble, dim, size)) {
418
    biffMovef(PULL, NRRD, "%s: trouble allocating output", me);
419
    return 1;
420
  }
421
  out_d = AIR_CAST(double *, ninfo->data);
422
423
  outIdx = 0;
424
  for (binIdx=0; binIdx<pctx->binNum; binIdx++) {
425
    bin = pctx->bin + binIdx;
426
    for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) {
427
      point = bin->point[pointIdx];
428
      _pullInfoCopy[alen](out_d + outIdx, point->info + aidx);
429
      outIdx += alen;
430
    }
431
  }
432
433
  return 0;
434
}
435
436
/* HEY this was written in a hurry;
437
** needs to be checked against parsing code */
438
int
439
pullInfoSpecSprint(char str[AIR_STRLEN_LARGE],
440
                   const pullContext *pctx, const pullInfoSpec *ispec) {
441
  static const char me[]="pullInfoSpecSprint";
442
  const pullVolume *pvol;
443
  char stmp[AIR_STRLEN_LARGE];
444
445
  if (!( str && pctx && ispec )) {
446
    biffAddf(PULL, "%s: got NULL pointer", me);
447
    return 1;
448
  }
449
  strcpy(str, "");
450
  /* HEY: no bounds checking! */
451
  strcat(str, airEnumStr(pullInfo, ispec->info));
452
  if (ispec->constraint) {
453
    strcat(str, "-c");
454
  }
455
  strcat(str, ":");
456
  if (pullSourceGage == ispec->source) {
457
    if (UINT_MAX == ispec->volIdx) {
458
      biffAddf(PULL, "%s: never learned volIdx for \"%s\"", me,
459
               ispec->volName);
460
      return 1;
461
    }
462
    strcat(str, ispec->volName);
463
    strcat(str, ":");
464
    pvol = pctx->vol[ispec->volIdx];
465
    strcat(str, airEnumStr(pvol->kind->enm, ispec->item));
466
  } else if (pullSourceProp == ispec->source) {
467
    strcat(str, airEnumStr(pullProp, ispec->prop));
468
  } else {
469
    biffAddf(PULL, "%s: unexplained source %d", me, ispec->source);
470
    return 1;
471
  }
472
  if ( (pullSourceGage == ispec->source
473
        && 1 == pullInfoLen(ispec->info))
474
       ||
475
       (pullSourceProp == ispec->source
476
        && 1 == pullPropLen(ispec->prop)) ) {
477
    sprintf(stmp, "%g", ispec->zero);
478
    strcat(str, stmp);
479
    strcat(str, ":");
480
    sprintf(stmp, "%g", ispec->scale);
481
    strcat(str, stmp);
482
  }
483
  return 0;
484
}
485