int _alanPerIteration(alanContext *actx, int iter) { char me[]="_alanPerIteration", fname[AIR_STRLEN_MED]; Nrrd *nslc, *nimg; if (!(actx->saveInterval || actx->frameInterval)) { if (actx->verbose && !(iter % 100)) { fprintf(stderr, "%s: iter = %d, averageChange = %g\n", me, iter, actx->averageChange); } } if (actx->saveInterval && !(iter % actx->saveInterval)) { sprintf(fname, "%06d.nrrd", actx->constFilename ? 0 : iter); nrrdSave(fname, actx->_nlev[(iter+1) % 2], NULL); fprintf(stderr, "%s: iter = %d, averageChange = %g, saved %s\n", me, iter, actx->averageChange, fname); } if (actx->frameInterval && !(iter % actx->frameInterval)) { nrrdSlice(nslc=nrrdNew(), actx->_nlev[(iter+1) % 2], 0, 0); nrrdQuantize(nimg=nrrdNew(), nslc, NULL, 8); sprintf(fname, (2 == actx->dim ? "%06d.png" : "%06d.nrrd"), actx->constFilename ? 0 : iter); nrrdSave(fname, nimg, NULL); fprintf(stderr, "%s: iter = %d, averageChange = %g, saved %s\n", me, iter, actx->averageChange, fname); nrrdNuke(nslc); nrrdNuke(nimg); } return 0; }
/* ******** coilOutputGet ** ** slice the present intermediate volume to get an output. ** ** No, this does not do quantization or rounding to match the input ** type (of cctx->nin). The reason is that after filtering, it is often ** the case that subtle differences in values emerge, and it may be ** reckless to dump them back into the limited type or value range ** that they started with. That sort of operation should be under ** explicit user control. */ int coilOutputGet(Nrrd *nout, coilContext *cctx) { static const char me[]="coilOutputGet"; int baseDim; if (!(nout && cctx)) { biffAddf(COIL, "%s: got NULL pointer", me); return 1; } baseDim = (1 == cctx->kind->valLen ? 0 : 1); if (nrrdSlice(nout, cctx->nvol, baseDim, 0) || nrrdAxisInfoCopy(nout, cctx->nin, NULL, NRRD_AXIS_INFO_NONE) || nrrdBasicInfoCopy(nout, cctx->nin, NRRD_BASIC_INFO_DATA_BIT | NRRD_BASIC_INFO_TYPE_BIT | NRRD_BASIC_INFO_BLOCKSIZE_BIT | NRRD_BASIC_INFO_DIMENSION_BIT | NRRD_BASIC_INFO_CONTENT_BIT | NRRD_BASIC_INFO_COMMENTS_BIT | (nrrdStateKeyValuePairsPropagate ? 0 : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) { biffMovef(COIL, NRRD, "%s: trouble getting output", me); return 1; } return 0; }
int unrrdu_diceMain(int argc, const char **argv, const char *me, hestParm *hparm) { hestOpt *opt = NULL; char *base, *err, fnout[AIR_STRLEN_MED], /* file name out */ fffname[AIR_STRLEN_MED], /* format for filename */ *ftmpl; /* format template */ Nrrd *nin, *nout; int pret, fit; unsigned int axis, start, pos, top, size, sanity; airArray *mop; OPT_ADD_AXIS(axis, "axis to slice along"); OPT_ADD_NIN(nin, "input nrrd"); hestOptAdd(&opt, "s,start", "start", airTypeUInt, 1, 1, &start, "0", "integer value to start numbering with"); hestOptAdd(&opt, "ff,format", "form", airTypeString, 1, 1, &ftmpl, "", "a printf-style format to use for generating all " "filenames. Use this to override the number of characters " "used to represent the slice position, or the file format " "of the output, e.g. \"-ff %03d.ppm\" for 000.ppm, " "001.ppm, etc. By default (not using this option), slices " "are saved in NRRD format (or PNM or PNG where possible) " "with shortest possible filenames."); /* the fact that we're using unsigned int instead of size_t is its own kind of sanity check */ hestOptAdd(&opt, "l,limit", "max#", airTypeUInt, 1, 1, &sanity, "9999", "a sanity check on how many slice files should be saved " "out, to prevent accidentally dicing the wrong axis " "or the wrong array. Can raise this value if needed."); hestOptAdd(&opt, "o,output", "prefix", airTypeString, 1, 1, &base, NULL, "output filename prefix (excluding info set via \"-ff\"), " "basically to set path of output files (so be sure to end " "with \"/\"."); mop = airMopNew(); airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways); USAGE(_unrrdu_diceInfoL); PARSE(); airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways); if (!( axis < nin->dim )) { fprintf(stderr, "%s: given axis (%u) outside range [0,%u]\n", me, axis, nin->dim-1); airMopError(mop); return 1; } if (nin->axis[axis].size > sanity) { char stmp[AIR_STRLEN_SMALL]; fprintf(stderr, "%s: axis %u size %s > sanity limit %u; " "increase via \"-l\"\n", me, axis, airSprintSize_t(stmp, nin->axis[axis].size), sanity); airMopError(mop); return 1; } size = AIR_UINT(nin->axis[axis].size); /* HEY: this should use nrrdSaveMulti(), and if there's additional smarts here, they should be moved into nrrdSaveMulti() */ if (airStrlen(ftmpl)) { if (!( _nrrdContainsPercentThisAndMore(ftmpl, 'd') || _nrrdContainsPercentThisAndMore(ftmpl, 'u') )) { fprintf(stderr, "%s: given filename format \"%s\" doesn't seem to " "have the converstion specification to print an integer\n", me, ftmpl); airMopError(mop); return 1; } sprintf(fffname, "%%s%s", ftmpl); } else { unsigned int dignum=0, tmps; tmps = top = start + size - 1; do { dignum++; tmps /= 10; } while (tmps); /* sprintf the number of digits into the string that will be used to sprintf the slice number into the filename */ sprintf(fffname, "%%s%%0%uu.nrrd", dignum); } nout = nrrdNew(); airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); for (pos=0; pos<size; pos++) { if (nrrdSlice(nout, nin, axis, pos)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error slicing nrrd:%s\n", me, err); airMopError(mop); return 1; } if (0 == pos && !airStrlen(ftmpl)) { /* See if these slices would be better saved as PNG or PNM images. Altering the file name will tell nrrdSave() to use a different file format. We wait till now to check this so that we can work from the actual slice */ if (nrrdFormatPNG->fitsInto(nout, nrrdEncodingRaw, AIR_FALSE)) { strcpy(fffname + strlen(fffname) - 4, "png"); } else { fit = nrrdFormatPNM->fitsInto(nout, nrrdEncodingRaw, AIR_FALSE); if (2 == fit) { strcpy(fffname + strlen(fffname) - 4, "pgm"); } else if (3 == fit) { strcpy(fffname + strlen(fffname) - 4, "ppm"); } } } sprintf(fnout, fffname, base, pos+start); fprintf(stderr, "%s: %s ...\n", me, fnout); if (nrrdSave(fnout, nout, NULL)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error writing nrrd to \"%s\":%s\n", me, fnout, err); airMopError(mop); return 1; } } airMopOkay(mop); return 0; }
int tend_estimThresholdFind(double *threshP, Nrrd *nbmat, Nrrd *nin4d) { char me[]="tend_estimThresholdFind", err[BIFF_STRLEN]; Nrrd **ndwi; airArray *mop; unsigned int slIdx, slNum, dwiAx, dwiNum, rangeAxisNum, rangeAxisIdx[NRRD_DIM_MAX]; double *bmat, bten[7], bnorm; int dwiIdx; mop = airMopNew(); if (!(threshP && nbmat && nin4d)) { sprintf(err, "%s: got NULL pointer", me); biffAdd(TEN, err); airMopError(mop); return 1; } if (tenBMatrixCheck(nbmat, nrrdTypeDouble, 6)) { sprintf(err, "%s: problem within given b-matrix", me); biffAdd(TEN, err); airMopError(mop); return 1; } /* HEY: copied from tenEpiRegister4D() */ rangeAxisNum = nrrdRangeAxesGet(nin4d, rangeAxisIdx); if (0 == rangeAxisNum) { /* we fall back on old behavior */ dwiAx = 0; } else if (1 == rangeAxisNum) { /* thankfully there's exactly one range axis */ dwiAx = rangeAxisIdx[0]; } else { sprintf(err, "%s: have %u range axes instead of 1, don't know which " "is DWI axis", me, rangeAxisNum); biffAdd(TEN, err); airMopError(mop); return 1; } slNum = nin4d->axis[dwiAx].size; bmat = AIR_CAST(double *, nbmat->data); dwiNum = 0; for (slIdx=0; slIdx<slNum; slIdx++) { TEN_T_SET(bten, 1.0, bmat[0], bmat[1], bmat[2], bmat[3], bmat[4], bmat[5]); bnorm = TEN_T_NORM(bten); dwiNum += bnorm > 0.0; bmat += 6; } if (0 == dwiNum) { sprintf(err, "%s: somehow got zero DWIs", me); biffAdd(TEN, err); airMopError(mop); return 1; } ndwi = AIR_CAST(Nrrd **, calloc(dwiNum, sizeof(Nrrd *))); airMopAdd(mop, ndwi, (airMopper)airFree, airMopAlways); bmat = AIR_CAST(double *, nbmat->data); dwiIdx = -1; for (slIdx=0; slIdx<slNum; slIdx++) { TEN_T_SET(bten, 1.0, bmat[0], bmat[1], bmat[2], bmat[3], bmat[4], bmat[5]); bnorm = TEN_T_NORM(bten); if (bnorm > 0.0) { dwiIdx++; ndwi[dwiIdx] = nrrdNew(); airMopAdd(mop, ndwi[dwiIdx], (airMopper)nrrdNuke, airMopAlways); if (nrrdSlice(ndwi[dwiIdx], nin4d, dwiAx, slIdx)) { sprintf(err, "%s: trouble slicing DWI at index %u", me, slIdx); biffMove(TEN, err, NRRD); airMopError(mop); return 1; } } bmat += 6; } if (_tenEpiRegThresholdFind(threshP, ndwi, dwiNum, AIR_FALSE, 1.5)) { sprintf(err, "%s: trouble finding thresh", me); biffAdd(TEN, err); airMopError(mop); return 1; } airMopOkay(mop); return 0; }
int unrrdu_diceMain(int argc, char **argv, char *me, hestParm *hparm) { hestOpt *opt = NULL; char *base, *err, fnout[AIR_STRLEN_MED], /* file name out */ fffname[AIR_STRLEN_MED], /* format for filename */ *ftmpl; /* format template */ Nrrd *nin, *nout; int top, pret, start, fit; unsigned int axis; size_t pos; airArray *mop; OPT_ADD_AXIS(axis, "axis to slice along"); OPT_ADD_NIN(nin, "input nrrd"); hestOptAdd(&opt, "s,start", "start", airTypeInt, 1, 1, &start, "0", "integer value to start numbering with"); hestOptAdd(&opt, "ff,format", "form", airTypeString, 1, 1, &ftmpl, "", "a printf-style format to use for generating all " "filenames. Use this to override the number of characters " "used to represent the slice position, or the file format " "of the output, e.g. \"-ff %03d.ppm\" for 000.ppm, " "001.ppm, etc. By default (not using this option), slices " "are saved in NRRD format (or PNM or PNG where possible) " "with shortest possible filenames."); hestOptAdd(&opt, "o,output", "prefix", airTypeString, 1, 1, &base, NULL, "output filename prefix (excluding info set via \"-ff\"), " "basically to set path of output files (so be sure to end " "with \"/\"."); mop = airMopNew(); airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways); USAGE(_unrrdu_diceInfoL); PARSE(); airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways); if (start < 0) { fprintf(stderr, "%s: given start index (%d) less than zero\n", me, start); airMopError(mop); return 1; } if (!( axis < nin->dim )) { fprintf(stderr, "%s: given axis (%u) outside range [0,%u]\n", me, axis, nin->dim-1); airMopError(mop); return 1; } /* HEY: this should use nrrdSaveMulti(), and if there's additional smarts here, they should be moved into nrrdSaveMulti() */ if (airStrlen(ftmpl)) { if (!( _nrrdContainsPercentThisAndMore(ftmpl, 'd') || _nrrdContainsPercentThisAndMore(ftmpl, 'u') )) { fprintf(stderr, "%s: given filename format \"%s\" doesn't seem to " "have the converstion specification to print an integer\n", me, ftmpl); airMopError(mop); return 1; } sprintf(fffname, "%%s%s", ftmpl); } else { top = start + nin->axis[axis].size-1; if (top > 9999999) { sprintf(fffname, "%%s%%08d.nrrd"); } else if (top > 999999) { sprintf(fffname, "%%s%%07d.nrrd"); } else if (top > 99999) { sprintf(fffname, "%%s%%06d.nrrd"); } else if (top > 9999) { sprintf(fffname, "%%s%%05d.nrrd"); } else if (top > 999) { sprintf(fffname, "%%s%%04d.nrrd"); } else if (top > 99) { sprintf(fffname, "%%s%%03d.nrrd"); } else if (top > 9) { sprintf(fffname, "%%s%%02d.nrrd"); } else { sprintf(fffname, "%%s%%01d.nrrd"); } } nout = nrrdNew(); airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); for (pos=0; pos<nin->axis[axis].size; pos++) { if (nrrdSlice(nout, nin, axis, pos)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error slicing nrrd:%s\n", me, err); airMopError(mop); return 1; } if (0 == pos && !airStrlen(ftmpl)) { /* See if these slices would be better saved as PNG or PNM images. Altering the file name will tell nrrdSave() to use a different file format. */ if (nrrdFormatPNG->fitsInto(nout, nrrdEncodingRaw, AIR_FALSE)) { strcpy(fffname + strlen(fffname) - 4, "png"); } else { fit = nrrdFormatPNM->fitsInto(nout, nrrdEncodingRaw, AIR_FALSE); if (2 == fit) { strcpy(fffname + strlen(fffname) - 4, "pgm"); } else if (3 == fit) { strcpy(fffname + strlen(fffname) - 4, "ppm"); } } } sprintf(fnout, fffname, base, pos+start); fprintf(stderr, "%s: %s ...\n", me, fnout); if (nrrdSave(fnout, nout, NULL)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error writing nrrd to \"%s\":%s\n", me, fnout, err); airMopError(mop); return 1; } } airMopOkay(mop); return 0; }
int unrrdu_cmedianMain(int argc, char **argv, char *me, hestParm *hparm) { hestOpt *opt = NULL; char *out, *err; Nrrd *nin, *nout, *ntmp, **mnout; int pad, pret, mode, chan, ni, nsize; unsigned int bins, radius; airArray *mop; float wght; hestOptAdd(&opt, "r,radius", "radius", airTypeUInt, 1, 1, &radius, NULL, "how big a window to filter over. \"-r 1\" leads to a " "3x3 window in an image, and a 3x3x3 window in a volume"); hestOptAdd(&opt, "mode", NULL, airTypeInt, 0, 0, &mode, NULL, "By default, median filtering is done. Using this option " "enables mode filtering, in which the most common value is " "used as output"); hestOptAdd(&opt, "b,bins", "num", airTypeUInt, 1, 1, &bins, "256", "# of bins in histogram. It is in your interest to minimize " "this number, since big histograms mean slower execution " "times. 8-bit data needs at most 256 bins."); hestOptAdd(&opt, "w,weight", "weight", airTypeFloat, 1, 1, &wght, "1.0", "How much higher to preferentially weight samples that are " "closer to the center of the window. \"1.0\" weight means that " "all samples are uniformly weighted over the window, which " "facilitates a simple speed-up. "); hestOptAdd(&opt, "p,pad", NULL, airTypeInt, 0, 0, &pad, NULL, "Pad the input (with boundary method \"bleed\"), " "and crop the output, so as to " "overcome our cheapness and correctly " "handle the border. Obviously, this takes more memory."); hestOptAdd(&opt, "c,channel", NULL, airTypeInt, 0, 0, &chan, NULL, "Slice the input along axis 0, run filtering on all slices, " "and join the results back together. This is the way you'd " "want to process color (multi-channel) images or volumes."); OPT_ADD_NIN(nin, "input nrrd"); OPT_ADD_NOUT(out, "output nrrd"); mop = airMopNew(); airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways); USAGE(_unrrdu_cmedianInfoL); PARSE(); airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways); nout = nrrdNew(); airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); if (chan) { nsize = nin->axis[0].size; mnout = (Nrrd **)calloc(nsize, sizeof(Nrrd)); airMopAdd(mop, mnout, airFree, airMopAlways); ntmp = nrrdNew(); airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways); for (ni=0; ni<nsize; ni++) { if (nrrdSlice(ntmp, nin, 0, ni)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error slicing input at pos = %d:\n%s", me, ni, err); airMopError(mop); return 1; } airMopAdd(mop, mnout[ni] = nrrdNew(), (airMopper)nrrdNuke, airMopAlways); if (nrrdCheapMedian(mnout[ni], ntmp, pad, mode, radius, wght, bins)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error doing cheap median:\n%s", me, err); airMopError(mop); return 1; } } if (nrrdJoin(nout, (const Nrrd**)mnout, nsize, 0, AIR_TRUE)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error doing final join:\n%s", me, err); airMopError(mop); return 1; } } else { if (nrrdCheapMedian(nout, nin, pad, mode, radius, wght, bins)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error doing cheap median:\n%s", me, err); airMopError(mop); return 1; } } SAVE(out, nout, NULL); airMopOkay(mop); return 0; }
int unrrdu_lut2Main(int argc, char **argv, char *me, hestParm *hparm) { hestOpt *opt = NULL; char *out, *err; Nrrd *nin, *nlut, *nout, *ntmp[2]; airArray *mop; int typeOut, rescale[2], pret, blind8BitRange; double min[2], max[2]; NrrdRange *range[2]={NULL,NULL}; unsigned int mapAxis, rai; hestOptAdd(&opt, "m,map", "lut", airTypeOther, 1, 1, &nlut, NULL, "lookup table to map input nrrd through", NULL, NULL, nrrdHestNrrd); hestOptAdd(&opt, "r,rescale", "bool bool", airTypeBool, 2, 2, rescale, "false false", "rescale one or both of the input values from the " "input range to the lut domain. The lut domain is either " "explicitly defined by the axis min,max along axis 0 or 1, " "or, it is implicitly defined as zero to the length of that axis " "minus one."); hestOptAdd(&opt, "min,minimum", "min0 min1", airTypeDouble, 2, 2, min, "nan nan", "Low ends of input range. Defaults to lowest values " "found in input nrrd. Explicitly setting this is useful " "only with rescaling (\"-r\")"); hestOptAdd(&opt, "max,maximum", "max0 max1", airTypeDouble, 2, 2, max, "nan nan", "High end of input range. Defaults to highest values " "found in input nrrd. Explicitly setting this is useful " "only with rescaling (\"-r\")"); hestOptAdd(&opt, "blind8", "bool", airTypeBool, 1, 1, &blind8BitRange, nrrdStateBlind8BitRange ? "true" : "false", "Whether to know the range of 8-bit data blindly " "(uchar is always [0,255], signed char is [-128,127]). " "Explicitly setting this is useful only with rescaling (\"-r\")"); hestOptAdd(&opt, "t,type", "type", airTypeOther, 1, 1, &typeOut, "default", "specify the type (\"int\", \"float\", etc.) of the " "output nrrd. " "By default (not using this option), the output type " "is the lut's type.", NULL, NULL, &unrrduHestMaybeTypeCB); OPT_ADD_NIN(nin, "input nrrd"); OPT_ADD_NOUT(out, "output nrrd"); mop = airMopNew(); airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways); USAGE(_unrrdu_lut2InfoL); PARSE(); airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways); nout = nrrdNew(); airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); if (!( nin->dim > 1 && 2 == nin->axis[0].size )) { fprintf(stderr, "%s: input nrrd dim must be > 1, and axis[0].size " "must be 2 (not " _AIR_SIZE_T_CNV ")", me, nin->axis[0].size); airMopError(mop); return 1; } mapAxis = nlut->dim - 2; if (!(0 == mapAxis || 1 == mapAxis)) { fprintf(stderr, "%s: dimension of lut should be 2 or 3, not %d", me, nlut->dim); airMopError(mop); return 1; } /* see comment in rmap.c */ for (rai=0; rai<=1; rai++) { if (!( AIR_EXISTS(nlut->axis[mapAxis + rai].min) && AIR_EXISTS(nlut->axis[mapAxis + rai].max) )) { rescale[rai] = AIR_TRUE; } if (rescale[rai]) { ntmp[rai] = nrrdNew(); airMopAdd(mop, ntmp[rai], AIR_CAST(airMopper, nrrdNuke), airMopAlways); if (nrrdSlice(ntmp[rai], nin, 0, rai)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble slicing input value %u:\n%s", me, rai, err); airMopError(mop); return 1; } range[rai] = nrrdRangeNew(min[rai], max[rai]); airMopAdd(mop, range[rai], (airMopper)nrrdRangeNix, airMopAlways); nrrdRangeSafeSet(range[rai], ntmp[rai], blind8BitRange); } } if (nrrdTypeDefault == typeOut) { typeOut = nlut->type; } if (nrrdApply2DLut(nout, nin, 0, range[0], range[1], nlut, typeOut, rescale[0], rescale[1])) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble applying 2-D LUT:\n%s", me, err); airMopError(mop); return 1; } SAVE(out, nout, NULL); airMopOkay(mop); return 0; }
int main(int argc, char *argv[]) { char *me, *err; hestOpt *hopt=NULL; airArray *mop; char *outTenS, *outCovarS, *outRmvS; int seed, E; unsigned int NN; Nrrd *_ninTen, *ninTen, *ngrad, *_ninB0, *ninB0, *nmask, *noutCovar, *noutTen, *noutRmv, *ntbuff; float sigma, bval; size_t sizeX, sizeY, sizeZ; tenEstimateContext *tec; int axmap[NRRD_DIM_MAX], randrot; mop = airMopNew(); me = argv[0]; hestOptAdd(&hopt, "i", "ten", airTypeOther, 1, 1, &_ninTen, NULL, "input tensor volume", NULL, NULL, nrrdHestNrrd); hestOptAdd(&hopt, "n", "#sim", airTypeUInt, 1, 1, &NN, "100", "number of simulations to run"); hestOptAdd(&hopt, "seed", "seed", airTypeInt, 1, 1, &seed, "42", "seed value for RNG which creates noise"); hestOptAdd(&hopt, "r", "reference field", airTypeOther, 1, 1, &_ninB0, NULL, "reference anatomical scan, with no diffusion weighting", NULL, NULL, nrrdHestNrrd); hestOptAdd(&hopt, "rr", NULL, airTypeOther, 0, 0, &randrot, NULL, "randomize gradient set orientation"); hestOptAdd(&hopt, "g", "grad list", airTypeOther, 1, 1, &ngrad, "", "gradient list, one row per diffusion-weighted image", NULL, NULL, nrrdHestNrrd); hestOptAdd(&hopt, "b", "b", airTypeFloat, 1, 1, &bval, "1000", "b value for simulated scan"); hestOptAdd(&hopt, "sigma", "sigma", airTypeFloat, 1, 1, &sigma, "0.0", "Rician noise parameter"); hestOptAdd(&hopt, "ot", "filename", airTypeString, 1, 1, &outTenS, "tout.nrrd", "file to write output tensor nrrd to"); hestOptAdd(&hopt, "oc", "filename", airTypeString, 1, 1, &outCovarS, "cout.nrrd", "file to write output covariance nrrd to"); hestOptAdd(&hopt, "or", "filename", airTypeString, 1, 1, &outRmvS, "rout.nrrd", "file to write output R_i means, variances to"); hestParseOrDie(hopt, argc-1, argv+1, NULL, me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE); airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); if (tenGradientCheck(ngrad, nrrdTypeDefault, 7)) { airMopAdd(mop, err = biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: problem with gradient list:\n%s\n", me, err); airMopError(mop); return 1; } if (tenTensorCheck(_ninTen, nrrdTypeDefault, AIR_TRUE, AIR_TRUE)) { airMopAdd(mop, err = biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: didn't like input:\n%s\n", me, err); airMopError(mop); return 1; } sizeX = _ninTen->axis[1].size; sizeY = _ninTen->axis[2].size; sizeZ = _ninTen->axis[3].size; if (!(3 == _ninB0->dim && sizeX == _ninB0->axis[0].size && sizeY == _ninB0->axis[1].size && sizeZ == _ninB0->axis[2].size)) { fprintf(stderr, "%s: given B0 (%u-D) volume not 3-D " _AIR_SIZE_T_CNV "x" _AIR_SIZE_T_CNV "x" _AIR_SIZE_T_CNV, me, _ninB0->dim, sizeX, sizeY, sizeZ); airMopError(mop); return 1; } ninTen = nrrdNew(); airMopAdd(mop, ninTen, (airMopper)nrrdNuke, airMopOnError); nmask = nrrdNew(); airMopAdd(mop, nmask, (airMopper)nrrdNuke, airMopOnError); ninB0 = nrrdNew(); airMopAdd(mop, ninB0, (airMopper)nrrdNuke, airMopOnError); noutCovar = nrrdNew(); airMopAdd(mop, noutCovar, (airMopper)nrrdNuke, airMopOnError); noutTen = nrrdNew(); airMopAdd(mop, noutTen, (airMopper)nrrdNuke, airMopOnError); noutRmv = nrrdNew(); airMopAdd(mop, noutRmv, (airMopper)nrrdNuke, airMopOnError); ntbuff = nrrdNew(); airMopAdd(mop, ntbuff, (airMopper)nrrdNuke, airMopOnError); if (nrrdConvert(ninTen, _ninTen, nrrdTypeDouble) || nrrdSlice(nmask, ninTen, 0, 0) || nrrdConvert(ninB0, _ninB0, nrrdTypeDouble) || nrrdMaybeAlloc_va(noutTen, nrrdTypeDouble, 4, AIR_CAST(size_t, 7), sizeX, sizeY, sizeZ) || nrrdMaybeAlloc_va(noutCovar, nrrdTypeDouble, 4, AIR_CAST(size_t, 21), sizeX, sizeY, sizeZ) || nrrdMaybeAlloc_va(noutRmv, nrrdTypeDouble, 4, AIR_CAST(size_t, 6), sizeX, sizeY, sizeZ) || nrrdMaybeAlloc_va(ntbuff, nrrdTypeDouble, 2, AIR_CAST(size_t, 7), NN)) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble setting up tec:\n%s\n", me, err); airMopError(mop); return 1; } tec = tenEstimateContextNew(); airMopAdd(mop, tec, (airMopper)tenEstimateContextNix, airMopAlways); E = 0; if (!E) E |= tenEstimateMethodSet(tec, tenEstimate1MethodLLS); if (!E) E |= tenEstimateValueMinSet(tec, 0.000000001); if (!E) E |= tenEstimateGradientsSet(tec, ngrad, bval, AIR_TRUE); if (!E) E |= tenEstimateThresholdSet(tec, 0, 0); if (!E) E |= tenEstimateUpdate(tec); if (E) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble setting up tec:\n%s\n", me, err); airMopError(mop); return 1; } airSrandMT(seed); fprintf(stderr, "!%s: randrot = %d\n", me, randrot); if (1) { unsigned int II; unsigned int nsamp; double *inTen, *outTen, *outCovar, *outRmv, *dwibuff, (*lup)(const void *, size_t); char doneStr[AIR_STRLEN_SMALL]; dwibuff = AIR_CAST(double *, calloc(ngrad->axis[1].size, sizeof(double))); airMopAdd(mop, dwibuff, airFree, airMopAlways); nsamp = sizeX*sizeY*sizeZ; inTen = AIR_CAST(double *, ninTen->data); lup = nrrdDLookup[nrrdTypeDouble]; outTen = AIR_CAST(double *, noutTen->data); outCovar = AIR_CAST(double *, noutCovar->data); outRmv = AIR_CAST(double *, noutRmv->data); fprintf(stderr, "!%s: simulating ... ", me); fflush(stderr); for (II=0; II<nsamp; II++) { if (!(II % sizeX)) { fprintf(stderr, "%s", airDoneStr(0, II, nsamp, doneStr)); fflush(stderr); } if (csimDo(outTen, outCovar, outRmv + 0, outRmv + 3, ntbuff, tec, dwibuff, sigma, bval, lup(ninB0->data, II), NN, randrot, inTen)) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble:\n%s\n", me, err); airMopError(mop); return 1; } inTen += 7; outTen += 7; outCovar += 21; outRmv += 6; } fprintf(stderr, "%s\n", airDoneStr(0, II, nsamp, doneStr)); }