int _nrrdReadNrrdParse_space (FILE *file, Nrrd *nrrd, NrrdIoState *nio, int useBiff) { char me[]="_nrrdReadNrrdParse_space", err[BIFF_STRLEN], *info; int space; AIR_UNUSED(file); info = nio->line + nio->pos; if (nio->seen[nrrdField_space_dimension]) { sprintf(err, "%s: can't specify space after specifying " "space dimension (%d)", me, nrrd->spaceDim); biffAdd(NRRD, err); return 1; } if (!(space = airEnumVal(nrrdSpace, info))) { sprintf(err, "%s: couldn't parse space \"%s\"", me, info); biffMaybeAdd(NRRD, err, useBiff); return 1; } if (nrrdSpaceSet(nrrd, space)) { sprintf(err, "%s: trouble", me); biffMaybeAdd(NRRD, err, useBiff); return 1; } if (_nrrdFieldCheck[nrrdField_space](nrrd, useBiff)) { sprintf(err, "%s: trouble", me); biffMaybeAdd(NRRD, err, useBiff); return 1; } return 0; }
int nrrdOrientationReduce(Nrrd *nout, const Nrrd *nin, int setMinsFromOrigin) { char me[]="nrrdOrientationReduce", err[BIFF_STRLEN]; unsigned int spatialAxisNum, spatialAxisIdx[NRRD_DIM_MAX], saxii; NrrdAxisInfo *axis; if (!(nout && nin)) { sprintf(err, "%s: got NULL spacing", me); biffAdd(NRRD, err); return 1; } if (nout != nin) { if (nrrdCopy(nout, nin)) { sprintf(err, "%s: trouble doing initial copying", me); biffAdd(NRRD, err); return 1; } } if (!nout->spaceDim) { /* we're done! */ return 0; } spatialAxisNum = nrrdSpatialAxesGet(nout, spatialAxisIdx); for (saxii=0; saxii<spatialAxisNum; saxii++) { axis = nout->axis + spatialAxisIdx[saxii]; axis->spacing = nrrdSpaceVecNorm(nout->spaceDim, axis->spaceDirection); if (setMinsFromOrigin) { axis->min = (saxii < nout->spaceDim ? nout->spaceOrigin[saxii] : AIR_NAN); } } nrrdSpaceSet(nout, nrrdSpaceUnknown); return 0; }
int tend_helixMain(int argc, char **argv, char *me, hestParm *hparm) { int pret; hestOpt *hopt = NULL; char *perr, *err; airArray *mop; int size[3], nit; Nrrd *nout; double R, r, S, bnd, angle, ev[3], ip[3], iq[4], mp[3], mq[4], tmp[9], orig[3], i2w[9], rot[9], mf[9], spd[4][3], bge; char *outS; hestOptAdd(&hopt, "s", "size", airTypeInt, 3, 3, size, NULL, "sizes along fast, medium, and slow axes of the sampled volume, " "often called \"X\", \"Y\", and \"Z\". It is best to use " "slightly different sizes here, to expose errors in interpreting " "axis ordering (e.g. \"-s 39 40 41\")"); hestOptAdd(&hopt, "ip", "image orientation", airTypeDouble, 3, 3, ip, "0 0 0", "quaternion quotient space orientation of image"); hestOptAdd(&hopt, "mp", "measurement orientation", airTypeDouble, 3, 3, mp, "0 0 0", "quaternion quotient space orientation of measurement frame"); hestOptAdd(&hopt, "b", "boundary", airTypeDouble, 1, 1, &bnd, "10", "parameter governing how fuzzy the boundary between high and " "low anisotropy is. Use \"-b 0\" for no fuzziness"); hestOptAdd(&hopt, "r", "little radius", airTypeDouble, 1, 1, &r, "30", "(minor) radius of cylinder tracing helix"); hestOptAdd(&hopt, "R", "big radius", airTypeDouble, 1, 1, &R, "50", "(major) radius of helical turns"); hestOptAdd(&hopt, "S", "spacing", airTypeDouble, 1, 1, &S, "100", "spacing between turns of helix (along its axis)"); hestOptAdd(&hopt, "a", "angle", airTypeDouble, 1, 1, &angle, "60", "maximal angle of twist of tensors along path. There is no " "twist at helical core of path, and twist increases linearly " "with radius around this path. Positive twist angle with " "positive spacing resulting in a right-handed twist around a " "right-handed helix. "); hestOptAdd(&hopt, "nit", NULL, airTypeInt, 0, 0, &nit, NULL, "changes behavior of twist angle as function of distance from " "center of helical core: instead of increasing linearly as " "describe above, be at a constant angle"); hestOptAdd(&hopt, "ev", "eigenvalues", airTypeDouble, 3, 3, ev, "0.006 0.002 0.001", "eigenvalues of tensors (in order) along direction of coil, " "circumferential around coil, and radial around coil. "); hestOptAdd(&hopt, "bg", "background", airTypeDouble, 1, 1, &bge, "0.5", "eigenvalue of isotropic background"); hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-", "output file"); mop = airMopNew(); airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); USAGE(_tend_helixInfoL); JUSTPARSE(); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); nout = nrrdNew(); airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); if (nrrdMaybeAlloc_va(nout, nrrdTypeFloat, 4, AIR_CAST(size_t, 7), AIR_CAST(size_t, size[0]), AIR_CAST(size_t, size[1]), AIR_CAST(size_t, size[2]))) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble allocating output:\n%s\n", me, err); airMopError(mop); return 1; } ELL_4V_SET(iq, 1.0, ip[0], ip[1], ip[2]); ell_q_to_3m_d(rot, iq); ELL_3V_SET(orig, -2*R + 2*R/size[0], -2*R + 2*R/size[1], -2*R + 2*R/size[2]); ELL_3M_ZERO_SET(i2w); ELL_3M_DIAG_SET(i2w, 4*R/size[0], 4*R/size[1], 4*R/size[2]); ELL_3MV_MUL(tmp, rot, orig); ELL_3V_COPY(orig, tmp); ELL_3M_MUL(tmp, rot, i2w); ELL_3M_COPY(i2w, tmp); ELL_4V_SET(mq, 1.0, mp[0], mp[1], mp[2]); ell_q_to_3m_d(mf, mq); tend_helixDoit(nout, bnd, orig, i2w, mf, r, R, S, angle*AIR_PI/180, !nit, ev, bge); nrrdSpaceSet(nout, nrrdSpaceRightAnteriorSuperior); nrrdSpaceOriginSet(nout, orig); ELL_3V_SET(spd[0], AIR_NAN, AIR_NAN, AIR_NAN); ELL_3MV_COL0_GET(spd[1], i2w); ELL_3MV_COL1_GET(spd[2], i2w); ELL_3MV_COL2_GET(spd[3], i2w); nrrdAxisInfoSet_va(nout, nrrdAxisInfoSpaceDirection, spd[0], spd[1], spd[2], spd[3]); nrrdAxisInfoSet_va(nout, nrrdAxisInfoCenter, nrrdCenterUnknown, nrrdCenterCell, nrrdCenterCell, nrrdCenterCell); nrrdAxisInfoSet_va(nout, nrrdAxisInfoKind, nrrdKind3DMaskedSymMatrix, nrrdKindSpace, nrrdKindSpace, nrrdKindSpace); nout->measurementFrame[0][0] = mf[0]; nout->measurementFrame[1][0] = mf[1]; nout->measurementFrame[2][0] = mf[2]; nout->measurementFrame[0][1] = mf[3]; nout->measurementFrame[1][1] = mf[4]; nout->measurementFrame[2][1] = mf[5]; nout->measurementFrame[0][2] = mf[6]; nout->measurementFrame[1][2] = mf[7]; nout->measurementFrame[2][2] = mf[8]; if (nrrdSave(outS, nout, NULL)) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble writing:\n%s\n", me, err); airMopError(mop); return 1; } airMopOkay(mop); return 0; }
int main() { airArray *mop, *submop; char *err; int typi; unsigned int supi, probePass, cti /* context copy index */, pvlIdx[NRRD_TYPE_MAX+1], sx, sy, sz, subnum; size_t sizes[3] = {42,61,50} /* one of these must be even */, ii, nn; Nrrd *norigScl, *nucharScl, *nunquant, *nqdiff, *nconvScl[NRRD_TYPE_MAX+1]; unsigned char *ucharScl; gageContext *gctx[2][KERN_SIZE_MAX+1]; gagePerVolume *gpvl[2][NRRD_TYPE_MAX+1][KERN_SIZE_MAX+1]; const double *vansScl[2][NRRD_TYPE_MAX+1][KERN_SIZE_MAX+1], *gansScl[2][NRRD_TYPE_MAX+1][KERN_SIZE_MAX+1], *hansScl[2][NRRD_TYPE_MAX+1][KERN_SIZE_MAX+1]; double *origScl, omin, omax, dsx, dsy, dsz, spcOrig[NRRD_SPACE_DIM_MAX] = {0.0, 0.0, 0.0}, spcVec[3][NRRD_SPACE_DIM_MAX] = { {1.1, 0.0, 0.0}, {0.0, 2.2, 0.0}, {0.0, 0.0, 3.3}}; mop = airMopNew(); #define NRRD_NEW(name, mop) \ (name) = nrrdNew(); \ airMopAdd((mop), (name), (airMopper)nrrdNuke, airMopAlways) /* --------------------------------------------------------------- */ /* Creating initial volume */ NRRD_NEW(norigScl, mop); if (nrrdMaybeAlloc_nva(norigScl, nrrdTypeDouble, 3, sizes)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "trouble allocating:\n%s", err); airMopError(mop); return 1; } origScl = AIR_CAST(double *, norigScl->data); nn = nrrdElementNumber(norigScl); airSrandMT(42*42); for (ii=0; ii<nn/2; ii++) { airNormalRand(origScl + 2*ii + 0, origScl + 2*ii + 1); } /* learn real range */ omin = omax = origScl[0]; for (ii=1; ii<nn; ii++) { omin = AIR_MIN(omin, origScl[ii]); omax = AIR_MAX(omax, origScl[ii]); } ELL_3V_SET(spcOrig, 0.0, 0.0, 0.0); if (nrrdSpaceSet(norigScl, nrrdSpaceRightAnteriorSuperior) || nrrdSpaceOriginSet(norigScl, spcOrig)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "trouble setting space:\n%s", err); airMopError(mop); return 1; } nrrdAxisInfoSet_nva(norigScl, nrrdAxisInfoSpaceDirection, spcVec); dsx = AIR_CAST(double, sizes[0]); dsy = AIR_CAST(double, sizes[1]); dsz = AIR_CAST(double, sizes[2]); sx = AIR_CAST(unsigned int, sizes[0]); sy = AIR_CAST(unsigned int, sizes[1]); sz = AIR_CAST(unsigned int, sizes[2]); subnum = AIR_CAST(unsigned int, PROBE_NUM*0.9); /* --------------------------------------------------------------- */ /* Quantizing to 8-bits and checking */ submop = airMopNew(); NRRD_NEW(nucharScl, mop); NRRD_NEW(nunquant, submop); NRRD_NEW(nqdiff, submop); if (nrrdQuantize(nucharScl, norigScl, NULL, 8) || nrrdUnquantize(nunquant, nucharScl, nrrdTypeDouble) || nrrdArithBinaryOp(nqdiff, nrrdBinaryOpSubtract, norigScl, nunquant)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "trouble quantizing and back:\n%s", err); airMopError(submop); airMopError(mop); return 1; } if (!( nucharScl->oldMin == omin && nucharScl->oldMax == omax )) { fprintf(stderr, "quantization range [%g,%g] != real range [%g,%g]\n", nucharScl->oldMin, nucharScl->oldMax, omin, omax); airMopError(submop); airMopError(mop); return 1; } { double *qdiff, *unquant; /* empirically determined tolerance, which had to be increased in order to work under valgrind (!)- perhaps because of a difference in the use of 80-bit registers */ double epsilon=0.50000000000004; qdiff = AIR_CAST(double *, nqdiff->data); unquant = AIR_CAST(double *, nunquant->data); for (ii=0; ii<nn; ii++) { double dd; /* with infinite precision, the max difference between original and quantized values should be exactly half the width (in value) of 1/256 of value range ==> dd = 0.5 */ dd = qdiff[ii]*256/(omax - omin); if (AIR_ABS(dd) > epsilon) { unsigned int ui; ui = AIR_CAST(unsigned int, ii); fprintf(stderr, "|orig[%u]=%.17g - unquant=%.17g|*256/%.17g " "= %.17g > %.17g!\n", ui, origScl[ii], unquant[ii], omax - omin, AIR_ABS(dd), epsilon); airMopError(submop); airMopError(mop); return 1; } } }
int unrrdu_basinfoMain(int argc, const char **argv, const char *me, hestParm *hparm) { /* these are stock for unrrdu */ hestOpt *opt = NULL; airArray *mop; int pret; char *err; /* these are stock for things using the usual -i and -o */ char *out; Nrrd *nin, *nout; /* these are specific to this command */ NrrdIoState *nio; char *spcStr, *_origStr, *origStr; int space; unsigned int spaceDim; hestOptAdd(&opt, "spc,space", "space", airTypeString, 1, 1, &spcStr, "", "identify the space (e.g. \"RAS\", \"LPS\") in which the array " "conceptually lives, from the nrrdSpace airEnum, which in turn " "determines the dimension of the space. Or, use an integer>0 to" "give the dimension of a space that nrrdSpace doesn't know about. " "By default (not using this option), the enclosing space is " "set as unknown."); hestOptAdd(&opt, "orig,origin", "origin", airTypeString, 1, 1, &_origStr, "", "(NOTE: must quote vector) the origin in space of the array: " "the location of the center " "of the first sample, of the form \"(x,y,z)\" (or however " "many coefficients are needed for the chosen space). Quoting the " "vector is needed to stop interpretation from the shell"); OPT_ADD_NIN(nin, "input nrrd"); OPT_ADD_NOUT(out, "output nrrd"); mop = airMopNew(); airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways); nio = nrrdIoStateNew(); airMopAdd(mop, nio, (airMopper)nrrdIoStateNix, airMopAlways); USAGE(_unrrdu_basinfoInfoL); PARSE(); airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways); nout = nrrdNew(); airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); if (nrrdCopy(nout, nin)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error copying input:\n%s", me, err); airMopError(mop); return 1; } /* HEY: copy and paste from unrrdu/make.c */ if (airStrlen(spcStr)) { space = airEnumVal(nrrdSpace, spcStr); if (!space) { /* couldn't parse it as space, perhaps its a uint */ if (1 != sscanf(spcStr, "%u", &spaceDim)) { fprintf(stderr, "%s: couldn't parse \"%s\" as a nrrdSpace " "or as a uint", me, spcStr); airMopError(mop); return 1; } /* else we did parse it as a uint */ nout->space = nrrdSpaceUnknown; nout->spaceDim = spaceDim; } else { /* we did parse a known space */ nrrdSpaceSet(nout, space); } } /* HEY: copy and paste from unrrdu/make.c */ if (airStrlen(_origStr)) { /* why this is necessary is a bit confusing to me, both the check for enclosing quotes, and the need to use to a separate variable (isn't hest doing memory management of addresses, not variables?) */ if ('\"' == _origStr[0] && '\"' == _origStr[strlen(_origStr)-1]) { _origStr[strlen(_origStr)-1] = 0; origStr = _origStr + 1; } else { origStr = _origStr; } /* same hack about using NrrdIoState->line as basis for parsing */ nio->line = origStr; nio->pos = 0; if (nrrdFieldInfoParse[nrrdField_space_origin](NULL, nout, nio, AIR_TRUE)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble with origin \"%s\":\n%s", me, origStr, err); nio->line = NULL; airMopError(mop); return 1; } nio->line = NULL; } SAVE(out, nout, NULL); airMopOkay(mop); return 0; }