GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/pull/parmPull.c Lines: 0 256 0.0 %
Date: 2017-05-26 Branches: 0 199 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
25
#include "pull.h"
26
#include "privatePull.h"
27
28
/* the Init() functions are up here for easier reference */
29
30
void
31
_pullIterParmInit(pullIterParm *iterParm) {
32
33
  iterParm->min = 0;
34
  iterParm->max = 0;
35
  iterParm->stuckMax = 4;
36
  iterParm->constraintMax = 15;
37
  iterParm->popCntlPeriod = 10;
38
  iterParm->addDescent = 10;
39
  iterParm->callback = 1;
40
  iterParm->snap = 0;
41
  iterParm->energyIncreasePermitHalfLife = 0;
42
  return;
43
}
44
45
void
46
_pullSysParmInit(pullSysParm *sysParm) {
47
48
  sysParm->alpha = 0.5;
49
  sysParm->beta = 0.5;
50
  sysParm->gamma = 1;
51
  sysParm->separableGammaLearnRescale = 8;
52
  sysParm->wall = 1;
53
  sysParm->radiusSpace = 1;
54
  sysParm->radiusScale = 1;
55
  sysParm->binWidthSpace = 1.001; /* supersititious */
56
  sysParm->neighborTrueProb = 1.0;
57
  sysParm->probeProb = 1.0;
58
  sysParm->stepInitial = 1;
59
  sysParm->opporStepScale = 1.0;
60
  sysParm->backStepScale = 0.5;
61
  sysParm->constraintStepMin = 0.0001;
62
  sysParm->energyDecreaseMin = 0.001;
63
  sysParm->energyDecreasePopCntlMin = 0.02;
64
  sysParm->energyIncreasePermit = 0.0;
65
  sysParm->fracNeighNixedMax = 0.25;
66
  return;
67
}
68
69
void
70
_pullFlagInit(pullFlag *flag) {
71
72
  flag->permuteOnRebin = AIR_FALSE;
73
  flag->noPopCntlWithZeroAlpha = AIR_FALSE;
74
  flag->useBetaForGammaLearn = AIR_FALSE;
75
  flag->restrictiveAddToBins = AIR_TRUE;
76
  flag->energyFromStrength = AIR_FALSE;
77
  flag->nixAtVolumeEdgeSpace = AIR_FALSE;
78
  flag->nixAtVolumeEdgeSpaceInitRorH = AIR_FALSE;
79
  flag->constraintBeforeSeedThresh = AIR_FALSE;
80
  flag->noAdd = AIR_FALSE;
81
  flag->popCntlEnoughTest = AIR_TRUE; /* really needs to be true by default */
82
  flag->convergenceIgnoresPopCntl = AIR_FALSE; /* false by default for
83
                                                  backwards compatibility,
84
                                                  even thought this was
85
                                                  probably a mistake */
86
  flag->binSingle = AIR_FALSE;
87
  flag->allowCodimension3Constraints = AIR_FALSE;
88
  flag->scaleIsTau = AIR_FALSE;
89
  flag->startSkipsPoints = AIR_FALSE; /* must be false by default */
90
  flag->zeroZ = AIR_FALSE;
91
  return;
92
}
93
94
int
95
_pullIterParmCheck(pullIterParm *iterParm) {
96
  static const char me[]="_pullIterParmCheck";
97
98
  if (!( 1 <= iterParm->constraintMax
99
         && iterParm->constraintMax <= 500 )) {
100
    biffAddf(PULL, "%s: iterParm->constraintMax %u not in range [%u,%u]",
101
             me, iterParm->constraintMax, 1, _PULL_CONSTRAINT_ITER_MAX);
102
    return 1;
103
  }
104
  return 0;
105
}
106
107
int
108
pullIterParmSet(pullContext *pctx, int which, unsigned int pval) {
109
  static const char me[]="pullIterParmSet";
110
111
  if (!pctx) {
112
    biffAddf(PULL, "%s: got NULL pointer", me);
113
    return 1;
114
  }
115
  if (!AIR_IN_OP(pullIterParmUnknown, which, pullIterParmLast)) {
116
    biffAddf(PULL, "%s: iter parm %d not valid", me, which);
117
    return 1;
118
  }
119
  switch(which) {
120
  case pullIterParmMin:
121
    pctx->iterParm.min = pval;
122
    break;
123
  case pullIterParmMax:
124
    pctx->iterParm.max = pval;
125
    break;
126
  case pullIterParmStuckMax:
127
    pctx->iterParm.stuckMax = pval;
128
    break;
129
  case pullIterParmConstraintMax:
130
    pctx->iterParm.constraintMax = pval;
131
    break;
132
  case pullIterParmPopCntlPeriod:
133
    pctx->iterParm.popCntlPeriod = pval;
134
    break;
135
  case pullIterParmAddDescent:
136
    pctx->iterParm.addDescent = pval;
137
    break;
138
  case pullIterParmCallback:
139
    pctx->iterParm.callback = pval;
140
    break;
141
  case pullIterParmSnap:
142
    pctx->iterParm.snap = pval;
143
    break;
144
  case pullIterParmEnergyIncreasePermitHalfLife:
145
    pctx->iterParm.energyIncreasePermitHalfLife = pval;
146
    if (pval) {
147
      pctx->eipScale = pow(0.5, 1.0/pval);
148
    } else {
149
      pctx->eipScale = 1;
150
    }
151
    break;
152
  default:
153
    biffAddf(me, "%s: sorry, iter parm %d valid but not handled?", me, which);
154
    return 1;
155
  }
156
  return 0;
157
}
158
159
#define CHECK(thing, min, max)                                         \
160
  if (!( AIR_EXISTS(sysParm->thing)                                    \
161
         && min <= sysParm->thing && sysParm->thing <= max )) {        \
162
    biffAddf(PULL, "%s: sysParm->" #thing " %g not in range [%g,%g]",  \
163
             me, sysParm->thing, min, max);                            \
164
    return 1;                                                          \
165
  }
