| File: | Testing/meet/probeSS.c |
| Location: | line 532, column 16 |
| Description: | Call to 'calloc' has an allocation size of 0 bytes |
| 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 "teem/meet.h" | |||||
| 25 | ||||||
| 26 | /* | |||||
| 27 | ** Tests: | |||||
| 28 | ** ... lots of gage stuff ... | |||||
| 29 | ** | |||||
| 30 | ** The main point of all this is to make sure of two (or maybe 2.5) separate | |||||
| 31 | ** things about gage, the testing of which requires so much in common that one | |||||
| 32 | ** program might as well do them all. The tasks are: | |||||
| 33 | ** | |||||
| 34 | ** 1) ensure that values and their derivatives (where the gageKind supports | |||||
| 35 | ** it) are correctly handled in the multi-value gageKinds (gageKindVec, | |||||
| 36 | ** tenGageKind, tenDwiGageKind), relative to the gageKindScl ground-truth: the | |||||
| 37 | ** per-component values and derivatives have to match those reconstructed from | |||||
| 38 | ** sets of scalar volumes of the components. | |||||
| 39 | ** ==> Also, that gageContextCopy works even on dynamic kinds (like DWIs) | |||||
| 40 | ** | |||||
| 41 | ** 1.5) that there is expected consistency between the scalar, vector, tensor, | |||||
| 42 | ** and DWI properties of a related set of volumes. So the test starts with a | |||||
| 43 | ** diffusion tensor field and generates DWIs, scalars (norm squared of the | |||||
| 44 | ** tensor), and vectors (gradient of norm squared) from this. | |||||
| 45 | ** | |||||
| 46 | ** 2) that scale-space reconstruction works: that sets of pre-blurred volumes | |||||
| 47 | ** can be generated and saved via the utilities in meet, that the smart | |||||
| 48 | ** hermite-spline based scale-space interpolation is working (for all kinds), | |||||
| 49 | ** and that gageContextCopy works on scale-space contexts | |||||
| 50 | */ | |||||
| 51 | ||||||
| 52 | #define BKEY"probeSS" "probeSS" | |||||
| 53 | #define KIND_NUM4 4 | |||||
| 54 | #define KI_SCL0 0 | |||||
| 55 | #define KI_VEC1 1 | |||||
| 56 | #define KI_TEN2 2 | |||||
| 57 | #define KI_DWI3 3 | |||||
| 58 | ||||||
| 59 | /* | |||||
| 60 | static const char *kindStr[KIND_NUM] = { | |||||
| 61 | "scalar", | |||||
| 62 | "vector", | |||||
| 63 | "tensor", | |||||
| 64 | " DWI " | |||||
| 65 | }; | |||||
| 66 | */ | |||||
| 67 | ||||||
| 68 | #define HALTON_BASE100 100 | |||||
| 69 | ||||||
| 70 | static unsigned int volSize[3] = {45, 46, 47}; | |||||
| 71 | ||||||
| 72 | #define NRRD_NEW(nn, mm) \ | |||||
| 73 | (nn) = nrrdNew(); \ | |||||
| 74 | airMopAdd((mm), (nn), (airMopper)nrrdNuke, airMopAlways) | |||||
| 75 | ||||||
| 76 | /* the weird function names of the various local functions here (created in a | |||||
| 77 | rather adhoc and organic way) should be read in usual Teem order: from | |||||
| 78 | right to left */ | |||||
| 79 | ||||||
| 80 | static int | |||||
| 81 | engageGenTensor(gageContext *gctx, Nrrd *ncten, | |||||
| 82 | /* out/in */ | |||||
| 83 | double noiseStdv, unsigned int seed, | |||||
| 84 | unsigned int sx, unsigned int sy, unsigned int sz) { | |||||
| 85 | static const char me[]="engageGenTensor"; | |||||
| 86 | hestParm *hparm; | |||||
| 87 | airArray *smop; | |||||
| 88 | char tmpStr[4][AIR_STRLEN_SMALL(128+1)]; | |||||
| 89 | Nrrd *nclean; | |||||
| 90 | NrrdIter *narg0, *narg1; | |||||
| 91 | const char *helixArgv[] = | |||||
| 92 | /* 0 1 2 3 4 5 6 7 8 9 */ | |||||
| 93 | {"-s", NULL((void*)0), NULL((void*)0), NULL((void*)0), "-v", "0", "-r", "40", "-o", NULL((void*)0), | |||||
| 94 | "-ev", "0.00086", "0.00043", "0.00021", "-bg", "0.003", "-b", "3", | |||||
| 95 | NULL((void*)0)}; | |||||
| 96 | int helixArgc; | |||||
| 97 | gagePerVolume *pvl; | |||||
| 98 | ||||||
| 99 | smop = airMopNew(); | |||||
| 100 | /* NOTE: this is currently the only place where a unrrduCmd | |||||
| 101 | is called from within C code; it was educational to get working. | |||||
| 102 | Learned: | |||||
| 103 | * hest does NOT tolerate having empty or NULL elements of | |||||
| 104 | its argv[]! More error checking for this in hest is needed. | |||||
| 105 | * the "const char **argv" type is not very convenient to | |||||
| 106 | set up in a dynamic way; the per-element setting done below | |||||
| 107 | is certainly awkward | |||||
| 108 | */ | |||||
| 109 | hparm = hestParmNew(); | |||||
| 110 | airMopAdd(smop, hparm, (airMopper)hestParmFree, airMopAlways); | |||||
| 111 | sprintf(tmpStr[0], "%u", sx)__builtin___sprintf_chk (tmpStr[0], 0, __builtin_object_size ( tmpStr[0], 2 > 1 ? 1 : 0), "%u", sx); helixArgv[1] = tmpStr[0]; | |||||
| 112 | sprintf(tmpStr[1], "%u", sy)__builtin___sprintf_chk (tmpStr[1], 0, __builtin_object_size ( tmpStr[1], 2 > 1 ? 1 : 0), "%u", sy); helixArgv[2] = tmpStr[1]; | |||||
| 113 | sprintf(tmpStr[2], "%u", sz)__builtin___sprintf_chk (tmpStr[2], 0, __builtin_object_size ( tmpStr[2], 2 > 1 ? 1 : 0), "%u", sz); helixArgv[3] = tmpStr[2]; | |||||
| 114 | sprintf(tmpStr[3], "tmp-ten.nrrd")__builtin___sprintf_chk (tmpStr[3], 0, __builtin_object_size ( tmpStr[3], 2 > 1 ? 1 : 0), "tmp-ten.nrrd"); | |||||
| 115 | helixArgv[9] = tmpStr[3]; | |||||
| 116 | helixArgc = AIR_CAST(int, sizeof(helixArgv)/sizeof(char *))((int)(sizeof(helixArgv)/sizeof(char *))) - 1; | |||||
| 117 | if (tend_helixCmd.main(helixArgc, helixArgv, me, hparm)) { | |||||
| 118 | /* error already went to stderr, not to any biff container */ | |||||
| 119 | biffAddf(BKEY"probeSS", "%s: problem running tend %s", me, tend_helixCmd.name); | |||||
| 120 | airMopError(smop); return 1; | |||||
| 121 | } | |||||
| 122 | NRRD_NEW(nclean, smop); | |||||
| 123 | if (nrrdLoad(nclean, tmpStr[3], NULL((void*)0))) { | |||||
| 124 | biffAddf(BKEY"probeSS", "%s: trouble loading from new vol %s", me, tmpStr[3]); | |||||
| 125 | airMopError(smop); return 1; | |||||
| 126 | } | |||||
| 127 | ||||||
| 128 | /* add some noise to tensor value; no, this isn't really physical; | |||||
| 129 | since we're adding noise to the tensor and then simulating DWIs, | |||||
| 130 | rather than adding noise to DWIs and then estimating tensor, | |||||
| 131 | but for the purposes of gage testing its fine */ | |||||
| 132 | narg0 = nrrdIterNew(); | |||||
| 133 | narg1 = nrrdIterNew(); | |||||
| 134 | airMopAdd(smop, narg0, (airMopper)nrrdIterNix, airMopAlways); | |||||
| 135 | airMopAdd(smop, narg1, (airMopper)nrrdIterNix, airMopAlways); | |||||
| 136 | nrrdIterSetNrrd(narg0, nclean); | |||||
| 137 | nrrdIterSetValue(narg1, noiseStdv); | |||||
| 138 | airSrandMT(seed); | |||||
| 139 | if (nrrdArithIterBinaryOp(ncten, nrrdBinaryOpNormalRandScaleAdd, | |||||
| 140 | narg0, narg1)) { | |||||
| 141 | biffMovef(BKEY"probeSS", NRRDnrrdBiffKey, "%s: trouble noisying output", me); | |||||
| 142 | airMopError(smop); return 1; | |||||
| 143 | } | |||||
| 144 | ||||||
| 145 | /* wrap in gage context */ | |||||
| 146 | if ( !(pvl = gagePerVolumeNew(gctx, ncten, tenGageKind)) | |||||
| 147 | || gagePerVolumeAttach(gctx, pvl) ) { | |||||
| 148 | biffMovef(BKEY"probeSS", GAGEgageBiffKey, "%s: trouble engaging tensor", me); | |||||
| 149 | return 1; | |||||
| 150 | } | |||||
| 151 | ||||||
| 152 | airMopOkay(smop); | |||||
| 153 | return 0; | |||||
| 154 | } | |||||
| 155 | ||||||
| 156 | /* | |||||
| 157 | ** takes in ncten, measures "S" to nscl, copies that to nsclCopy, | |||||
| 158 | ** wraps those in gctx and gctxComp | |||||
| 159 | */ | |||||
| 160 | static int | |||||
| 161 | engageGenScalar(gageContext *gctx, Nrrd *nscl, | |||||
| 162 | gageContext *gctxComp, Nrrd *nsclCopy, | |||||
| 163 | /* out/in */ | |||||
| 164 | const Nrrd *ncten) { | |||||
| 165 | static const char me[]="engageGenScalar"; | |||||
| 166 | gagePerVolume *pvl; | |||||
| 167 | ||||||
| 168 | if (tenAnisoVolume(nscl, ncten, tenAniso_S, 0)) { | |||||
| 169 | biffMovef(BKEY"probeSS", TENtenBiffKey, "%s: trouble creating scalar volume", me); | |||||
| 170 | return 1; | |||||
| 171 | } | |||||
| 172 | if (nrrdCopy(nsclCopy, nscl)) { | |||||
| 173 | biffMovef(BKEY"probeSS", NRRDnrrdBiffKey, "%s: trouble copying scalar volume", me); | |||||
| 174 | return 1; | |||||
| 175 | } | |||||
| 176 | ||||||
| 177 | /* wrap both in gage context */ | |||||
| 178 | if ( !(pvl = gagePerVolumeNew(gctx, nscl, gageKindScl)) | |||||
| 179 | || gagePerVolumeAttach(gctx, pvl) | |||||
| 180 | || !(pvl = gagePerVolumeNew(gctxComp, nsclCopy, gageKindScl)) | |||||
| 181 | || gagePerVolumeAttach(gctxComp, pvl)) { | |||||
| 182 | biffMovef(BKEY"probeSS", GAGEgageBiffKey, "%s: trouble engaging scalars", me); | |||||
| 183 | return 1; | |||||
| 184 | } | |||||
| 185 | ||||||
| 186 | return 0; | |||||
| 187 | } | |||||
| 188 | ||||||
| 189 | /* | |||||
| 190 | ** Makes a vector volume by measuring the gradient | |||||
| 191 | ** Being the gradient of the given scalar volume is just to make | |||||
| 192 | ** something vaguely interesting, and to test consistency with | |||||
| 193 | ** the the same gradient as measured in the tensor field. | |||||
| 194 | */ | |||||
| 195 | static int | |||||
| 196 | engageGenVector(gageContext *gctx, Nrrd *nvec, | |||||
| 197 | /* out/in */ | |||||
| 198 | const Nrrd *nscl) { | |||||
| 199 | static const char me[]="engageGenVector"; | |||||
| 200 | ptrdiff_t padMin[4] = {0, 0, 0, 0}, padMax[4]; | |||||
| 201 | Nrrd *ntmp; | |||||
| 202 | airArray *smop; | |||||
| 203 | float *vec, *scl; | |||||
| 204 | size_t sx, sy, sz, xi, yi, zi, Px, Mx, Py, My, Pz, Mz; | |||||
| 205 | double dnmX, dnmY, dnmZ; | |||||
| 206 | gagePerVolume *pvl; | |||||
| 207 | ||||||
| 208 | smop = airMopNew(); | |||||
| 209 | if (nrrdTypeFloat != nscl->type) { | |||||
| 210 | biffAddf(BKEY"probeSS", "%s: expected %s not %s type", me, | |||||
| 211 | airEnumStr(nrrdType, nrrdTypeFloat), | |||||
| 212 | airEnumStr(nrrdType, nscl->type)); | |||||
| 213 | airMopError(smop); return 1; | |||||
| 214 | } | |||||
| 215 | NRRD_NEW(ntmp, smop); | |||||
| 216 | sx = nscl->axis[0].size; | |||||
| 217 | sy = nscl->axis[1].size; | |||||
| 218 | sz = nscl->axis[2].size; | |||||
| 219 | ELL_4V_SET(padMax, 2,((padMax)[0] = (2), (padMax)[1] = (((ptrdiff_t)(sx-1))), (padMax )[2] = (((ptrdiff_t)(sy-1))), (padMax)[3] = (((ptrdiff_t)(sz- 1)))) | |||||
| 220 | AIR_CAST(ptrdiff_t, sx-1),((padMax)[0] = (2), (padMax)[1] = (((ptrdiff_t)(sx-1))), (padMax )[2] = (((ptrdiff_t)(sy-1))), (padMax)[3] = (((ptrdiff_t)(sz- 1)))) | |||||
| 221 | AIR_CAST(ptrdiff_t, sy-1),((padMax)[0] = (2), (padMax)[1] = (((ptrdiff_t)(sx-1))), (padMax )[2] = (((ptrdiff_t)(sy-1))), (padMax)[3] = (((ptrdiff_t)(sz- 1)))) | |||||
| 222 | AIR_CAST(ptrdiff_t, sz-1))((padMax)[0] = (2), (padMax)[1] = (((ptrdiff_t)(sx-1))), (padMax )[2] = (((ptrdiff_t)(sy-1))), (padMax)[3] = (((ptrdiff_t)(sz- 1)))); | |||||
| 223 | /* we do axinsert and pad in order to keep all the per-axis info */ | |||||
| 224 | if (nrrdAxesInsert(ntmp, nscl, 0) | |||||
| 225 | || nrrdPad_nva(nvec, ntmp, padMin, padMax, | |||||
| 226 | nrrdBoundaryPad, 0.0)) { | |||||
| 227 | biffMovef(BKEY"probeSS", NRRDnrrdBiffKey, "%s: trouble", me); | |||||
| 228 | airMopError(smop); return 1; | |||||
| 229 | } | |||||
| 230 | dnmX = 0.5/nrrdSpaceVecNorm(nscl->spaceDim, nscl->axis[0].spaceDirection); | |||||
| 231 | dnmY = 0.5/nrrdSpaceVecNorm(nscl->spaceDim, nscl->axis[1].spaceDirection); | |||||
| 232 | dnmZ = 0.5/nrrdSpaceVecNorm(nscl->spaceDim, nscl->axis[2].spaceDirection); | |||||
| 233 | vec = AIR_CAST(float *, nvec->data)((float *)(nvec->data)); | |||||
| 234 | scl = AIR_CAST(float *, nscl->data)((float *)(nscl->data)); | |||||
| 235 | #define INDEX(xj, yj, zj) (xj + sx*(yj + sy*zj)) | |||||
| 236 | for (zi=0; zi<sz; zi++) { | |||||
| 237 | Mz = (zi == 0 ? 0 : zi-1); | |||||
| 238 | Pz = AIR_MIN(zi+1, sz-1)((zi+1) < (sz-1) ? (zi+1) : (sz-1)); | |||||
| 239 | for (yi=0; yi<sy; yi++) { | |||||
| 240 | My = (yi == 0 ? 0 : yi-1); | |||||
| 241 | Py = AIR_MIN(yi+1, sy-1)((yi+1) < (sy-1) ? (yi+1) : (sy-1)); | |||||
| 242 | for (xi=0; xi<sx; xi++) { | |||||
| 243 | Mx = (xi == 0 ? 0 : xi-1); | |||||
| 244 | Px = AIR_MIN(xi+1, sx-1)((xi+1) < (sx-1) ? (xi+1) : (sx-1)); | |||||
| 245 | vec[0 + 3*INDEX(xi, yi, zi)] = | |||||
| 246 | AIR_CAST(float, (scl[INDEX(Px, yi, zi)] - scl[INDEX(Mx, yi, zi)])*dnmX)((float)((scl[INDEX(Px, yi, zi)] - scl[INDEX(Mx, yi, zi)])*dnmX )); | |||||
| 247 | vec[1 + 3*INDEX(xi, yi, zi)] = | |||||
| 248 | AIR_CAST(float, (scl[INDEX(xi, Py, zi)] - scl[INDEX(xi, My, zi)])*dnmY)((float)((scl[INDEX(xi, Py, zi)] - scl[INDEX(xi, My, zi)])*dnmY )); | |||||
| 249 | vec[2 + 3*INDEX(xi, yi, zi)] = | |||||
| 250 | AIR_CAST(float, (scl[INDEX(xi, yi, Pz)] - scl[INDEX(xi, yi, Mz)])*dnmZ)((float)((scl[INDEX(xi, yi, Pz)] - scl[INDEX(xi, yi, Mz)])*dnmZ )); | |||||
| 251 | } | |||||
| 252 | } | |||||
| 253 | } | |||||
| 254 | #undef INDEX | |||||
| 255 | ||||||
| 256 | /* wrap in gage context */ | |||||
| 257 | if ( !(pvl = gagePerVolumeNew(gctx, nvec, gageKindVec)) | |||||
| 258 | || gagePerVolumeAttach(gctx, pvl) ) { | |||||
| 259 | biffMovef(BKEY"probeSS", GAGEgageBiffKey, "%s: trouble engaging vectors", me); | |||||
| 260 | return 1; | |||||
| 261 | } | |||||
| 262 | airMopError(smop); | |||||
| 263 | return 0; | |||||
| 264 | } | |||||
| 265 | ||||||
| 266 | /* | |||||
| 267 | ** make a DWI volume by simulating DWIs from given tensor | |||||
| 268 | ** this includes generating a new gradient set | |||||
| 269 | */ | |||||
| 270 | static int | |||||
| 271 | genDwi(Nrrd *ndwi, Nrrd *ngrad, | |||||
| 272 | /* out/in */ | |||||
| 273 | unsigned int gradNum, double bval, const Nrrd *ncten) { | |||||
| 274 | static const char me[]="genDwi"; | |||||
| 275 | tenGradientParm *gparm; | |||||
| 276 | tenExperSpec *espec; | |||||
| 277 | Nrrd *nten, *nb0; | |||||
| 278 | NrrdIter *narg0, *narg1; | |||||
| 279 | size_t cropMin[4] = {1, 0, 0, 0}, cropMax[4]; | |||||
| 280 | airArray *smop; | |||||
| 281 | ||||||
| 282 | smop = airMopNew(); | |||||
| 283 | gparm = tenGradientParmNew(); | |||||
| 284 | airMopAdd(smop, gparm, (airMopper)tenGradientParmNix, airMopAlways); | |||||
| 285 | espec = tenExperSpecNew(); | |||||
| 286 | airMopAdd(smop, espec, (airMopper)tenExperSpecNix, airMopAlways); | |||||
| 287 | gparm->verbose = 0; | |||||
| 288 | gparm->minMean = 0.002; | |||||
| 289 | gparm->seed = 4242; | |||||
| 290 | gparm->insertZeroVec = AIR_TRUE1; | |||||
| 291 | if (tenGradientGenerate(ngrad, gradNum, gparm) | |||||
| 292 | || tenExperSpecGradSingleBValSet(espec, AIR_FALSE0 /* insertB0 */, | |||||
| 293 | bval, | |||||
| 294 | AIR_CAST(double *, ngrad->data)((double *)(ngrad->data)), | |||||
| 295 | AIR_CAST(unsigned int,((unsigned int)(ngrad->axis[1].size)) | |||||
| 296 | ngrad->axis[1].size)((unsigned int)(ngrad->axis[1].size)))) { | |||||
| 297 | biffMovef(BKEY"probeSS", TENtenBiffKey, "%s: trouble generating grads or espec", me); | |||||
| 298 | airMopError(smop); return 1; | |||||
| 299 | } | |||||
| 300 | NRRD_NEW(nten, smop); | |||||
| 301 | NRRD_NEW(nb0, smop); | |||||
| 302 | ELL_4V_SET(cropMax,((cropMax)[0] = (ncten->axis[0].size-1), (cropMax)[1] = (ncten ->axis[1].size-1), (cropMax)[2] = (ncten->axis[2].size- 1), (cropMax)[3] = (ncten->axis[3].size-1)) | |||||
| 303 | ncten->axis[0].size-1,((cropMax)[0] = (ncten->axis[0].size-1), (cropMax)[1] = (ncten ->axis[1].size-1), (cropMax)[2] = (ncten->axis[2].size- 1), (cropMax)[3] = (ncten->axis[3].size-1)) | |||||
| 304 | ncten->axis[1].size-1,((cropMax)[0] = (ncten->axis[0].size-1), (cropMax)[1] = (ncten ->axis[1].size-1), (cropMax)[2] = (ncten->axis[2].size- 1), (cropMax)[3] = (ncten->axis[3].size-1)) | |||||
| 305 | ncten->axis[2].size-1,((cropMax)[0] = (ncten->axis[0].size-1), (cropMax)[1] = (ncten ->axis[1].size-1), (cropMax)[2] = (ncten->axis[2].size- 1), (cropMax)[3] = (ncten->axis[3].size-1)) | |||||
| 306 | ncten->axis[3].size-1)((cropMax)[0] = (ncten->axis[0].size-1), (cropMax)[1] = (ncten ->axis[1].size-1), (cropMax)[2] = (ncten->axis[2].size- 1), (cropMax)[3] = (ncten->axis[3].size-1)); | |||||
| 307 | if (nrrdSlice(nb0, ncten, 0, 0) | |||||
| 308 | || nrrdCrop(nten, ncten, cropMin, cropMax)) { | |||||
| 309 | biffMovef(BKEY"probeSS", NRRDnrrdBiffKey, "%s: trouble slicing or cropping ten vol", me); | |||||
| 310 | airMopError(smop); return 1; | |||||
| 311 | } | |||||
| 312 | narg0 = nrrdIterNew(); | |||||
| 313 | narg1 = nrrdIterNew(); | |||||
| 314 | airMopAdd(smop, narg0, (airMopper)nrrdIterNix, airMopAlways); | |||||
| 315 | airMopAdd(smop, narg1, (airMopper)nrrdIterNix, airMopAlways); | |||||
| 316 | nrrdIterSetValue(narg1, 50000.0); | |||||
| 317 | nrrdIterSetNrrd(narg0, nb0); | |||||
| 318 | if (nrrdArithIterBinaryOp(nb0, nrrdBinaryOpMultiply, | |||||
| 319 | narg0, narg1)) { | |||||
| 320 | biffMovef(BKEY"probeSS", NRRDnrrdBiffKey, "%s: trouble generating b0 vol", me); | |||||
| 321 | airMopError(smop); return 1; | |||||
| 322 | } | |||||
| 323 | if (tenModelSimulate(ndwi, nrrdTypeUShort, espec, | |||||
| 324 | tenModel1Tensor2, | |||||
| 325 | nb0, nten, AIR_TRUE1 /* keyValueSet */)) { | |||||
| 326 | biffMovef(BKEY"probeSS", TENtenBiffKey, "%s: trouble simulating DWI vol", me); | |||||
| 327 | airMopError(smop); return 1; | |||||
| 328 | } | |||||
| 329 | ||||||
| 330 | airMopOkay(smop); | |||||
| 331 | return 0; | |||||
| 332 | } | |||||
| 333 | ||||||
| 334 | int | |||||
| 335 | engageMopDiceVector(gageContext *gctx, Nrrd *nvecComp[3], | |||||
| 336 | /* out/in */ | |||||
| 337 | airArray *mop, const Nrrd* nvec) { | |||||
| 338 | static const char me[]="engageMopDiceVector"; | |||||
| 339 | gagePerVolume *pvl; | |||||
| 340 | unsigned int ci; | |||||
| 341 | char stmp[AIR_STRLEN_SMALL(128+1)]; | |||||
| 342 | ||||||
| 343 | if (!( 4 == nvec->dim && 3 == nvec->axis[0].size )) { | |||||
| 344 | biffAddf(BKEY"probeSS", "%s: expected 4-D 3-by-X nrrd (not %u-D %s-by-X)", | |||||
| 345 | me, nvec->dim, airSprintSize_t(stmp, nvec->axis[0].size)); | |||||
| 346 | return 1; | |||||
| 347 | } | |||||
| 348 | for (ci=0; ci<3; ci++) { | |||||
| 349 | NRRD_NEW(nvecComp[ci], mop); | |||||
| 350 | if (nrrdSlice(nvecComp[ci], nvec, 0, ci)) { | |||||
| 351 | biffMovef(BKEY"probeSS", NRRDnrrdBiffKey, "%s: trouble getting component %u", me, ci); | |||||
| 352 | return 1; | |||||
| 353 | } | |||||
| 354 | if ( !(pvl = gagePerVolumeNew(gctx, nvecComp[ci], gageKindScl)) | |||||
| 355 | || gagePerVolumeAttach(gctx, pvl) ) { | |||||
| 356 | biffMovef(BKEY"probeSS", GAGEgageBiffKey, "%s: trouble engaging component %u", me, ci); | |||||
| 357 | return 1; | |||||
| 358 | } | |||||
| 359 | } | |||||
| 360 | ||||||
| 361 | return 0; | |||||
| 362 | } | |||||
| 363 | ||||||
| 364 | int | |||||
| 365 | engageMopDiceTensor(gageContext *gctx, Nrrd *nctenComp[7], | |||||
| 366 | /* out/in */ | |||||
| 367 | airArray *mop, const Nrrd* ncten) { | |||||
| 368 | static const char me[]="engageMopDiceTensor"; | |||||
| 369 | gagePerVolume *pvl; | |||||
| 370 | unsigned int ci; | |||||
| 371 | ||||||
| 372 | if (tenTensorCheck(ncten, nrrdTypeFloat, AIR_TRUE1 /* want4F */, | |||||
| 373 | AIR_TRUE1 /* useBiff */)) { | |||||
| 374 | biffMovef(BKEY"probeSS", TENtenBiffKey, "%s: didn't get tensor volume", me); | |||||
| 375 | return 1; | |||||
| 376 | } | |||||
| 377 | for (ci=0; ci<7; ci++) { | |||||
| 378 | NRRD_NEW(nctenComp[ci], mop); | |||||
| 379 | if (nrrdSlice(nctenComp[ci], ncten, 0, ci)) { | |||||
| 380 | biffMovef(BKEY"probeSS", NRRDnrrdBiffKey, "%s: trouble getting component %u", me, ci); | |||||
| 381 | return 1; | |||||
| 382 | } | |||||
| 383 | if ( !(pvl = gagePerVolumeNew(gctx, nctenComp[ci], gageKindScl)) | |||||
| 384 | || gagePerVolumeAttach(gctx, pvl) ) { | |||||
| 385 | biffMovef(BKEY"probeSS", GAGEgageBiffKey, "%s: trouble engaging component %u", me, ci); | |||||
| 386 | return 1; | |||||
| 387 | } | |||||
| 388 | } | |||||
| 389 | ||||||
| 390 | return 0; | |||||
| 391 | } | |||||
| 392 | ||||||
| 393 | int | |||||
| 394 | engageMopDiceDwi(gageContext *gctx, Nrrd ***ndwiCompP, | |||||
| 395 | /* out/in */ | |||||
| 396 | airArray *mop, const Nrrd* ndwi) { | |||||
| 397 | static const char me[]="mopDiceDwi"; | |||||
| 398 | Nrrd **ndwiComp; | |||||
| 399 | size_t dwiNum; | |||||
| 400 | char stmp[AIR_STRLEN_SMALL(128+1)]; | |||||
| 401 | gagePerVolume *pvl; | |||||
| 402 | unsigned int ci; | |||||
| 403 | ||||||
| 404 | if (!( 4 == ndwi->dim )) { | |||||
| 405 | biffAddf(BKEY"probeSS", "%s: wanted 4D volume (not %u)", me, ndwi->dim); | |||||
| 406 | return 1; | |||||
| 407 | } | |||||
| 408 | if (!( nrrdKindList == ndwi->axis[0].kind && | |||||
| 409 | nrrdKindSpace == ndwi->axis[1].kind && | |||||
| 410 | nrrdKindSpace == ndwi->axis[2].kind && | |||||
| 411 | nrrdKindSpace == ndwi->axis[3].kind )) { | |||||
| 412 | biffAddf(BKEY"probeSS", "%s: wanted kinds %s,3x%s, not %s,%s,%s,%s", me, | |||||
| 413 | airEnumStr(nrrdKind, nrrdKindList), | |||||
| 414 | airEnumStr(nrrdKind, nrrdKindSpace), | |||||
| 415 | airEnumStr(nrrdKind, ndwi->axis[0].kind), | |||||
| 416 | airEnumStr(nrrdKind, ndwi->axis[1].kind), | |||||
| 417 | airEnumStr(nrrdKind, ndwi->axis[2].kind), | |||||
| 418 | airEnumStr(nrrdKind, ndwi->axis[3].kind)); | |||||
| 419 | return 1; | |||||
| 420 | } | |||||
| 421 | dwiNum = ndwi->axis[0].size; | |||||
| 422 | if (!(ndwiComp = AIR_CALLOC(dwiNum, Nrrd *)(Nrrd **)(calloc((dwiNum), sizeof(Nrrd *))))) { | |||||
| 423 | biffAddf(BKEY"probeSS", "%s: couldn't alloc %s Nrrd*", me, | |||||
| 424 | airSprintSize_t(stmp, dwiNum)); | |||||
| 425 | return 1; | |||||
| 426 | } | |||||
| 427 | airMopAdd(mop, ndwiComp, airFree, airMopAlways); | |||||
| 428 | *ndwiCompP = ndwiComp; | |||||
| 429 | for (ci=0; ci<dwiNum; ci++) { | |||||
| 430 | NRRD_NEW(ndwiComp[ci], mop); | |||||
| 431 | if (nrrdSlice(ndwiComp[ci], ndwi, 0, ci)) { | |||||
| 432 | biffMovef(BKEY"probeSS", NRRDnrrdBiffKey, "%s: trouble getting component %u", me, ci); | |||||
| 433 | return 1; | |||||
| 434 | } | |||||
| 435 | if ( !(pvl = gagePerVolumeNew(gctx, ndwiComp[ci], gageKindScl)) | |||||
| 436 | || gagePerVolumeAttach(gctx, pvl) ) { | |||||
| 437 | biffMovef(BKEY"probeSS", GAGEgageBiffKey, "%s: trouble engaging component %u", me, ci); | |||||
| 438 | return 1; | |||||
| 439 | } | |||||
| 440 | } | |||||
| 441 | return 0; | |||||
| 442 | } | |||||
| 443 | ||||||
| 444 | typedef struct { | |||||
| 445 | char name[AIR_STRLEN_SMALL(128+1)]; | |||||
| 446 | const double **aptr; /* array of pointers to (const) answers */ | |||||
| 447 | gageItemSpec *ispec; /* array of gageItemSpecs (not pointers to them) */ | |||||
| 448 | unsigned int *alen; /* array of answer lengths */ | |||||
| 449 | unsigned int *sidx; /* array of index (within san) of copied answer */ | |||||
| 450 | unsigned int anum; /* lenth of aptr, ispec, alen, sidx arrays */ | |||||
| 451 | double *san; /* single buffer for copy + concating answers */ | |||||
| 452 | unsigned int slen; /* length of single buffer (sum of all alen[i]) */ | |||||
| 453 | } multiAnswer; | |||||
| 454 | ||||||
| 455 | static void | |||||
| 456 | multiAnswerInit(multiAnswer *man) { | |||||
| 457 | ||||||
| 458 | /* HEY sloppy: not resetting name */ | |||||
| 459 | man->aptr = airFree(AIR_VOIDP(man->aptr)((void *)(man->aptr))); | |||||
| 460 | man->ispec = airFree(man->ispec); | |||||
| 461 | man->alen = airFree(man->alen); | |||||
| 462 | man->sidx = airFree(man->sidx); | |||||
| 463 | man->anum = 0; | |||||
| 464 | man->san = airFree(man->san); | |||||
| 465 | man->slen = 0; | |||||
| 466 | } | |||||
| 467 | ||||||
| 468 | static multiAnswer* | |||||
| 469 | multiAnswerNew(char *name) { | |||||
| 470 | multiAnswer *man; | |||||
| 471 | ||||||
| 472 | man = AIR_CALLOC(1, multiAnswer)(multiAnswer*)(calloc((1), sizeof(multiAnswer))); | |||||
| 473 | airStrcpy(man->name, AIR_STRLEN_SMALL(128+1), name); | |||||
| 474 | multiAnswerInit(man); | |||||
| 475 | return man; | |||||
| 476 | } | |||||
| 477 | ||||||
| 478 | void | |||||
| 479 | multiAnswerLenSet(multiAnswer *man, unsigned int anum) { | |||||
| 480 | /* | |||||
| 481 | static const char me[]="multiAnswerLenSet"; | |||||
| 482 | ||||||
| 483 | fprintf(stderr, "!%s: %s hello -> answer number = %u\n", me, | |||||
| 484 | man->name, anum); | |||||
| 485 | */ | |||||
| 486 | man->aptr = AIR_CALLOC(anum, const double *)(const double **)(calloc((anum), sizeof(const double *))); | |||||
| 487 | man->ispec = AIR_CALLOC(anum, gageItemSpec)(gageItemSpec*)(calloc((anum), sizeof(gageItemSpec))); | |||||
| 488 | man->alen = AIR_CALLOC(anum, unsigned int)(unsigned int*)(calloc((anum), sizeof(unsigned int))); | |||||
| 489 | man->sidx = AIR_CALLOC(anum, unsigned int)(unsigned int*)(calloc((anum), sizeof(unsigned int))); | |||||
| 490 | man->anum = anum; | |||||
| 491 | /* don't know answer lengths yet */ | |||||
| 492 | man->san = airFree(man->san); | |||||
| 493 | man->slen = 0; | |||||
| 494 | return; | |||||
| 495 | } | |||||
| 496 | ||||||
| 497 | static multiAnswer* | |||||
| 498 | multiAnswerNix(multiAnswer *man) { | |||||
| 499 | ||||||
| 500 | airFree(AIR_VOIDP(man->aptr)((void *)(man->aptr))); | |||||
| 501 | airFree(man->ispec); | |||||
| 502 | airFree(man->alen); | |||||
| 503 | airFree(man->sidx); | |||||
| 504 | airFree(man->san); | |||||
| 505 | airFree(man); | |||||
| 506 | return NULL((void*)0); | |||||
| 507 | } | |||||
| 508 | ||||||
| 509 | static void | |||||
| 510 | multiAnswerAdd(multiAnswer *man, unsigned int ansIdx, | |||||
| 511 | const gageContext *gctx, const gagePerVolume *pvl, | |||||
| 512 | unsigned int item) { | |||||
| 513 | /* | |||||
| 514 | static const char me[]="multiAnswerAdd"; | |||||
| 515 | ||||||
| 516 | fprintf(stderr, "!%s: %s hello (aidx = %u)\n", me, man->name, ansIdx); | |||||
| 517 | */ | |||||
| 518 | man->aptr[ansIdx] = gageAnswerPointer(gctx, pvl, item); | |||||
| 519 | man->ispec[ansIdx].kind = pvl->kind; | |||||
| 520 | man->ispec[ansIdx].item = item; | |||||
| 521 | man->alen[ansIdx] = gageAnswerLength(gctx, pvl, item); | |||||
| 522 | /* HEY hack: doing this tally and allocation only on the last time | |||||
| 523 | we're called, presuming calls with increasing ansIdx */ | |||||
| 524 | man->slen = 0; | |||||
| ||||||
| 525 | if (ansIdx == man->anum-1) { | |||||
| 526 | unsigned int ai; | |||||
| 527 | /* fprintf(stderr, "!%s: %s hello aidx reached anum-1 = %u\n", me, man->name, man->anum-1); */ | |||||
| 528 | for (ai=0; ai<man->anum; ai++) { | |||||
| 529 | man->sidx[ai] = man->slen; | |||||
| 530 | man->slen += man->alen[ai]; | |||||
| 531 | } | |||||
| 532 | man->san = AIR_CALLOC(man->slen, double)(double*)(calloc((man->slen), sizeof(double))); | |||||
| ||||||
| 533 | /* | |||||
| 534 | fprintf(stderr, "!%s: (%s) slen = %u\n", "multiAnswerAdd", | |||||
| 535 | pvl->kind->name, man->slen); | |||||
| 536 | */ | |||||
| 537 | } | |||||
| 538 | return; | |||||
| 539 | } | |||||
| 540 | ||||||
| 541 | static void | |||||
| 542 | multiAnswerCollect(multiAnswer *man) { | |||||
| 543 | unsigned int ai; | |||||
| 544 | /* | |||||
| 545 | static const char me[]="multiAnswerCollect"; | |||||
| 546 | ||||||
| 547 | fprintf(stderr, "%s: %s hi\n", me, man->name); | |||||
| 548 | */ | |||||
| 549 | for (ai=0; ai<man->anum; ai++) { | |||||
| 550 | /* | |||||
| 551 | fprintf(stderr, "!%s: (%s/%s) ai=%u/%u to %p+%u=%p for %u doubles\n", "multiAnswerCollect", | |||||
| 552 | man->ispec[ai].kind->name, | |||||
| 553 | airEnumStr(man->ispec[ai].kind->enm, man->ispec[ai].item), | |||||
| 554 | ai, man->anum, man->san, man->sidx[ai], man->san + man->sidx[ai], | |||||
| 555 | man->alen[ai]); | |||||
| 556 | */ | |||||
| 557 | memcpy(man->san + man->sidx[ai],__builtin___memcpy_chk (man->san + man->sidx[ai], man-> aptr[ai], man->alen[ai]*sizeof(double), __builtin_object_size (man->san + man->sidx[ai], 0)) | |||||
| 558 | man->aptr[ai],__builtin___memcpy_chk (man->san + man->sidx[ai], man-> aptr[ai], man->alen[ai]*sizeof(double), __builtin_object_size (man->san + man->sidx[ai], 0)) | |||||
| 559 | man->alen[ai]*sizeof(double))__builtin___memcpy_chk (man->san + man->sidx[ai], man-> aptr[ai], man->alen[ai]*sizeof(double), __builtin_object_size (man->san + man->sidx[ai], 0)); | |||||
| 560 | } | |||||
| 561 | return; | |||||
| 562 | } | |||||
| 563 | ||||||
| 564 | static int | |||||
| 565 | multiAnswerCompare(multiAnswer *man1, multiAnswer *man2) { | |||||
| 566 | static const char me[]="multiAnswerCompare"; | |||||
| 567 | unsigned int si, slen; | |||||
| 568 | ||||||
| 569 | ||||||
| 570 | #if 1 | |||||
| 571 | if (man1->slen != man2->slen) { | |||||
| 572 | biffAddf(BKEY"probeSS", "%s: man1->slen %u != man2->slen %u\n", me, | |||||
| 573 | man1->slen, man2->slen); | |||||
| 574 | return 1; | |||||
| 575 | } | |||||
| 576 | slen = man1->slen; | |||||
| 577 | #else | |||||
| 578 | slen = AIR_MIN(man1->slen, man2->slen)((man1->slen) < (man2->slen) ? (man1->slen) : (man2 ->slen)); | |||||
| 579 | #endif | |||||
| 580 | for (si=0; si<slen; si++) { | |||||
| 581 | if (man1->san[si] != man2->san[si]) { | |||||
| 582 | /* HEY should track down which part of which answer, | |||||
| 583 | in man1 and man2, is different, which was the | |||||
| 584 | purpose of recording ispec and sidx */ | |||||
| 585 | biffAddf(BKEY"probeSS", "%s: man1->san[si] %.17g != man2->san[si] %.17g", me, | |||||
| 586 | man1->san[si], man2->san[si]); | |||||
| 587 | return 1; | |||||
| 588 | } | |||||
| 589 | } | |||||
| 590 | return 0; | |||||
| 591 | } | |||||
| 592 | ||||||
| 593 | /* | |||||
| 594 | ** setting up gageContexts for the first of the two tasks listed above: making | |||||
| 595 | ** sure per-component information is handled correctly. NOTE: The combination | |||||
| 596 | ** of function calls made here is very atypical for a Teem-using program | |||||
| 597 | */ | |||||
| 598 | static int | |||||
| 599 | updateQueryKernelSetTask1(gageContext *gctxComp[KIND_NUM4], | |||||
| 600 | gageContext *gctx[KIND_NUM4], int gSetup, | |||||
| 601 | multiAnswer *manComp[KIND_NUM4], | |||||
| 602 | multiAnswer *man[KIND_NUM4], | |||||
| 603 | NrrdKernel *kpack[3], | |||||
| 604 | double support) { | |||||
| 605 | static const char me[]="updateQueryKernelSetTask1"; | |||||
| 606 | double parm1[NRRD_KERNEL_PARMS_NUM8], parmV[NRRD_KERNEL_PARMS_NUM8]; | |||||
| 607 | unsigned int kindIdx; | |||||
| 608 | ||||||
| 609 | if (4 != KIND_NUM4) { | |||||
| 610 | biffAddf(BKEY"probeSS", "%s: sorry, confused: KIND_NUM %u != 4", | |||||
| 611 | me, KIND_NUM4); | |||||
| 612 | return 1; | |||||
| 613 | } | |||||
| 614 | parm1[0] = 1.0; | |||||
| 615 | parmV[0] = support; | |||||
| 616 | if (gSetup) { | |||||
| 617 | for (kindIdx=0; kindIdx<KIND_NUM4; kindIdx++) { | |||||
| 618 | if (0 /* (no-op for formatting) */ | |||||
| 619 | || gageKernelSet(gctxComp[kindIdx], gageKernel00, kpack[0], parm1) | |||||
| 620 | || gageKernelSet(gctxComp[kindIdx], gageKernel11, kpack[1], parm1) | |||||
| 621 | || gageKernelSet(gctxComp[kindIdx], gageKernel22, kpack[2], parm1) | |||||
| 622 | || gageKernelSet(gctx[kindIdx], gageKernel00, kpack[0], parmV) | |||||
| 623 | || gageKernelSet(gctx[kindIdx], gageKernel11, kpack[1], parmV) | |||||
| 624 | || gageKernelSet(gctx[kindIdx], gageKernel22, kpack[2], parmV)) { | |||||
| 625 | biffMovef(BKEY"probeSS", GAGEgageBiffKey, "%s: trouble setting kernel (kind %u)", | |||||
| 626 | me, kindIdx); | |||||
| 627 | return 1; | |||||
| 628 | } | |||||
| 629 | } | |||||
| 630 | /* Note that the contexts for the diced-up volumes of components are always | |||||
| 631 | of kind gageKindScl, and all the items are from the gageScl* enum */ | |||||
| 632 | for (kindIdx=0; kindIdx<KIND_NUM4; kindIdx++) { | |||||
| 633 | unsigned int pvi; | |||||
| 634 | /* | |||||
| 635 | fprintf(stderr, "!%s: gctx[%u] has %u pvls\n", me, kindIdx, gctx[kindIdx]->pvlNum); | |||||
| 636 | fprintf(stderr, "!%s: gctxComp[%u] has %u pvls\n", me, kindIdx, gctxComp[kindIdx]->pvlNum); | |||||
| 637 | */ | |||||
| 638 | for (pvi=0; pvi<gctxComp[kindIdx]->pvlNum; pvi++) { | |||||
| 639 | if (0 /* (no-op for formatting) */ | |||||
| 640 | || gageQueryItemOn(gctxComp[kindIdx], gctxComp[kindIdx]->pvl[pvi], gageSclValue) | |||||
| 641 | || gageQueryItemOn(gctxComp[kindIdx], gctxComp[kindIdx]->pvl[pvi], gageSclGradVec) | |||||
| 642 | || gageQueryItemOn(gctxComp[kindIdx], gctxComp[kindIdx]->pvl[pvi], gageSclHessian)) { | |||||
| 643 | biffMovef(BKEY"probeSS", GAGEgageBiffKey, "%s: trouble setting query (kind %u) on pvi %u", | |||||
| 644 | me, kindIdx, pvi); | |||||
| 645 | return 1; | |||||
| 646 | } | |||||
| 647 | } | |||||
| 648 | if (gageUpdate(gctxComp[kindIdx])) { | |||||
| 649 | biffMovef(BKEY"probeSS", GAGEgageBiffKey, "%s: trouble updating comp gctx %u", | |||||
| 650 | me, kindIdx); | |||||
| 651 | return 1; | |||||
| 652 | } | |||||
| 653 | } | |||||
| 654 | /* For the original contexts, we have to use the kind-specific items that | |||||
| 655 | correspond to the values and derivatives */ | |||||
| 656 | if (0 /* (no-op for formatting) */ | |||||
| 657 | || gageQueryItemOn(gctx[KI_SCL0], gctx[KI_SCL0]->pvl[0], gageSclValue) | |||||
| 658 | || gageQueryItemOn(gctx[KI_SCL0], gctx[KI_SCL0]->pvl[0], gageSclGradVec) | |||||
| 659 | || gageQueryItemOn(gctx[KI_SCL0], gctx[KI_SCL0]->pvl[0], gageSclHessian) | |||||
| 660 | ||||||
| 661 | || gageQueryItemOn(gctx[KI_VEC1], gctx[KI_VEC1]->pvl[0], gageVecVector) | |||||
| 662 | || gageQueryItemOn(gctx[KI_VEC1], gctx[KI_VEC1]->pvl[0], gageVecJacobian) | |||||
| 663 | || gageQueryItemOn(gctx[KI_VEC1], gctx[KI_VEC1]->pvl[0], gageVecHessian) | |||||
| 664 | ||||||
| 665 | || gageQueryItemOn(gctx[KI_TEN2], gctx[KI_TEN2]->pvl[0], tenGageTensor) | |||||
| 666 | || gageQueryItemOn(gctx[KI_TEN2], gctx[KI_TEN2]->pvl[0], tenGageTensorGrad) | |||||
| 667 | || gageQueryItemOn(gctx[KI_TEN2], gctx[KI_TEN2]->pvl[0], tenGageS) | |||||
| 668 | || gageQueryItemOn(gctx[KI_TEN2], gctx[KI_TEN2]->pvl[0], tenGageSGradVec) | |||||
| 669 | || gageQueryItemOn(gctx[KI_TEN2], gctx[KI_TEN2]->pvl[0], tenGageHessian) | |||||
| 670 | || gageQueryItemOn(gctx[KI_TEN2], gctx[KI_TEN2]->pvl[0], tenGageSHessian) | |||||
| 671 | ||||||
| 672 | || gageQueryItemOn(gctx[KI_DWI3], gctx[KI_DWI3]->pvl[0], tenDwiGageAll) | |||||
| 673 | || gageQueryItemOn(gctx[KI_DWI3], gctx[KI_DWI3]->pvl[0], tenDwiGageTensorLLS)) { | |||||
| 674 | biffMovef(BKEY"probeSS", GAGEgageBiffKey, "%s: trouble setting item", me); | |||||
| 675 | return 1; | |||||
| 676 | } | |||||
| 677 | for (kindIdx=0; kindIdx<KIND_NUM4; kindIdx++) { | |||||
| 678 | if (gageUpdate(gctx[kindIdx])) { | |||||
| 679 | biffMovef(BKEY"probeSS", GAGEgageBiffKey, "%s: trouble updating single gctx %u", | |||||
| 680 | me, kindIdx); | |||||
| 681 | return 1; | |||||
| 682 | } | |||||
| 683 | } | |||||
| 684 | } /* if (gSetup) */ | |||||
| 685 | ||||||
| 686 | for (kindIdx=0; kindIdx<KIND_NUM4; kindIdx++) { | |||||
| 687 | multiAnswerInit(man[kindIdx]); | |||||
| 688 | multiAnswerInit(manComp[kindIdx]); | |||||
| 689 | } | |||||
| 690 | for (kindIdx=0; kindIdx<KIND_NUM4; kindIdx++) { | |||||
| 691 | unsigned int pvi; | |||||
| 692 | multiAnswerLenSet(manComp[kindIdx], (KI_DWI3 != kindIdx ? 3 : 1)*gctxComp[kindIdx]->pvlNum); | |||||
| 693 | for (pvi=0; pvi<gctxComp[kindIdx]->pvlNum; pvi++) { | |||||
| 694 | multiAnswerAdd(manComp[kindIdx], pvi, | |||||
| 695 | gctxComp[kindIdx], gctxComp[kindIdx]->pvl[pvi], | |||||
| 696 | gageSclValue); | |||||
| 697 | } | |||||
| 698 | if (KI_DWI3 != kindIdx) { | |||||
| 699 | for (pvi=0; pvi<gctxComp[kindIdx]->pvlNum; pvi++) { | |||||
| 700 | multiAnswerAdd(manComp[kindIdx], pvi + gctxComp[kindIdx]->pvlNum, | |||||
| 701 | gctxComp[kindIdx], gctxComp[kindIdx]->pvl[pvi], | |||||
| 702 | gageSclGradVec); | |||||
| 703 | } | |||||
| 704 | for (pvi=0; pvi<gctxComp[kindIdx]->pvlNum; pvi++) { | |||||
| 705 | multiAnswerAdd(manComp[kindIdx], pvi + 2*gctxComp[kindIdx]->pvlNum, | |||||
| 706 | gctxComp[kindIdx], gctxComp[kindIdx]->pvl[pvi], | |||||
| 707 | gageSclHessian); | |||||
| 708 | } | |||||
| 709 | } | |||||
| 710 | multiAnswerLenSet(man[kindIdx], KI_DWI3 != kindIdx ? 3 : 1); | |||||
| 711 | switch(kindIdx) { | |||||
| 712 | case KI_SCL0: | |||||
| 713 | multiAnswerAdd(man[kindIdx], 0, gctx[kindIdx], gctx[kindIdx]->pvl[0], gageSclValue); | |||||
| 714 | multiAnswerAdd(man[kindIdx], 1, gctx[kindIdx], gctx[kindIdx]->pvl[0], gageSclGradVec); | |||||
| 715 | multiAnswerAdd(man[kindIdx], 2, gctx[kindIdx], gctx[kindIdx]->pvl[0], gageSclHessian); | |||||
| 716 | break; | |||||
| 717 | case KI_VEC1: | |||||
| 718 | multiAnswerAdd(man[kindIdx], 0, gctx[kindIdx], gctx[kindIdx]->pvl[0], gageVecVector); | |||||
| 719 | multiAnswerAdd(man[kindIdx], 1, gctx[kindIdx], gctx[kindIdx]->pvl[0], gageVecJacobian); | |||||
| 720 | multiAnswerAdd(man[kindIdx], 2, gctx[kindIdx], gctx[kindIdx]->pvl[0], gageVecHessian); | |||||
| 721 | break; | |||||
| 722 | case KI_TEN2: | |||||
| 723 | multiAnswerAdd(man[kindIdx], 0, gctx[kindIdx], gctx[kindIdx]->pvl[0], tenGageTensor); | |||||
| 724 | multiAnswerAdd(man[kindIdx], 1, gctx[kindIdx], gctx[kindIdx]->pvl[0], tenGageTensorGrad); | |||||
| 725 | multiAnswerAdd(man[kindIdx], 2, gctx[kindIdx], gctx[kindIdx]->pvl[0], tenGageHessian); | |||||
| 726 | break; | |||||
| 727 | case KI_DWI3: | |||||
| 728 | multiAnswerAdd(man[kindIdx], 0, gctx[kindIdx], gctx[kindIdx]->pvl[0], tenDwiGageAll); | |||||
| 729 | break; | |||||
| 730 | } | |||||
| 731 | } | |||||
| 732 | ||||||
| 733 | return 0; | |||||
| 734 | } | |||||
| 735 | ||||||
| 736 | static int | |||||
| 737 | probeTask1(gageContext *gctxComp[KIND_NUM4], | |||||
| 738 | gageContext *gctx[KIND_NUM4], | |||||
| 739 | multiAnswer *manComp[KIND_NUM4], | |||||
| 740 | multiAnswer *man[KIND_NUM4], | |||||
| 741 | unsigned int probeNum, NrrdKernel *kpack[3], | |||||
| 742 | double ksupport) { | |||||
| 743 | static const char me[]="probeTask1"; | |||||
| 744 | unsigned int kindIdx, probeIdx, errNumMax, tenErrNum, sclErrNum; | |||||
| 745 | double pos[3], upos[3], minp[3], maxp[3], | |||||
| 746 | tenDiff[7], tenAvg[7], tenErr, tenErrMax, | |||||
| 747 | vecDiff[3], vecAvg[3], vecErr, vecErrMax, vecErrNum, | |||||
| 748 | sclDiff, sclAvg, sclErr, sclErrMax, errNumFrac; | |||||
| 749 | const double *dwiTenEstP, | |||||
| 750 | *tenTenP, *tenTenNormP, *tenTenNormGradP, | |||||
| 751 | *sclSclP, *sclGradP, *vecVecP; | |||||
| 752 | ||||||
| 753 | ELL_3V_SET(minp, ksupport, ksupport, ksupport)((minp)[0] = (ksupport), (minp)[1] = (ksupport), (minp)[2] = ( ksupport)); | |||||
| 754 | ELL_3V_SET(maxp, volSize[0]-1-ksupport, volSize[1]-1-ksupport, volSize[2]-1-ksupport)((maxp)[0] = (volSize[0]-1-ksupport), (maxp)[1] = (volSize[1] -1-ksupport), (maxp)[2] = (volSize[2]-1-ksupport)); | |||||
| 755 | ||||||
| 756 | /* this is all for task 1.5 */ | |||||
| 757 | sclSclP = gageAnswerPointer(gctx[KI_SCL0], gctx[KI_SCL0]->pvl[0], gageSclValue); | |||||
| 758 | sclGradP = gageAnswerPointer(gctx[KI_SCL0], gctx[KI_SCL0]->pvl[0], gageSclGradVec); | |||||
| 759 | vecVecP = gageAnswerPointer(gctx[KI_VEC1], gctx[KI_VEC1]->pvl[0], gageVecVector); | |||||
| 760 | tenTenP = gageAnswerPointer(gctx[KI_TEN2], gctx[KI_TEN2]->pvl[0], tenGageTensor); | |||||
| 761 | tenTenNormP = gageAnswerPointer(gctx[KI_TEN2], gctx[KI_TEN2]->pvl[0], tenGageS); | |||||
| 762 | tenTenNormGradP = gageAnswerPointer(gctx[KI_TEN2], gctx[KI_TEN2]->pvl[0], tenGageSGradVec); | |||||
| 763 | dwiTenEstP = gageAnswerPointer(gctx[KI_DWI3], gctx[KI_DWI3]->pvl[0], tenDwiGageTensorLLS); | |||||
| 764 | tenErrNum = sclErrNum = 0; | |||||
| 765 | vecErrNum = 0.0; | |||||
| 766 | errNumFrac = 0.02; | |||||
| 767 | ||||||
| 768 | if (nrrdKernelBoxSupportDebug == kpack[0]) { | |||||
| 769 | /* not actually here for any derivatives, mainly to check on | |||||
| 770 | tensor esimation (in addition to usual check of multivariate as | |||||
| 771 | set of scalars) */ | |||||
| 772 | tenErrMax = 0.0002; | |||||
| 773 | vecErrMax = AIR_NAN(airFloatQNaN.f); | |||||
| 774 | sclErrMax = AIR_NAN(airFloatQNaN.f); | |||||
| 775 | } else if (nrrdKernelCos4SupportDebug == kpack[0]) { | |||||
| 776 | tenErrMax = AIR_NAN(airFloatQNaN.f); | |||||
| 777 | vecErrMax = AIR_NAN(airFloatQNaN.f); | |||||
| 778 | sclErrMax = AIR_NAN(airFloatQNaN.f); | |||||
| 779 | } else if (nrrdKernelCatmullRomSupportDebug == kpack[0]) { | |||||
| 780 | tenErrMax = 0.14; /* honestly, not sure how meaningful this test | |||||
| 781 | is, given how significant we're allowing the | |||||
| 782 | error to be. might be more meaningful if | |||||
| 783 | this was with comparison to a pre-computed | |||||
| 784 | non-linear least-squares fit, instead of the | |||||
| 785 | (log-based) linear least-squares. */ | |||||
| 786 | vecErrMax = 0.0016; | |||||
| 787 | sclErrMax = 0.0008; | |||||
| 788 | } else { | |||||
| 789 | biffAddf(BKEY"probeSS", "%s: unexpected kpack[0] %s\n", me, kpack[0]->name); | |||||
| 790 | return 1; | |||||
| 791 | } | |||||
| 792 | errNumMax = AIR_CAST(unsigned int, errNumFrac*probeNum)((unsigned int)(errNumFrac*probeNum)); | |||||
| 793 | for (probeIdx=0; probeIdx<probeNum; probeIdx++) { | |||||
| 794 | airHalton(upos, probeIdx+HALTON_BASE100, airPrimeList + 0, 3); | |||||
| 795 | pos[0] = AIR_AFFINE(0.0, upos[0], 1.0, minp[0], maxp[0])( ((double)(maxp[0])-(minp[0]))*((double)(upos[0])-(0.0)) / ( (double)(1.0)-(0.0)) + (minp[0])); | |||||
| 796 | pos[1] = AIR_AFFINE(0.0, upos[1], 1.0, minp[1], maxp[1])( ((double)(maxp[1])-(minp[1]))*((double)(upos[1])-(0.0)) / ( (double)(1.0)-(0.0)) + (minp[1])); | |||||
| 797 | pos[2] = AIR_AFFINE(0.0, upos[2], 1.0, minp[2], maxp[2])( ((double)(maxp[2])-(minp[2]))*((double)(upos[2])-(0.0)) / ( (double)(1.0)-(0.0)) + (minp[2])); | |||||
| 798 | for (kindIdx=0; kindIdx<KIND_NUM4; kindIdx++) { | |||||
| 799 | #define PROBE(gctx, what, pos) \ | |||||
| 800 | if (gageProbeSpace((gctx), (pos)[0], (pos)[1], (pos)[2], \ | |||||
| 801 | AIR_TRUE1 /* indexSpace */, \ | |||||
| 802 | AIR_FALSE0 /* clamp */)) { \ | |||||
| 803 | biffAddf(BKEY"probeSS", "%s: probe (%s) error(%d): %s", me, \ | |||||
| 804 | what, (gctx)->errNum, (gctx)->errStr); \ | |||||
| 805 | return 1; \ | |||||
| 806 | } | |||||
| 807 | ||||||
| 808 | PROBE(gctxComp[kindIdx], "comp", pos); | |||||
| 809 | PROBE(gctx[kindIdx], "single", pos); | |||||
| 810 | ||||||
| 811 | #undef PROBE | |||||
| 812 | ||||||
| 813 | multiAnswerCollect(man[kindIdx]); | |||||
| 814 | multiAnswerCollect(manComp[kindIdx]); | |||||
| 815 | if (multiAnswerCompare(manComp[kindIdx], man[kindIdx])) { | |||||
| 816 | biffAddf(BKEY"probeSS", "%s: on point %u of kindIdx %u", me, | |||||
| 817 | probeIdx, kindIdx); | |||||
| 818 | return 1; | |||||
| 819 | } | |||||
| 820 | } | |||||
| 821 | ||||||
| 822 | /* see if probed tensors mostly agree with | |||||
| 823 | tensors estimated from probed DWIs */ | |||||
| 824 | if (AIR_EXISTS(tenErrMax)(((int)(!((tenErrMax) - (tenErrMax)))))) { | |||||
| 825 | TEN_T_SUB(tenDiff, dwiTenEstP, tenTenP)( (tenDiff)[0] = ((dwiTenEstP)[0] + (tenTenP)[0])/2.0, (tenDiff )[1] = (dwiTenEstP)[1] - (tenTenP)[1], (tenDiff)[2] = (dwiTenEstP )[2] - (tenTenP)[2], (tenDiff)[3] = (dwiTenEstP)[3] - (tenTenP )[3], (tenDiff)[4] = (dwiTenEstP)[4] - (tenTenP)[4], (tenDiff )[5] = (dwiTenEstP)[5] - (tenTenP)[5], (tenDiff)[6] = (dwiTenEstP )[6] - (tenTenP)[6]); | |||||
| 826 | TEN_T_LERP(tenAvg, 0.5, dwiTenEstP, tenTenP)( (tenAvg)[0] = (((0.5))*(((tenTenP)[0]) - ((dwiTenEstP)[0])) + ((dwiTenEstP)[0])), (tenAvg)[1] = (((0.5))*(((tenTenP)[1]) - ((dwiTenEstP)[1])) + ((dwiTenEstP)[1])), (tenAvg)[2] = ((( 0.5))*(((tenTenP)[2]) - ((dwiTenEstP)[2])) + ((dwiTenEstP)[2] )), (tenAvg)[3] = (((0.5))*(((tenTenP)[3]) - ((dwiTenEstP)[3] )) + ((dwiTenEstP)[3])), (tenAvg)[4] = (((0.5))*(((tenTenP)[4 ]) - ((dwiTenEstP)[4])) + ((dwiTenEstP)[4])), (tenAvg)[5] = ( ((0.5))*(((tenTenP)[5]) - ((dwiTenEstP)[5])) + ((dwiTenEstP)[ 5])), (tenAvg)[6] = (((0.5))*(((tenTenP)[6]) - ((dwiTenEstP)[ 6])) + ((dwiTenEstP)[6]))); | |||||
| 827 | tenErr = TEN_T_NORM(tenDiff)(sqrt(( (tenDiff)[1]*(tenDiff)[1] + 2*(tenDiff)[2]*(tenDiff)[ 2] + 2*(tenDiff)[3]*(tenDiff)[3] + (tenDiff)[4]*(tenDiff)[4] + 2*(tenDiff)[5]*(tenDiff)[5] + (tenDiff)[6]*(tenDiff)[6] )))/TEN_T_NORM(tenAvg)(sqrt(( (tenAvg)[1]*(tenAvg)[1] + 2*(tenAvg)[2]*(tenAvg)[2] + 2*(tenAvg)[3]*(tenAvg)[3] + (tenAvg)[4]*(tenAvg)[4] + 2*(tenAvg )[5]*(tenAvg)[5] + (tenAvg)[6]*(tenAvg)[6] ))); | |||||
| 828 | if (tenErr > tenErrMax) { | |||||
| 829 | tenErrNum++; | |||||
| 830 | if (tenErrNum > errNumMax) { | |||||
| 831 | biffAddf(BKEY"probeSS", "%s: (probe %u) tenErr %g > %g too many times %u > %u", | |||||
| 832 | me, probeIdx, tenErr, tenErrMax, tenErrNum, errNumMax); | |||||
| 833 | return 1; | |||||
| 834 | } | |||||
| 835 | } | |||||
| 836 | } | |||||
| 837 | ||||||
| 838 | /* see if invariant gradient learned from tensor volume agrees with | |||||
| 839 | volume of pre-computed invariant gradients, and with | |||||
| 840 | gradient of pre-computed invariants */ | |||||
| 841 | if (AIR_EXISTS(vecErrMax)(((int)(!((vecErrMax) - (vecErrMax)))))) { | |||||
| 842 | ELL_3V_SUB(vecDiff, sclGradP, vecVecP)((vecDiff)[0] = (sclGradP)[0] - (vecVecP)[0], (vecDiff)[1] = ( sclGradP)[1] - (vecVecP)[1], (vecDiff)[2] = (sclGradP)[2] - ( vecVecP)[2]); | |||||
| 843 | ELL_3V_LERP(vecAvg, 0.5, sclGradP, vecVecP)((vecAvg)[0] = (((0.5))*(((vecVecP)[0]) - ((sclGradP)[0])) + ( (sclGradP)[0])), (vecAvg)[1] = (((0.5))*(((vecVecP)[1]) - ((sclGradP )[1])) + ((sclGradP)[1])), (vecAvg)[2] = (((0.5))*(((vecVecP) [2]) - ((sclGradP)[2])) + ((sclGradP)[2]))); | |||||
| 844 | vecErr = ELL_3V_LEN(vecDiff)(sqrt((((vecDiff))[0]*((vecDiff))[0] + ((vecDiff))[1]*((vecDiff ))[1] + ((vecDiff))[2]*((vecDiff))[2])))/sqrt(ELL_3V_LEN(vecAvg)(sqrt((((vecAvg))[0]*((vecAvg))[0] + ((vecAvg))[1]*((vecAvg)) [1] + ((vecAvg))[2]*((vecAvg))[2])))); | |||||
| 845 | if (vecErr > vecErrMax) { | |||||
| 846 | vecErrNum += 0.5; | |||||
| 847 | if (vecErrNum > errNumMax) { | |||||
| 848 | biffAddf(BKEY"probeSS", "%s: (probe %u) (A) vecErr %g > %g too many times %g > %u", | |||||
| 849 | me, probeIdx, vecErr, vecErrMax, vecErrNum, errNumMax); | |||||
| 850 | return 1; | |||||
| 851 | } | |||||
| 852 | } | |||||
| 853 | ELL_3V_SUB(vecDiff, tenTenNormGradP, vecVecP)((vecDiff)[0] = (tenTenNormGradP)[0] - (vecVecP)[0], (vecDiff )[1] = (tenTenNormGradP)[1] - (vecVecP)[1], (vecDiff)[2] = (tenTenNormGradP )[2] - (vecVecP)[2]); | |||||
| 854 | ELL_3V_LERP(vecAvg, 0.5, tenTenNormGradP, vecVecP)((vecAvg)[0] = (((0.5))*(((vecVecP)[0]) - ((tenTenNormGradP)[ 0])) + ((tenTenNormGradP)[0])), (vecAvg)[1] = (((0.5))*(((vecVecP )[1]) - ((tenTenNormGradP)[1])) + ((tenTenNormGradP)[1])), (vecAvg )[2] = (((0.5))*(((vecVecP)[2]) - ((tenTenNormGradP)[2])) + ( (tenTenNormGradP)[2]))); | |||||
| 855 | vecErr = ELL_3V_LEN(vecDiff)(sqrt((((vecDiff))[0]*((vecDiff))[0] + ((vecDiff))[1]*((vecDiff ))[1] + ((vecDiff))[2]*((vecDiff))[2])))/sqrt(ELL_3V_LEN(vecAvg)(sqrt((((vecAvg))[0]*((vecAvg))[0] + ((vecAvg))[1]*((vecAvg)) [1] + ((vecAvg))[2]*((vecAvg))[2])))); | |||||
| 856 | if (vecErr > vecErrMax) { | |||||
| 857 | vecErrNum += 0.5; | |||||
| 858 | if (vecErrNum > errNumMax) { | |||||
| 859 | biffAddf(BKEY"probeSS", "%s: (probe %u) (B) vecErr %g > %g too many times %g > %u", | |||||
| 860 | me, probeIdx, vecErr, vecErrMax, vecErrNum, errNumMax); | |||||
| 861 | return 1; | |||||
| 862 | } | |||||
| 863 | } | |||||
| 864 | } | |||||
| 865 | ||||||
| 866 | /* see if invariant learned from tensor volume agrees with | |||||
| 867 | volume of precomputed invariants */ | |||||
| 868 | if (AIR_EXISTS(sclErrMax)(((int)(!((sclErrMax) - (sclErrMax)))))) { | |||||
| 869 | sclDiff = sclSclP[0] - tenTenNormP[0]; | |||||
| 870 | sclAvg = (sclSclP[0] + tenTenNormP[0])/2; | |||||
| 871 | sclErr = AIR_ABS(sclDiff)((sclDiff) > 0.0f ? (sclDiff) : -(sclDiff))/sqrt(AIR_ABS(sclAvg)((sclAvg) > 0.0f ? (sclAvg) : -(sclAvg))); | |||||
| 872 | if (sclErr > sclErrMax) { | |||||
| 873 | sclErrNum++; | |||||
| 874 | if (sclErrNum > errNumMax) { | |||||
| 875 | biffAddf(BKEY"probeSS", "%s: (probe %u) (B) sclErr %g > %g too many times %u > %u", | |||||
| 876 | me, probeIdx, sclErr, sclErrMax, sclErrNum, errNumMax); | |||||
| 877 | return 1; | |||||
| 878 | } | |||||
| 879 | } | |||||
| 880 | } | |||||
| 881 | } | |||||
| 882 | ||||||
| 883 | return 0; | |||||
| 884 | } | |||||
| 885 | ||||||
| 886 | static const char *testInfo = "for testing gage"; | |||||
| 887 | ||||||
| 888 | int | |||||
| 889 | main(int argc, const char **argv) { | |||||
| 890 | const char *me; | |||||
| 891 | char *err = NULL((void*)0); | |||||
| 892 | hestOpt *hopt=NULL((void*)0); | |||||
| 893 | hestParm *hparm; | |||||
| 894 | airArray *mop; | |||||
| 895 | ||||||
| 896 | const gageKind *kind[KIND_NUM4]; | |||||
| 897 | char name[KIND_NUM4][AIR_STRLEN_SMALL(128+1)] = { "scl", "vec", "ten", "dwi" }; | |||||
| 898 | char nameComp[KIND_NUM4][AIR_STRLEN_SMALL(128+1)] = { "sclComp", "vecComp", "tenComp", "dwiComp" }; | |||||
| 899 | char *kernS; | |||||
| 900 | gageKind *dwikind = NULL((void*)0); | |||||
| 901 | gageContext *gctxComp[KIND_NUM4], *gctxCompCopy[KIND_NUM4], | |||||
| 902 | *gctx[KIND_NUM4], *gctxCopy[KIND_NUM4]; | |||||
| 903 | multiAnswer *manComp[KIND_NUM4], *man[KIND_NUM4]; | |||||
| 904 | Nrrd *nin[KIND_NUM4], | |||||
| 905 | /* these are the volumes that are used in gctxComp[] */ | |||||
| 906 | *nsclCopy, *nvecComp[3], *nctenComp[7], **ndwiComp, | |||||
| 907 | *ngrad; /* need access to list of gradients used to make DWIs; | |||||
| 908 | (this is not the gradient of a scalar field) */ | |||||
| 909 | double bval = 1000, noiseStdv=0.0001, ksupport; | |||||
| 910 | unsigned int kindIdx, probeNum, | |||||
| 911 | gradNum = 10; /* small number so that missing one will produce | |||||
| 912 | a big reconstruction error */ | |||||
| 913 | NrrdKernel *kpack[3]; | |||||
| 914 | ||||||
| 915 | kind[0] = gageKindScl; | |||||
| 916 | kind[1] = gageKindVec; | |||||
| 917 | kind[2] = tenGageKind; | |||||
| 918 | kind[3] = NULL((void*)0); /* dwi */ | |||||
| 919 | ||||||
| 920 | me = argv[0]; | |||||
| 921 | mop = airMopNew(); | |||||
| 922 | hparm = hestParmNew(); | |||||
| 923 | airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways); | |||||
| 924 | /* learn things from hest */ | |||||
| 925 | hestOptAdd(&hopt, "supp", "r", airTypeDouble, 1, 1, &ksupport, "1.0", | |||||
| 926 | "kernel support"); | |||||
| 927 | hestOptAdd(&hopt, "pnum", "N", airTypeUInt, 1, 1, &probeNum, "100", | |||||
| 928 | "# of probes"); | |||||
| 929 | hestOptAdd(&hopt, "k", "kern", airTypeString, 1, 1, &kernS, NULL((void*)0), | |||||
| 930 | "kernel to use; can be: box, cos, or ctmr"); | |||||
| 931 | hestParseOrDie(hopt, argc-1, argv+1, hparm, me, testInfo, | |||||
| 932 | AIR_TRUE1, AIR_TRUE1, AIR_TRUE1); | |||||
| 933 | airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); | |||||
| 934 | airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); | |||||
| 935 | ||||||
| 936 | if (!strcmp(kernS, "box")) { | |||||
| 937 | ELL_3V_SET(kpack,((kpack)[0] = (nrrdKernelBoxSupportDebug), (kpack)[1] = (nrrdKernelZero ), (kpack)[2] = (nrrdKernelZero)) | |||||
| 938 | nrrdKernelBoxSupportDebug,((kpack)[0] = (nrrdKernelBoxSupportDebug), (kpack)[1] = (nrrdKernelZero ), (kpack)[2] = (nrrdKernelZero)) | |||||
| 939 | nrrdKernelZero,((kpack)[0] = (nrrdKernelBoxSupportDebug), (kpack)[1] = (nrrdKernelZero ), (kpack)[2] = (nrrdKernelZero)) | |||||
| 940 | nrrdKernelZero)((kpack)[0] = (nrrdKernelBoxSupportDebug), (kpack)[1] = (nrrdKernelZero ), (kpack)[2] = (nrrdKernelZero)); | |||||
| 941 | } else if (!strcmp(kernS, "cos")) { | |||||
| 942 | ELL_3V_SET(kpack,((kpack)[0] = (nrrdKernelCos4SupportDebug), (kpack)[1] = (nrrdKernelCos4SupportDebugD ), (kpack)[2] = (nrrdKernelCos4SupportDebugDD)) | |||||
| 943 | nrrdKernelCos4SupportDebug,((kpack)[0] = (nrrdKernelCos4SupportDebug), (kpack)[1] = (nrrdKernelCos4SupportDebugD ), (kpack)[2] = (nrrdKernelCos4SupportDebugDD)) | |||||
| 944 | nrrdKernelCos4SupportDebugD,((kpack)[0] = (nrrdKernelCos4SupportDebug), (kpack)[1] = (nrrdKernelCos4SupportDebugD ), (kpack)[2] = (nrrdKernelCos4SupportDebugDD)) | |||||
| 945 | nrrdKernelCos4SupportDebugDD)((kpack)[0] = (nrrdKernelCos4SupportDebug), (kpack)[1] = (nrrdKernelCos4SupportDebugD ), (kpack)[2] = (nrrdKernelCos4SupportDebugDD)); | |||||
| 946 | } else if (!strcmp(kernS, "ctmr")) { | |||||
| 947 | ELL_3V_SET(kpack,((kpack)[0] = (nrrdKernelCatmullRomSupportDebug), (kpack)[1] = (nrrdKernelCatmullRomSupportDebugD), (kpack)[2] = (nrrdKernelCatmullRomSupportDebugDD )) | |||||
| 948 | nrrdKernelCatmullRomSupportDebug,((kpack)[0] = (nrrdKernelCatmullRomSupportDebug), (kpack)[1] = (nrrdKernelCatmullRomSupportDebugD), (kpack)[2] = (nrrdKernelCatmullRomSupportDebugDD )) | |||||
| 949 | nrrdKernelCatmullRomSupportDebugD,((kpack)[0] = (nrrdKernelCatmullRomSupportDebug), (kpack)[1] = (nrrdKernelCatmullRomSupportDebugD), (kpack)[2] = (nrrdKernelCatmullRomSupportDebugDD )) | |||||
| 950 | nrrdKernelCatmullRomSupportDebugDD)((kpack)[0] = (nrrdKernelCatmullRomSupportDebug), (kpack)[1] = (nrrdKernelCatmullRomSupportDebugD), (kpack)[2] = (nrrdKernelCatmullRomSupportDebugDD )); | |||||
| 951 | } else { | |||||
| 952 | fprintf(stderr__stderrp, "%s: kernel \"%s\" not recognized", me, kernS); | |||||
| 953 | airMopError(mop); return 1; | |||||
| 954 | } | |||||
| 955 | fprintf(stderr__stderrp, "kpack = %s, %s, %s\n", kpack[0]->name, kpack[1]->name, kpack[2]->name); | |||||
| 956 | ||||||
| 957 | /* This was a tricky bug: Adding gageContextNix(gctx) to the mop | |||||
| 958 | as soon as a gctx is created makes sense. But, in the first | |||||
| 959 | version of this code, gageContextNix was added to the mop | |||||
| 960 | BEFORE tenDwiGageKindNix was added, which meant that gageContextNix | |||||
| 961 | was being called AFTER tenDwiGageKindNix. However, that meant | |||||
| 962 | that existing pvls had their pvl->kind being freed from under them, | |||||
| 963 | but gagePerVolumeNix certainly needs to look at and possibly call | |||||
| 964 | pvl->kind->pvlDataNix in order clean up pvl->data. *Therefore*, | |||||
| 965 | we have to add tenDwiGageKindNix to the mop prior to gageContextNix, | |||||
| 966 | even though nothing about the (dyanamic) kind has been set yet. | |||||
| 967 | If we had something like smart pointers, then tenDwiGageKindNix | |||||
| 968 | would not have freed something that an extant pvl was using */ | |||||
| 969 | dwikind = tenDwiGageKindNew(); | |||||
| 970 | airMopAdd(mop, dwikind, (airMopper)tenDwiGageKindNix, airMopAlways); | |||||
| 971 | ||||||
| 972 | #define GAGE_CTX_NEW(gg, mm) \ | |||||
| 973 | (gg) = gageContextNew(); \ | |||||
| 974 | airMopAdd((mm), (gg), (airMopper)gageContextNix, airMopAlways); \ | |||||
| 975 | gageParmSet((gg), gageParmRenormalize, AIR_FALSE0); \ | |||||
| 976 | gageParmSet((gg), gageParmCheckIntegrals, AIR_TRUE1) | |||||
| 977 | ||||||
| 978 | for (kindIdx=0; kindIdx<KIND_NUM4; kindIdx++) { | |||||
| 979 | GAGE_CTX_NEW(gctx[kindIdx], mop); | |||||
| 980 | GAGE_CTX_NEW(gctxComp[kindIdx], mop); | |||||
| 981 | /* | |||||
| 982 | fprintf(stderr, "%s: kind %s (%u): gctx=%p, gctxComp=%p\n", me, | |||||
| 983 | kindStr[kindIdx], kindIdx, | |||||
| 984 | AIR_VOIDP(gctx[kindIdx]), | |||||
| 985 | AIR_VOIDP(gctxComp[kindIdx])); | |||||
| 986 | */ | |||||
| 987 | man[kindIdx] = multiAnswerNew(name[kindIdx]); | |||||
| 988 | manComp[kindIdx] = multiAnswerNew(nameComp[kindIdx]); | |||||
| 989 | airMopAdd(mop, man[kindIdx], (airMopper)multiAnswerNix, airMopAlways); | |||||
| 990 | airMopAdd(mop, manComp[kindIdx], (airMopper)multiAnswerNix, airMopAlways); | |||||
| 991 | } | |||||
| 992 | #undef GAGE_CTX_NEW | |||||
| 993 | ||||||
| 994 | for (kindIdx=0; kindIdx<KIND_NUM4; kindIdx++) { | |||||
| 995 | NRRD_NEW(nin[kindIdx], mop); | |||||
| 996 | } | |||||
| 997 | NRRD_NEW(ngrad, mop); | |||||
| 998 | NRRD_NEW(nsclCopy, mop); | |||||
| 999 | if (engageGenTensor(gctx[KI_TEN2], nin[KI_TEN2], | |||||
| 1000 | /* out/in */ | |||||
| 1001 | noiseStdv, 42 /* RNG seed, could be a command-line option */, | |||||
| 1002 | volSize[0], volSize[1], volSize[2]) | |||||
| 1003 | || engageGenScalar(gctx[KI_SCL0], nin[KI_SCL0], | |||||
| 1004 | gctxComp[KI_SCL0], nsclCopy, | |||||
| 1005 | /* out/in */ | |||||
| 1006 | nin[KI_TEN2]) | |||||
| 1007 | || engageGenVector(gctx[KI_VEC1], nin[KI_VEC1], | |||||
| 1008 | /* out/in */ | |||||
| 1009 | nin[KI_SCL0]) | |||||
| 1010 | /* engage'ing of nin[KI_DWI] done below */ | |||||
| 1011 | || genDwi(nin[KI_DWI3], ngrad, | |||||
| 1012 | /* out/in */ | |||||
| 1013 | gradNum /* for B0 */, bval, nin[KI_TEN2]) | |||||
| 1014 | || engageMopDiceVector(gctxComp[KI_VEC1], nvecComp, | |||||
| 1015 | /* out/in */ | |||||
| 1016 | mop, nin[KI_VEC1]) | |||||
| 1017 | || engageMopDiceTensor(gctxComp[KI_TEN2], nctenComp, | |||||
| 1018 | /* out/in */ | |||||
| 1019 | mop, nin[KI_TEN2]) | |||||
| 1020 | || engageMopDiceDwi(gctxComp[KI_DWI3], &ndwiComp, | |||||
| 1021 | /* out/in */ | |||||
| 1022 | mop, nin[KI_DWI3])) { | |||||
| 1023 | airMopAdd(mop, err = biffGetDone(BKEY"probeSS"), airFree, airMopAlways); | |||||
| 1024 | fprintf(stderr__stderrp, "%s: trouble creating volumes:\n%s", me, err); | |||||
| 1025 | airMopError(mop); return 1; | |||||
| 1026 | } | |||||
| 1027 | if (tenDwiGageKindSet(dwikind, -1 /* thresh */, 0 /* soft */, | |||||
| 1028 | bval, 1 /* valueMin */, | |||||
| 1029 | ngrad, NULL((void*)0), | |||||
| 1030 | tenEstimate1MethodLLS, | |||||
| 1031 | tenEstimate2MethodPeled, | |||||
| 1032 | 424242)) { | |||||
| 1033 | airMopAdd(mop, err = biffGetDone(TENtenBiffKey), airFree, airMopAlways); | |||||
| 1034 | fprintf(stderr__stderrp, "%s: trouble creating DWI kind:\n%s", me, err); | |||||
| 1035 | airMopError(mop); return 1; | |||||
| 1036 | } | |||||
| 1037 | /* access through kind[] is const, but not through dwikind */ | |||||
| 1038 | kind[KI_DWI3] = dwikind; | |||||
| 1039 | /* engage dwi vol */ | |||||
| 1040 | { | |||||
| 1041 | gagePerVolume *pvl; | |||||
| 1042 | if ( !(pvl = gagePerVolumeNew(gctx[KI_DWI3], nin[KI_DWI3], kind[KI_DWI3])) | |||||
| 1043 | || gagePerVolumeAttach(gctx[KI_DWI3], pvl) ) { | |||||
| 1044 | airMopAdd(mop, err = biffGetDone(GAGEgageBiffKey), airFree, airMopAlways); | |||||
| 1045 | fprintf(stderr__stderrp, "%s: trouble creating DWI context:\n%s", me, err); | |||||
| 1046 | airMopError(mop); return 1; | |||||
| 1047 | } | |||||
| 1048 | /* | |||||
| 1049 | fprintf(stderr, "%s: %s gctx=%p gets pvl %p\n", me, | |||||
| 1050 | kindStr[KI_DWI], AIR_VOIDP(gctx[KI_DWI]), AIR_VOIDP(pvl)); | |||||
| 1051 | */ | |||||
| 1052 | } | |||||
| 1053 | ||||||
| 1054 | /* make sure kinds can parse back to themselves */ | |||||
| 1055 | /* the messiness here is in part because of problems with the gage | |||||
| 1056 | API, and the weirdness of how meetGageKindParse is either allocating | |||||
| 1057 | something, or not, depending on its input. There is no way to | |||||
| 1058 | refer to the "name" of a dwi kind without having allocated something. */ | |||||
| 1059 | for (kindIdx=0; kindIdx<KIND_NUM4; kindIdx++) { | |||||
| 1060 | if (!(kind[kindIdx]->dynamicAlloc)) { | |||||
| 1061 | if (kind[kindIdx] != meetGageKindParse(kind[kindIdx]->name)) { | |||||
| 1062 | fprintf(stderr__stderrp, "%s: static kind[%u]->name %s wasn't parsed\n", me, | |||||
| 1063 | kindIdx, kind[kindIdx]->name); | |||||
| 1064 | airMopError(mop); return 1; | |||||
| 1065 | } | |||||
| 1066 | } else { | |||||
| 1067 | gageKind *ktmp; | |||||
| 1068 | ktmp = meetGageKindParse(kind[kindIdx]->name); | |||||
| 1069 | if (!ktmp) { | |||||
| 1070 | fprintf(stderr__stderrp, "%s: dynamic kind[%u]->name %s wasn't parsed\n", me, | |||||
| 1071 | kindIdx, kind[kindIdx]->name); | |||||
| 1072 | airMopError(mop); return 1; | |||||
| 1073 | } | |||||
| 1074 | if (airStrcmp(ktmp->name, kind[kindIdx]->name)) { | |||||
| 1075 | fprintf(stderr__stderrp, "%s: parsed dynamic kind[%u]->name %s didn't match %s\n", me, | |||||
| 1076 | kindIdx, ktmp->name, kind[kindIdx]->name); | |||||
| 1077 | airMopError(mop); return 1; | |||||
| 1078 | } | |||||
| 1079 | if (!airStrcmp(TEN_DWI_GAGE_KIND_NAME"dwi", ktmp->name)) { | |||||
| 1080 | /* HEY: there needs to be a generic way of freeing | |||||
| 1081 | a dynamic kind, perhaps a new nixer field in gageKind */ | |||||
| 1082 | ktmp = tenDwiGageKindNix(ktmp); | |||||
| 1083 | } | |||||
| 1084 | } | |||||
| 1085 | } | |||||
| 1086 | /* | |||||
| 1087 | for (kindIdx=0; kindIdx<KIND_NUM; kindIdx++) { | |||||
| 1088 | printf("%s: %s (%s) -> (%u) %u\n", me, kind[kindIdx]->name, | |||||
| 1089 | kind[kindIdx]->dynamicAlloc ? "dynamic" : "static", | |||||
| 1090 | kind[kindIdx]->baseDim, kind[kindIdx]->valLen); | |||||
| 1091 | } | |||||
| 1092 | */ | |||||
| 1093 | ||||||
| 1094 | /* | |||||
| 1095 | nrrdSave("tmp-cten.nrrd", nin[KI_TEN], NULL); | |||||
| 1096 | nrrdSave("tmp-scl.nrrd", nin[KI_SCL], NULL); | |||||
| 1097 | nrrdSave("tmp-vec.nrrd", nin[KI_VEC], NULL); | |||||
| 1098 | nrrdSave("tmp-dwi.nrrd", nin[KI_DWI], NULL); | |||||
| 1099 | */ | |||||
| 1100 | ||||||
| 1101 | /* ========================== TASK 1 */ | |||||
| 1102 | if (updateQueryKernelSetTask1(gctxComp, gctx, AIR_TRUE1, manComp, man, kpack, ksupport) | |||||
| 1103 | || probeTask1(gctxComp, gctx, manComp, man, probeNum, kpack, ksupport)) { | |||||
| 1104 | airMopAdd(mop, err = biffGetDone(BKEY"probeSS"), airFree, airMopAlways); | |||||
| 1105 | fprintf(stderr__stderrp, "%s: trouble (orig, orig):\n%s", me, err); | |||||
| 1106 | airMopError(mop); return 1; | |||||
| 1107 | } | |||||
| 1108 | /* testing gageContextCopy on multi-variate volumes */ | |||||
| 1109 | for (kindIdx=0; kindIdx<KIND_NUM4; kindIdx++) { | |||||
| 1110 | if (!( gctxCopy[kindIdx] = gageContextCopy(gctx[kindIdx]) )) { | |||||
| 1111 | airMopAdd(mop, err = biffGetDone(GAGEgageBiffKey), airFree, airMopAlways); | |||||
| 1112 | fprintf(stderr__stderrp, "%s: trouble w/ multi-variate contexts:\n%s", me, err); | |||||
| 1113 | airMopError(mop); return 1; | |||||
| 1114 | } | |||||
| 1115 | airMopAdd(mop, gctxCopy[kindIdx], (airMopper)gageContextNix, airMopAlways); | |||||
| 1116 | } | |||||
| 1117 | if (updateQueryKernelSetTask1(gctxComp, gctxCopy, AIR_FALSE0, manComp, man, kpack, ksupport) | |||||
| 1118 | || probeTask1(gctxComp, gctxCopy, manComp, man, probeNum, kpack, ksupport)) { | |||||
| 1119 | airMopAdd(mop, err = biffGetDone(BKEY"probeSS"), airFree, airMopAlways); | |||||
| 1120 | fprintf(stderr__stderrp, "%s: trouble (orig, copy):\n%s", me, err); | |||||
| 1121 | airMopError(mop); return 1; | |||||
| 1122 | } | |||||
| 1123 | for (kindIdx=0; kindIdx<KIND_NUM4; kindIdx++) { | |||||
| 1124 | if (!( gctxCompCopy[kindIdx] = gageContextCopy(gctxComp[kindIdx]) )) { | |||||
| 1125 | airMopAdd(mop, err = biffGetDone(GAGEgageBiffKey), airFree, airMopAlways); | |||||
| 1126 | fprintf(stderr__stderrp, "%s: trouble w/ component contexts:\n%s", me, err); | |||||
| 1127 | airMopError(mop); return 1; | |||||
| 1128 | } | |||||
| 1129 | airMopAdd(mop, gctxCompCopy[kindIdx], (airMopper)gageContextNix, airMopAlways); | |||||
| 1130 | } | |||||
| 1131 | if (updateQueryKernelSetTask1(gctxCompCopy, gctxCopy, AIR_FALSE0, manComp, man, kpack, ksupport) | |||||
| 1132 | || probeTask1(gctxCompCopy, gctxCopy, manComp, man, probeNum, kpack, ksupport)) { | |||||
| 1133 | airMopAdd(mop, err = biffGetDone(BKEY"probeSS"), airFree, airMopAlways); | |||||
| 1134 | fprintf(stderr__stderrp, "%s: trouble (copy, copy):\n%s", me, err); | |||||
| 1135 | airMopError(mop); return 1; | |||||
| 1136 | } | |||||
| 1137 | ||||||
| 1138 | /* ========================== TASK 2 */ | |||||
| 1139 | /* create scale-space stacks with tent, ctmr, and hermite */ | |||||
| 1140 | /* save them, free, and read them back in */ | |||||
| 1141 | /* gageContextCopy on stack */ | |||||
| 1142 | /* pick a scale in-between tau samples */ | |||||
| 1143 | /* for all the tau's half-way between tau samples in scale: | |||||
| 1144 | blur at that tau to get correct values | |||||
| 1145 | check that error with hermite is lower than ctmr is lower than tent */ | |||||
| 1146 | /* for all tau samples: | |||||
| 1147 | blur at that tau to (re-)get correct values | |||||
| 1148 | check that everything agrees there */ | |||||
| 1149 | ||||||
| 1150 | ||||||
| 1151 | /* single probe with high verbosity */ | |||||
| 1152 | ||||||
| 1153 | airMopOkay(mop); | |||||
| 1154 | return 0; | |||||
| 1155 | } | |||||
| 1156 | #undef NRRD_NEW |