File: | src/pull/pointPull.c |
Location: | line 1030, column 3 |
Description: | Array access results in a null pointer dereference |
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 | #define DEBUG1 1 | |||||
29 | ||||||
30 | /* | |||||
31 | ** HEY: this has to be threadsafe, at least threadsafe when there | |||||
32 | ** are no errors, because this can now be called from multiple | |||||
33 | ** tasks during population control | |||||
34 | */ | |||||
35 | pullPoint * | |||||
36 | pullPointNew(pullContext *pctx) { | |||||
37 | static const char me[]="pullPointNew"; | |||||
38 | pullPoint *pnt; | |||||
39 | unsigned int ii; | |||||
40 | size_t pntSize; | |||||
41 | pullPtrPtrUnion pppu; | |||||
42 | ||||||
43 | if (!pctx) { | |||||
44 | biffAddf(PULLpullBiffKey, "%s: got NULL pointer", me); | |||||
45 | return NULL((void*)0); | |||||
46 | } | |||||
47 | if (!pctx->infoTotalLen) { | |||||
48 | biffAddf(PULLpullBiffKey, "%s: can't allocate points w/out infoTotalLen set\n", me); | |||||
49 | return NULL((void*)0); | |||||
50 | } | |||||
51 | /* Allocate the pullPoint so that it has pctx->infoTotalLen doubles. | |||||
52 | The pullPoint declaration has info[1], hence the "- 1" below */ | |||||
53 | pntSize = sizeof(pullPoint) + sizeof(double)*(pctx->infoTotalLen - 1); | |||||
54 | pnt = AIR_CAST(pullPoint *, calloc(1, pntSize))((pullPoint *)(calloc(1, pntSize))); | |||||
55 | if (!pnt) { | |||||
56 | biffAddf(PULLpullBiffKey, "%s: couldn't allocate point (info len %u)\n", me, | |||||
57 | pctx->infoTotalLen - 1); | |||||
58 | return NULL((void*)0); | |||||
59 | } | |||||
60 | ||||||
61 | pnt->idtag = pctx->idtagNext++; | |||||
62 | pnt->idCC = 0; | |||||
63 | pnt->neighPoint = NULL((void*)0); | |||||
64 | pnt->neighPointNum = 0; | |||||
65 | pppu.points = &(pnt->neighPoint); | |||||
66 | pnt->neighPointArr = airArrayNew(pppu.v, &(pnt->neighPointNum), | |||||
67 | sizeof(pullPoint *), | |||||
68 | PULL_POINT_NEIGH_INCR16); | |||||
69 | pnt->neighPointArr->noReallocWhenSmaller = AIR_TRUE1; | |||||
70 | pnt->neighDistMean = 0; | |||||
71 | ELL_10V_ZERO_SET(pnt->neighCovar)((pnt->neighCovar)[0]=0, (pnt->neighCovar)[1]=0, (pnt-> neighCovar)[2]=0, (pnt->neighCovar)[3]=0, (pnt->neighCovar )[4]=0, (pnt->neighCovar)[5]=0, (pnt->neighCovar)[6]=0, (pnt->neighCovar)[7]=0, (pnt->neighCovar)[8]=0, (pnt-> neighCovar)[9]=0); | |||||
72 | pnt->stability = 0.0; | |||||
73 | #if PULL_TANCOVAR1 | |||||
74 | ELL_6V_ZERO_SET(pnt->neighTanCovar)((pnt->neighTanCovar)[0]=(0), (pnt->neighTanCovar)[1]=( 0), (pnt->neighTanCovar)[2]=(0), (pnt->neighTanCovar)[3 ]=(0), (pnt->neighTanCovar)[4]=(0), (pnt->neighTanCovar )[5]=(0)); | |||||
75 | #endif | |||||
76 | pnt->neighInterNum = 0; | |||||
77 | pnt->stuckIterNum = 0; | |||||
78 | #if PULL_PHIST0 | |||||
79 | pnt->phist = NULL((void*)0); | |||||
80 | pnt->phistNum = 0; | |||||
81 | pnt->phistArr = airArrayNew(AIR_CAST(void**, &(pnt->phist))((void**)(&(pnt->phist))), | |||||
82 | &(pnt->phistNum), | |||||
83 | _PHN6*sizeof(double), 32); | |||||
84 | #endif | |||||
85 | pnt->status = 0; | |||||
86 | ELL_4V_SET(pnt->pos, AIR_NAN, AIR_NAN, AIR_NAN, AIR_NAN)((pnt->pos)[0] = ((airFloatQNaN.f)), (pnt->pos)[1] = (( airFloatQNaN.f)), (pnt->pos)[2] = ((airFloatQNaN.f)), (pnt ->pos)[3] = ((airFloatQNaN.f))); | |||||
87 | pnt->energy = AIR_NAN(airFloatQNaN.f); | |||||
88 | ELL_4V_SET(pnt->force, AIR_NAN, AIR_NAN, AIR_NAN, AIR_NAN)((pnt->force)[0] = ((airFloatQNaN.f)), (pnt->force)[1] = ((airFloatQNaN.f)), (pnt->force)[2] = ((airFloatQNaN.f)), (pnt->force)[3] = ((airFloatQNaN.f))); | |||||
89 | pnt->stepEnergy = pctx->sysParm.stepInitial; | |||||
90 | pnt->stepConstr = pctx->sysParm.stepInitial; | |||||
91 | for (ii=0; ii<pctx->infoTotalLen; ii++) { | |||||
92 | pnt->info[ii] = AIR_NAN(airFloatQNaN.f); | |||||
93 | } | |||||
94 | return pnt; | |||||
95 | } | |||||
96 | ||||||
97 | pullPoint * | |||||
98 | pullPointNix(pullPoint *pnt) { | |||||
99 | ||||||
100 | pnt->neighPointArr = airArrayNuke(pnt->neighPointArr); | |||||
101 | #if PULL_PHIST0 | |||||
102 | pnt->phistArr = airArrayNuke(pnt->phistArr); | |||||
103 | #endif | |||||
104 | airFree(pnt); | |||||
105 | return NULL((void*)0); | |||||
106 | } | |||||
107 | ||||||
108 | #if PULL_PHIST0 | |||||
109 | void | |||||
110 | _pullPointHistInit(pullPoint *point) { | |||||
111 | ||||||
112 | airArrayLenSet(point->phistArr, 0); | |||||
113 | return; | |||||
114 | } | |||||
115 | ||||||
116 | void | |||||
117 | _pullPointHistAdd(pullPoint *point, int cond, double val) { | |||||
118 | static const char me[]="_pullPointHistAdd"; | |||||
119 | unsigned int phistIdx; | |||||
120 | ||||||
121 | phistIdx = airArrayLenIncr(point->phistArr, 1); | |||||
122 | ELL_4V_COPY(point->phist + _PHN*phistIdx, point->pos)((point->phist + 6*phistIdx)[0] = (point->pos)[0], (point ->phist + 6*phistIdx)[1] = (point->pos)[1], (point-> phist + 6*phistIdx)[2] = (point->pos)[2], (point->phist + 6*phistIdx)[3] = (point->pos)[3]); | |||||
123 | ||||||
124 | fprintf(stderr__stderrp, "!%s: point %p pos = %.17g %.17g %.17g %.17g (%g)\n", me, | |||||
125 | point, point->pos[0], point->pos[1], point->pos[2], point->pos[3], | |||||
126 | val); | |||||
127 | ||||||
128 | (point->phist + _PHN6*phistIdx)[4] = cond; | |||||
129 | (point->phist + _PHN6*phistIdx)[5] = val; | |||||
130 | return; | |||||
131 | } | |||||
132 | #endif | |||||
133 | ||||||
134 | /* | |||||
135 | ** HEY: there should be something like a "map" over all the points, | |||||
136 | ** which could implement all these redundant functions | |||||
137 | */ | |||||
138 | ||||||
139 | unsigned int | |||||
140 | pullPointNumberFilter(const pullContext *pctx, | |||||
141 | unsigned int idtagMin, | |||||
142 | unsigned int idtagMax) { | |||||
143 | unsigned int binIdx, pointNum; | |||||
144 | const pullBin *bin; | |||||
145 | const pullPoint *point; | |||||
146 | ||||||
147 | pointNum = 0; | |||||
148 | for (binIdx=0; binIdx<pctx->binNum; binIdx++) { | |||||
149 | unsigned int pointIdx; | |||||
150 | bin = pctx->bin + binIdx; | |||||
151 | if (0 == idtagMin && 0 == idtagMax) { | |||||
152 | pointNum += bin->pointNum; | |||||
153 | } else { | |||||
154 | for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) { | |||||
155 | point = bin->point[pointIdx]; | |||||
156 | pointNum += (idtagMin <= point->idtag | |||||
157 | && (0 == idtagMax | |||||
158 | || point->idtag <= idtagMax)); | |||||
159 | } | |||||
160 | } | |||||
161 | } | |||||
162 | return pointNum; | |||||
163 | } | |||||
164 | ||||||
165 | unsigned int | |||||
166 | pullPointNumber(const pullContext *pctx) { | |||||
167 | ||||||
168 | return pullPointNumberFilter(pctx, 0, 0); | |||||
169 | } | |||||
170 | ||||||
171 | double | |||||
172 | _pullEnergyTotal(const pullContext *pctx) { | |||||
173 | unsigned int binIdx, pointIdx; | |||||
174 | const pullBin *bin; | |||||
175 | const pullPoint *point; | |||||
176 | double sum; | |||||
177 | ||||||
178 | sum = 0; | |||||
179 | for (binIdx=0; binIdx<pctx->binNum; binIdx++) { | |||||
180 | bin = pctx->bin + binIdx; | |||||
181 | for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) { | |||||
182 | point = bin->point[pointIdx]; | |||||
183 | sum += point->energy; | |||||
184 | } | |||||
185 | } | |||||
186 | return sum; | |||||
187 | } | |||||
188 | ||||||
189 | void | |||||
190 | _pullPointStepEnergyScale(pullContext *pctx, double scale) { | |||||
191 | unsigned int binIdx, pointIdx; | |||||
192 | const pullBin *bin; | |||||
193 | pullPoint *point; | |||||
194 | ||||||
195 | for (binIdx=0; binIdx<pctx->binNum; binIdx++) { | |||||
196 | bin = pctx->bin + binIdx; | |||||
197 | for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) { | |||||
198 | point = bin->point[pointIdx]; | |||||
199 | point->stepEnergy *= scale; | |||||
200 | point->stepEnergy = AIR_MIN(point->stepEnergy,((point->stepEnergy) < (3.40282347e+38F) ? (point->stepEnergy ) : (3.40282347e+38F)) | |||||
201 | _PULL_STEP_ENERGY_MAX)((point->stepEnergy) < (3.40282347e+38F) ? (point->stepEnergy ) : (3.40282347e+38F)); | |||||
202 | } | |||||
203 | } | |||||
204 | return; | |||||
205 | } | |||||
206 | ||||||
207 | double | |||||
208 | _pullStepInterAverage(const pullContext *pctx) { | |||||
209 | unsigned int binIdx, pointIdx, pointNum; | |||||
210 | const pullBin *bin; | |||||
211 | const pullPoint *point; | |||||
212 | double sum, avg; | |||||
213 | ||||||
214 | sum = 0; | |||||
215 | pointNum = 0; | |||||
216 | for (binIdx=0; binIdx<pctx->binNum; binIdx++) { | |||||
217 | bin = pctx->bin + binIdx; | |||||
218 | pointNum += bin->pointNum; | |||||
219 | for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) { | |||||
220 | point = bin->point[pointIdx]; | |||||
221 | sum += point->stepEnergy; | |||||
222 | } | |||||
223 | } | |||||
224 | avg = (!pointNum ? AIR_NAN(airFloatQNaN.f) : sum/pointNum); | |||||
225 | return avg; | |||||
226 | } | |||||
227 | /* ^^^ vvv HEY HEY HEY: COPY + PASTE COPY + PASTE COPY + PASTE */ | |||||
228 | double | |||||
229 | _pullStepConstrAverage(const pullContext *pctx) { | |||||
230 | unsigned int binIdx, pointIdx, pointNum; | |||||
231 | const pullBin *bin; | |||||
232 | const pullPoint *point; | |||||
233 | double sum, avg; | |||||
234 | ||||||
235 | sum = 0; | |||||
236 | pointNum = 0; | |||||
237 | for (binIdx=0; binIdx<pctx->binNum; binIdx++) { | |||||
238 | bin = pctx->bin + binIdx; | |||||
239 | pointNum += bin->pointNum; | |||||
240 | for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) { | |||||
241 | point = bin->point[pointIdx]; | |||||
242 | sum += point->stepConstr; | |||||
243 | } | |||||
244 | } | |||||
245 | avg = (!pointNum ? AIR_NAN(airFloatQNaN.f) : sum/pointNum); | |||||
246 | return avg; | |||||
247 | } | |||||
248 | ||||||
249 | /* | |||||
250 | ** convenience function for learning a scalar AND its gradient or hessian | |||||
251 | ** | |||||
252 | */ | |||||
253 | double | |||||
254 | pullPointScalar(const pullContext *pctx, const pullPoint *point, int sclInfo, | |||||
255 | /* output */ | |||||
256 | double grad[3], double hess[9]) { | |||||
257 | static const char me[]="pullPointScalar"; | |||||
258 | double scl; | |||||
259 | const pullInfoSpec *ispec; | |||||
260 | int gradInfo[1+PULL_INFO_MAX23] = { | |||||
261 | 0, /* pullInfoUnknown */ | |||||
262 | 0, /* pullInfoTensor */ | |||||
263 | 0, /* pullInfoTensorInverse */ | |||||
264 | 0, /* pullInfoHessian */ | |||||
265 | pullInfoInsideGradient, /* pullInfoInside */ | |||||
266 | 0, /* pullInfoInsideGradient */ | |||||
267 | pullInfoHeightGradient, /* pullInfoHeight */ | |||||
268 | 0, /* pullInfoHeightGradient */ | |||||
269 | 0, /* pullInfoHeightHessian */ | |||||
270 | 0, /* pullInfoHeightLaplacian */ | |||||
271 | 0, /* pullInfoSeedPreThresh */ | |||||
272 | 0, /* pullInfoSeedThresh */ | |||||
273 | 0, /* pullInfoLiveThresh */ | |||||
274 | 0, /* pullInfoLiveThresh2 */ | |||||
275 | 0, /* pullInfoLiveThresh3 */ | |||||
276 | 0, /* pullInfoTangent1 */ | |||||
277 | 0, /* pullInfoTangent2 */ | |||||
278 | 0, /* pullInfoNegativeTangent1 */ | |||||
279 | 0, /* pullInfoNegativeTangent2 */ | |||||
280 | pullInfoIsovalueGradient, /* pullInfoIsovalue */ | |||||
281 | 0, /* pullInfoIsovalueGradient */ | |||||
282 | 0, /* pullInfoIsovalueHessian */ | |||||
283 | 0, /* pullInfoStrength */ | |||||
284 | }; | |||||
285 | int hessInfo[1+PULL_INFO_MAX23] = { | |||||
286 | 0, /* pullInfoUnknown */ | |||||
287 | 0, /* pullInfoTensor */ | |||||
288 | 0, /* pullInfoTensorInverse */ | |||||
289 | 0, /* pullInfoHessian */ | |||||
290 | 0, /* pullInfoInside */ | |||||
291 | 0, /* pullInfoInsideGradient */ | |||||
292 | pullInfoHeightHessian, /* pullInfoHeight */ | |||||
293 | 0, /* pullInfoHeightGradient */ | |||||
294 | 0, /* pullInfoHeightHessian */ | |||||
295 | 0, /* pullInfoHeightLaplacian */ | |||||
296 | 0, /* pullInfoSeedPreThresh */ | |||||
297 | 0, /* pullInfoSeedThresh */ | |||||
298 | 0, /* pullInfoLiveThresh */ | |||||
299 | 0, /* pullInfoLiveThresh2 */ | |||||
300 | 0, /* pullInfoLiveThresh3 */ | |||||
301 | 0, /* pullInfoTangent1 */ | |||||
302 | 0, /* pullInfoTangent2 */ | |||||
303 | 0, /* pullInfoNegativeTangent1 */ | |||||
304 | 0, /* pullInfoNegativeTangent2 */ | |||||
305 | pullInfoIsovalueHessian, /* pullInfoIsovalue */ | |||||
306 | 0, /* pullInfoIsovalueGradient */ | |||||
307 | 0, /* pullInfoIsovalueHessian */ | |||||
308 | 0, /* pullInfoStrength */ | |||||
309 | }; | |||||
310 | const unsigned int *infoIdx; | |||||
311 | ||||||
312 | infoIdx = pctx->infoIdx; | |||||
313 | ispec = pctx->ispec[sclInfo]; | |||||
314 | /* NB: this "scl" is not scale-space scale; its the scaling | |||||
315 | of the scalar. this is getting confusing ... */ | |||||
316 | scl = point->info[infoIdx[sclInfo]]; | |||||
317 | scl = (scl - ispec->zero)*ispec->scale; | |||||
318 | /* if (289 == pctx->iter) { | |||||
319 | fprintf(stderr, "!%s(%04u,%s)@(%g,%g): (%g - %g)*%g == %g\n", | |||||
320 | me, point->idtag, airEnumStr(pullInfo, sclInfo), | |||||
321 | point->pos[0], point->pos[1], | |||||
322 | point->info[infoIdx[sclInfo]], ispec->zero, ispec->scale, scl); | |||||
323 | } */ | |||||
324 | if (0 && _pullVerbose) { | |||||
325 | if (pullInfoSeedThresh == sclInfo) { | |||||
326 | printf("!%s: seed thresh (%g - %g)*%g == %g\n", me, | |||||
327 | point->info[infoIdx[sclInfo]], ispec->zero, ispec->scale, scl); | |||||
328 | } | |||||
329 | } | |||||
330 | /* | |||||
331 | learned: this wasn't thought through: the idea was that the height | |||||
332 | *laplacian* answer should be transformed by the *height* zero and | |||||
333 | scale. scale might make sense, but not zero. This cost a few | |||||
334 | hours of tracking down the fact that the first zero-crossing | |||||
335 | detection phase of the lapl constraint was failing because the | |||||
336 | laplacian was vacillating around hspec->zero, not 0.0 . . . | |||||
337 | if (pullInfoHeightLaplacian == sclInfo) { | |||||
338 | const pullInfoSpec *hspec; | |||||
339 | hspec = pctx->ispec[pullInfoHeight]; | |||||
340 | scl = (scl - hspec->zero)*hspec->scale; | |||||
341 | } else { | |||||
342 | scl = (scl - ispec->zero)*ispec->scale; | |||||
343 | } | |||||
344 | */ | |||||
345 | /* | |||||
346 | fprintf(stderr, "!%s: %s = (%g - %g)*%g = %g*%g = %g = %g\n", me, | |||||
347 | airEnumStr(pullInfo, sclInfo), | |||||
348 | point->info[infoIdx[sclInfo]], | |||||
349 | ispec->zero, ispec->scale, | |||||
350 | point->info[infoIdx[sclInfo]] - ispec->zero, ispec->scale, | |||||
351 | (point->info[infoIdx[sclInfo]] - ispec->zero)*ispec->scale, | |||||
352 | scl); | |||||
353 | */ | |||||
354 | if (grad && gradInfo[sclInfo]) { | |||||
355 | const double *ptr = point->info + infoIdx[gradInfo[sclInfo]]; | |||||
356 | ELL_3V_SCALE(grad, ispec->scale, ptr)((grad)[0] = (ispec->scale)*(ptr)[0], (grad)[1] = (ispec-> scale)*(ptr)[1], (grad)[2] = (ispec->scale)*(ptr)[2]); | |||||
357 | } | |||||
358 | if (hess && hessInfo[sclInfo]) { | |||||
359 | const double *ptr = point->info + infoIdx[hessInfo[sclInfo]]; | |||||
360 | ELL_3M_SCALE(hess, ispec->scale, ptr)((((hess)+0)[0] = ((ispec->scale))*((ptr)+0)[0], ((hess)+0 )[1] = ((ispec->scale))*((ptr)+0)[1], ((hess)+0)[2] = ((ispec ->scale))*((ptr)+0)[2]), (((hess)+3)[0] = ((ispec->scale ))*((ptr)+3)[0], ((hess)+3)[1] = ((ispec->scale))*((ptr)+3 )[1], ((hess)+3)[2] = ((ispec->scale))*((ptr)+3)[2]), (((hess )+6)[0] = ((ispec->scale))*((ptr)+6)[0], ((hess)+6)[1] = ( (ispec->scale))*((ptr)+6)[1], ((hess)+6)[2] = ((ispec-> scale))*((ptr)+6)[2])); | |||||
361 | } | |||||
362 | return scl; | |||||
363 | } | |||||
364 | ||||||
365 | int | |||||
366 | pullProbe(pullTask *task, pullPoint *point) { | |||||
367 | static const char me[]="pullProbe"; | |||||
368 | unsigned int ii, gret=0; | |||||
369 | int edge; | |||||
370 | /* | |||||
371 | fprintf(stderr, "!%s: task->probeSeedPreThreshOnly = %d\n", me, | |||||
372 | task->probeSeedPreThreshOnly); | |||||
373 | */ | |||||
374 | #if 0 | |||||
375 | static int opened=AIR_FALSE0; | |||||
376 | static FILE *flog; | |||||
377 | #endif | |||||
378 | ||||||
379 | /* | |||||
380 | fprintf(stderr, "%s(%u,%u): A volNum = %u\n", me, task->pctx->iter, point->idtag,task->pctx->volNum); | |||||
381 | */ | |||||
382 | #if 0 | |||||
383 | static int logIdx=0, logDone=AIR_FALSE0, logStarted=AIR_FALSE0; | |||||
384 | static Nrrd *nlog; | |||||
385 | static double *log=NULL((void*)0); | |||||
386 | if (!logStarted) { | |||||
387 | if (81 == point->idtag) { | |||||
388 | printf("\n\n%s: ###### HELLO begin logging . . .\n\n\n", me); | |||||
389 | /* knowing the logIdx at the end of logging . . . */ | |||||
390 | nlog = nrrdNew(); | |||||
391 | nrrdMaybeAlloc_va(nlog, nrrdTypeDouble, 2, | |||||
392 | AIR_CAST(size_t, 25)((size_t)(25)), | |||||
393 | AIR_CAST(size_t, 2754)((size_t)(2754))); | |||||
394 | log = AIR_CAST(double*, nlog->data)((double*)(nlog->data)); | |||||
395 | logStarted = AIR_TRUE1; | |||||
396 | } | |||||
397 | } | |||||
398 | #endif | |||||
399 | ||||||
400 | if (!ELL_4V_EXISTS(point->pos)((((int)(!(((point->pos)[0]) - ((point->pos)[0]))))) && (((int)(!(((point->pos)[1]) - ((point->pos)[1]))))) && (((int)(!(((point->pos)[2]) - ((point->pos)[2]))))) && (((int)(!(((point->pos)[3]) - ((point->pos)[3]))))))) { | |||||
401 | fprintf(stderr__stderrp, "%s: pnt %u non-exist pos (%g,%g,%g,%g)\n\n!!!\n\n\n", | |||||
402 | me, point->idtag, point->pos[0], point->pos[1], | |||||
403 | point->pos[2], point->pos[3]); | |||||
404 | biffAddf(PULLpullBiffKey, "%s: pnt %u non-exist pos (%g,%g,%g,%g)", | |||||
405 | me, point->idtag, point->pos[0], point->pos[1], | |||||
406 | point->pos[2], point->pos[3]); | |||||
407 | return 1; | |||||
408 | /* can't probe, but make it go away as quickly as possible */ | |||||
409 | /* | |||||
410 | ELL_4V_SET(point->pos, 0, 0, 0, 0); | |||||
411 | point->status |= PULL_STATUS_NIXME_BIT; | |||||
412 | return 0; | |||||
413 | */ | |||||
414 | } | |||||
415 | if (task->pctx->verbose > 3) { | |||||
416 | printf("%s: hello; probing %u volumes\n", me, task->pctx->volNum); | |||||
417 | } | |||||
418 | edge = AIR_FALSE0; | |||||
419 | task->pctx->count[pullCountProbe] += 1; | |||||
420 | /* | |||||
421 | fprintf(stderr, "%s(%u,%u): B volNum = %u\n", me, task->pctx->iter, point->idtag,task->pctx->volNum); | |||||
422 | */ | |||||
423 | for (ii=0; ii<task->pctx->volNum; ii++) { | |||||
424 | pullVolume *vol; | |||||
425 | vol = task->vol[ii]; | |||||
426 | if (task->probeSeedPreThreshOnly | |||||
427 | && !(vol->forSeedPreThresh)) { | |||||
428 | /* we're here *only* to probe SeedPreThresh, | |||||
429 | and this volume isn't used for that */ | |||||
430 | continue; | |||||
431 | } | |||||
432 | if (task->pctx->iter && vol->seedOnly) { | |||||
433 | /* its after the 1st iteration (#0), and this vol is only for seeding */ | |||||
434 | continue; | |||||
435 | } | |||||
436 | /* HEY should task->vol[ii]->scaleNum be the using-scale-space test? */ | |||||
437 | if (!task->vol[ii]->ninScale) { | |||||
438 | gret = gageProbeSpace(task->vol[ii]->gctx, | |||||
439 | point->pos[0], point->pos[1], point->pos[2], | |||||
440 | AIR_FALSE0 /* index-space */, | |||||
441 | AIR_TRUE1 /* clamp */); | |||||
442 | } else { | |||||
443 | if (task->pctx->verbose > 3) { | |||||
444 | printf("%s: vol[%u] has scale (%u)-> " | |||||
445 | "gageStackProbeSpace(%p) (v %d)\n", | |||||
446 | me, ii, task->vol[ii]->scaleNum, | |||||
447 | AIR_VOIDP(task->vol[ii]->gctx)((void *)(task->vol[ii]->gctx)), | |||||
448 | task->vol[ii]->gctx->verbose); | |||||
449 | } | |||||
450 | /* | |||||
451 | if (81 == point->idtag) { | |||||
452 | printf("%s: probing vol[%u] @ %g %g %g %g\n", me, ii, | |||||
453 | point->pos[0], point->pos[1], point->pos[2], point->pos[3]); | |||||
454 | } | |||||
455 | */ | |||||
456 | gret = gageStackProbeSpace(task->vol[ii]->gctx, | |||||
457 | point->pos[0], point->pos[1], point->pos[2], | |||||
458 | (task->pctx->flag.scaleIsTau | |||||
459 | ? gageSigOfTau(point->pos[3])airSigmaOfTau(point->pos[3]) | |||||
460 | : point->pos[3]), | |||||
461 | AIR_FALSE0 /* index-space */, | |||||
462 | AIR_TRUE1 /* clamp */); | |||||
463 | } | |||||
464 | if (gret) { | |||||
465 | biffAddf(PULLpullBiffKey, "%s: probe failed on vol %u/%u: (%d) %s", me, | |||||
466 | ii, task->pctx->volNum, | |||||
467 | task->vol[ii]->gctx->errNum, task->vol[ii]->gctx->errStr); | |||||
468 | return 1; | |||||
469 | } | |||||
470 | /* | |||||
471 | if (!edge | |||||
472 | && AIR_ABS(point->pos[1] - 67) < 1 | |||||
473 | && AIR_ABS(point->pos[2] - 67) < 1 | |||||
474 | && point->pos[3] > 3.13 | |||||
475 | && !!task->vol[ii]->gctx->edgeFrac) { | |||||
476 | fprintf(stderr, "!%s(%u @ %g,%g,%g,%g): " | |||||
477 | "vol[%u]->gctx->edgeFrac %g => edge bit on\n", | |||||
478 | me, point->idtag, | |||||
479 | point->pos[0], point->pos[1], | |||||
480 | point->pos[2], point->pos[3], | |||||
481 | ii, task->vol[ii]->gctx->edgeFrac); | |||||
482 | } | |||||
483 | */ | |||||
484 | edge |= !!task->vol[ii]->gctx->edgeFrac; | |||||
485 | } | |||||
486 | if (edge) { | |||||
487 | point->status |= PULL_STATUS_EDGE_BIT(1<< 4); | |||||
488 | } else { | |||||
489 | point->status &= ~PULL_STATUS_EDGE_BIT(1<< 4); | |||||
490 | } | |||||
491 | ||||||
492 | /* maybe is a little stupid to have the infos indexed this way, | |||||
493 | since it means that we always have to loop through all indices, | |||||
494 | but at least the compiler can unroll it . . . */ | |||||
495 | for (ii=0; ii<=PULL_INFO_MAX23; ii++) { | |||||
496 | unsigned int alen, aidx; | |||||
497 | const pullInfoSpec *ispec; | |||||
498 | ispec = task->pctx->ispec[ii]; | |||||
499 | if (ispec) { | |||||
500 | alen = _pullInfoLen[ii]; | |||||
501 | aidx = task->pctx->infoIdx[ii]; | |||||
502 | if (pullSourceGage == ispec->source) { | |||||
503 | _pullInfoCopy[alen](point->info + aidx, task->ans[ii]); | |||||
504 | /* if (289 == task->pctx->iter) { | |||||
505 | fprintf(stderr, "!%s(%u): copied info %u (%s) len %u\n", me, point->idtag, | |||||
506 | ii, airEnumStr(pullInfo, ii), alen); | |||||
507 | if (1 == alen) { | |||||
508 | fprintf(stderr, "!%s(%u): (point->info + %u)[0] = %g\n", me, point->idtag, | |||||
509 | aidx, (point->info + aidx)[0]); | |||||
510 | } | |||||
511 | } */ | |||||
512 | /* | |||||
513 | if (81 == point->idtag) { | |||||
514 | pullVolume *vol; | |||||
515 | pullInfoSpec *isp; | |||||
516 | isp = task->pctx->ispec[ii]; | |||||
517 | vol = task->pctx->vol[isp->volIdx]; | |||||
518 | if (1 == alen) { | |||||
519 | printf("!%s: info[%u] %s: %s(\"%s\") = %g\n", me, | |||||
520 | ii, airEnumStr(pullInfo, ii), | |||||
521 | airEnumStr(vol->kind->enm, isp->item), | |||||
522 | vol->name, task->ans[ii][0]); | |||||
523 | } else { | |||||
524 | unsigned int vali; | |||||
525 | printf("!%s: info[%u] %s: %s(\"%s\") =\n", me, | |||||
526 | ii, airEnumStr(pullInfo, ii), | |||||
527 | airEnumStr(vol->kind->enm, isp->item), vol->name); | |||||
528 | for (vali=0; vali<alen; vali++) { | |||||
529 | printf("!%s: [%u] %g\n", me, vali, | |||||
530 | task->ans[ii][vali]); | |||||
531 | } | |||||
532 | } | |||||
533 | } | |||||
534 | */ | |||||
535 | } else if (pullSourceProp == ispec->source) { | |||||
536 | switch (ispec->prop) { | |||||
537 | case pullPropIdtag: | |||||
538 | point->info[aidx] = point->idtag; | |||||
539 | break; | |||||
540 | case pullPropIdCC: | |||||
541 | point->info[aidx] = point->idCC; | |||||
542 | break; | |||||
543 | case pullPropEnergy: | |||||
544 | point->info[aidx] = point->energy; | |||||
545 | break; | |||||
546 | case pullPropStepEnergy: | |||||
547 | point->info[aidx] = point->stepEnergy; | |||||
548 | break; | |||||
549 | case pullPropStepConstr: | |||||
550 | point->info[aidx] = point->stepConstr; | |||||
551 | break; | |||||
552 | case pullPropStuck: | |||||
553 | point->info[aidx] = ((point->status & PULL_STATUS_STUCK_BIT(1<< 1)) | |||||
554 | ? point->stuckIterNum | |||||
555 | : 0); | |||||
556 | break; | |||||
557 | case pullPropPosition: | |||||
558 | ELL_4V_COPY(point->info + aidx, point->pos)((point->info + aidx)[0] = (point->pos)[0], (point-> info + aidx)[1] = (point->pos)[1], (point->info + aidx) [2] = (point->pos)[2], (point->info + aidx)[3] = (point ->pos)[3]); | |||||
559 | break; | |||||
560 | case pullPropForce: | |||||
561 | ELL_4V_COPY(point->info + aidx, point->force)((point->info + aidx)[0] = (point->force)[0], (point-> info + aidx)[1] = (point->force)[1], (point->info + aidx )[2] = (point->force)[2], (point->info + aidx)[3] = (point ->force)[3]); | |||||
562 | break; | |||||
563 | case pullPropNeighDistMean: | |||||
564 | point->info[aidx] = point->neighDistMean; | |||||
565 | break; | |||||
566 | case pullPropScale: | |||||
567 | point->info[aidx] = point->pos[3]; | |||||
568 | break; | |||||
569 | case pullPropNeighCovar: | |||||
570 | ELL_10V_COPY(point->info + aidx, point->neighCovar)((point->info + aidx)[0] = (point->neighCovar)[0], (point ->info + aidx)[1] = (point->neighCovar)[1], (point-> info + aidx)[2] = (point->neighCovar)[2], (point->info + aidx)[3] = (point->neighCovar)[3], (point->info + aidx )[4] = (point->neighCovar)[4], (point->info + aidx)[5] = (point->neighCovar)[5], (point->info + aidx)[6] = (point ->neighCovar)[6], (point->info + aidx)[7] = (point-> neighCovar)[7], (point->info + aidx)[8] = (point->neighCovar )[8], (point->info + aidx)[9] = (point->neighCovar)[9]); | |||||
571 | break; | |||||
572 | case pullPropNeighCovar7Ten: | |||||
573 | TEN_T_SET(point->info + aidx, 1.0f,( (point->info + aidx)[0] = (1.0f), (point->info + aidx )[1] = (point->neighCovar[0]), (point->info + aidx)[2] = (point->neighCovar[1]), (point->info + aidx)[3] = (point ->neighCovar[2]), (point->info + aidx)[4] = (point-> neighCovar[4]), (point->info + aidx)[5] = (point->neighCovar [5]), (point->info + aidx)[6] = (point->neighCovar[7]) ) | |||||
574 | point->neighCovar[0],( (point->info + aidx)[0] = (1.0f), (point->info + aidx )[1] = (point->neighCovar[0]), (point->info + aidx)[2] = (point->neighCovar[1]), (point->info + aidx)[3] = (point ->neighCovar[2]), (point->info + aidx)[4] = (point-> neighCovar[4]), (point->info + aidx)[5] = (point->neighCovar [5]), (point->info + aidx)[6] = (point->neighCovar[7]) ) | |||||
575 | point->neighCovar[1],( (point->info + aidx)[0] = (1.0f), (point->info + aidx )[1] = (point->neighCovar[0]), (point->info + aidx)[2] = (point->neighCovar[1]), (point->info + aidx)[3] = (point ->neighCovar[2]), (point->info + aidx)[4] = (point-> neighCovar[4]), (point->info + aidx)[5] = (point->neighCovar [5]), (point->info + aidx)[6] = (point->neighCovar[7]) ) | |||||
576 | point->neighCovar[2],( (point->info + aidx)[0] = (1.0f), (point->info + aidx )[1] = (point->neighCovar[0]), (point->info + aidx)[2] = (point->neighCovar[1]), (point->info + aidx)[3] = (point ->neighCovar[2]), (point->info + aidx)[4] = (point-> neighCovar[4]), (point->info + aidx)[5] = (point->neighCovar [5]), (point->info + aidx)[6] = (point->neighCovar[7]) ) | |||||
577 | point->neighCovar[4],( (point->info + aidx)[0] = (1.0f), (point->info + aidx )[1] = (point->neighCovar[0]), (point->info + aidx)[2] = (point->neighCovar[1]), (point->info + aidx)[3] = (point ->neighCovar[2]), (point->info + aidx)[4] = (point-> neighCovar[4]), (point->info + aidx)[5] = (point->neighCovar [5]), (point->info + aidx)[6] = (point->neighCovar[7]) ) | |||||
578 | point->neighCovar[5],( (point->info + aidx)[0] = (1.0f), (point->info + aidx )[1] = (point->neighCovar[0]), (point->info + aidx)[2] = (point->neighCovar[1]), (point->info + aidx)[3] = (point ->neighCovar[2]), (point->info + aidx)[4] = (point-> neighCovar[4]), (point->info + aidx)[5] = (point->neighCovar [5]), (point->info + aidx)[6] = (point->neighCovar[7]) ) | |||||
579 | point->neighCovar[7])( (point->info + aidx)[0] = (1.0f), (point->info + aidx )[1] = (point->neighCovar[0]), (point->info + aidx)[2] = (point->neighCovar[1]), (point->info + aidx)[3] = (point ->neighCovar[2]), (point->info + aidx)[4] = (point-> neighCovar[4]), (point->info + aidx)[5] = (point->neighCovar [5]), (point->info + aidx)[6] = (point->neighCovar[7]) ); | |||||
580 | break; | |||||
581 | #if PULL_TANCOVAR1 | |||||
582 | case pullPropNeighTanCovar: | |||||
583 | TEN_T_SET(point->info + aidx, 1.0f,( (point->info + aidx)[0] = (1.0f), (point->info + aidx )[1] = (point->neighTanCovar[0]), (point->info + aidx)[ 2] = (point->neighTanCovar[1]), (point->info + aidx)[3] = (point->neighTanCovar[2]), (point->info + aidx)[4] = (point->neighTanCovar[3]), (point->info + aidx)[5] = ( point->neighTanCovar[4]), (point->info + aidx)[6] = (point ->neighTanCovar[5]) ) | |||||
584 | point->neighTanCovar[0],( (point->info + aidx)[0] = (1.0f), (point->info + aidx )[1] = (point->neighTanCovar[0]), (point->info + aidx)[ 2] = (point->neighTanCovar[1]), (point->info + aidx)[3] = (point->neighTanCovar[2]), (point->info + aidx)[4] = (point->neighTanCovar[3]), (point->info + aidx)[5] = ( point->neighTanCovar[4]), (point->info + aidx)[6] = (point ->neighTanCovar[5]) ) | |||||
585 | point->neighTanCovar[1],( (point->info + aidx)[0] = (1.0f), (point->info + aidx )[1] = (point->neighTanCovar[0]), (point->info + aidx)[ 2] = (point->neighTanCovar[1]), (point->info + aidx)[3] = (point->neighTanCovar[2]), (point->info + aidx)[4] = (point->neighTanCovar[3]), (point->info + aidx)[5] = ( point->neighTanCovar[4]), (point->info + aidx)[6] = (point ->neighTanCovar[5]) ) | |||||
586 | point->neighTanCovar[2],( (point->info + aidx)[0] = (1.0f), (point->info + aidx )[1] = (point->neighTanCovar[0]), (point->info + aidx)[ 2] = (point->neighTanCovar[1]), (point->info + aidx)[3] = (point->neighTanCovar[2]), (point->info + aidx)[4] = (point->neighTanCovar[3]), (point->info + aidx)[5] = ( point->neighTanCovar[4]), (point->info + aidx)[6] = (point ->neighTanCovar[5]) ) | |||||
587 | point->neighTanCovar[3],( (point->info + aidx)[0] = (1.0f), (point->info + aidx )[1] = (point->neighTanCovar[0]), (point->info + aidx)[ 2] = (point->neighTanCovar[1]), (point->info + aidx)[3] = (point->neighTanCovar[2]), (point->info + aidx)[4] = (point->neighTanCovar[3]), (point->info + aidx)[5] = ( point->neighTanCovar[4]), (point->info + aidx)[6] = (point ->neighTanCovar[5]) ) | |||||
588 | point->neighTanCovar[4],( (point->info + aidx)[0] = (1.0f), (point->info + aidx )[1] = (point->neighTanCovar[0]), (point->info + aidx)[ 2] = (point->neighTanCovar[1]), (point->info + aidx)[3] = (point->neighTanCovar[2]), (point->info + aidx)[4] = (point->neighTanCovar[3]), (point->info + aidx)[5] = ( point->neighTanCovar[4]), (point->info + aidx)[6] = (point ->neighTanCovar[5]) ) | |||||
589 | point->neighTanCovar[5])( (point->info + aidx)[0] = (1.0f), (point->info + aidx )[1] = (point->neighTanCovar[0]), (point->info + aidx)[ 2] = (point->neighTanCovar[1]), (point->info + aidx)[3] = (point->neighTanCovar[2]), (point->info + aidx)[4] = (point->neighTanCovar[3]), (point->info + aidx)[5] = ( point->neighTanCovar[4]), (point->info + aidx)[6] = (point ->neighTanCovar[5]) ); | |||||
590 | break; | |||||
591 | #endif | |||||
592 | case pullPropStability: | |||||
593 | point->info[aidx] = point->stability; | |||||
594 | break; | |||||
595 | default: | |||||
596 | break; | |||||
597 | } | |||||
598 | } | |||||
599 | } | |||||
600 | } | |||||
601 | ||||||
602 | #if 0 | |||||
603 | if (logStarted && !logDone) { | |||||
604 | unsigned int ai; | |||||
605 | /* the actual logging */ | |||||
606 | log[0] = point->idtag; | |||||
607 | ELL_4V_COPY(log + 1, point->pos)((log + 1)[0] = (point->pos)[0], (log + 1)[1] = (point-> pos)[1], (log + 1)[2] = (point->pos)[2], (log + 1)[3] = (point ->pos)[3]); | |||||
608 | for (ai=0; ai<20; ai++) { | |||||
609 | log[5 + ai] = point->info[ai]; | |||||
610 | } | |||||
611 | log += nlog->axis[0].size; | |||||
612 | logIdx++; | |||||
613 | if (1 == task->pctx->iter && 81 == point->idtag) { | |||||
614 | printf("\n\n%s: ###### OKAY done logging (%u). . .\n\n\n", me, logIdx); | |||||
615 | nrrdSave("probelog.nrrd", nlog, NULL((void*)0)); | |||||
616 | nlog = nrrdNuke(nlog); | |||||
617 | logDone = AIR_TRUE1; | |||||
618 | } | |||||
619 | } | |||||
620 | #endif | |||||
621 | ||||||
622 | ||||||
623 | #if 0 | |||||
624 | if (!opened) { | |||||
625 | flog = fopen("flog.txt", "w"); | |||||
626 | opened = AIR_TRUE1; | |||||
627 | } | |||||
628 | if (opened) { | |||||
629 | fprintf(flog, "%s(%u): spthr(%g,%g,%g,%g) = %g\n", me, point->idtag, | |||||
630 | point->pos[0], point->pos[1], point->pos[2], point->pos[3], | |||||
631 | point->info[task->pctx->infoIdx[pullInfoSeedPreThresh]]); | |||||
632 | } | |||||
633 | #endif | |||||
634 | ||||||
635 | return 0; | |||||
636 | } | |||||
637 | ||||||
638 | static int | |||||
639 | _threshFail(const pullContext *pctx, const pullPoint *point, int info) { | |||||
640 | /* static const char me[]="_threshFail"; */ | |||||
641 | double val; | |||||
642 | int ret; | |||||
643 | ||||||
644 | if (pctx->ispec[info]) { | |||||
645 | val = pullPointScalar(pctx, point, info, NULL((void*)0), NULL((void*)0)); | |||||
646 | ret = (val < 0); | |||||
647 | /* | |||||
648 | fprintf(stderr, "%s(%s): val=%g -> ret=%d\n", me, | |||||
649 | airEnumStr(pullInfo, info), val, ret); | |||||
650 | */ | |||||
651 | } else { | |||||
652 | ret = AIR_FALSE0; | |||||
653 | } | |||||
654 | return ret; | |||||
655 | } | |||||
656 | ||||||
657 | int | |||||
658 | pullPointInitializePerVoxel(const pullContext *pctx, | |||||
659 | const unsigned int pointIdx, | |||||
660 | pullPoint *point, pullVolume *scaleVol, | |||||
661 | /* output */ | |||||
662 | int *createFailP) { | |||||
663 | static const char me[]="pullPointInitializePerVoxel"; | |||||
664 | unsigned int vidx[3], pix; | |||||
665 | double iPos[3]; | |||||
666 | airRandMTState *rng; | |||||
667 | pullVolume *seedVol; | |||||
668 | gageShape *seedShape; | |||||
669 | int reject, rejectEdge, constrFail; | |||||
670 | unsigned int k; | |||||
671 | ||||||
672 | seedVol = pctx->vol[pctx->ispec[pullInfoSeedThresh]->volIdx]; | |||||
673 | seedShape = seedVol->gctx->shape; | |||||
674 | rng = pctx->task[0]->rng; | |||||
675 | ||||||
676 | /* Obtain voxel and indices from pointIdx */ | |||||
677 | /* axis ordering for this is x, y, z, scale */ | |||||
678 | pix = pointIdx; | |||||
679 | if (pctx->initParm.pointPerVoxel > 0) { | |||||
680 | pix /= pctx->initParm.pointPerVoxel; | |||||
681 | } else { | |||||
682 | pix *= -pctx->initParm.pointPerVoxel; | |||||
683 | } | |||||
684 | vidx[0] = pix % seedShape->size[0]; | |||||
685 | pix = (pix - vidx[0])/seedShape->size[0]; | |||||
686 | vidx[1] = pix % seedShape->size[1]; | |||||
687 | pix = (pix - vidx[1])/seedShape->size[1]; | |||||
688 | if (pctx->initParm.ppvZRange[0] <= pctx->initParm.ppvZRange[1]) { | |||||
689 | unsigned int zrn; | |||||
690 | zrn = pctx->initParm.ppvZRange[1] - pctx->initParm.ppvZRange[0] + 1; | |||||
691 | vidx[2] = (pix % zrn) + pctx->initParm.ppvZRange[0]; | |||||
692 | pix = (pix - (pix % zrn))/zrn; | |||||
693 | } else { | |||||
694 | vidx[2] = pix % seedShape->size[2]; | |||||
695 | pix = (pix - vidx[2])/seedShape->size[2]; | |||||
696 | } | |||||
697 | for (k=0; k<=2; k++) { | |||||
698 | iPos[k] = vidx[k] + pctx->initParm.jitter*(airDrandMT_r(rng)-0.5); | |||||
699 | } | |||||
700 | gageShapeItoW(seedShape, point->pos, iPos); | |||||
701 | if (pctx->flag.zeroZ) { | |||||
702 | point->pos[2] = 0.0; | |||||
703 | } | |||||
704 | ||||||
705 | if (0 && _pullVerbose) { | |||||
706 | printf("!%s: pointIdx %u -> vidx %u %u %u (%u)\n" | |||||
707 | " -> iPos %g %g %g -> wPos %g %g %g\n", | |||||
708 | me, pointIdx, vidx[0], vidx[1], vidx[2], pix, | |||||
709 | iPos[0], iPos[1], iPos[2], | |||||
710 | point->pos[0], point->pos[1], point->pos[2]); | |||||
711 | } | |||||
712 | ||||||
713 | /* Compute sigma coordinate from pix */ | |||||
714 | if (pctx->haveScale) { | |||||
715 | int outside; | |||||
716 | double aidx, bidx; | |||||
717 | /* pix should already be integer in [0, pctx->samplesAlongScaleNum-1)]. */ | |||||
718 | aidx = pix + pctx->initParm.jitter*(airDrandMT_r(rng)-0.5); | |||||
719 | bidx = AIR_AFFINE(-0.5, aidx, pctx->initParm.samplesAlongScaleNum-0.5,( ((double)(scaleVol->scaleNum-1)-(0.0))*((double)(aidx)-( -0.5)) / ((double)(pctx->initParm.samplesAlongScaleNum-0.5 )-(-0.5)) + (0.0)) | |||||
720 | 0.0, scaleVol->scaleNum-1)( ((double)(scaleVol->scaleNum-1)-(0.0))*((double)(aidx)-( -0.5)) / ((double)(pctx->initParm.samplesAlongScaleNum-0.5 )-(-0.5)) + (0.0)); | |||||
721 | point->pos[3] = gageStackItoW(scaleVol->gctx, bidx, &outside); | |||||
722 | if (pctx->flag.scaleIsTau) { | |||||
723 | point->pos[3] = gageTauOfSig(point->pos[3])airTauOfSigma(point->pos[3]); | |||||
724 | } | |||||
725 | if (0 && _pullVerbose) { | |||||
726 | printf("!%s(%u): pix %u -> a %g b %g -> wpos %g\n", me, point->idtag, | |||||
727 | pix, aidx, bidx, point->pos[3]); | |||||
728 | } | |||||
729 | } else { | |||||
730 | point->pos[3] = 0; | |||||
731 | } | |||||
732 | ||||||
733 | if (pctx->ispec[pullInfoSeedPreThresh]) { | |||||
734 | /* we first do a special-purpose probe just for SeedPreThresh */ | |||||
735 | pctx->task[0]->probeSeedPreThreshOnly = AIR_TRUE1; | |||||
736 | if (pullProbe(pctx->task[0], point)) { | |||||
737 | biffAddf(PULLpullBiffKey, "%s: pre-probing pointIdx %u of world", me, pointIdx); | |||||
738 | return 1; | |||||
739 | } | |||||
740 | pctx->task[0]->probeSeedPreThreshOnly = AIR_FALSE0; | |||||
741 | if (_threshFail(pctx, point, pullInfoSeedPreThresh)) { | |||||
742 | reject = AIR_TRUE1; | |||||
743 | /* HEY! this obviously need to be re-written */ | |||||
744 | goto finish; | |||||
745 | } | |||||
746 | } | |||||
747 | /* else, we didn't have a SeedPreThresh, or we did, and we passed | |||||
748 | it. Now we REDO the probe, including possibly re-learning | |||||
749 | SeedPreThresh, which is silly, but the idea is that this is a | |||||
750 | small price compared to what has been saved by avoiding all the | |||||
751 | gageProbe()s on volumes unrelated to SeedPreThresh */ | |||||
752 | if (pullProbe(pctx->task[0], point)) { | |||||
753 | biffAddf(PULLpullBiffKey, "%s: probing pointIdx %u of world", me, pointIdx); | |||||
754 | return 1; | |||||
755 | } | |||||
756 | ||||||
757 | constrFail = AIR_FALSE0; | |||||
758 | reject = AIR_FALSE0; | |||||
759 | ||||||
760 | /* Check we pass pre-threshold */ | |||||
761 | if (!reject) reject |= _threshFail(pctx, point, pullInfoSeedPreThresh); | |||||
762 | ||||||
763 | if (!pctx->flag.constraintBeforeSeedThresh) { | |||||
764 | /* we should be guaranteed to have a seed thresh info */ | |||||
765 | if (!reject) reject |= _threshFail(pctx, point, pullInfoSeedThresh); | |||||
766 | if (pctx->initParm.liveThreshUse) { | |||||
767 | if (!reject) reject |= _threshFail(pctx, point, pullInfoLiveThresh); | |||||
768 | if (!reject) reject |= _threshFail(pctx, point, pullInfoLiveThresh2); | |||||
769 | if (!reject) reject |= _threshFail(pctx, point, pullInfoLiveThresh3); | |||||
770 | } | |||||
771 | } | |||||
772 | ||||||
773 | if (!reject && pctx->constraint) { | |||||
774 | if (_pullConstraintSatisfy(pctx->task[0], point, | |||||
775 | 10*_PULL_CONSTRAINT_TRAVEL_MAX2, | |||||
776 | &constrFail)) { | |||||
777 | biffAddf(PULLpullBiffKey, "%s: on pnt %u", | |||||
778 | me, pointIdx); | |||||
779 | return 1; | |||||
780 | } | |||||
781 | reject |= constrFail; | |||||
782 | /* post constraint-satisfaction, we certainly have to assert thresholds */ | |||||
783 | if (!reject) reject |= _threshFail(pctx, point, pullInfoSeedThresh); | |||||
784 | if (pctx->initParm.liveThreshUse) { | |||||
785 | if (!reject) reject |= _threshFail(pctx, point, pullInfoLiveThresh); | |||||
786 | if (!reject) reject |= _threshFail(pctx, point, pullInfoLiveThresh2); | |||||
787 | if (!reject) reject |= _threshFail(pctx, point, pullInfoLiveThresh3); | |||||
788 | } | |||||
789 | if (pctx->flag.nixAtVolumeEdgeSpace | |||||
790 | && (point->status & PULL_STATUS_EDGE_BIT(1<< 4))) { | |||||
791 | rejectEdge = AIR_TRUE1; | |||||
792 | } else { | |||||
793 | rejectEdge = AIR_FALSE0; | |||||
794 | } | |||||
795 | reject |= rejectEdge; | |||||
796 | if (pctx->verbose > 1) { | |||||
797 | fprintf(stderr__stderrp, "%s(%u): constr %d, seed %d, thresh %d %d %d, edge %d\n", | |||||
798 | me, point->idtag, constrFail, | |||||
799 | _threshFail(pctx, point, pullInfoSeedThresh), | |||||
800 | _threshFail(pctx, point, pullInfoLiveThresh), | |||||
801 | _threshFail(pctx, point, pullInfoLiveThresh2), | |||||
802 | _threshFail(pctx, point, pullInfoLiveThresh3), rejectEdge); | |||||
803 | } | |||||
804 | } else { | |||||
805 | constrFail = AIR_FALSE0; | |||||
806 | } | |||||
807 | ||||||
808 | finish: | |||||
809 | /* Gather consensus */ | |||||
810 | if (reject) { | |||||
811 | *createFailP = AIR_TRUE1; | |||||
812 | } else { | |||||
813 | *createFailP = AIR_FALSE0; | |||||
814 | } | |||||
815 | ||||||
816 | return 0; | |||||
817 | } | |||||
818 | ||||||
819 | static void | |||||
820 | _pullUnitToWorld(const pullContext *pctx, const pullVolume *scaleVol, | |||||
821 | double wrld[4], const double unit[4]) { | |||||
822 | /* static const char me[]="_pullUnitToWorld"; */ | |||||
823 | ||||||
824 | wrld[0] = AIR_AFFINE(0.0, unit[0], 1.0, pctx->bboxMin[0], pctx->bboxMax[0])( ((double)(pctx->bboxMax[0])-(pctx->bboxMin[0]))*((double )(unit[0])-(0.0)) / ((double)(1.0)-(0.0)) + (pctx->bboxMin [0])); | |||||
825 | wrld[1] = AIR_AFFINE(0.0, unit[1], 1.0, pctx->bboxMin[1], pctx->bboxMax[1])( ((double)(pctx->bboxMax[1])-(pctx->bboxMin[1]))*((double )(unit[1])-(0.0)) / ((double)(1.0)-(0.0)) + (pctx->bboxMin [1])); | |||||
826 | wrld[2] = AIR_AFFINE(0.0, unit[2], 1.0, pctx->bboxMin[2], pctx->bboxMax[2])( ((double)(pctx->bboxMax[2])-(pctx->bboxMin[2]))*((double )(unit[2])-(0.0)) / ((double)(1.0)-(0.0)) + (pctx->bboxMin [2])); | |||||
827 | if (pctx->haveScale) { | |||||
828 | double sridx; | |||||
829 | int outside; | |||||
830 | sridx = AIR_AFFINE(0.0, unit[3], 1.0, 0, scaleVol->scaleNum-1)( ((double)(scaleVol->scaleNum-1)-(0))*((double)(unit[3])- (0.0)) / ((double)(1.0)-(0.0)) + (0)); | |||||
831 | wrld[3] = gageStackItoW(scaleVol->gctx, sridx, &outside); | |||||
832 | if (pctx->flag.scaleIsTau) { | |||||
833 | wrld[3] = gageTauOfSig(wrld[3])airTauOfSigma(wrld[3]); | |||||
834 | } | |||||
835 | } else { | |||||
836 | wrld[3] = 0.0; | |||||
837 | } | |||||
838 | /* | |||||
839 | fprintf(stderr, "!%s: (%g,%g,%g,%g) -- [%g,%g]x[%g,%g]x[%g,%g]--> (%g,%g,%g,%g)\n", me, | |||||
840 | unit[0], unit[1], unit[2], unit[3], | |||||
841 | pctx->bboxMin[0], pctx->bboxMin[1], pctx->bboxMin[2], | |||||
842 | pctx->bboxMax[0], pctx->bboxMax[1], pctx->bboxMax[2], | |||||
843 | wrld[0], wrld[1], wrld[2], wrld[3]); | |||||
844 | */ | |||||
845 | return; | |||||
846 | } | |||||
847 | ||||||
848 | int | |||||
849 | pullPointInitializeRandomOrHalton(pullContext *pctx, | |||||
850 | const unsigned int pointIdx, | |||||
851 | pullPoint *point, pullVolume *scaleVol) { | |||||
852 | static const char me[]="pullPointInitializeRandomOrHalton"; | |||||
853 | int reject, verbo; | |||||
854 | airRandMTState *rng; | |||||
855 | unsigned int tryCount = 0, threshFailCount = 0, spthreshFailCount = 0, | |||||
856 | constrFailCount = 0; | |||||
857 | rng = pctx->task[0]->rng; | |||||
858 | ||||||
859 | do { | |||||
860 | double rpos[4]; | |||||
861 | /* fprintf(stderr, "!%s: starting doooo (tryCount %u)!\n", me, tryCount); */ | |||||
862 | tryCount++; | |||||
863 | reject = AIR_FALSE0; | |||||
864 | _pullPointHistInit(point); | |||||
865 | /* Populate tentative random point */ | |||||
866 | if (pullInitMethodHalton == pctx->initParm.method) { | |||||
867 | /* we generate all 4 coordinates, even if we don't need them all */ | |||||
868 | airHalton(rpos, (pointIdx + threshFailCount + constrFailCount | |||||
869 | + pctx->haltonOffset + pctx->initParm.haltonStartIndex), | |||||
870 | airPrimeList, 4); | |||||
871 | /* | |||||
872 | fprintf(stderr, "!%s(%u/%u): halton(%u=%u+%u+%u+%u+%u) => %g %g %g %g\n", | |||||
873 | me, pointIdx, pctx->idtagNext, | |||||
874 | (pointIdx + threshFailCount + constrFailCount + | |||||
875 | pctx->haltonOffset + pctx->initParm.haltonStartIndex), | |||||
876 | pointIdx, threshFailCount, constrFailCount, | |||||
877 | pctx->haltonOffset, pctx->initParm.haltonStartIndex, | |||||
878 | rpos[0], rpos[1], rpos[2], rpos[3]); | |||||
879 | */ | |||||
880 | /* | |||||
881 | fprintf(stderr, "%g %g %g %g ", | |||||
882 | rpos[0], rpos[1], rpos[2], rpos[3]); | |||||
883 | */ | |||||
884 | if (!pctx->haveScale) { | |||||
885 | rpos[3] = 0; | |||||
886 | } | |||||
887 | } else { | |||||
888 | ELL_3V_SET(rpos, airDrandMT_r(rng), airDrandMT_r(rng), airDrandMT_r(rng))((rpos)[0] = (airDrandMT_r(rng)), (rpos)[1] = (airDrandMT_r(rng )), (rpos)[2] = (airDrandMT_r(rng))); | |||||
889 | if (pctx->haveScale) { | |||||
890 | rpos[3] = airDrandMT_r(rng); | |||||
891 | } else { | |||||
892 | rpos[3] = 0; | |||||
893 | } | |||||
894 | } | |||||
895 | _pullUnitToWorld(pctx, scaleVol, point->pos, rpos); | |||||
896 | if (pctx->flag.zeroZ) { | |||||
897 | point->pos[2] = 0.0; | |||||
898 | } | |||||
899 | /* | |||||
900 | verbo = (AIR_ABS(-0.246015 - point->pos[0]) < 0.1 && | |||||
901 | AIR_ABS(-144.78 - point->pos[0]) < 0.1 && | |||||
902 | AIR_ABS(-85.3813 - point->pos[0]) < 0.1); | |||||
903 | */ | |||||
904 | verbo = AIR_FALSE0; | |||||
905 | if (verbo) { | |||||
906 | fprintf(stderr__stderrp, "%s: verbo on for point %u at %g %g %g %g\n", me, | |||||
907 | point->idtag, point->pos[0], point->pos[1], | |||||
908 | point->pos[2], point->pos[3]); | |||||
909 | } | |||||
910 | _pullPointHistAdd(point, pullCondOld, AIR_NAN); | |||||
911 | ||||||
912 | /* HEY copy and paste */ | |||||
913 | if (pctx->ispec[pullInfoSeedPreThresh]) { | |||||
914 | /* we first do a special-purpose probe just for SeedPreThresh */ | |||||
915 | pctx->task[0]->probeSeedPreThreshOnly = AIR_TRUE1; | |||||
916 | if (pullProbe(pctx->task[0], point)) { | |||||
917 | biffAddf(PULLpullBiffKey, "%s: pre-probing pointIdx %u of world", me, pointIdx); | |||||
918 | return 1; | |||||
919 | } | |||||
920 | pctx->task[0]->probeSeedPreThreshOnly = AIR_FALSE0; | |||||
921 | if (_threshFail(pctx, point, pullInfoSeedPreThresh)) { | |||||
922 | threshFailCount++; | |||||
923 | spthreshFailCount++; | |||||
924 | reject = AIR_TRUE1; | |||||
925 | goto reckoning; | |||||
926 | } | |||||
927 | } | |||||
928 | if (pullProbe(pctx->task[0], point)) { | |||||
929 | biffAddf(PULLpullBiffKey, "%s: probing pointIdx %u of world", me, pointIdx); | |||||
930 | return 1; | |||||
931 | } | |||||
932 | /* Check we pass pre-threshold */ | |||||
933 | #define THRESH_TEST(INFO)if (pctx->ispec[INFO] && _threshFail(pctx, point, INFO )) { threshFailCount++; reject = 1; goto reckoning; } \ | |||||
934 | if (pctx->ispec[INFO] && _threshFail(pctx, point, INFO)) { \ | |||||
935 | threshFailCount++; \ | |||||
936 | reject = AIR_TRUE1; \ | |||||
937 | goto reckoning; \ | |||||
938 | } | |||||
939 | /* fprintf(stderr, "!%s: bi ngo 0 (%d) %d %p\n", me, | |||||
940 | !pctx->flag.constraintBeforeSeedThresh, | |||||
941 | pctx->initParm.liveThreshUse, pctx->ispec[pullInfoLiveThresh]); */ | |||||
942 | if (!pctx->flag.constraintBeforeSeedThresh) { | |||||
943 | THRESH_TEST(pullInfoSeedThresh)if (pctx->ispec[pullInfoSeedThresh] && _threshFail (pctx, point, pullInfoSeedThresh)) { threshFailCount++; reject = 1; goto reckoning; }; | |||||
944 | if (pctx->initParm.liveThreshUse) { | |||||
945 | THRESH_TEST(pullInfoLiveThresh)if (pctx->ispec[pullInfoLiveThresh] && _threshFail (pctx, point, pullInfoLiveThresh)) { threshFailCount++; reject = 1; goto reckoning; }; | |||||
946 | THRESH_TEST(pullInfoLiveThresh2)if (pctx->ispec[pullInfoLiveThresh2] && _threshFail (pctx, point, pullInfoLiveThresh2)) { threshFailCount++; reject = 1; goto reckoning; }; | |||||
947 | THRESH_TEST(pullInfoLiveThresh3)if (pctx->ispec[pullInfoLiveThresh3] && _threshFail (pctx, point, pullInfoLiveThresh3)) { threshFailCount++; reject = 1; goto reckoning; }; | |||||
948 | } | |||||
949 | } | |||||
950 | /* fprintf(stderr, "!%s: bi ngo 1\n", me); */ | |||||
951 | ||||||
952 | if (pctx->constraint) { | |||||
953 | int constrFail; | |||||
954 | /* fprintf(stderr, "!%s: calling _pullConstraintSatisfy(%u)\n", me, pointIdx); */ | |||||
955 | if (_pullConstraintSatisfy(pctx->task[0], point, | |||||
956 | _PULL_CONSTRAINT_TRAVEL_MAX2, | |||||
957 | &constrFail)) { | |||||
958 | biffAddf(PULLpullBiffKey, "%s: trying constraint on point %u", me, pointIdx); | |||||
959 | return 1; | |||||
960 | } | |||||
961 | #if PULL_PHIST0 | |||||
962 | if (DEBUG1) { | |||||
963 | Nrrd *nhist; | |||||
964 | FILE *fhist; | |||||
965 | char fname[AIR_STRLEN_SMALL(128+1)]; | |||||
966 | nhist = nrrdNew(); | |||||
967 | if (pullPositionHistoryNrrdGet(nhist, pctx, point)) { | |||||
968 | biffAddf(PULLpullBiffKey, "%s: trouble", me); | |||||
969 | return 1; | |||||
970 | } | |||||
971 | sprintf(fname, "%04u-%04u-%04u-phist.nrrd", pctx->iter,__builtin___sprintf_chk (fname, 0, __builtin_object_size (fname , 2 > 1 ? 1 : 0), "%04u-%04u-%04u-phist.nrrd", pctx->iter , point->idtag, tryCount) | |||||
972 | point->idtag, tryCount)__builtin___sprintf_chk (fname, 0, __builtin_object_size (fname , 2 > 1 ? 1 : 0), "%04u-%04u-%04u-phist.nrrd", pctx->iter , point->idtag, tryCount); | |||||
973 | if ((fhist = fopen(fname, "w"))) { | |||||
974 | if (nrrdSave(fname, nhist, NULL((void*)0))) { | |||||
975 | biffMovef(PULLpullBiffKey, NRRDnrrdBiffKey, "%s: trouble", me); | |||||
976 | return 1; | |||||
977 | } | |||||
978 | fclose(fhist); | |||||
979 | } | |||||
980 | nrrdNuke(nhist); | |||||
981 | } | |||||
982 | #endif | |||||
983 | if (constrFail) { | |||||
984 | constrFailCount++; | |||||
985 | reject = AIR_TRUE1; | |||||
986 | goto reckoning; | |||||
987 | } | |||||
988 | /* fprintf(stderr, "!%s: bi ngo 2\n", me); */ | |||||
989 | /* post constraint-satisfaction, we certainly have to assert thresholds */ | |||||
990 | THRESH_TEST(pullInfoSeedThresh)if (pctx->ispec[pullInfoSeedThresh] && _threshFail (pctx, point, pullInfoSeedThresh)) { threshFailCount++; reject = 1; goto reckoning; }; | |||||
991 | if (pctx->initParm.liveThreshUse) { | |||||
992 | THRESH_TEST(pullInfoLiveThresh)if (pctx->ispec[pullInfoLiveThresh] && _threshFail (pctx, point, pullInfoLiveThresh)) { threshFailCount++; reject = 1; goto reckoning; }; | |||||
993 | THRESH_TEST(pullInfoLiveThresh2)if (pctx->ispec[pullInfoLiveThresh2] && _threshFail (pctx, point, pullInfoLiveThresh2)) { threshFailCount++; reject = 1; goto reckoning; }; | |||||
994 | THRESH_TEST(pullInfoLiveThresh3)if (pctx->ispec[pullInfoLiveThresh3] && _threshFail (pctx, point, pullInfoLiveThresh3)) { threshFailCount++; reject = 1; goto reckoning; }; | |||||
995 | } | |||||
996 | /* fprintf(stderr, "!%s: bi ngo 3 (reject=%d)\n", me, reject); */ | |||||
997 | } | |||||
998 | ||||||
999 | reckoning: | |||||
1000 | if (reject) { | |||||
1001 | if (threshFailCount + constrFailCount >= _PULL_RANDOM_SEED_TRY_MAX1000000) { | |||||
1002 | /* Very bad luck; we've too many times */ | |||||
1003 | biffAddf(PULLpullBiffKey, "%s: failed too often (%u times) placing point %u: " | |||||
1004 | "%u fails on thresh (%u on pre-thresh), %u on constr", | |||||
1005 | me, _PULL_RANDOM_SEED_TRY_MAX1000000, pointIdx, | |||||
1006 | threshFailCount, spthreshFailCount, constrFailCount); | |||||
1007 | return 1; | |||||
1008 | } | |||||
1009 | } | |||||
1010 | } while (reject); | |||||
1011 | ||||||
1012 | if (pullInitMethodHalton == pctx->initParm.method) { | |||||
1013 | pctx->haltonOffset += threshFailCount + constrFailCount; | |||||
1014 | } | |||||
1015 | ||||||
1016 | return 0; | |||||
1017 | } | |||||
1018 | ||||||
1019 | int | |||||
1020 | pullPointInitializeGivenPos(pullContext *pctx, | |||||
1021 | const double *posData, | |||||
1022 | const unsigned int pointIdx, | |||||
1023 | pullPoint *point, | |||||
1024 | /* output */ | |||||
1025 | int *createFailP) { | |||||
1026 | static const char me[]="pullPointInitializeGivenPos"; | |||||
1027 | int reject, rejectEdge; | |||||
1028 | ||||||
1029 | /* Copy nrrd point into pullPoint */ | |||||
1030 | ELL_4V_COPY(point->pos, posData + 4*pointIdx)((point->pos)[0] = (posData + 4*pointIdx)[0], (point->pos )[1] = (posData + 4*pointIdx)[1], (point->pos)[2] = (posData + 4*pointIdx)[2], (point->pos)[3] = (posData + 4*pointIdx )[3]); | |||||
| ||||||
1031 | if (pctx->flag.zeroZ) { | |||||
1032 | point->pos[2] = 0.0; | |||||
1033 | } | |||||
1034 | ||||||
1035 | /* | |||||
1036 | if (AIR_ABS(247.828 - point->pos[0]) < 0.1 && | |||||
1037 | AIR_ABS(66.8817 - point->pos[1]) < 0.1 && | |||||
1038 | AIR_ABS(67.0031 - point->pos[2]) < 0.1) { | |||||
1039 | fprintf(stderr, "%s: --------- point %u at %g %g %g %g\n", me, | |||||
1040 | point->idtag, | |||||
1041 | point->pos[0], point->pos[1], | |||||
1042 | point->pos[2], point->pos[3]); | |||||
1043 | } | |||||
1044 | */ | |||||
1045 | ||||||
1046 | /* we're dictating positions, but still have to do initial probe, | |||||
1047 | and possibly liveThresholding */ | |||||
1048 | if (pullProbe(pctx->task[0], point)) { | |||||
1049 | biffAddf(PULLpullBiffKey, "%s: probing pointIdx %u of npos", me, pointIdx); | |||||
1050 | return 1; | |||||
1051 | } | |||||
1052 | reject = AIR_FALSE0; | |||||
1053 | if (pctx->flag.nixAtVolumeEdgeSpace | |||||
1054 | && (point->status & PULL_STATUS_EDGE_BIT(1<< 4))) { | |||||
1055 | rejectEdge = AIR_TRUE1; | |||||
1056 | } else { | |||||
1057 | rejectEdge = AIR_FALSE0; | |||||
1058 | } | |||||
1059 | reject |= rejectEdge; | |||||
1060 | if (pctx->initParm.liveThreshUse) { | |||||
1061 | if (!reject) reject |= _threshFail(pctx, point, pullInfoLiveThresh); | |||||
1062 | if (!reject) reject |= _threshFail(pctx, point, pullInfoLiveThresh2); | |||||
1063 | if (!reject) reject |= _threshFail(pctx, point, pullInfoLiveThresh3); | |||||
1064 | } | |||||
1065 | /* | |||||
1066 | if (reject) { | |||||
1067 | fprintf(stderr, "!%s(%u): edge %d thresh %d %d %d\n", | |||||
1068 | me, point->idtag, rejectEdge, | |||||
1069 | _threshFail(pctx, point, pullInfoLiveThresh), | |||||
1070 | _threshFail(pctx, point, pullInfoLiveThresh2), | |||||
1071 | _threshFail(pctx, point, pullInfoLiveThresh3)); | |||||
1072 | } | |||||
1073 | */ | |||||
1074 | if (reject) { | |||||
1075 | *createFailP = AIR_TRUE1; | |||||
1076 | } else { | |||||
1077 | *createFailP = AIR_FALSE0; | |||||
1078 | } | |||||
1079 | ||||||
1080 | return 0; | |||||
1081 | } | |||||
1082 | ||||||
1083 | /* | |||||
1084 | ** _pullPointSetup sets: | |||||
1085 | ** | |||||
1086 | ** This is only called by the master thread | |||||
1087 | ** | |||||
1088 | ** this should set stuff to be like after an update stage and | |||||
1089 | ** just before the rebinning | |||||
1090 | */ | |||||
1091 | int | |||||
1092 | _pullPointSetup(pullContext *pctx) { | |||||
1093 | static const char me[]="_pullPointSetup"; | |||||
1094 | char doneStr[AIR_STRLEN_SMALL(128+1)]; | |||||
1095 | unsigned int pointIdx, binIdx, tick, pn; | |||||
1096 | pullPoint *point; | |||||
1097 | pullBin *bin; | |||||
1098 | int createFail,added; | |||||
1099 | airArray *mop; | |||||
1100 | Nrrd *npos; | |||||
1101 | pullVolume *seedVol, *scaleVol; | |||||
1102 | gageShape *seedShape; | |||||
1103 | double factor, *posData; | |||||
1104 | unsigned int totalNumPoints, voxNum, ii; | |||||
1105 | ||||||
1106 | /* on using pullBinsPointMaybeAdd: This is used only in the context | |||||
1107 | of constraints; it makes sense to be a little more selective | |||||
1108 | about adding points, so that they aren't completely piled on top | |||||
1109 | of each other. This relies on _PULL_BINNING_MAYBE_ADD_THRESH: its | |||||
1110 | tempting to set this value high, to more aggressively limit the | |||||
1111 | number of points added, but that's really the job of population | |||||
1112 | control, and we can't always guarantee that constraint manifolds | |||||
1113 | will be well-sampled (with respect to pctx->radiusSpace and | |||||
1114 | pctx->radiusScale) to start with */ | |||||
1115 | ||||||
1116 | if (pctx->verbose) { | |||||
| ||||||
1117 | printf("%s: beginning (%s). . . ", me, | |||||
1118 | airEnumStr(pullInitMethod, pctx->initParm.method)); | |||||
1119 | fflush(stdout__stdoutp); | |||||
1120 | } | |||||
1121 | mop = airMopNew(); | |||||
1122 | switch (pctx->initParm.method) { | |||||
1123 | case pullInitMethodGivenPos: | |||||
1124 | npos = nrrdNew(); | |||||
1125 | airMopAdd(mop, npos, (airMopper)nrrdNuke, airMopAlways); | |||||
1126 | /* even if npos came in as double, we have to copy it */ | |||||
1127 | if (nrrdConvert(npos, pctx->initParm.npos, nrrdTypeDouble)) { | |||||
1128 | biffMovef(PULLpullBiffKey, NRRDnrrdBiffKey, "%s: trouble converting npos", me); | |||||
1129 | airMopError(mop); return 1; | |||||
1130 | } | |||||
1131 | posData = AIR_CAST(double *, npos->data)((double *)(npos->data)); | |||||
1132 | if (pctx->initParm.numInitial || pctx->initParm.pointPerVoxel) { | |||||
1133 | printf("%s: with npos, overriding both numInitial (%u) " | |||||
1134 | "and pointPerVoxel (%d)\n", me, pctx->initParm.numInitial, | |||||
1135 | pctx->initParm.pointPerVoxel); | |||||
1136 | } | |||||
1137 | totalNumPoints = AIR_CAST(unsigned int, npos->axis[1].size)((unsigned int)(npos->axis[1].size)); | |||||
1138 | break; | |||||
1139 | case pullInitMethodPointPerVoxel: | |||||
1140 | npos = NULL((void*)0); | |||||
1141 | posData = NULL((void*)0); | |||||
1142 | if (pctx->initParm.numInitial && pctx->verbose) { | |||||
1143 | printf("%s: pointPerVoxel %d overrides numInitial (%u)\n", me, | |||||
1144 | pctx->initParm.pointPerVoxel, pctx->initParm.numInitial); | |||||
1145 | } | |||||
1146 | /* Obtain number of voxels */ | |||||
1147 | seedVol = pctx->vol[pctx->ispec[pullInfoSeedThresh]->volIdx]; | |||||
1148 | seedShape = seedVol->gctx->shape; | |||||
1149 | if (pctx->initParm.ppvZRange[0] <= pctx->initParm.ppvZRange[1]) { | |||||
1150 | unsigned int zrn; | |||||
1151 | if (!( pctx->initParm.ppvZRange[0] < seedShape->size[2] | |||||
1152 | && pctx->initParm.ppvZRange[1] < seedShape->size[2] )) { | |||||
1153 | biffAddf(PULLpullBiffKey, "%s: ppvZRange[%u,%u] outside volume [0,%u]", me, | |||||
1154 | pctx->initParm.ppvZRange[0], pctx->initParm.ppvZRange[1], | |||||
1155 | seedShape->size[2]-1); | |||||
1156 | airMopError(mop); return 1; | |||||
1157 | } | |||||
1158 | zrn = pctx->initParm.ppvZRange[1] - pctx->initParm.ppvZRange[0] + 1; | |||||
1159 | voxNum = seedShape->size[0]*seedShape->size[1]*zrn; | |||||
1160 | if (pctx->verbose) { | |||||
1161 | printf("%s: vol size %u %u [%u,%u] -> voxNum %u\n", me, | |||||
1162 | seedShape->size[0], seedShape->size[1], | |||||
1163 | pctx->initParm.ppvZRange[0], pctx->initParm.ppvZRange[1], | |||||
1164 | voxNum); | |||||
1165 | } | |||||
1166 | } else { | |||||
1167 | voxNum = seedShape->size[0]*seedShape->size[1]*seedShape->size[2]; | |||||
1168 | if (pctx->verbose) { | |||||
1169 | printf("%s: vol size %u %u %u -> voxNum %u\n", me, | |||||
1170 | seedShape->size[0], seedShape->size[1], seedShape->size[2], | |||||
1171 | voxNum); | |||||
1172 | } | |||||
1173 | } | |||||
1174 | ||||||
1175 | /* Compute total number of points */ | |||||
1176 | if (pctx->initParm.pointPerVoxel > 0) { | |||||
1177 | factor = pctx->initParm.pointPerVoxel; | |||||
1178 | } else { | |||||
1179 | factor = -1.0/pctx->initParm.pointPerVoxel; | |||||
1180 | } | |||||
1181 | if (pctx->haveScale) { | |||||
1182 | unsigned int sasn; | |||||
1183 | sasn = pctx->initParm.samplesAlongScaleNum; | |||||
1184 | totalNumPoints = AIR_CAST(unsigned int, voxNum * factor * sasn)((unsigned int)(voxNum * factor * sasn)); | |||||
1185 | } else { | |||||
1186 | totalNumPoints = AIR_CAST(unsigned int, voxNum * factor)((unsigned int)(voxNum * factor)); | |||||
1187 | } | |||||
1188 | break; | |||||
1189 | case pullInitMethodRandom: | |||||
1190 | case pullInitMethodHalton: | |||||
1191 | npos = NULL((void*)0); | |||||
1192 | posData = NULL((void*)0); | |||||
1193 | totalNumPoints = pctx->initParm.numInitial; | |||||
1194 | break; | |||||
1195 | default: | |||||
1196 | biffAddf(PULLpullBiffKey, "%s: pullInitMethod %d not handled!", me, | |||||
1197 | pctx->initParm.method); | |||||
1198 | airMopError(mop); return 1; | |||||
1199 | break; | |||||
1200 | } | |||||
1201 | if (pctx->verbose) { | |||||
1202 | printf("%s: initializing/seeding %u pts. . . ", me, totalNumPoints); | |||||
1203 | fflush(stdout__stdoutp); | |||||
1204 | } | |||||
1205 | ||||||
1206 | /* find first scale volume, if there is one; this is used by some | |||||
1207 | seeders to determine placement along the scale axis */ | |||||
1208 | scaleVol = NULL((void*)0); | |||||
1209 | for (ii=0; ii<pctx->volNum; ii++) { | |||||
1210 | if (pctx->vol[ii]->ninScale) { | |||||
1211 | scaleVol = pctx->vol[ii]; | |||||
1212 | break; | |||||
1213 | } | |||||
1214 | } | |||||
1215 | ||||||
1216 | /* Start adding points */ | |||||
1217 | tick = totalNumPoints/1000; | |||||
1218 | point = NULL((void*)0); | |||||
1219 | unsigned int initRorHack = 0; | |||||
1220 | /* This loop would normally be: | |||||
1221 | for (pointIdx = 0; pointIdx < totalNumPoints; pointIdx++) { | |||||
1222 | but because of pctx->flag.nixAtVolumeEdgeSpaceInitRorH we | |||||
1223 | need to be able to decrement pointIdx to force another redo, | |||||
1224 | even if pointIdx==0. So loop index is actually one greater | |||||
1225 | than the index value actually used */ | |||||
1226 | for (pointIdx = 1; pointIdx <= totalNumPoints; pointIdx++) { | |||||
1227 | int E; | |||||
1228 | if (pctx->verbose) { | |||||
1229 | if (tick < 100 || 0 == (pointIdx-1) % tick) { | |||||
1230 | printf("%s", airDoneStr(0, pointIdx-1, totalNumPoints, doneStr)); | |||||
1231 | fflush(stdout__stdoutp); | |||||
1232 | } | |||||
1233 | } | |||||
1234 | if (pctx->verbose > 5) { | |||||
1235 | printf("\n%s: setting up point = %u/%u\n", me, | |||||
1236 | pointIdx-1, totalNumPoints); | |||||
1237 | } | |||||
1238 | /* Create point */ | |||||
1239 | if (!point) { | |||||
1240 | point = pullPointNew(pctx); | |||||
1241 | } | |||||
1242 | /* Filling array according to initialization method */ | |||||
1243 | E = 0; | |||||
1244 | switch(pctx->initParm.method) { | |||||
1245 | case pullInitMethodRandom: | |||||
1246 | case pullInitMethodHalton: | |||||
1247 | /* point index passed here always increments, even if | |||||
1248 | we failed last time because of being at edge */ | |||||
1249 | E = pullPointInitializeRandomOrHalton(pctx, pointIdx-1 + initRorHack, | |||||
1250 | point, scaleVol); | |||||
1251 | if (pctx->flag.nixAtVolumeEdgeSpaceInitRorH) { | |||||
1252 | createFail = !!(point->status & PULL_STATUS_EDGE_BIT(1<< 4)); | |||||
1253 | if (createFail) { | |||||
1254 | initRorHack++; | |||||
1255 | if (initRorHack > 10*totalNumPoints) { | |||||
1256 | biffAddf(PULLpullBiffKey, "%s: (point %u) handling nixAtVolumeEdgeSpaceInitRorH, " | |||||
1257 | "have failed so often (%u > 10*#pnts = %u); something " | |||||
1258 | "must be wrong", me, point->idtag, initRorHack, | |||||
1259 | totalNumPoints); | |||||
1260 | airMopError(mop); return 1; | |||||
1261 | } | |||||
1262 | /* this is a for-loop, post-body increment will always happen; | |||||
1263 | we need to subvert it. */ | |||||
1264 | pointIdx--; | |||||
1265 | } | |||||
1266 | } else { | |||||
1267 | createFail = AIR_FALSE0; | |||||
1268 | } | |||||
1269 | break; | |||||
1270 | case pullInitMethodPointPerVoxel: | |||||
1271 | E = pullPointInitializePerVoxel(pctx, pointIdx-1, point, scaleVol, | |||||
1272 | &createFail); | |||||
1273 | break; | |||||
1274 | case pullInitMethodGivenPos: | |||||
1275 | E = pullPointInitializeGivenPos(pctx, posData, pointIdx-1, point, | |||||
1276 | &createFail); | |||||
1277 | break; | |||||
1278 | } | |||||
1279 | if (E) { | |||||
1280 | biffAddf(PULLpullBiffKey, "%s: trouble trying point %u (id %u)", me, | |||||
1281 | pointIdx-1, point->idtag); | |||||
1282 | airMopError(mop); return 1; | |||||
1283 | } | |||||
1284 | if (createFail) { | |||||
1285 | /* We were not successful in creating a point; not an error */ | |||||
1286 | continue; | |||||
1287 | } | |||||
1288 | ||||||
1289 | /* else, the point is ready for binning */ | |||||
1290 | if (pctx->constraint) { | |||||
1291 | if (pullBinsPointMaybeAdd(pctx, point, NULL((void*)0), &added)) { | |||||
1292 | biffAddf(PULLpullBiffKey, "%s: trouble binning point %u", me, point->idtag); | |||||
1293 | airMopError(mop); return 1; | |||||
1294 | } | |||||
1295 | /* | |||||
1296 | if (4523 == point->idtag) { | |||||
1297 | fprintf(stderr, "!%s(%u): ----- added=%d at %g %g %g %g\n", | |||||
1298 | me, point->idtag, added, | |||||
1299 | point->pos[0], point->pos[1], point->pos[2], point->pos[3]); | |||||
1300 | } | |||||
1301 | */ | |||||
1302 | if (added) { | |||||
1303 | point = NULL((void*)0); | |||||
1304 | } | |||||
1305 | } else { | |||||
1306 | if (pullBinsPointAdd(pctx, point, NULL((void*)0))) { | |||||
1307 | biffAddf(PULLpullBiffKey, "%s: trouble binning point %u", me, point->idtag); | |||||
1308 | airMopError(mop); return 1; | |||||
1309 | } | |||||
1310 | point = NULL((void*)0); | |||||
1311 | } | |||||
1312 | } /* Done looping through total number of points */ | |||||
1313 | if (pctx->verbose) { | |||||
1314 | printf("%s\n", airDoneStr(0, pointIdx-1, totalNumPoints, | |||||
1315 | doneStr)); | |||||
1316 | } | |||||
1317 | if (point) { | |||||
1318 | /* we created a new test point, but it was never placed in the volume */ | |||||
1319 | /* so, HACK: undo pullPointNew . . . */ | |||||
1320 | point = pullPointNix(point); | |||||
1321 | /* pctx->idtagNext -= 1; */ | |||||
1322 | } | |||||
1323 | ||||||
1324 | /* Final check: do we have any points? */ | |||||
1325 | pn = pullPointNumber(pctx); | |||||
1326 | if (!pn) { | |||||
1327 | char stmp1[AIR_STRLEN_MED(256+1)], stmp2[AIR_STRLEN_MED(256+1)]; | |||||
1328 | int guess=AIR_FALSE0; | |||||
1329 | sprintf(stmp1, "%s: seeded 0 points", me)__builtin___sprintf_chk (stmp1, 0, __builtin_object_size (stmp1 , 2 > 1 ? 1 : 0), "%s: seeded 0 points", me); | |||||
1330 | if (pctx->ispec[pullInfoSeedThresh]) { | |||||
1331 | guess=AIR_TRUE1; | |||||
1332 | sprintf(stmp2, " (? bad seedthresh %g ?)",__builtin___sprintf_chk (stmp2, 0, __builtin_object_size (stmp2 , 2 > 1 ? 1 : 0), " (? bad seedthresh %g ?)", pctx->ispec [pullInfoSeedThresh]->zero) | |||||
1333 | pctx->ispec[pullInfoSeedThresh]->zero)__builtin___sprintf_chk (stmp2, 0, __builtin_object_size (stmp2 , 2 > 1 ? 1 : 0), " (? bad seedthresh %g ?)", pctx->ispec [pullInfoSeedThresh]->zero); | |||||
1334 | strcat(stmp1, stmp2)__builtin___strcat_chk (stmp1, stmp2, __builtin_object_size ( stmp1, 2 > 1 ? 1 : 0)); | |||||
1335 | } | |||||
1336 | if (pctx->flag.nixAtVolumeEdgeSpace) { | |||||
1337 | guess=AIR_TRUE1; | |||||
1338 | sprintf(stmp2, " (? flag.nixAtVolumeEdgeSpace true ?)")__builtin___sprintf_chk (stmp2, 0, __builtin_object_size (stmp2 , 2 > 1 ? 1 : 0), " (? flag.nixAtVolumeEdgeSpace true ?)"); | |||||
1339 | strcat(stmp1, stmp2)__builtin___strcat_chk (stmp1, stmp2, __builtin_object_size ( stmp1, 2 > 1 ? 1 : 0)); | |||||
1340 | } | |||||
1341 | if (!guess) { | |||||
1342 | sprintf(stmp2, " (no guess as to why)")__builtin___sprintf_chk (stmp2, 0, __builtin_object_size (stmp2 , 2 > 1 ? 1 : 0), " (no guess as to why)"); | |||||
1343 | strcat(stmp1, stmp2)__builtin___strcat_chk (stmp1, stmp2, __builtin_object_size ( stmp1, 2 > 1 ? 1 : 0)); | |||||
1344 | } | |||||
1345 | biffAddf(PULLpullBiffKey, "%s", stmp1); | |||||
1346 | airMopError(mop); return 1; | |||||
1347 | } | |||||
1348 | if (pctx->verbose) { | |||||
1349 | fprintf(stderr__stderrp, "%s: initialized to %u points (idtagNext = %u)\n", | |||||
1350 | me, pn, pctx->idtagNext); | |||||
1351 | } | |||||
1352 | /* */ | |||||
1353 | if (1) { | |||||
1354 | Nrrd *ntmp; | |||||
1355 | ntmp = nrrdNew(); | |||||
1356 | pullOutputGet(ntmp, NULL((void*)0), NULL((void*)0), NULL((void*)0), 0.0, pctx); | |||||
1357 | nrrdSave("pos-init.nrrd", ntmp, NULL((void*)0)); | |||||
1358 | nrrdNuke(ntmp); | |||||
1359 | } | |||||
1360 | /* */ | |||||
1361 | pctx->tmpPointPtr = AIR_CAST(pullPoint **,((pullPoint **)(calloc(pn, sizeof(pullPoint*)))) | |||||
1362 | calloc(pn, sizeof(pullPoint*)))((pullPoint **)(calloc(pn, sizeof(pullPoint*)))); | |||||
1363 | pctx->tmpPointPerm = AIR_CAST(unsigned int *,((unsigned int *)(calloc(pn, sizeof(unsigned int)))) | |||||
1364 | calloc(pn, sizeof(unsigned int)))((unsigned int *)(calloc(pn, sizeof(unsigned int)))); | |||||
1365 | if (!( pctx->tmpPointPtr && pctx->tmpPointPerm )) { | |||||
1366 | biffAddf(PULLpullBiffKey, "%s: couldn't allocate tmp buffers %p %p", me, | |||||
1367 | AIR_VOIDP(pctx->tmpPointPtr)((void *)(pctx->tmpPointPtr)), AIR_VOIDP(pctx->tmpPointPerm)((void *)(pctx->tmpPointPerm))); | |||||
1368 | airMopError(mop); return 1; | |||||
1369 | } | |||||
1370 | pctx->tmpPointNum = pn; | |||||
1371 | ||||||
1372 | /* now that all points have been added, set their energy to help | |||||
1373 | inspect initial state */ | |||||
1374 | for (binIdx=0; binIdx<pctx->binNum; binIdx++) { | |||||
1375 | bin = pctx->bin + binIdx; | |||||
1376 | for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) { | |||||
1377 | point = bin->point[pointIdx]; | |||||
1378 | point->energy = _pullPointEnergyTotal(pctx->task[0], bin, point, | |||||
1379 | /* ignoreImage */ | |||||
1380 | !pctx->haveScale, | |||||
1381 | point->force); | |||||
1382 | } | |||||
1383 | } | |||||
1384 | ||||||
1385 | if (pctx->verbose) { | |||||
1386 | printf("%s: all done. ", me); | |||||
1387 | fflush(stdout__stdoutp); | |||||
1388 | } | |||||
1389 | airMopOkay(mop); | |||||
1390 | return 0; | |||||
1391 | } | |||||
1392 | ||||||
1393 | void | |||||
1394 | _pullPointFinish(pullContext *pctx) { | |||||
1395 | ||||||
1396 | airFree(pctx->tmpPointPtr); | |||||
1397 | airFree(pctx->tmpPointPerm); | |||||
1398 | return ; | |||||
1399 | } |