Exemplo n.º 1
0
int
tend_anplotMain(int argc, const char **argv, const char *me,
                hestParm *hparm) {
  int pret;
  hestOpt *hopt = NULL;
  char *perr, *err;
  airArray *mop;

  int res, aniso, whole, nanout, hflip;
  Nrrd *nout;
  char *outS;

  hestOptAdd(&hopt, "r", "res", airTypeInt, 1, 1, &res, "256",
             "resolution of anisotropy plot");
  hestOptAdd(&hopt, "w", NULL, airTypeInt, 0, 0, &whole, NULL,
             "sample the whole triangle of constant trace, "
             "instead of just the "
             "sixth of it in which the eigenvalues have the "
             "traditional sorted order. ");
  hestOptAdd(&hopt, "hflip", NULL, airTypeInt, 0, 0, &hflip, NULL,
             "flip the two bottom corners (swapping the place of "
             "linear and planar)");
  hestOptAdd(&hopt, "nan", NULL, airTypeInt, 0, 0, &nanout, NULL,
             "set the pixel values outside the triangle to be NaN, "
             "instead of 0");
  hestOptAdd(&hopt, "a", "aniso", airTypeEnum, 1, 1, &aniso, NULL,
             "Which anisotropy metric to plot.  " TEN_ANISO_DESC,
             NULL, tenAniso);
  hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-",
             "output image (floating point)");

  mop = airMopNew();
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  USAGE(_tend_anplotInfoL);
  JUSTPARSE();
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
  if (tenAnisoPlot(nout, aniso, res, hflip, whole, nanout)) {
    airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble making plot:\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;
}
Exemplo n.º 2
0
int
tend_makeMain(int argc, char **argv, char *me, hestParm *hparm) {
  int pret;
  hestOpt *hopt = NULL;
  char *perr, *err;
  airArray *mop;

  Nrrd *nin[3], *nout;
  char *outS;

  hestOptAdd(&hopt, "i", "conf evals evecs", airTypeOther, 3, 3, nin, NULL,
             "input diffusion tensor volume", NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-",
             "output image (floating point)");

  mop = airMopNew();
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  USAGE(_tend_makeInfoL);
  JUSTPARSE();
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
  if (tenMake(nout, nin[0], nin[1], nin[2])) {
    airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble making tensor volume:\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;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
int
tend_epiregMain(int argc, const char **argv, const char *me,
                hestParm *hparm) {
  int pret, rret;
  hestOpt *hopt = NULL;
  char *perr, *err;
  airArray *mop;
  char *outS, *buff;

  char *gradS;
  NrrdKernelSpec *ksp;
  Nrrd **nin, **nout3D, *nout4D, *ngrad, *ngradKVP, *nbmatKVP;
  unsigned int ni, ninLen, *skip, skipNum;
  int ref, noverbose, progress, nocc, baseNum;
  float bw[2], thr, fitFrac;
  double bvalue;

  hestOptAdd(&hopt, "i", "dwi0 dwi1", airTypeOther, 1, -1, &nin, NULL,
             "all the diffusion-weighted images (DWIs), as separate 3D nrrds, "
             "**OR**: one 4D nrrd of all DWIs stacked along axis 0",
             &ninLen, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "g", "grads", airTypeString, 1, 1, &gradS, NULL,
             "array of gradient directions, in the same order as the "
             "associated DWIs were given to \"-i\", "
             "**OR** \"-g kvp\" signifies that gradient directions should "
             "be read from the key/value pairs of the DWI",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "r", "reference", airTypeInt, 1, 1, &ref, "-1",
             "which of the DW volumes (zero-based numbering) should be used "
             "as the standard, to which all other images are transformed. "
             "Using -1 (the default) means that 9 intrinsic parameters "
             "governing the relationship between the gradient direction "
             "and the resulting distortion are estimated and fitted, "
             "ensuring good registration with the non-diffusion-weighted "
             "T2 image (which is never explicitly used in registration). "
             "Otherwise, by picking a specific DWI, no distortion parameter "
             "estimation is done. ");
  hestOptAdd(&hopt, "nv", NULL, airTypeInt, 0, 0, &noverbose, NULL,
             "turn OFF verbose mode, and "
             "have no idea what stage processing is at.");
  hestOptAdd(&hopt, "p", NULL, airTypeInt, 0, 0, &progress, NULL,
             "save out intermediate steps of processing");
  hestOptAdd(&hopt, "bw", "x,y blur", airTypeFloat, 2, 2, bw, "1.0 2.0",
             "standard devs in X and Y directions of gaussian filter used "
             "to blur the DWIs prior to doing segmentation. This blurring "
             "does not effect the final resampling of registered DWIs. "
             "Use \"0.0 0.0\" to say \"no blurring\"");
  hestOptAdd(&hopt, "t", "DWI thresh", airTypeFloat, 1, 1, &thr, "nan",
             "Threshold value to use on DWIs, "
             "to do initial separation of brain and non-brain.  By default, "
             "the threshold is determined automatically by histogram "
             "analysis. ");
  hestOptAdd(&hopt, "ncc", NULL, airTypeInt, 0, 0, &nocc, NULL,
             "do *NOT* do connected component (CC) analysis, after "
             "thresholding and before moment calculation.  Doing CC analysis "
             "usually gives better results because it converts the "
             "thresholding output into something much closer to a "
             "real segmentation");
  hestOptAdd(&hopt, "f", "fit frac", airTypeFloat, 1, 1, &fitFrac, "0.70",
             "(only meaningful with \"-r -1\") When doing linear fitting "
             "of the intrinsic distortion parameters, it is good "
             "to ignore the slices for which the segmentation was poor.  A "
             "heuristic is used to rank the slices according to segmentation "
             "quality.  This option controls how many of the (best) slices "
             "contribute to the fitting.  Use \"0\" to disable distortion "
             "parameter fitting. ");
  hestOptAdd(&hopt, "k", "kernel", airTypeOther, 1, 1, &ksp, "cubic:0,0.5",
             "kernel for resampling DWIs along the phase-encoding "
             "direction during final registration stage",
             NULL, NULL, nrrdHestKernelSpec);
  hestOptAdd(&hopt, "s", "start #", airTypeInt, 1, 1, &baseNum, "1",
             "first number to use in numbered sequence of output files.");
  hestOptAdd(&hopt, "o", "output/prefix", airTypeString, 1, 1, &outS, "-",
             "For separate 3D DWI volume inputs: prefix for output filenames; "
             "will save out one (registered) "
             "DWI for each input DWI, using the same type as the input. "
             "**OR**: For single 4D DWI input: output file name. ");

  mop = airMopNew();
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  USAGE(_tend_epiregInfoL);
  JUSTPARSE();
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  if (strcmp("kvp", gradS)) {
    /* they're NOT coming from key/value pairs */
    if (nrrdLoad(ngrad=nrrdNew(), gradS, NULL)) {
      airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble loading gradient list:\n%s\n", me, err);
      airMopError(mop); return 1;
    }
  } else {
    if (1 != ninLen) {
      fprintf(stderr, "%s: can do key/value pairs only from single nrrd", me);
      airMopError(mop); return 1;
    }
    /* they are coming from key/value pairs */
    if (tenDWMRIKeyValueParse(&ngradKVP, &nbmatKVP, &bvalue,
                              &skip, &skipNum, nin[0])) {
      airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble parsing gradient list:\n%s\n", me, err);
      airMopError(mop); return 1;
    }
    if (nbmatKVP) {
      fprintf(stderr, "%s: sorry, can only use gradients, not b-matrices", me);
      airMopError(mop); return 1;
    }
    ngrad = ngradKVP;
  }
  airMopAdd(mop, ngrad, (airMopper)nrrdNuke, airMopAlways);

  nout3D = AIR_CALLOC(ninLen, Nrrd *);
  airMopAdd(mop, nout3D, airFree, airMopAlways);
  nout4D = nrrdNew();
  airMopAdd(mop, nout4D, (airMopper)nrrdNuke, airMopAlways);
  buff = AIR_CALLOC(airStrlen(outS) + 10, char);
  airMopAdd(mop, buff, airFree, airMopAlways);
  if (!( nout3D && nout4D && buff )) {
    fprintf(stderr, "%s: couldn't allocate buffers", me);
    airMopError(mop); return 1;
  }
  for (ni=0; ni<ninLen; ni++) {
    nout3D[ni]=nrrdNew();
    airMopAdd(mop, nout3D[ni], (airMopper)nrrdNuke, airMopAlways);
  }
  if (1 == ninLen) {
    rret = tenEpiRegister4D(nout4D, nin[0], ngrad,
                            ref,
                            bw[0], bw[1], fitFrac, thr, !nocc,
                            ksp->kernel, ksp->parm,
                            progress, !noverbose);
  } else {
    rret = tenEpiRegister3D(nout3D, nin, ninLen, ngrad,
                            ref,
                            bw[0], bw[1], fitFrac, thr, !nocc,
                            ksp->kernel, ksp->parm,
                            progress, !noverbose);
  }
  if (rret) {
    airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble doing epireg:\n%s\n", me, err);
    airMopError(mop); return 1;
  }

  if (1 == ninLen) {
    if (nrrdSave(outS, nout4D, NULL)) {
      airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble writing \"%s\":\n%s\n", me, outS, err);
      airMopError(mop); return 1;
    }
  } else {
    for (ni=0; ni<ninLen; ni++) {
      if (ninLen+baseNum > 99) {
        sprintf(buff, "%s%05d.nrrd", outS, ni+baseNum);
      } else if (ninLen+baseNum > 9) {
        sprintf(buff, "%s%02d.nrrd", outS, ni+baseNum);
      } else {
        sprintf(buff, "%s%d.nrrd", outS, ni+baseNum);
      }
      if (nrrdSave(buff, nout3D[ni], NULL)) {
        airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways);
        fprintf(stderr, "%s: trouble writing \"%s\":\n%s\n", me, buff, err);
        airMopError(mop); return 1;
      }
    }
  }

  airMopOkay(mop);
  return 0;
}
Exemplo n.º 7
0
int
tend_ellipseMain(int argc, char **argv, char *me, hestParm *hparm) {
  int pret;
  hestOpt *hopt = NULL;
  char *perr;
  airArray *mop;

  Nrrd *nten, *npos, *nstn;
  char *outS;
  float gscale, dotRad, lineWidth, cthresh, min[2], max[2];
  FILE *fout;
  int invert;

  mop = airMopNew();

  hestOptAdd(&hopt, "ctr", "conf thresh", airTypeFloat, 1, 1, &cthresh, "0.5",
             "Glyphs will be drawn only for tensors with confidence "
             "values greater than this threshold");
  hestOptAdd(&hopt, "gsc", "scale", airTypeFloat, 1, 1, &gscale, "1",
             "over-all glyph size");
  hestOptAdd(&hopt, "dot", "radius", airTypeFloat, 1, 1, &dotRad, "0.0",
             "radius of little dot to put in middle of ellipse, or \"0\" "
             "for no such dot");
  hestOptAdd(&hopt, "wid", "width", airTypeFloat, 1, 1, &lineWidth, "0.0",
             "with of lines for tractlets");
  hestOptAdd(&hopt, "inv", NULL, airTypeInt, 0, 0, &invert, NULL,
             "use white ellipses on black background, instead of reverse");
  hestOptAdd(&hopt, "min", "minX minY", airTypeFloat, 2, 2, min, "-1 -1",
             "when using \"-p\", minimum corner");
  hestOptAdd(&hopt, "max", "maxX maxY", airTypeFloat, 2, 2, max, "1 1",
             "when using \"-p\", maximum corner");

  /* input/output */
  hestOptAdd(&hopt, "i", "nin", airTypeOther, 1, 1, &nten, "-",
             "image of 2D tensors", NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "p", "pos array", airTypeOther, 1, 1, &npos, "",
             "Instead of being on a grid, tensors are at arbitrary locations, "
             "as defined by this 2-by-N array of floats", NULL, NULL,
             nrrdHestNrrd);
  hestOptAdd(&hopt, "s", "stn array", airTypeOther, 1, 1, &nstn, "",
             "Locations given by \"-p\" have this connectivity", NULL, NULL,
             nrrdHestNrrd);
  hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-",
             "output PostScript file");

  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  USAGE(_tend_ellipseInfoL);
  JUSTPARSE();
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  if (npos) {
    if (!( 2 == nten->dim && 4 == nten->axis[0].size
           && 2 == npos->dim && 2 == npos->axis[0].size
           && nten->axis[1].size == npos->axis[1].size )) {
      fprintf(stderr, "%s: didn't get matching lists of tensors and pos's\n",
              me);
      airMopError(mop); return 1;
    }
    if (!( nrrdTypeFloat == npos->type )) {
      fprintf(stderr, "%s: didn't get float type positions\n", me);
      airMopError(mop); return 1;
    }
  } else {
    if (!(3 == nten->dim && 4 == nten->axis[0].size)) {
      fprintf(stderr, "%s: didn't get a 3-D 4-by-X-by-Y 2D tensor array\n",
              me);
      airMopError(mop); return 1;
    }
  }
  if (!( nrrdTypeFloat == nten->type )) {
    fprintf(stderr, "%s: didn't get float type tensors\n", me);
    airMopError(mop); return 1;
  }
  if (nstn) {
    if (!( nrrdTypeUInt == nstn->type 
           && 2 == nstn->dim
           && 3 == nstn->axis[0].size )) {
      fprintf(stderr, "%s: connectivity isn't 2-D 3-by-N array of %ss\n",
              me, airEnumStr(nrrdType, nrrdTypeInt));
      airMopError(mop); return 1;
    }
  }
  if (!(fout = airFopen(outS, stdout, "wb"))) {
    fprintf(stderr, "%s: couldn't open \"%s\" for writing\n", me, outS);
    airMopError(mop); return 1;
  }
  airMopAdd(mop, fout, (airMopper)airFclose, airMopAlways);

  tend_ellipseDoit(fout, nten, npos, nstn, min, max, 
                   gscale, dotRad, lineWidth, cthresh, invert);

  airMopOkay(mop);
  return 0;
}