166
167
int
168
_pullSysParmCheck(pullSysParm *sysParm) {
169
  static const char me[]="_pullSysParmCheck";
170
171
  /* these reality-check bounds are somewhat arbitrary */
172
  CHECK(alpha, 0.0, 1.0);
173
  CHECK(beta, 0.0, 1.0);
174
  /* HEY: no check on gamma? */
175
  CHECK(wall, 0.0, 100.0);
176
  CHECK(radiusSpace, 0.000001, 80.0);
177
  CHECK(radiusScale, 0.000001, 80.0);
178
  CHECK(binWidthSpace, 1.0, 15.0);
179
  CHECK(neighborTrueProb, 0.02, 1.0);
180
  CHECK(probeProb, 0.02, 1.0);
181
  if (!( AIR_EXISTS(sysParm->stepInitial)
182
         && sysParm->stepInitial > 0 )) {
183
    biffAddf(PULL, "%s: sysParm->stepInitial %g not > 0", me,
184
             sysParm->stepInitial);
185
    return 1;
186
  }
187
  CHECK(opporStepScale, 1.0, 5.0);
188
  CHECK(backStepScale, 0.01, 0.99);
189
  CHECK(constraintStepMin, 0.00000000000000001, 0.1);
190
  CHECK(energyDecreaseMin, -0.2, 1.0);
191
  CHECK(energyDecreasePopCntlMin, -1.0, 1.0);
192
  CHECK(energyIncreasePermit, 0.0, 1.0);
193
  CHECK(fracNeighNixedMax, 0.01, 0.99);
194
  return 0;
195
}
196
#undef CHECK
197
198
int
199
pullSysParmSet(pullContext *pctx, int which, double pval) {
200
  static const char me[]="pullSysParmSet";
201
202
  if (!pctx) {
203
    biffAddf(PULL, "%s: got NULL pointer", me);
204
    return 1;
205
  }
206
  if (!AIR_IN_OP(pullSysParmUnknown, which, pullSysParmLast)) {
207
    biffAddf(PULL, "%s: sys parm %d not valid", me, which);
208
    return 1;
209
  }
210
  switch(which) {
211
  case pullSysParmAlpha:
212
    pctx->sysParm.alpha = pval;
213
    break;
214
  case pullSysParmBeta:
215
    pctx->sysParm.beta = pval;
216
    break;
217
  case pullSysParmGamma:
218
    pctx->sysParm.gamma = pval;
219
    break;
220
  case pullSysParmSeparableGammaLearnRescale:
221
    pctx->sysParm.separableGammaLearnRescale = pval;
222
    break;
223
  case pullSysParmStepInitial:
224
    pctx->sysParm.stepInitial = pval;
225
    break;
226
  case pullSysParmRadiusSpace:
227
    pctx->sysParm.radiusSpace = pval;
228
    break;
229
  case pullSysParmRadiusScale:
230
    pctx->sysParm.radiusScale = pval;
231
    break;
232
  case pullSysParmBinWidthSpace:
233
    pctx->sysParm.binWidthSpace = pval;
234
    break;
235
  case pullSysParmNeighborTrueProb:
236
    pctx->sysParm.neighborTrueProb = pval;
237
    break;
238
  case pullSysParmProbeProb:
239
    pctx->sysParm.probeProb = pval;
240
    break;
241
  case pullSysParmOpporStepScale:
242
    pctx->sysParm.opporStepScale = pval;
243
    break;
244
  case pullSysParmBackStepScale:
245
    pctx->sysParm.backStepScale = pval;
246
    break;
247
  case pullSysParmEnergyDecreasePopCntlMin:
248
    pctx->sysParm.energyDecreasePopCntlMin = pval;
249
    break;
250
  case pullSysParmEnergyDecreaseMin:
251
    pctx->sysParm.energyDecreaseMin = pval;
252
    break;
253
  case pullSysParmConstraintStepMin:
254
    pctx->sysParm.constraintStepMin = pval;
255
    break;
256
  case pullSysParmEnergyIncreasePermit:
257
    pctx->sysParm.energyIncreasePermit = pval;
258
    break;
259
  case pullSysParmFracNeighNixedMax:
260
    pctx->sysParm.fracNeighNixedMax = pval;
261
    break;
262
  case pullSysParmWall:
263
    pctx->sysParm.wall = pval;
264
    break;
265
  default:
266
    biffAddf(me, "%s: sorry, sys parm %d valid but not handled?", me, which);
267
    return 1;
268
  }
269
  return 0;
270
}
271
272
/*
273
******** pullFlagSet
274
**
275
** uniform way of setting all the boolean-ish flags
276
*/
277
int
278
pullFlagSet(pullContext *pctx, int which, int flag) {
279
  static const char me[]="pullFlagSet";
280
281
  if (!pctx) {
282
    biffAddf(PULL, "%s: got NULL pointer", me);
283
    return 1;
284
  }
285
  if (!AIR_IN_OP(pullFlagUnknown, which, pullFlagLast)) {
286
    biffAddf(PULL, "%s: flag %d not valid", me, which);
287
    return 1;
288
  }
289
  switch (which) {
290
  case pullFlagPermuteOnRebin:
291
    pctx->flag.permuteOnRebin = flag;
292
    break;
293
  case pullFlagNoPopCntlWithZeroAlpha:
294
    pctx->flag.noPopCntlWithZeroAlpha = flag;
295
    break;
296
  case pullFlagUseBetaForGammaLearn:
297
    pctx->flag.useBetaForGammaLearn = flag;
298
    break;
299
  case pullFlagRestrictiveAddToBins:
300
    pctx->flag.restrictiveAddToBins = flag;
301
    break;
302
  case pullFlagEnergyFromStrength:
303
    pctx->flag.energyFromStrength = flag;
304
    break;
305
  case pullFlagNixAtVolumeEdgeSpace:
306
    pctx->flag.nixAtVolumeEdgeSpace = flag;
307
    break;
308
  case pullFlagNixAtVolumeEdgeSpaceInitRorH:
309
    pctx->flag.nixAtVolumeEdgeSpaceInitRorH = flag;
310
    break;
311
  case pullFlagConstraintBeforeSeedThresh:
312
    pctx->flag.constraintBeforeSeedThresh = flag;
313
    break;
314
  case pullFlagNoAdd:
315
    pctx->flag.noAdd = flag;
316
    break;
317
  case pullFlagPopCntlEnoughTest:
318
    pctx->flag.popCntlEnoughTest = flag;
319
    break;
320
  case pullFlagConvergenceIgnoresPopCntl:
321
    pctx->flag.convergenceIgnoresPopCntl = flag;
322
    break;
323
  case pullFlagBinSingle:
324
    pctx->flag.binSingle = flag;
325
    break;
326
  case pullFlagAllowCodimension3Constraints:
327
    pctx->flag.allowCodimension3Constraints = flag;
328
    break;
329
  case pullFlagScaleIsTau:
330
    pctx->flag.scaleIsTau = flag;
331
    break;
332
  case pullFlagStartSkipsPoints:
333
    pctx->flag.startSkipsPoints = flag;
334
    break;
335
  case pullFlagZeroZ:
336
    pctx->flag.zeroZ = flag;
337
    break;
338
  default:
339
    biffAddf(me, "%s: sorry, flag %d valid but not handled?", me, which);
340
    return 1;
341
  }
342
  return 0;
343
}
344
345
/*
346
** HEY: its really confusing to have the array of per-CONTEXT volumes.
347
** I know they're there to be copied upon task creation to create the
348
** per-TASK volumes, but its easy to think that one is supposed to be
349
** doing something with them, or that changes to them will have some
350
** effect . . .
351
*/
352
int
353
pullVerboseSet(pullContext *pctx, int verbose) {
354
  static const char me[]="pullVerboseSet";
355
  unsigned int volIdx, taskIdx;
356
357
  if (!pctx) {
358
    biffAddf(PULL, "%s: got NULL pointer", me);
359
    return 1;
360
  }
361
  pctx->verbose = verbose;
362
  for (volIdx=0; volIdx<pctx->volNum; volIdx++) {
363
    int v;
364
    v = verbose > 0 ? verbose - 1 : 0;
365
    gageParmSet(pctx->vol[volIdx]->gctx, gageParmVerbose, v);
366
  }
367
  for (taskIdx=0; taskIdx<pctx->threadNum; taskIdx++) {
368
    for (volIdx=0; volIdx<pctx->volNum; volIdx++) {
369
      int v;
370
      v = verbose > 0 ? verbose - 1 : 0;
371
      gageParmSet(pctx->task[taskIdx]->vol[volIdx]->gctx, gageParmVerbose, v);
372
    }
373
  }
374
  return 0;
375
}
376
377
int
378
pullThreadNumSet(pullContext *pctx, unsigned int threadNum) {
379
  static const char me[]="pullThreadNumSet";
380
381
  if (!pctx) {
382
    biffAddf(PULL, "%s: got NULL pointer", me);
383
    return 1;
384
  }
385
  pctx->threadNum = threadNum;
386
  return 0;
387
}
388
389
int
390
pullRngSeedSet(pullContext *pctx, unsigned int rngSeed) {
391
  static const char me[]="pullRngSeedSet";
392
393
  if (!pctx) {
394
    biffAddf(PULL, "%s: got NULL pointer", me);
395
    return 1;
396
  }
397
  pctx->rngSeed = rngSeed;
398
  return 0;
399
}
400
401
int
402
pullProgressBinModSet(pullContext *pctx, unsigned int bmod) {
403
  static const char me[]="pullProgressBinModSet";
404
405
  if (!pctx) {
406
    biffAddf(PULL, "%s: got NULL pointer", me);
407
    return 1;
408
  }
409
  pctx->progressBinMod = bmod;
410
  return 0;
411
}
412
413
int
414
pullCallbackSet(pullContext *pctx,
415
                void (*iter_cb)(void *data_cb),
416
                void *data_cb) {
417
  static const char me[]="pullCallbackSet";
418
419
  if (!pctx) {
420
    biffAddf(PULL, "%s: got NULL pointer", me);
421
    return 1;
422
  }
423
  pctx->iter_cb = iter_cb;
424
  pctx->data_cb = data_cb;
425
  return 0;
426
}
427
428
/*
429
******** pullInterEnergySet
430
**
431
** This is the single function for setting the inter-particle energy,
432
** which is clumsy because which pullEnergySpecs are necessary is
433
** different depending on interType.  Pass NULL for those not needed.
434
**
435
** Note that all the pullEnergySpecs inside the pctx are created
436
** by pullContextNew, so they should never be NULL.  When a pullEnergySpec
437
** is not needed for a given interType, we set it to pullEnergyZero
438
** and a vector of NaNs.
439
*/
440
int
441
pullInterEnergySet(pullContext *pctx, int interType,
442
                   const pullEnergySpec *enspR,
443
                   const pullEnergySpec *enspS,
444
                   const pullEnergySpec *enspWin) {
445
  static const char me[]="pullInterEnergySet";
446
  unsigned int zpi;
447
  double zeroParm[PULL_ENERGY_PARM_NUM];
448
449
  if (!pctx) {
450
    biffAddf(PULL, "%s: got NULL pointer", me);
451
    return 1;
452
  }
453
  if (!AIR_IN_OP(pullInterTypeUnknown, interType, pullInterTypeLast)) {
454
    biffAddf(PULL, "%s: interType %d not valid", me, interType);
455
    return 1;
456
  }
457
  for (zpi=0; zpi<PULL_ENERGY_PARM_NUM; zpi++) {
458
    zeroParm[zpi] = AIR_NAN;
459
  }
460
461
#define CHECK_N_COPY(X)                                                 \
462
  if (!ensp##X) {                                                       \
463
    biffAddf(PULL, "%s: need non-NULL ensp" #X " for interType %s", me, \
464
             airEnumStr(pullInterType, interType));                     \
465
    return 1;                                                           \
466
  }                                                                     \
467
  pullEnergySpecCopy(pctx->energySpec##X, ensp##X)
468
469
  switch (interType) {
470
  case pullInterTypeJustR:
471
    /* 1: phi(r,s) = phi_r(r) */
472
  case pullInterTypeUnivariate:
473
    /* 2: phi(r,s) = phi_r(u); u = sqrt(r*r+s*s) */
474
    CHECK_N_COPY(R);
475
    pullEnergySpecSet(pctx->energySpecS, pullEnergyZero, zeroParm);
476
    pullEnergySpecSet(pctx->energySpecWin, pullEnergyZero, zeroParm);
477
    break;
478
  case pullInterTypeSeparable:
479
    /* 3: phi(r,s) = phi_r(r)*phi_s(s) */
480
    CHECK_N_COPY(R);
481
    CHECK_N_COPY(S);
482
    pullEnergySpecSet(pctx->energySpecWin, pullEnergyZero, zeroParm);
483
    break;
484
  case pullInterTypeAdditive:
485
    /* 4: phi(r,s) = beta*phi_r(r)*win(s) + (1-beta)*win(r)*phi_s(s) */
486
    CHECK_N_COPY(R);
487
    CHECK_N_COPY(S);
488
    CHECK_N_COPY(Win);
489
    break;
490
  default:
491
    biffAddf(PULL, "%s: interType %d valid but no handled?", me, interType);
492
    return 1;
493
  }
494
#undef CHECK_N_COPY
495
496
  pctx->interType = interType;
497
  return 0;
498
}
499
500
/*
501
** you can pass in a NULL FILE* if you want
502
*/
503
int
504
pullLogAddSet(pullContext *pctx, FILE *flog) {
505
  static const char me[]="pullLogAddSet";
506
507
  if (!(pctx)) {
508
    biffAddf(PULL, "%s: got NULL pointer", me);
509
    return 1;
510
  }
511
512
  pctx->logAdd = flog;
513
  return 0;
514
}