int tend_msimMain(int argc, const char **argv, const char *me, hestParm *hparm) { int pret; hestOpt *hopt = NULL; char *perr, *err; airArray *mop; tenExperSpec *espec; const tenModel *model; int E, seed, keyValueSet, outType, plusB0, insertB0; Nrrd *nin, *nT2, *_ngrad, *ngrad, *nout; char *outS, *modS; double bval, sigma; /* maybe this can go in tend.c, but for some reason its explicitly set to AIR_FALSE there */ hparm->elideSingleOtherDefault = AIR_TRUE; hestOptAdd(&hopt, "sigma", "sigma", airTypeDouble, 1, 1, &sigma, "0.0", "Gaussian/Rician noise parameter"); hestOptAdd(&hopt, "seed", "seed", airTypeInt, 1, 1, &seed, "42", "seed value for RNG which creates noise"); hestOptAdd(&hopt, "g", "grad list", airTypeOther, 1, 1, &_ngrad, NULL, "gradient list, one row per diffusion-weighted image", NULL, NULL, nrrdHestNrrd); hestOptAdd(&hopt, "b0", "b0 image", airTypeOther, 1, 1, &nT2, "", "reference non-diffusion-weighted (\"B0\") image, which " "may be needed if it isn't part of give model param image", NULL, NULL, nrrdHestNrrd); hestOptAdd(&hopt, "i", "model image", airTypeOther, 1, 1, &nin, "-", "input model image", NULL, NULL, nrrdHestNrrd); hestOptAdd(&hopt, "m", "model", airTypeString, 1, 1, &modS, NULL, "model with which to simulate DWIs, which must be specified if " "it is not indicated by the first axis in input model image."); hestOptAdd(&hopt, "ib0", "bool", airTypeBool, 1, 1, &insertB0, "false", "insert a non-DW B0 image at the beginning of the experiment " "specification (useful if the given gradient list doesn't " "already have one) and hence also insert a B0 image at the " "beginning of the output simulated DWIs"); hestOptAdd(&hopt, "b", "b", airTypeDouble, 1, 1, &bval, "1000", "b value for simulated scan"); hestOptAdd(&hopt, "kvp", "bool", airTypeBool, 1, 1, &keyValueSet, "true", "generate key/value pairs in the NRRD header corresponding " "to the input b-value and gradients."); hestOptAdd(&hopt, "t", "type", airTypeEnum, 1, 1, &outType, "float", "output type of DWIs", NULL, nrrdType); hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-", "output dwis"); mop = airMopNew(); airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); USAGE(_tend_msimInfoL); PARSE(); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); nout = nrrdNew(); airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); espec = tenExperSpecNew(); airMopAdd(mop, espec, (airMopper)tenExperSpecNix, airMopAlways); airSrandMT(seed); if (nrrdTypeDouble == _ngrad->type) { ngrad = _ngrad; } else { ngrad = nrrdNew(); airMopAdd(mop, ngrad, (airMopper)nrrdNuke, airMopAlways); if (nrrdConvert(ngrad, _ngrad, nrrdTypeDouble)) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble converting grads to %s:\n%s\n", me, airEnumStr(nrrdType, nrrdTypeDouble), err); airMopError(mop); return 1; } } plusB0 = AIR_FALSE; if (airStrlen(modS)) { if (tenModelParse(&model, &plusB0, AIR_FALSE, modS)) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble parsing model \"%s\":\n%s\n", me, modS, err); airMopError(mop); return 1; } } else if (tenModelFromAxisLearnPossible(nin->axis + 0)) { if (tenModelFromAxisLearn(&model, &plusB0, nin->axis + 0)) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble parsing model frmo axis 0 of nin:\n%s\n", me, err); airMopError(mop); return 1; } } else { fprintf(stderr, "%s: need model specified either via \"-m\" or input " "model image axis 0\n", me); airMopError(mop); return 1; } /* we have learned plusB0, but we don't actually need it; either: it describes the given model param image (which is courteous but not necessary since the logic inside tenModeSimulate will see this), or: it is trying to say something about including B0 amongst model parameters (which isn't actually meaningful in the context of simulated DWIs */ E = 0; if (!E) E |= tenGradientCheck(ngrad, nrrdTypeDouble, 1); if (!E) E |= tenExperSpecGradSingleBValSet(espec, insertB0, bval, AIR_CAST(const double *, ngrad->data), ngrad->axis[1].size); if (!E) E |= tenModelSimulate(nout, outType, espec, model, nT2, nin, keyValueSet); if (E) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble:\n%s\n", me, err); airMopError(mop); return 1; } 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 tend_mfitMain(int argc, char **argv, char *me, hestParm *hparm) { int pret; hestOpt *hopt = NULL; char *perr, *err; airArray *mop; Nrrd *nin, *nout, *nterr; char *outS, *terrS, *modS; int knownB0, saveB0, verbose, mlfit, typeOut; unsigned int maxIter, minIter, starts; double sigma, eps; const tenModel *model; tenExperSpec *espec; hestOptAdd(&hopt, "v", "verbose", airTypeInt, 1, 1, &verbose, "0", "verbosity level"); hestOptAdd(&hopt, "m", "model", airTypeString, 1, 1, &modS, NULL, "which model to fit. Use optional \"b0+\" prefix to " "indicate that the B0 image should also be saved."); hestOptAdd(&hopt, "ns", "# starts", airTypeUInt, 1, 1, &starts, "1", "number of random starting points at which to initialize " "fitting"); hestOptAdd(&hopt, "ml", NULL, airTypeInt, 0, 0, &mlfit, NULL, "do ML fitting, rather than least-squares, which also " "requires setting \"-sigma\""); hestOptAdd(&hopt, "sigma", "sigma", airTypeDouble, 1, 1, &sigma, "nan", "Rician noise parameter"); hestOptAdd(&hopt, "eps", "eps", airTypeDouble, 1, 1, &eps, "0.01", "convergence epsilon"); hestOptAdd(&hopt, "mini", "min iters", airTypeUInt, 1, 1, &minIter, "3", "minimum required # iterations for fitting."); hestOptAdd(&hopt, "maxi", "max iters", airTypeUInt, 1, 1, &maxIter, "100", "maximum allowable # iterations for fitting."); hestOptAdd(&hopt, "knownB0", "bool", airTypeBool, 1, 1, &knownB0, NULL, "Indicates if the B=0 non-diffusion-weighted reference image " "is known (\"true\"), or if it has to be estimated along with " "the other model parameters (\"false\")"); hestOptAdd(&hopt, "t", "type", airTypeEnum, 1, 1, &typeOut, "float", "output type of model parameters", NULL, nrrdType); hestOptAdd(&hopt, "i", "dwi", airTypeOther, 1, 1, &nin, "-", "all the diffusion-weighted images in one 4D nrrd", NULL, NULL, nrrdHestNrrd); hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-", "output tensor volume"); hestOptAdd(&hopt, "eo", "filename", airTypeString, 1, 1, &terrS, "", "Giving a filename here allows you to save out the per-sample " "fitting error. By default, no such error is saved."); mop = airMopNew(); airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); USAGE(_tend_mfitInfoL); JUSTPARSE(); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); nterr = NULL; espec = tenExperSpecNew(); airMopAdd(mop, espec, (airMopper)tenExperSpecNix, airMopAlways); nout = nrrdNew(); airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); if (tenModelParse(&model, &saveB0, AIR_FALSE, modS)) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble parsing model \"%s\":\n%s\n", me, modS, err); airMopError(mop); return 1; } if (tenExperSpecFromKeyValueSet(espec, nin)) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble getting exper from kvp:\n%s\n", me, err); airMopError(mop); return 1; } if (tenModelSqeFit(nout, airStrlen(terrS) ? &nterr : NULL, model, espec, nin, knownB0, saveB0, typeOut, minIter, maxIter, starts, eps, NULL)) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble fitting:\n%s\n", me, err); airMopError(mop); return 1; } if (nrrdSave(outS, nout, NULL) || (airStrlen(terrS) && nrrdSave(terrS, nterr, NULL))) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble writing output:\n%s\n", me, err); airMopError(mop); return 1; } airMopOkay(mop); return 0; }