/* ** note that if tgparm->insertZeroVec, there will be one sample more ** along axis 1 of nout than the requested #gradients "num" */ int tenGradientGenerate(Nrrd *nout, unsigned int num, tenGradientParm *tgparm) { static const char me[]="tenGradientGenerate"; Nrrd *nin; airArray *mop; if (!(nout && tgparm)) { biffAddf(TEN, "%s: got NULL pointer", me); return 1; } if (!( num >= 3 )) { biffAddf(TEN, "%s: can generate minimum of 3 gradient directions " "(not %d)", me, num); return 1; } mop = airMopNew(); nin = nrrdNew(); airMopAdd(mop, nin, (airMopper)nrrdNuke, airMopAlways); if (tenGradientRandom(nin, num, tgparm->seed) || tenGradientDistribute(nout, nin, tgparm)) { biffAddf(TEN, "%s: trouble", me); airMopError(mop); return 1; } if (tgparm->insertZeroVec) { /* this is potentially confusing: the second axis (axis 1) is going to come back one longer than the requested number of gradients! */ Nrrd *ntmp; ptrdiff_t padMin[2] = {0, -1}, padMax[2]; padMax[0] = AIR_CAST(ptrdiff_t, nout->axis[0].size-1); padMax[1] = AIR_CAST(ptrdiff_t, num-1); ntmp = nrrdNew(); airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); if (nrrdPad_nva(ntmp, nout, padMin, padMax, nrrdBoundaryPad, 0.0) || nrrdCopy(nout, ntmp)) { biffMovef(TEN, NRRD, "%s: trouble adding zero vector", me); airMopError(mop); return 1; } } airMopOkay(mop); return 0; }
int unrrdu_fftMain(int argc, const char **argv, const char *me, hestParm *hparm) { hestOpt *opt = NULL; char *out, *err; Nrrd *nin, *_nin, *nout; int pret; airArray *mop; int sign, rigor, rescale, realInput; char *wispath; FILE *fwise; unsigned int *axes, axesLen; hestOptAdd(&opt, NULL, "dir", airTypeEnum, 1, 1, &sign, NULL, "forward (\"forw\", \"f\") or backward/inverse " "(\"back\", \"b\") transform ", NULL, direction_enm); hestOptAdd(&opt, "a,axes", "ax0", airTypeUInt, 1, -1, &axes, NULL, "the one or more axes that should be transformed", &axesLen); hestOptAdd(&opt, "pr,planrigor", "pr", airTypeEnum, 1, 1, &rigor, "est", "rigor with which fftw plan is constructed. Options include:\n " "\b\bo \"e\", \"est\", \"estimate\": only an estimate\n " "\b\bo \"m\", \"meas\", \"measure\": standard amount of " "measurements of system properties\n " "\b\bo \"p\", \"pat\", \"patient\": slower, more measurements\n " "\b\bo \"x\", \"ex\", \"exhaustive\": slowest, most measurements", NULL, nrrdFFTWPlanRigor); hestOptAdd(&opt, "r,rescale", "bool", airTypeBool, 1, 1, &rescale, "true", "scale fftw output (by sqrt(1/N)) so that forward and backward " "transforms will get back to original values"); hestOptAdd(&opt, "w,wisdom", "filename", airTypeString, 1, 1, &wispath, "", "A filename here is used to read in fftw wisdom (if the file " "exists already), and is used to save out updated wisdom " "after the transform. By default (not using this option), " "no wisdom is read or saved. Note: no wisdom is gained " "(that is, learned by FFTW) with planning rigor \"estimate\"."); OPT_ADD_NIN(_nin, "input nrrd"); hestOptAdd(&opt, "ri,realinput", NULL, airTypeInt, 0, 0, &realInput, NULL, "input is real-valued, so insert new length-2 axis 0 " "and set complex component to 0.0. Axes to transform " "(indicated by \"-a\") will be incremented accordingly."); OPT_ADD_NOUT(out, "output nrrd"); mop = airMopNew(); airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways); if (nrrdFFTWEnabled) { USAGE(_unrrdu_fftInfoL_yes); } else { USAGE(_unrrdu_fftInfoL_no); } PARSE(); airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways); nout = nrrdNew(); airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); if (realInput) { ptrdiff_t minPad[NRRD_DIM_MAX], maxPad[NRRD_DIM_MAX]; unsigned int axi; Nrrd *ntmp; ntmp = nrrdNew(); airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); if (nrrdAxesInsert(ntmp, _nin, 0)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error creating complex axis:\n%s", me, err); airMopError(mop); return 1; } nin = nrrdNew(); airMopAdd(mop, nin, (airMopper)nrrdNuke, airMopAlways); minPad[0] = 0; maxPad[0] = 1; for (axi=1; axi<ntmp->dim; axi++) { minPad[axi] = 0; maxPad[axi] = AIR_CAST(ptrdiff_t, ntmp->axis[axi].size-1); } if (nrrdPad_nva(nin, ntmp, minPad, maxPad, nrrdBoundaryPad, 0.0)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error padding out complex axis:\n%s", me, err); airMopError(mop); return 1; } /* increment specified axes to transform */ for (axi=0; axi<axesLen; axi++) { axes[axi]++; } /* ntmp is really done with, we can free up the space now; this is one of the rare times we want airMopSub */ airMopSub(mop, ntmp, (airMopper)nrrdNuke); nrrdNuke(ntmp); } else { /* input is apparently already complex */ nin = _nin; } if (airStrlen(wispath) && nrrdFFTWEnabled) { fwise = fopen(wispath, "r"); if (fwise) { if (nrrdFFTWWisdomRead(fwise)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error with fft wisdom:\n%s", me, err); airMopError(mop); return 1; } fclose(fwise); } else { fprintf(stderr, "%s: (\"%s\" couldn't be opened, will try to save " "wisdom afterwards)", me, wispath); } } if (nrrdFFT(nout, nin, axes, axesLen, sign, rescale, rigor)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error with fft:\n%s", me, err); airMopError(mop); return 1; } if (airStrlen(wispath) && nrrdFFTWEnabled) { if (!(fwise = fopen(wispath, "w"))) { fprintf(stderr, "%s: couldn't open %s for writing: %s\n", me, wispath, strerror(errno)); airMopError(mop); return 1; } if (nrrdFFTWWisdomWrite(fwise)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error with fft wisdom:\n%s", me, err); airMopError(mop); return 1; } fclose(fwise); } SAVE(out, nout, NULL); airMopOkay(mop); return 0; }
int unrrdu_padMain(int argc, char **argv, char *me, hestParm *hparm) { hestOpt *opt = NULL; char *out, *err; Nrrd *nin, *nout; unsigned int ai; int minLen, maxLen, bb, pret; long int *minOff, *maxOff; ptrdiff_t min[NRRD_DIM_MAX], max[NRRD_DIM_MAX]; double padVal; airArray *mop; OPT_ADD_BOUND("min,minimum", minOff, "low corner of bounding box.\n " "\b\bo <int> gives 0-based index\n " "\b\bo M, M+<int>, M-<int> give index relative " "to the last sample on the axis (M == #samples-1).", minLen); OPT_ADD_BOUND("max,maximum", maxOff, "high corner of bounding box. " "Besides the specification styles described above, " "there's also:\n " "\b\bo m+<int> give index relative to minimum.", maxLen); hestOptAdd(&opt, "b,boundary", "behavior", airTypeEnum, 1, 1, &bb, "bleed", "How to handle samples beyond the input bounds:\n " "\b\bo \"pad\": use some specified value\n " "\b\bo \"bleed\": extend border values outward\n " "\b\bo \"wrap\": wrap-around to other side", NULL, nrrdBoundary); hestOptAdd(&opt, "v,value", "val", airTypeDouble, 1, 1, &padVal, "0.0", "for \"pad\" boundary behavior, pad with this value"); OPT_ADD_NIN(nin, "input nrrd"); OPT_ADD_NOUT(out, "output nrrd"); mop = airMopNew(); airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways); USAGE(_unrrdu_padInfoL); /* hammerhead problems were here */ PARSE(); airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways); if (!( minLen == (int)nin->dim && maxLen == (int)nin->dim )) { fprintf(stderr, "%s: # min coords (%d) or max coords (%d) != nrrd dim (%d)\n", me, minLen, maxLen, nin->dim); airMopError(mop); return 1; } for (ai=0; ai<nin->dim; ai++) { if (-1 == minOff[0 + 2*ai]) { fprintf(stderr, "%s: can't use m+<int> specification for axis %d min\n", me, ai); airMopError(mop); return 1; } } for (ai=0; ai<nin->dim; ai++) { min[ai] = minOff[0 + 2*ai]*(nin->axis[ai].size-1) + minOff[1 + 2*ai]; if (-1 == maxOff[0 + 2*ai]) { max[ai] = min[ai] + maxOff[1 + 2*ai]; } else { max[ai] = maxOff[0 + 2*ai]*(nin->axis[ai].size-1) + maxOff[1 + 2*ai]; } /* fprintf(stderr, "%s: ai %2d: min = %4d, max = %4d\n", me, ai, min[ai], mai[ai]); */ } nout = nrrdNew(); airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); if (nrrdPad_nva(nout, nin, min, max, bb, padVal)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error padding nrrd:\n%s", me, err); airMopError(mop); return 1; } SAVE(out, nout, NULL); airMopOkay(mop); return 0; }