int probeParseKind(void *ptr, char *str, char err[AIR_STRLEN_HUGE]) { char me[] = "probeParseKind"; gageKind **kindP; if (!(ptr && str)) { sprintf(err, "%s: got NULL pointer", me); return 1; } kindP = (gageKind **)ptr; airToLower(str); if (!strcmp(gageKindScl->name, str)) { *kindP = gageKindScl; } else if (!strcmp(gageKindVec->name, str)) { *kindP = gageKindVec; } else if (!strcmp(tenGageKind->name, str)) { *kindP = tenGageKind; } else if (!strcmp(TEN_DWI_GAGE_KIND_NAME, str)) { *kindP = tenDwiGageKindNew(); } else { sprintf(err, "%s: not \"%s\", \"%s\", \"%s\", or \"%s\"", me, gageKindScl->name, gageKindVec->name, tenGageKind->name, TEN_DWI_GAGE_KIND_NAME); return 1; } return 0; }
int probeParseKind(void *ptr, char *str, char err[AIR_STRLEN_HUGE]) { char me[] = "probeParseKind"; gageKind **kindP; if (!(ptr && str)) { sprintf(err, "%s: got NULL pointer", me); return 1; } kindP = (gageKind **)ptr; airToLower(str); if (!strcmp("scalar", str)) { *kindP = gageKindScl; } else if (!strcmp("vector", str)) { *kindP = gageKindVec; } else if (!strcmp("tensor", str)) { *kindP = tenGageKind; } else if (!strcmp("dwi", str)) { *kindP = tenDwiGageKindNew(); } else { sprintf(err, "%s: not \"scalar\", \"vector\", \"tensor\", or \"dwi\"", me); return 1; } return 0; }
gageKind * pullGageKindParse(const char *_str) { char me[]="pullGageKindParse", err[BIFF_STRLEN], *str; gageKind *ret; airArray *mop; if (!_str) { sprintf(err, "%s: got NULL pointer", me); return NULL; } mop = airMopNew(); str = airStrdup(_str); airMopAdd(mop, str, airFree, airMopAlways); airToLower(str); if (!strcmp(gageKindScl->name, str)) { ret = gageKindScl; } else if (!strcmp(gageKindVec->name, str)) { ret = gageKindVec; } else if (!strcmp(tenGageKind->name, str)) { ret = tenGageKind; } else /* not allowing DWIs for now */ { sprintf(err, "%s: not \"%s\", \"%s\", or \"%s\"", me, gageKindScl->name, gageKindVec->name, tenGageKind->name); airMopError(mop); return NULL; } airMopOkay(mop); return ret; }
gageKind * _meetGageKindParse(const char *_str, int constOnly) { char *str; gageKind *ret; if (!_str) { return NULL; } str = airToLower(airStrdup(_str)); if (!str) { return NULL; } if (!strcmp(gageKindScl->name, str)) { ret = gageKindScl; } else if (!strcmp(gageKindVec->name, str)) { ret = gageKindVec; } else if (!strcmp(tenGageKind->name, str)) { ret = tenGageKind; } else if (!constOnly && !strcmp(TEN_DWI_GAGE_KIND_NAME, str)) { ret = tenDwiGageKindNew(); } else { ret = NULL; } airFree(str); return ret; }
int airEnumVal(const airEnum *enm, const char *str) { char *strCpy, test[AIR_STRLEN_SMALL]; unsigned int ii; if (!str) { return airEnumUnknown(enm); } strCpy = airStrdup(str); if (!enm->sense) { airToLower(strCpy); } if (enm->strEqv) { /* want strlen and not airStrlen here because the strEqv array should be terminated by a non-null empty string */ for (ii=0; strlen(enm->strEqv[ii]); ii++) { strncpy(test, enm->strEqv[ii], AIR_STRLEN_SMALL); test[AIR_STRLEN_SMALL-1] = '\0'; if (!enm->sense) { airToLower(test); } if (!strcmp(test, strCpy)) { free(strCpy); return enm->valEqv[ii]; } } } else { /* enm->strEqv NULL */ for (ii=1; ii<=enm->M; ii++) { strncpy(test, enm->str[ii], AIR_STRLEN_SMALL); test[AIR_STRLEN_SMALL-1] = '\0'; if (!enm->sense) { airToLower(test); } if (!strcmp(test, strCpy)) { free(strCpy); return enm->val ? enm->val[ii] : (int)ii; /* HEY scrutinize cast */ } } } /* else we never matched a string */ free(strCpy); return airEnumUnknown(enm); }
int airSingleSscanf(const char *str, const char *fmt, void *ptr) { char *tmp; double val; int ret; if (!strcmp(fmt, "%e") || !strcmp(fmt, "%f") || !strcmp(fmt, "%g") || !strcmp(fmt, "%le") || !strcmp(fmt, "%lf") || !strcmp(fmt, "%lg")) { tmp = airStrdup(str); if (!tmp) { return 0; } airToLower(tmp); if (strstr(tmp, "nan")) { val = AIR_NAN; } else if (strstr(tmp, "-inf")) { val = AIR_NEG_INF; } else if (strstr(tmp, "inf")) { val = AIR_POS_INF; } else { /* nothing special matched; pass it off to sscanf() */ ret = sscanf(str, fmt, ptr); free(tmp); return ret; } /* else we matched "nan", "-inf", or "inf", and set val accordingly */ if (!strncmp(fmt, "%l", 2)) { /* we were given a double pointer */ *((double *)(ptr)) = val; } else { /* we were given a float pointer */ *((float *)(ptr)) = (float)val; } free(tmp); return 1; } else { /* this is neither a float nor double */ return sscanf(str, fmt, ptr); } }
int _mossHestTransformParse (void *ptr, char *_str, char err[AIR_STRLEN_HUGE]) { char me[]="_mossHestTransformParse", *str; double **matP, tx, ty, sx, sy, angle, mat[6], shf, sha; airArray *mop; if (!(ptr && _str)) { sprintf(err, "%s: got NULL pointer", me); return 1; } matP = (double **)ptr; mop = airMopNew(); *matP = (double *)calloc(6, sizeof(double)); airMopMem(mop, matP, airMopOnError); str = airToLower(airStrdup(_str)); airMopMem(mop, &str, airMopAlways); if (!strcmp("identity", str)) { mossMatIdentitySet(*matP); } else if (1 == sscanf(str, "flip:%lf", &angle)) { mossMatFlipSet(*matP, angle); } else if (2 == sscanf(str, "translate:%lf,%lf", &tx, &ty)) { mossMatTranslateSet(*matP, tx, ty); } else if (2 == sscanf(str, "t:%lf,%lf", &tx, &ty)) { mossMatTranslateSet(*matP, tx, ty); } else if (1 == sscanf(str, "rotate:%lf", &angle)) { mossMatRotateSet(*matP, angle); } else if (1 == sscanf(str, "r:%lf", &angle)) { mossMatRotateSet(*matP, angle); } else if (2 == sscanf(str, "scale:%lf,%lf", &sx, &sy)) { mossMatScaleSet(*matP, sx, sy); } else if (2 == sscanf(str, "s:%lf,%lf", &sx, &sy)) { mossMatScaleSet(*matP, sx, sy); } else if (2 == sscanf(str, "shear:%lf,%lf", &shf, &sha)) { mossMatShearSet(*matP, shf, sha); } else if (6 == sscanf(str, "%lf,%lf,%lf,%lf,%lf,%lf", mat+0, mat+1, mat+2, mat+3, mat+4, mat+5)) { MOSS_MAT_COPY(*matP, mat); } else { sprintf(err, "%s: couldn't parse \"%s\" as a transform", me, _str); airMopError(mop); return 1; } airMopOkay(mop); return 0; }
/* ******** airEnumFmtDesc() ** ** Formats a description line for one element "val" of airEnum "enm", ** and puts the result in a NEWLY ALLOCATED string which is the return ** of this function. The formatting is done via sprintf(), as governed ** by "fmt", which should contain to "%s" conversion sequences, the ** first for the string version "val", and the second for the ** description If "canon", then the canonical string representation ** will be used (the one in enm->str[]), otherwise the shortest string ** representation will be used (which differs from the canonical one ** when there is a strEqv[]/valEqv[] pair defining a shorter string) */ char * airEnumFmtDesc(const airEnum *enm, int val, int canon, const char *fmt) { const char *desc; char *buff, ident[AIR_STRLEN_SMALL]; const char *_ident; int i; size_t len; if (!(enm && enm->desc && fmt)) { return airStrdup("(airEnumDesc: invalid args)"); } if (airEnumValCheck(enm, val)) { val = airEnumUnknown(enm); } _ident = airEnumStr(enm, val); if (!canon && enm->strEqv) { len = airStrlen(_ident); for (i=0; airStrlen(enm->strEqv[i]); i++) { if (val != enm->valEqv[i]) { /* this isn't a string representing the value we care about */ continue; } if (airStrlen(enm->strEqv[i]) < len) { /* this one is shorter */ len = airStrlen(enm->strEqv[i]); _ident = enm->strEqv[i]; } } } strncpy(ident, _ident, AIR_STRLEN_SMALL); ident[AIR_STRLEN_SMALL-1] = '\0'; if (!enm->sense) { airToLower(ident); } desc = enm->desc[_airEnumIndex(enm, val)]; buff = AIR_CALLOC(airStrlen(fmt) + airStrlen(ident) + airStrlen(desc) + 1, char); if (buff) { sprintf(buff, fmt, ident, desc); } return buff; }
int probeParseKind(void *ptr, char *str, char err[AIR_STRLEN_HUGE]) { char me[] = "probeParseKind"; gageKind **kindP; if (!(ptr && str)) { sprintf(err, "%s: got NULL pointer", me); return 1; } kindP = (gageKind **)ptr; airToLower(str); if (!strcmp(gageKindScl->name, str)) { *kindP = gageKindScl; } else if (!strcmp(gageKindVec->name, str)) { *kindP = gageKindVec; } else { sprintf(err, "%s: not \"%s\" or \"%s\"", me, gageKindScl->name, gageKindVec->name); return 1; } return 0; }
int _nrrdFormatVTK_read(FILE *file, Nrrd *nrrd, NrrdIoState *nio) { static const char me[]="_nrrdReadVTK"; char *three[3]; int sx, sy, sz, ret, N; double xm=0.0, ym=0.0, zm=0.0, xs=1.0, ys=1.0, zs=1.0; airArray *mop; unsigned int llen; if (!_nrrdFormatVTK_contentStartsLike(nio)) { biffAddf(NRRD, "%s: this doesn't look like a %s file", me, nrrdFormatVTK->name); return 1; } #define GETLINE(what) \ do { \ ret = _nrrdOneLine(&llen, nio, file); \ } while (!ret && (1 == llen)); \ if (ret || !llen) { \ biffAddf(NRRD, "%s: couldn't get " #what " line", me); \ return 1; \ } /* read in content */ GETLINE(content); if (strcmp(NRRD_UNKNOWN, nio->line)) { if (!(nrrd->content = airStrdup(nio->line))) { biffAddf(NRRD, "%s: couldn't read or copy content string", me); return 1; } } GETLINE(encoding); airToUpper(nio->line); if (!strcmp("ASCII", nio->line)) { nio->encoding = nrrdEncodingAscii; } else if (!strcmp("BINARY", nio->line)) { nio->encoding = nrrdEncodingRaw; } else { biffAddf(NRRD, "%s: encoding \"%s\" wasn't \"ASCII\" or \"BINARY\"", me, nio->line); return 1; } GETLINE(DATASET); airToUpper(nio->line); if (!strstr(nio->line, "STRUCTURED_POINTS")) { biffAddf(NRRD, "%s: sorry, only STRUCTURED_POINTS data is nrrd-ready", me); return 1; } GETLINE(DIMENSIONS); airToUpper(nio->line); if (!strstr(nio->line, "DIMENSIONS") || 3 != sscanf(nio->line, "DIMENSIONS %d %d %d", &sx, &sy, &sz)) { biffAddf(NRRD, "%s: couldn't parse DIMENSIONS line (\"%s\")", me, nio->line); return 1; } GETLINE(next); airToUpper(nio->line); while (!strstr(nio->line, "POINT_DATA")) { if (strstr(nio->line, "ORIGIN")) { if (3 != sscanf(nio->line, "ORIGIN %lf %lf %lf", &xm, &ym, &zm)) { biffAddf(NRRD, "%s: couldn't parse ORIGIN line (\"%s\")", me, nio->line); return 1; } } else if (strstr(nio->line, "SPACING")) { if (3 != sscanf(nio->line, "SPACING %lf %lf %lf", &xs, &ys, &zs)) { biffAddf(NRRD, "%s: couldn't parse SPACING line (\"%s\")", me, nio->line); return 1; } } else if (strstr(nio->line, "ASPECT_RATIO")) { if (3 != sscanf(nio->line, "ASPECT_RATIO %lf %lf %lf", &xs, &ys, &zs)) { biffAddf(NRRD, "%s: couldn't parse ASPECT_RATIO line (\"%s\")", me, nio->line); return 1; } } GETLINE(next); airToUpper(nio->line); } if (1 != sscanf(nio->line, "POINT_DATA %d", &N)) { biffAddf(NRRD, "%s: couldn't parse POINT_DATA line (\"%s\")", me, nio->line); return 1; } if (N != sx*sy*sz) { biffAddf(NRRD, "%s: product of sizes (%d*%d*%d == %d) != # elements (%d)", me, sx, sy, sz, sx*sy*sz, N); return 1; } GETLINE(attribute declaration); mop = airMopNew(); if (3 != airParseStrS(three, nio->line, AIR_WHITESPACE, 3, AIR_FALSE)) { biffAddf(NRRD, "%s: didn't see three words in attribute declaration \"%s\"", me, nio->line); return 1; } airMopAdd(mop, three[0], airFree, airMopAlways); airMopAdd(mop, three[1], airFree, airMopAlways); airMopAdd(mop, three[2], airFree, airMopAlways); airToLower(three[2]); if (!strcmp(three[2], "bit")) { if (nrrdEncodingAscii == nio->encoding) { fprintf(stderr, "%s: WARNING: \"bit\"-type data will be read in as " "unsigned char\n", me); nrrd->type = nrrdTypeUChar; } else { biffAddf(NRRD, "%s: can't read in \"bit\"-type data as BINARY", me); return 1; } } else if (!strcmp(three[2], "unsigned_char")) { nrrd->type = nrrdTypeUChar; } else if (!strcmp(three[2], "char")) { nrrd->type = nrrdTypeChar; } else if (!strcmp(three[2], "unsigned_short")) { nrrd->type = nrrdTypeUShort; } else if (!strcmp(three[2], "short")) { nrrd->type = nrrdTypeShort; } else if (!strcmp(three[2], "unsigned_int")) { nrrd->type = nrrdTypeUInt; } else if (!strcmp(three[2], "int")) { nrrd->type = nrrdTypeInt; } else if (!strcmp(three[2], "float")) { nrrd->type = nrrdTypeFloat; } else if (!strcmp(three[2], "double")) { nrrd->type = nrrdTypeDouble; } else { /* "unsigned_long" and "long" fall in here- I don't know what the VTK people mean by these types, since always mean different things on 32-bit versus 64-bit architectures */ biffAddf(NRRD, "%s: type \"%s\" not recognized", me, three[2]); airMopError(mop); return 1; } airToUpper(three[0]); if (!strncmp("SCALARS", three[0], strlen("SCALARS"))) { GETLINE(LOOKUP_TABLE); airToUpper(nio->line); if (strcmp(nio->line, "LOOKUP_TABLE DEFAULT")) { biffAddf(NRRD, "%s: sorry, can only deal with default LOOKUP_TABLE", me); airMopError(mop); return 1; } nrrd->dim = 3; nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSize, AIR_CAST(size_t, sx), AIR_CAST(size_t, sy), AIR_CAST(size_t, sz)); nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSpacing, xs, ys, zs); nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMin, xm, ym, zm); } else if (!strncmp("VECTORS", three[0], strlen("VECTORS"))) { nrrd->dim = 4; nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSize, AIR_CAST(size_t, 3), AIR_CAST(size_t, sx), AIR_CAST(size_t, sy), AIR_CAST(size_t, sz)); nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSpacing, AIR_NAN, xs, ys, zs); nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMin, AIR_NAN, xm, ym, zm); nrrd->axis[0].kind = nrrdKind3Vector; } else if (!strncmp("TENSORS", three[0], strlen("TENSORS"))) { nrrd->dim = 4; nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSize, AIR_CAST(size_t, 9), AIR_CAST(size_t, sx), AIR_CAST(size_t, sy), AIR_CAST(size_t, sz)); nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSpacing, AIR_NAN, xs, ys, zs); nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMin, AIR_NAN, xm, ym, zm); nrrd->axis[0].kind = nrrdKind3DMatrix; } else { biffAddf(NRRD, "%s: sorry, can only deal with SCALARS, VECTORS, and TENSORS " "currently, so couldn't parse attribute declaration \"%s\"", me, nio->line); airMopError(mop); return 1; } if (!nio->skipData) { if (_nrrdCalloc(nrrd, nio, file)) { biffAddf(NRRD, "%s: couldn't allocate memory for data", me); return 1; } if (nio->encoding->read(file, nrrd->data, nrrdElementNumber(nrrd), nrrd, nio)) { biffAddf(NRRD, "%s:", me); return 1; } if (1 < nrrdElementSize(nrrd) && nio->encoding->endianMatters && airMyEndian() != airEndianBig) { /* encoding exposes endianness, and its big, but we aren't */ nrrdSwapEndian(nrrd); } } else { nrrd->data = NULL; } airMopOkay(mop); return 0; }
int tend_estimMain(int argc, char **argv, char *me, hestParm *hparm) { int pret; hestOpt *hopt = NULL; char *perr, *err; airArray *mop; Nrrd **nin, *nin4d, *nbmat, *nterr, *nB0, *nout; char *outS, *terrS, *bmatS, *eb0S; float soft, scale, sigma; int dwiax, EE, knownB0, oldstuff, estmeth, verbose, fixneg; unsigned int ninLen, axmap[4], wlsi, *skip, skipNum, skipIdx; double valueMin, thresh; Nrrd *ngradKVP=NULL, *nbmatKVP=NULL; double bKVP, bval; tenEstimateContext *tec; hestOptAdd(&hopt, "old", NULL, airTypeInt, 0, 0, &oldstuff, NULL, "instead of the new tenEstimateContext code, use " "the old tenEstimateLinear code"); hestOptAdd(&hopt, "sigma", "sigma", airTypeFloat, 1, 1, &sigma, "nan", "Rician noise parameter"); hestOptAdd(&hopt, "v", "verbose", airTypeInt, 1, 1, &verbose, "0", "verbosity level"); hestOptAdd(&hopt, "est", "estimate method", airTypeEnum, 1, 1, &estmeth, "lls", "estimation method to use. \"lls\": linear-least squares", NULL, tenEstimate1Method); hestOptAdd(&hopt, "wlsi", "WLS iters", airTypeUInt, 1, 1, &wlsi, "1", "when using weighted-least-squares (\"-est wls\"), how " "many iterations to do after the initial weighted fit."); hestOptAdd(&hopt, "fixneg", NULL, airTypeInt, 0, 0, &fixneg, NULL, "after estimating the tensor, ensure that there are no negative " "eigenvalues by adding (to all eigenvalues) the amount by which " "the smallest is negative (corresponding to increasing the " "non-DWI image value)."); hestOptAdd(&hopt, "ee", "filename", airTypeString, 1, 1, &terrS, "", "Giving a filename here allows you to save out the tensor " "estimation error: a value which measures how much error there " "is between the tensor model and the given diffusion weighted " "measurements for each sample. By default, no such error " "calculation is saved."); hestOptAdd(&hopt, "eb", "filename", airTypeString, 1, 1, &eb0S, "", "In those cases where there is no B=0 reference image given " "(\"-knownB0 false\"), " "giving a filename here allows you to save out the B=0 image " "which is estimated from the data. By default, this image value " "is estimated but not saved."); hestOptAdd(&hopt, "t", "thresh", airTypeDouble, 1, 1, &thresh, "nan", "value at which to threshold the mean DWI value per pixel " "in order to generate the \"confidence\" mask. By default, " "the threshold value is calculated automatically, based on " "histogram analysis."); hestOptAdd(&hopt, "soft", "soft", airTypeFloat, 1, 1, &soft, "0", "how fuzzy the confidence boundary should be. By default, " "confidence boundary is perfectly sharp"); hestOptAdd(&hopt, "scale", "scale", airTypeFloat, 1, 1, &scale, "1", "After estimating the tensor, scale all of its elements " "(but not the confidence value) by this amount. Can help with " "downstream numerical precision if values are very large " "or small."); hestOptAdd(&hopt, "mv", "min val", airTypeDouble, 1, 1, &valueMin, "1.0", "minimum plausible value (especially important for linear " "least squares estimation)"); hestOptAdd(&hopt, "B", "B-list", airTypeString, 1, 1, &bmatS, NULL, "6-by-N list of B-matrices characterizing " "the diffusion weighting for each " "image. \"tend bmat\" is one source for such a matrix; see " "its usage info for specifics on how the coefficients of " "the B-matrix are ordered. " "An unadorned plain text file is a great way to " "specify the B-matrix.\n **OR**\n " "Can say just \"-B kvp\" to try to learn B matrices from " "key/value pair information in input images."); hestOptAdd(&hopt, "b", "b", airTypeDouble, 1, 1, &bval, "nan", "\"b\" diffusion-weighting factor (units of sec/mm^2)"); hestOptAdd(&hopt, "knownB0", "bool", airTypeBool, 1, 1, &knownB0, NULL, "Determines of the B=0 non-diffusion-weighted reference image " "is known, or if it has to be estimated along with the tensor " "elements.\n " "\b\bo if \"true\": in the given list of diffusion gradients or " "B-matrices, there are one or more with zero norm, which are " "simply averaged to find the B=0 reference image value\n " "\b\bo if \"false\": there may or may not be diffusion-weighted " "images among the input; the B=0 image value is going to be " "estimated along with the diffusion model"); hestOptAdd(&hopt, "i", "dwi0 dwi1", airTypeOther, 1, -1, &nin, "-", "all the diffusion-weighted images (DWIs), as seperate 3D nrrds, " "**OR**: One 4D nrrd of all DWIs stacked along axis 0", &ninLen, NULL, nrrdHestNrrd); hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-", "output tensor volume"); mop = airMopNew(); airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); USAGE(_tend_estimInfoL); JUSTPARSE(); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); nout = nrrdNew(); airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); nbmat = nrrdNew(); airMopAdd(mop, nbmat, (airMopper)nrrdNuke, airMopAlways); /* figure out B-matrix */ if (strcmp("kvp", airToLower(bmatS))) { /* its NOT coming from key/value pairs */ if (!AIR_EXISTS(bval)) { fprintf(stderr, "%s: need to specify scalar b-value\n", me); airMopError(mop); return 1; } if (nrrdLoad(nbmat, bmatS, NULL)) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble loading B-matrix:\n%s\n", me, err); airMopError(mop); return 1; } nin4d = nin[0]; skip = NULL; skipNum = 0; } else { /* it IS coming from key/value pairs */ if (1 != ninLen) { fprintf(stderr, "%s: require a single 4-D DWI volume for " "key/value pair based calculation of B-matrix\n", me); airMopError(mop); return 1; } if (oldstuff) { if (knownB0) { fprintf(stderr, "%s: sorry, key/value-based DWI info not compatible " "with older implementation of knownB0\n", me); airMopError(mop); return 1; } } if (tenDWMRIKeyValueParse(&ngradKVP, &nbmatKVP, &bKVP, &skip, &skipNum, nin[0])) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble parsing DWI info:\n%s\n", me, err); airMopError(mop); return 1; } if (AIR_EXISTS(bval)) { fprintf(stderr, "%s: WARNING: key/value pair derived b-value %g " "over-riding %g from command-line", me, bKVP, bval); } bval = bKVP; if (ngradKVP) { airMopAdd(mop, ngradKVP, (airMopper)nrrdNuke, airMopAlways); if (tenBMatrixCalc(nbmat, ngradKVP)) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble finding B-matrix:\n%s\n", me, err); airMopError(mop); return 1; } } else { airMopAdd(mop, nbmatKVP, (airMopper)nrrdNuke, airMopAlways); if (nrrdConvert(nbmat, nbmatKVP, nrrdTypeDouble)) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble converting B-matrix:\n%s\n", me, err); airMopError(mop); return 1; } } /* this will work because of the impositions of tenDWMRIKeyValueParse */ dwiax = ((nrrdKindList == nin[0]->axis[0].kind || nrrdKindVector == nin[0]->axis[0].kind) ? 0 : ((nrrdKindList == nin[0]->axis[1].kind || nrrdKindVector == nin[0]->axis[1].kind) ? 1 : ((nrrdKindList == nin[0]->axis[2].kind || nrrdKindVector == nin[0]->axis[2].kind) ? 2 : 3))); if (0 == dwiax) { nin4d = nin[0]; } else { axmap[0] = dwiax; axmap[1] = 1 > dwiax ? 1 : 0; axmap[2] = 2 > dwiax ? 2 : 1; axmap[3] = 3 > dwiax ? 3 : 2; nin4d = nrrdNew(); airMopAdd(mop, nin4d, (airMopper)nrrdNuke, airMopAlways); if (nrrdAxesPermute(nin4d, nin[0], axmap)) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble creating DWI volume:\n%s\n", me, err); airMopError(mop); return 1; } } } nterr = NULL; nB0 = NULL; if (!oldstuff) { if (1 != ninLen) { fprintf(stderr, "%s: sorry, currently need single 4D volume " "for new implementation\n", me); airMopError(mop); return 1; } if (!AIR_EXISTS(thresh)) { if (tend_estimThresholdFind(&thresh, nbmat, nin4d)) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble finding threshold:\n%s\n", me, err); airMopError(mop); return 1; } /* HACK to lower threshold a titch */ thresh *= 0.93; fprintf(stderr, "%s: using mean DWI threshold %g\n", me, thresh); } tec = tenEstimateContextNew(); tec->progress = AIR_TRUE; airMopAdd(mop, tec, (airMopper)tenEstimateContextNix, airMopAlways); EE = 0; if (!EE) tenEstimateVerboseSet(tec, verbose); if (!EE) tenEstimateNegEvalShiftSet(tec, fixneg); if (!EE) EE |= tenEstimateMethodSet(tec, estmeth); if (!EE) EE |= tenEstimateBMatricesSet(tec, nbmat, bval, !knownB0); if (!EE) EE |= tenEstimateValueMinSet(tec, valueMin); for (skipIdx=0; skipIdx<skipNum; skipIdx++) { /* fprintf(stderr, "%s: skipping %u\n", me, skip[skipIdx]); */ if (!EE) EE |= tenEstimateSkipSet(tec, skip[skipIdx], AIR_TRUE); } switch(estmeth) { case tenEstimate1MethodLLS: if (airStrlen(terrS)) { tec->recordErrorLogDwi = AIR_TRUE; /* tec->recordErrorDwi = AIR_TRUE; */ } break; case tenEstimate1MethodNLS: if (airStrlen(terrS)) { tec->recordErrorDwi = AIR_TRUE; } break; case tenEstimate1MethodWLS: if (!EE) tec->WLSIterNum = wlsi; if (airStrlen(terrS)) { tec->recordErrorDwi = AIR_TRUE; } break; case tenEstimate1MethodMLE: if (!(AIR_EXISTS(sigma) && sigma > 0.0)) { fprintf(stderr, "%s: can't do %s w/out sigma > 0 (not %g)\n", me, airEnumStr(tenEstimate1Method, tenEstimate1MethodMLE), sigma); airMopError(mop); return 1; } if (!EE) EE |= tenEstimateSigmaSet(tec, sigma); if (airStrlen(terrS)) { tec->recordLikelihoodDwi = AIR_TRUE; } break; } if (!EE) EE |= tenEstimateThresholdSet(tec, thresh, soft); if (!EE) EE |= tenEstimateUpdate(tec); if (EE) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble setting up estimation:\n%s\n", me, err); airMopError(mop); return 1; } if (tenEstimate1TensorVolume4D(tec, nout, &nB0, airStrlen(terrS) ? &nterr : NULL, nin4d, nrrdTypeFloat)) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble doing estimation:\n%s\n", me, err); airMopError(mop); return 1; } if (airStrlen(terrS)) { airMopAdd(mop, nterr, (airMopper)nrrdNuke, airMopAlways); } } else { EE = 0; if (1 == ninLen) { EE = tenEstimateLinear4D(nout, airStrlen(terrS) ? &nterr : NULL, &nB0, nin4d, nbmat, knownB0, thresh, soft, bval); } else { EE = tenEstimateLinear3D(nout, airStrlen(terrS) ? &nterr : NULL, &nB0, (const Nrrd**)nin, ninLen, nbmat, knownB0, thresh, soft, bval); } if (EE) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble making tensor volume:\n%s\n", me, err); airMopError(mop); return 1; } } if (nterr) { /* it was allocated by tenEstimate*, we have to clean it up */ airMopAdd(mop, nterr, (airMopper)nrrdNuke, airMopAlways); } if (nB0) { /* it was allocated by tenEstimate*, we have to clean it up */ airMopAdd(mop, nB0, (airMopper)nrrdNuke, airMopAlways); } if (1 != scale) { if (tenSizeScale(nout, nout, scale)) { airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways); fprintf(stderr, "%s: trouble doing scaling:\n%s\n", me, err); airMopError(mop); return 1; } } if (nterr) { if (nrrdSave(terrS, nterr, NULL)) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble writing error image:\n%s\n", me, err); airMopError(mop); return 1; } } if (!knownB0 && airStrlen(eb0S)) { if (nrrdSave(eb0S, nB0, NULL)) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble writing estimated B=0 image:\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; }
/* ******** meetPullVolParse ** ** parses a string to extract all the information necessary to create ** the pullVolume (this function originated in Deft/src/main-pull.c) */ int meetPullVolParse(meetPullVol *mpv, const char *_str) { static const char me[]="meetPullVolParse"; #define VFMT_SHRT "<fileName>:<kind>:<volName>" #define SFMT "<minScl>-<#smp>-<maxScl>[-no|u]" #define VFMT_LONG "<fileName>:<kind>:" SFMT ":<volName>" char *str, *ctok, *clast=NULL, *dtok, *dlast=NULL; airArray *mop; int wantSS; if (!(mpv && _str)) { biffAddf(MEET, "%s: got NULL pointer", me); return 1; } if (!( str = airStrdup(_str) )) { biffAddf(MEET, "%s: couldn't strdup input", me); return 1; } mop = airMopNew(); airMopAdd(mop, str, airFree, airMopAlways); if (!( 3 == airStrntok(str, ":") || 4 == airStrntok(str, ":") )) { biffAddf(MEET, "%s: didn't get 3 or 4 \":\"-separated tokens in \"%s\"; " "not of form " VFMT_SHRT " or " VFMT_LONG , me, _str); airMopError(mop); return 1; } /* mpv->nin is set elsewhere */ wantSS = (4 == airStrntok(str, ":")); ctok = airStrtok(str, ":", &clast); if (!(mpv->fileName = airStrdup(ctok))) { biffAddf(MEET, "%s: couldn't strdup fileName", me); airMopError(mop); return 1; } airMopAdd(mop, &(mpv->fileName), (airMopper)airSetNull, airMopOnError); airMopAdd(mop, mpv->fileName, airFree, airMopOnError); ctok = airStrtok(NULL, ":", &clast); if (!(mpv->kind = meetConstGageKindParse(ctok))) { biffAddf(MEET, "%s: couldn't parse \"%s\" as kind", me, ctok); airMopError(mop); return 1; } if (wantSS) { int haveFlags; ctok = airStrtok(NULL, ":", &clast); if (!( 3 == airStrntok(ctok, "-") || 4 == airStrntok(ctok, "-") )) { biffAddf(MEET, "%s: didn't get 3 or 4 \"-\"-separated tokens in \"%s\"; " "not of form SFMT" , me, ctok); airMopError(mop); return 1; } haveFlags = (4 == airStrntok(ctok, "-")); dtok = airStrtok(ctok, "-", &dlast); if (1 != sscanf(dtok, "%lg", &(mpv->rangeSS[0]))) { biffAddf(MEET, "%s: couldn't parse \"%s\" as min scale", me, dtok); airMopError(mop); return 1; } dtok = airStrtok(NULL, "-", &dlast); if (1 != sscanf(dtok, "%u", &(mpv->numSS))) { biffAddf(MEET, "%s: couldn't parse \"%s\" as # scale samples", me, dtok); airMopError(mop); return 1; } if (!( mpv->numSS >= 2 )) { biffAddf(MEET, "%s: need # scale samples >= 2 (not %u)", me, mpv->numSS); airMopError(mop); return 1; } dtok = airStrtok(NULL, "-", &dlast); if (1 != sscanf(dtok, "%lg", &(mpv->rangeSS[1]))) { biffAddf(MEET, "%s: couldn't parse \"%s\" as max scale", me, dtok); airMopError(mop); return 1; } /* initialize things as if there were no flags */ mpv->derivNormSS = AIR_FALSE; mpv->uniformSS = AIR_FALSE; mpv->optimSS = AIR_FALSE; mpv->derivNormBiasSS = 0.0; if (haveFlags) { char *flags, *bias; /* look for various things in flags */ flags = airToLower(airStrdup(airStrtok(NULL, "-", &dlast))); airMopAdd(mop, flags, airFree, airMopAlways); if (strchr(flags, 'n')) { mpv->derivNormSS = AIR_TRUE; } if (strchr(flags, 'u')) { mpv->uniformSS = AIR_TRUE; } if (strchr(flags, 'o')) { mpv->optimSS = AIR_TRUE; } if (mpv->optimSS && mpv->uniformSS) { biffAddf(MEET, "%s: can't have both optimal ('o') and uniform ('u') " "flags set in \"%s\"", me, flags); airMopError(mop); return 1; } if ((bias = strchr(flags, '+'))) { /* indicating a bias, unfortunately only a positive one is possible here, because of the way that other fields are tokenized by '-' */ bias++; if (1 != sscanf(bias, "%lf", &(mpv->derivNormBiasSS))) { biffAddf(MEET, "%s: couldn't parse bias \"%s\"", me, bias); airMopError(mop); return 1; } } } /* mpv->ninSS and mpv->posSS are allocated and filled elsewhere */ mpv->ninSS = NULL; mpv->posSS = NULL; /* we don't actually create nrrds nor load the volumes here, because we don't know cachePath, and because we might want different pullVolumes to share the same underlying Nrrds */ } else { /* no scale-space stuff wanted */ mpv->numSS = 0; mpv->rangeSS[0] = mpv->rangeSS[1] = AIR_NAN; mpv->ninSS = NULL; mpv->posSS = NULL; } ctok = airStrtok(NULL, ":", &clast); if (!(mpv->volName = airStrdup(ctok))) { biffAddf(MEET, "%s: couldn't strdup volName", me); airMopError(mop); return 1; } airMopAdd(mop, &(mpv->volName), (airMopper)airSetNull, airMopOnError); airMopAdd(mop, mpv->volName, airFree, airMopOnError); if (strchr(ctok, '-')) { biffAddf(MEET, "%s: you probably don't want \"-\" in volume name \"%s\"; " "forgot last \":\" in scale sampling specification?", me, ctok); airMopError(mop); return 1; } airMopOkay(mop); return 0; }
/* ******** miteShadeSpecParse ** ** set up a miteShadeSpec based on a string. Valid forms are: ** ** none ** phong:<vector> ** litten:<vector>,<vector>,<scalar>,<scalar> ** ** where <vector> and <scalar> are specifications of 3-vector and scalar ** parsable by miteVariableParse */ int miteShadeSpecParse(miteShadeSpec *shpec, char *shadeStr) { static const char me[]="miteShadeSpecParse"; char *buff, *qstr, *tok, *state; airArray *mop; int ansLength; mop = airMopNew(); if (!( shpec && airStrlen(shadeStr) )) { biffAddf(MITE, "%s: got NULL pointer and/or empty string", me); airMopError(mop); return 1; } buff = airToLower(airStrdup(shadeStr)); if (!buff) { biffAddf(MITE, "%s: couldn't strdup shading spec", me); airMopError(mop); return 1; } airMopAdd(mop, buff, airFree, airMopAlways); shpec->method = miteShadeMethodUnknown; if (!strcmp("none", buff)) { shpec->method = miteShadeMethodNone; } else if (buff == strstr(buff, "phong:")) { shpec->method = miteShadeMethodPhong; qstr = buff + strlen("phong:"); if (miteVariableParse(shpec->vec0, qstr)) { biffAddf(MITE, "%s: couldn't parse \"%s\" as shading vector", me, qstr); airMopError(mop); return 1; } ansLength = shpec->vec0->kind->table[shpec->vec0->item].answerLength; if (3 != ansLength) { biffAddf(MITE, "%s: \"%s\" isn't a vector (answer length is %d, not 3)", me, qstr, ansLength); airMopError(mop); return 1; } shpec->method = miteShadeMethodPhong; } else if (buff == strstr(buff, "litten:")) { qstr = buff + strlen("litten:"); /* ---- first vector */ tok = airStrtok(qstr, ",", &state); if (miteVariableParse(shpec->vec0, tok)) { biffAddf(MITE, "%s: couldn't parse \"%s\" as first lit-tensor vector", me, tok); airMopError(mop); return 1; } ansLength = shpec->vec0->kind->table[shpec->vec0->item].answerLength; if (3 != ansLength) { biffAddf(MITE, "%s: \"%s\" isn't a vector (answer length is %d, not 3)", me, qstr, ansLength); airMopError(mop); return 1; } /* ---- second vector */ tok = airStrtok(qstr, ",", &state); if (miteVariableParse(shpec->vec1, tok)) { biffAddf(MITE, "%s: couldn't parse \"%s\" as second lit-tensor vector", me, tok); airMopError(mop); return 1; } ansLength = shpec->vec1->kind->table[shpec->vec1->item].answerLength; if (3 != ansLength) { biffAddf(MITE, "%s: \"%s\" isn't a vector (answer length is %d, not 3)", me, qstr, ansLength); airMopError(mop); return 1; } /* ---- first scalar */ tok = airStrtok(qstr, ",", &state); if (miteVariableParse(shpec->scl0, tok)) { biffAddf(MITE, "%s: couldn't parse \"%s\" as first lit-tensor scalar", me, tok); airMopError(mop); return 1; } ansLength = shpec->scl0->kind->table[shpec->scl0->item].answerLength; if (1 != ansLength) { biffAddf(MITE, "%s: \"%s\" isn't a scalar (answer length is %d, not 1)", me, qstr, ansLength); airMopError(mop); return 1; } /* ---- second scalar */ tok = airStrtok(qstr, ",", &state); if (miteVariableParse(shpec->scl1, tok)) { biffAddf(MITE, "%s: couldn't parse \"%s\" as second lit-tensor scalar", me, tok); airMopError(mop); return 1; } ansLength = shpec->scl1->kind->table[shpec->scl1->item].answerLength; if (1 != ansLength) { biffAddf(MITE, "%s: \"%s\" isn't a scalar (answer length is %d, not 1)", me, qstr, ansLength); airMopError(mop); return 1; } shpec->method = miteShadeMethodLitTen; } else { biffAddf(MITE, "%s: shading specification \"%s\" not understood", me, shadeStr); airMopError(mop); return 1; } airMopOkay(mop); return 0; }