Beispiel #1
0
void
tenTripleCalcSingle_f(float dst[3], int ttype, float ten[7]) {
  double dst_d[3], ten_d[7];

  TEN_T_COPY(ten_d, ten);
  tenTripleCalcSingle_d(dst_d, ttype, ten_d);
  ELL_3V_COPY_TT(dst, float, dst_d);
  return;
}
Beispiel #2
0
int
main(int argc, char *argv[]) {
  char *me, *err;
  hestOpt *hopt=NULL;
  airArray *mop;

  char *outS;
  double _tA[6], tA[7], _tB[6], tB[7], time0, time1, conv, confThresh,
    pA[3], pB[3], qA[4], qB[4], rA[9], rB[9], mat1[9], mat2[9], tmp,
    stepSize, minNorm, sclA, sclB;
  unsigned int NN, maxiter, refIdx[3];
  int recurse, ptype, verb;
  Nrrd *_nin, *nin, *nout;
  tenInterpParm *tip;

  mop = airMopNew();
  me = argv[0];
  hestOptAdd(&hopt, "a", "tensor", airTypeDouble, 6, 6, _tA, "1 0 0 1 0 1",
             "first tensor");
  hestOptAdd(&hopt, "pa", "qq", airTypeDouble, 3, 3, pA, "0 0 0",
             "rotation of first tensor");
  hestOptAdd(&hopt, "sa", "scl", airTypeDouble, 1, 1, &sclA, "1.0",
             "scaling of first tensor");
  hestOptAdd(&hopt, "b", "tensor", airTypeDouble, 6, 6, _tB, "1 0 0 1 0 1",
             "second tensor");
  hestOptAdd(&hopt, "pb", "qq", airTypeDouble, 3, 3, pB, "0 0 0",
             "rotation of second tensor");
  hestOptAdd(&hopt, "sb", "scl", airTypeDouble, 1, 1, &sclB, "1.0",
             "scaling of second tensor");
  hestOptAdd(&hopt, "i", "nten", airTypeOther, 1, 1, &_nin, "",
             "input tensor volume (makes previous options moot)",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "ri", "x y z", airTypeUInt, 3, 3, refIdx, "0 0 0",
             "index of reference tensor in input tensor volume");
  hestOptAdd(&hopt, "th", "thresh", airTypeDouble, 1, 1, &confThresh, "0.5",
             "conf mask threshold on \"-i\"");
  hestOptAdd(&hopt, "n", "# steps", airTypeUInt, 1, 1, &NN, "100",
             "number of steps in between two tensors");
  hestOptAdd(&hopt, "s", "stepsize", airTypeDouble, 1, 1, &stepSize, "1",
             "step size in update");
  hestOptAdd(&hopt, "mn", "minnorm", airTypeDouble, 1, 1, &minNorm, "0.000001",
             "minnorm of something");
  hestOptAdd(&hopt, "c", "conv", airTypeDouble, 1, 1, &conv, "0.0001",
             "convergence threshold of length fraction");
  hestOptAdd(&hopt, "mi", "maxiter", airTypeUInt, 1, 1, &maxiter, "0",
             "if non-zero, max # iterations for computation");
  hestOptAdd(&hopt, "r", "recurse", airTypeInt, 0, 0, &recurse, NULL,
             "enable recursive solution, when useful");
  hestOptAdd(&hopt, "t", "path type", airTypeEnum, 1, 1, &ptype, "lerp",
             "what type of path to compute", NULL, tenInterpType);
  hestOptAdd(&hopt, "o", "filename", airTypeString, 1, 1, &outS, "-",
             "file to write output nrrd to");
  hestOptAdd(&hopt, "v", "verbosity", airTypeInt, 1, 1, &verb, "0",
             "verbosity");
  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);

  tip = tenInterpParmNew();
  airMopAdd(mop, tip, (airMopper)tenInterpParmNix, airMopAlways);
  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);

  tip->verbose = verb;
  tip->convStep = stepSize;
  tip->enableRecurse = recurse;
  tip->minNorm = minNorm;
  tip->maxIter = maxiter;
  tip->convEps = conv;
  if (_nin) {
    double refTen[7], inTen[7], *in, *out;
    unsigned int xi, yi, zi, sx, sy, sz, dimOut;
    int axmap[NRRD_DIM_MAX], numerical;
    size_t size[NRRD_DIM_MAX];

    if (tenTensorCheck(_nin, nrrdTypeDefault, AIR_TRUE, AIR_TRUE)) {
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: input volume not valid:\n%s\n",
              me, err);
      airMopError(mop); 
      return 1;
    }
    sx = AIR_CAST(unsigned int, _nin->axis[1].size);
    sy = AIR_CAST(unsigned int, _nin->axis[2].size);
    sz = AIR_CAST(unsigned int, _nin->axis[3].size);
    if (!( refIdx[0] < sx 
           && refIdx[1] < sy
           && refIdx[2] < sz )) {
      fprintf(stderr, "%s: index (%u,%u,%u) out of bounds (%u,%u,%u)\n", me,
              refIdx[0], refIdx[1], refIdx[2], sx, sy, sz);
      airMopError(mop);
      return 1;
    }
    nin = nrrdNew();
    airMopAdd(mop, nin, (airMopper)nrrdNuke, airMopAlways);
    numerical = (ptype == tenInterpTypeGeoLoxK
                 || ptype == tenInterpTypeGeoLoxR
                 || ptype == tenInterpTypeLoxK
                 || ptype == tenInterpTypeLoxR
                 || ptype == tenInterpTypeQuatGeoLoxK
                 || ptype == tenInterpTypeQuatGeoLoxR);
    if (numerical) {
      tip->lengthFancy = AIR_TRUE;
      dimOut = 4;
      size[0] = 3;
      size[1] = _nin->axis[1].size;
      size[2] = _nin->axis[2].size;
      size[3] = _nin->axis[3].size;
      axmap[0] = -1;
      axmap[1] = 1;
      axmap[2] = 2;
      axmap[3] = 3;
    } else {
      dimOut = 3;
      size[0] = _nin->axis[1].size;
      size[1] = _nin->axis[2].size;
      size[2] = _nin->axis[3].size;
      axmap[0] = 1;
      axmap[1] = 2;
      axmap[2] = 3;
    }      
    if (nrrdConvert(nin, _nin, nrrdTypeDouble)
        || nrrdMaybeAlloc_nva(nout, nrrdTypeDouble, dimOut, size)
        || nrrdAxisInfoCopy(nout, nin, axmap, 
                            NRRD_AXIS_INFO_SIZE_BIT)
        || nrrdBasicInfoCopy(nout, nin, 
                             (NRRD_BASIC_INFO_DATA_BIT
                              | NRRD_BASIC_INFO_TYPE_BIT
                              | NRRD_BASIC_INFO_DIMENSION_BIT
                              | NRRD_BASIC_INFO_CONTENT_BIT
                              | NRRD_BASIC_INFO_SAMPLEUNITS_BIT))) {
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble:\n%s\n", me, err);
      airMopError(mop); 
      return 1;
    }
    in = AIR_CAST(double *, nin->data);
    out = AIR_CAST(double *, nout->data);
    TEN_T_COPY(refTen, in + 7*(refIdx[0] + sx*(refIdx[1] + sy*refIdx[2])));
    fprintf(stderr, "!%s: reference tensor = (%g) %g %g %g   %g %g    %g\n",
            me, refTen[0], refTen[1], refTen[2], refTen[3],
            refTen[4], refTen[5], refTen[6]);
    for (zi=0; zi<sz; zi++) {
      for (yi=0; yi<sy; yi++) {
        for (xi=0; xi<sx; xi++) {
          TEN_T_COPY(inTen, in + 7*(xi + sx*(yi + sy*zi)));
          if (numerical) {
            fprintf(stderr, "!%s: %u %u %u \n", me, xi, yi, zi);
            if (inTen[0] < confThresh) {
              out[0] = AIR_NAN;
              out[1] = AIR_NAN;
              out[2] = AIR_NAN;
            } else {
              tip->verbose = 10*(xi == refIdx[0]
                                 && yi == refIdx[1]
                                 && zi == refIdx[2]);
              out[0] =  tenInterpDistanceTwo_d(inTen, refTen, ptype, tip);
              out[1] =  tip->lengthShape;
              out[2] =  tip->lengthOrient;
            }
            out += 3;
          } else {
            if (inTen[0] < confThresh) {
              *out = AIR_NAN;
            } else {
              *out =  tenInterpDistanceTwo_d(inTen, refTen, ptype, tip);
            }
            out += 1;
          }
        }
        if (numerical) {
          if (nrrdSave(outS, nout, NULL)) {
            airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
            fprintf(stderr, "%s: trouble saving output:\n%s\n", me, err);
            airMopError(mop); 
            return 1;
          }
        }
      }
    }
  } else {
Beispiel #3
0
void
_tenDwiGageAnswer(gageContext *ctx, gagePerVolume *pvl) {
  char me[]="_tenDwiGageAnswer";
  unsigned int dwiIdx;
  tenDwiGageKindData *kindData;
  tenDwiGagePvlData *pvlData;
  double *dwiAll, dwiMean=0, tentmp[7];

  kindData = AIR_CAST(tenDwiGageKindData *, pvl->kind->data);
  pvlData = AIR_CAST(tenDwiGagePvlData *, pvl->data);

  dwiAll = pvl->directAnswer[tenDwiGageAll];
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageAll)) {
    /* done if doV */
    if (ctx->verbose) {
      for (dwiIdx=0; dwiIdx<pvl->kind->valLen; dwiIdx++) {
        fprintf(stderr, "%s(%d+%g,%d+%g,%d+%g): dwi[%u] = %g\n", me,
                ctx->point.xi, ctx->point.xf,
                ctx->point.yi, ctx->point.yf,
                ctx->point.zi, ctx->point.zf,
                dwiIdx, dwiAll[dwiIdx]);
      }
      fprintf(stderr, "%s: type(ngrad) = %d = %s\n", me,
              kindData->ngrad->type,
              airEnumStr(nrrdType, kindData->ngrad->type));
    }
  }

  /*
    if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageB0)) {
    if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageJustDWI)) {
    done if doV
    }
  */
  /* HEY this isn't valid for multiple b-values */
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageADC)) {
    double logdwi, logb0;
    logb0 = log(AIR_MAX(kindData->valueMin,
                        pvl->directAnswer[tenDwiGageB0][0]));
    for (dwiIdx=1; dwiIdx<pvl->kind->valLen; dwiIdx++) {
      logdwi = log(AIR_MAX(kindData->valueMin,
                           pvl->directAnswer[tenDwiGageJustDWI][dwiIdx-1]));
      pvl->directAnswer[tenDwiGageADC][dwiIdx-1]
        = (logb0 - logdwi)/kindData->bval;
    }
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageMeanDWIValue)) {
    dwiMean = 0;
    for (dwiIdx=1; dwiIdx<pvl->kind->valLen; dwiIdx++) {
      dwiMean += dwiAll[dwiIdx];
    }
    dwiMean /= pvl->kind->valLen;
    pvl->directAnswer[tenDwiGageMeanDWIValue][0] = dwiMean;
  }

  /* note: the gage interface to tenEstimate functionality 
     allows you exactly one kind of tensor estimation (per kind),
     so the function call to do the estimation is actually
     repeated over and over again; the copy into the answer
     buffer is what changes... */
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageTensorLLS)) {
    tenEstimate1TensorSingle_d(pvlData->tec1, tentmp, dwiAll);
    TEN_T_COPY(pvl->directAnswer[tenDwiGageTensorLLS], tentmp);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageTensorLLSError)) {
    pvl->directAnswer[tenDwiGageTensorLLSError][0] = pvlData->tec1->errorDwi;
  }  
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageTensorLLSErrorLog)) {
    pvl->directAnswer[tenDwiGageTensorLLSErrorLog][0] 
      = pvlData->tec1->errorLogDwi;
  }  
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageTensorWLS)) {
    tenEstimate1TensorSingle_d(pvlData->tec1, tentmp, dwiAll);
    TEN_T_COPY(pvl->directAnswer[tenDwiGageTensorWLS], tentmp);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageTensorNLS)) {
    tenEstimate1TensorSingle_d(pvlData->tec1, tentmp, dwiAll);
    TEN_T_COPY(pvl->directAnswer[tenDwiGageTensorNLS], tentmp);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageTensorMLE)) {
    tenEstimate1TensorSingle_d(pvlData->tec1, tentmp, dwiAll);
    TEN_T_COPY(pvl->directAnswer[tenDwiGageTensorMLE], tentmp);
  }
  /* HEY: have to implement all the different kinds of errors */

  /* BEGIN sneakiness ........ */
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageTensor)) {
    gageItemEntry *item;
    item = pvl->kind->table + tenDwiGageTensor;
    TEN_T_COPY(pvl->directAnswer[tenDwiGageTensor],
               pvl->directAnswer[item->prereq[0]]);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageTensorError)) {
    gageItemEntry *item;
    item = pvl->kind->table + tenDwiGageTensorError;
    pvl->directAnswer[tenDwiGageTensorError][0]
      = pvl->directAnswer[item->prereq[0]][0];
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageTensorErrorLog)) {
    gageItemEntry *item;
    item = pvl->kind->table + tenDwiGageTensorErrorLog;
    pvl->directAnswer[tenDwiGageTensorErrorLog][0]
      = pvl->directAnswer[item->prereq[0]][0];
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageTensorLikelihood)) {
    gageItemEntry *item;
    item = pvl->kind->table + tenDwiGageTensorLikelihood;
    pvl->directAnswer[tenDwiGageTensorLikelihood][0]
      = pvl->directAnswer[item->prereq[0]][0];
  }
  /* END sneakiness ........ */

  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageFA)) {
    pvl->directAnswer[tenDwiGageFA][0]
      = pvl->directAnswer[tenDwiGageTensor][0]
      * tenAnisoTen_d(pvl->directAnswer[tenDwiGageTensor],
                      tenAniso_FA);
  }

  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGageTensorAllDWIError)) {
    const double *grads;
    int gradcount;
    double *ten, d;
    int i;
    
    /* HEY: should switch to tenEstimate-based DWI simulation */
    ten = pvl->directAnswer[tenDwiGageTensor];
    gradcount = pvl->kind->valLen -1; /* Dont count b0 */
    grads = ((const double*) kindData->ngrad->data) +3; /* Ignore b0 grad */
    for( i=0; i < gradcount; i++ ) {
      d = dwiAll[0]*exp(- pvlData->tec1->bValue 
                        * TEN_T3V_CONTR(ten, grads + 3*i));
      pvl->directAnswer[tenDwiGageTensorAllDWIError][i] = dwiAll[i+1] - d;
    }
  }

  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGage2TensorQSeg)) {
    const double *grads;
    int gradcount;
    double *twoten;
    unsigned int valIdx, E;
    
    twoten = pvl->directAnswer[tenDwiGage2TensorQSeg];
    
    gradcount = pvl->kind->valLen -1; /* Dont count b0 */
    grads = ((const double*) kindData->ngrad->data) +3; /* Ignore b0 grad */
    if (dwiAll[0] != 0) { /*  S0 = 0 */
      _tenQball(pvlData->tec2->bValue, gradcount, dwiAll, grads,
                pvlData->qvals);
      _tenQvals2points(gradcount, pvlData->qvals, grads, pvlData->qpoints);
      _tenSegsamp2(gradcount, pvlData->qvals, grads, pvlData->qpoints,
                   pvlData->wght + 1, pvlData->dists );
    } else {
      /* stupid; should really return right here since data is garbage */
      for (valIdx=1; valIdx < AIR_CAST(unsigned int, gradcount+1); valIdx++) {
        pvlData->wght[valIdx] = valIdx % 2;
      }
    }
    
    E = 0;
    for (valIdx=1; valIdx<pvl->kind->valLen; valIdx++) {
      if (!E) E |= tenEstimateSkipSet(pvlData->tec2, valIdx,
                                      pvlData->wght[valIdx]);
    }
    if (!E) E |= tenEstimateUpdate(pvlData->tec2);
    if (!E) E |= tenEstimate1TensorSingle_d(pvlData->tec2,
                                            twoten + 0, dwiAll);
    for (valIdx=1; valIdx<pvl->kind->valLen; valIdx++) {
      if (!E) E |= tenEstimateSkipSet(pvlData->tec2, valIdx,
                                      1 - pvlData->wght[valIdx]);
    }
    if (!E) E |= tenEstimateUpdate(pvlData->tec2);
    if (!E) E |= tenEstimate1TensorSingle_d(pvlData->tec2,
                                            twoten + 7, dwiAll);
    if (E) {
      fprintf(stderr, "!%s: (trouble) %s\n", me, biffGetDone(TEN));
    }
    
    /* hack: confidence for two-tensor fit */
    twoten[0] = (twoten[0] + twoten[7])/2;
    twoten[7] = 0.5; /* fraction that is the first tensor (initial value) */
    /* twoten[1 .. 6] = first tensor */
    /* twoten[8 .. 13] = second tensor */
    
    /* Compute fraction between tensors if not garbage in this voxel */
    if (twoten[0] > 0.5) {
      double exp0,exp1,d,e=0,g=0, a=0,b=0;
      int i;
      
      for( i=0; i < gradcount; i++ ) {
        exp0 = exp(-pvlData->tec2->bValue * TEN_T3V_CONTR(twoten + 0,
                                                          grads + 3*i));
        exp1 = exp(-pvlData->tec2->bValue * TEN_T3V_CONTR(twoten + 7,
                                                          grads + 3*i));
        
        d = dwiAll[i+1] / dwiAll[0];
        e = exp0 - exp1;
        g = d - exp1;
        
        a += .5*e*e;
        b += e*g;
      }
      
      twoten[7] = AIR_CLAMP(0, 0.5*(b/a), 1);
    }
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGage2TensorQSegError)) {
    const double *grads;
    int gradcount;
    double *twoten, d;
    int i;
    
    /* HEY: should switch to tenEstimate-based DWI simulation */
    if (dwiAll[0] != 0) { /* S0 = 0 */
      twoten = pvl->directAnswer[tenDwiGage2TensorQSeg];
      gradcount = pvl->kind->valLen -1; /* Dont count b0 */
      grads = ((const double*) kindData->ngrad->data) +3; /* Ignore b0 grad */
      
      pvl->directAnswer[tenDwiGage2TensorQSegError][0] = 0;
      for( i=0; i < gradcount; i++ ) {
        d = twoten[7]*exp(-pvlData->tec2->bValue * TEN_T3V_CONTR(twoten + 0,
                                                                 grads + 3*i));
        d += (1 - twoten[7])*exp(-pvlData->tec2->bValue 
                                 *TEN_T3V_CONTR(twoten + 7, grads + 3*i));
        d = dwiAll[i+1]/dwiAll[0] - d;
        pvl->directAnswer[tenDwiGage2TensorQSegError][0] += d*d;
      }
      pvl->directAnswer[tenDwiGage2TensorQSegError][0] = 
        sqrt( pvl->directAnswer[tenDwiGage2TensorQSegError][0] );
    } else {
      /* HEY: COMPLETELY WRONG!! An error is not defined! */
      pvl->directAnswer[tenDwiGage2TensorQSegError][0] = 0;
    }
    /* printf("%f\n",pvl->directAnswer[tenDwiGage2TensorQSegError][0]); */
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGage2TensorQSegAndError)) {
    double *twoten, *err, *twotenerr;
    
    twoten = pvl->directAnswer[tenDwiGage2TensorQSeg];
    err = pvl->directAnswer[tenDwiGage2TensorQSegError];
    twotenerr = pvl->directAnswer[tenDwiGage2TensorQSegAndError];
    TEN_T_COPY(twotenerr + 0, twoten + 0);
    TEN_T_COPY(twotenerr + 7, twoten + 7);
    twotenerr[14] = err[0];
  }

  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenDwiGage2TensorPeled)) {
#if TEEM_LEVMAR
#define PARAMS 4
    double *twoTen, Cp /* , residual, AICSingFit, AICTwoFit */;
    /* Vars for the NLLS */
    double guess[PARAMS], loBnd[PARAMS], upBnd[PARAMS],
      opts[LM_OPTS_SZ], *grad, *egrad, tenA[7], tenB[7],
      matA[9], matB[9], matTmp[9], rott[9];
    unsigned int gi;
    int lmret;
    
    /* Pointer to the location where the two tensor will be written */
    twoTen = pvl->directAnswer[tenDwiGage2TensorPeled];
    /* Estimate the DWI error, error is given as standard deviation */
    pvlData->tec2->recordErrorDwi = AIR_FALSE;
    /* Estimate the single tensor */
    tenEstimate1TensorSingle_d(pvlData->tec2, pvlData->ten1, dwiAll);
    /* Get the eigenValues and eigen vectors for this tensor */
    tenEigensolve_d(pvlData->ten1Eval, pvlData->ten1Evec, pvlData->ten1);
    /* Get westins Cp */
    Cp = tenAnisoEval_d(pvlData->ten1Eval, tenAniso_Cp1);
    
    /* Calculate the residual, need the variance to sqr it */
    /* residual = pvlData->tec2->errorDwi*pvlData->tec2->errorDwi; */
    /* Calculate the AIC for single tensor fit */
    /* AICSingFit = _tenComputeAIC(residual, pvlData->tec2->dwiNum, 6); */

    /* the CP-based test is gone; caller's responsibility */
      
    /* rotate DW gradients by inverse of eigenvector column matrix
       and place into pvlData->nten1EigenGrads (which has been
       allocated by _tenDwiGagePvlDataNew()) */
    grad = AIR_CAST(double *, kindData->ngrad->data);
    egrad = AIR_CAST(double *, pvlData->nten1EigenGrads->data);
    for (gi=0; gi<kindData->ngrad->axis[1].size; gi++) {
      /* yes, this is also transforming some zero-length (B0) gradients;
         that's harmless */
      ELL_3MV_MUL(egrad, pvlData->ten1Evec, grad);
      grad += 3;
      egrad += 3;
    }
    
    /* Lower and upper bounds for the NLLS routine */
    loBnd[0] = 0.0;
    loBnd[1] = 0.0;       
    loBnd[2] = -AIR_PI/2;
    loBnd[3] = -AIR_PI/2;
    upBnd[0] = pvlData->ten1Eval[0]*5;
    upBnd[1] = 1.0;
    upBnd[2] = AIR_PI/2;
    upBnd[3] = AIR_PI/2;
    /* Starting point for the NLLS */
    guess[0] = pvlData->ten1Eval[0];
    guess[1] = 0.5;

    guess[2] = AIR_PI/4;
    guess[3] = -AIR_PI/4;
    /*
    guess[2] = AIR_AFFINE(0, airDrandMT_r(pvlData->randState), 1,
                          AIR_PI/6, AIR_PI/3);
    guess[3] = AIR_AFFINE(0, airDrandMT_r(pvlData->randState), 1,
                          -AIR_PI/6, -AIR_PI/3);
    */
    /* Fill in the constraints for the LM optimization, 
       the threshold of error difference */
    opts[0] = pvlData->levmarTau;
    opts[1] = pvlData->levmarEps1;
    opts[2] = pvlData->levmarEps2;
    opts[3] = pvlData->levmarEps3;
    /* Very imp to set this opt, note that only forward
       differences are used to approx Jacobian */
    opts[4] = pvlData->levmarDelta;
    
    /* run NLLS, results are stored back into guess[] */
    pvlData->levmarUseFastExp = AIR_FALSE;
    lmret = dlevmar_bc_dif(_tenLevmarPeledCB, guess, pvlData->tec2->dwi,
                           PARAMS, pvlData->tec2->dwiNum, loBnd, upBnd,
                           pvlData->levmarMaxIter, opts,
                           pvlData->levmarInfo,
                           NULL, NULL, pvlData);
    if (-1 == lmret) {
      ctx->errNum = 1;
      sprintf(ctx->errStr, "%s: dlevmar_bc_dif() failed!", me);
    } else {
      /* Get the AIC for the two tensor fit, use the levmarinfo
         to get the residual */
      /*
        residual = pvlData->levmarInfo[1]/pvlData->tec2->dwiNum;
        AICTwoFit = _tenComputeAIC(residual, pvlData->tec2->dwiNum, 12);
      */
      /* Form the tensors using the estimated pp, returned in guess */
      _tenPeledRotate2D(tenA, guess[0], pvlData->ten1Eval[2], guess[2]);
      _tenPeledRotate2D(tenB, guess[0], pvlData->ten1Eval[2], guess[3]);
      TEN_T2M(matA, tenA);
      TEN_T2M(matB, tenB);
      
      ELL_3M_TRANSPOSE(rott, pvlData->ten1Evec);
      ELL_3M_MUL(matTmp, matA, pvlData->ten1Evec);
      ELL_3M_MUL(matA, rott, matTmp);
      ELL_3M_MUL(matTmp, matB, pvlData->ten1Evec);
      ELL_3M_MUL(matB, rott, matTmp);
      
      /* Copy two two tensors */
      /* guess[1] is population fraction of first tensor */
      if (guess[1] > 0.5) {
        twoTen[7] = guess[1];
        TEN_M2T(twoTen + 0, matA);
        TEN_M2T(twoTen + 7, matB);
      } else {
        twoTen[7] = 1 - guess[1];
        TEN_M2T(twoTen + 0, matB);
        TEN_M2T(twoTen + 7, matA);
      }
      twoTen[0] = 1;
    }
#undef PARAMS
#else
    double *twoTen;
    twoTen = pvl->directAnswer[tenDwiGage2TensorPeled];
    TEN_T_SET(twoTen + 0, AIR_NAN, AIR_NAN, AIR_NAN, AIR_NAN,
              AIR_NAN, AIR_NAN, AIR_NAN);
    TEN_T_SET(twoTen + 7, AIR_NAN, AIR_NAN, AIR_NAN, AIR_NAN,
              AIR_NAN, AIR_NAN, AIR_NAN);
    fprintf(stderr, "%s: sorry, not compiled with TEEM_LEVMAR\n", me);
#endif
  }
Beispiel #4
0
static int
csimDo(double tm[7], double tcov[21], double rm[3], double rv[3],
       Nrrd *ntbuff, tenEstimateContext *tec, double *dwibuff, double sigma,
       double bvalue, double B0, unsigned int NN, int randrot,
       double _tenOrig[7]) {
  char me[]="csimDo", err[BIFF_STRLEN];
  double *tbuff;
  unsigned int II, taa, tbb, cc;

  if (!(ntbuff
        && ntbuff->data
        && 2 == ntbuff->dim
        && 7 == ntbuff->axis[0].size
        && NN == ntbuff->axis[1].size)) {
    sprintf(err, "%s: ntbuff not allocated for 2-by-%u array of %s", me,
            NN, airEnumStr(nrrdType, nrrdTypeDouble));
    biffAdd(TEN, err); return 1;
  }

  /* find all tensors from simulated DWIs */
  tbuff = AIR_CAST(double *, ntbuff->data);
  for (II=0; II<NN; II++) {
    double tenOrig[7], rotf[9], rotb[9], matA[9], matB[9], qq[4], tmp;
    ELL_3M_IDENTITY_SET(rotf); /* sssh warnings */
    ELL_3M_IDENTITY_SET(rotb); /* sssh warnings */

    if (randrot) {
      if (1) {
        double eval[3], evec[9], eps, ma[9], mb[9], rf[9], rb[9];
        tenEigensolve_d(eval, evec, _tenOrig);
        airNormalRand(&eps, NULL);
        ell_aa_to_3m_d(rf, 0*eps/20, evec + 0);
        TEN_T_SCALE_INCR(_tenOrig, 0*eps/30, _tenOrig);
        TEN_T2M(ma, _tenOrig);
        ELL_3M_TRANSPOSE(rb, rf);
        ELL_3M_MUL(mb, ma, rf);
        ELL_3M_MUL(ma, rb, mb);
        TEN_M2T(_tenOrig, ma);
      }
      TEN_T2M(matA, _tenOrig);
      airNormalRand(qq+0, qq+1);
      airNormalRand(qq+2, qq+3);
      ELL_4V_NORM(qq, qq, tmp);
      ell_q_to_3m_d(rotf, qq);
      ELL_3M_TRANSPOSE(rotb, rotf);
      ELL_3M_MUL(matB, matA, rotf);
      ELL_3M_MUL(matA, rotb, matB);
      TEN_M2T(tenOrig, matA);
    } else {
      TEN_T_COPY(tenOrig, _tenOrig);
    }
    if (tenEstimate1TensorSimulateSingle_d(tec, dwibuff, sigma,
                                           bvalue, B0, tenOrig)
        || tenEstimate1TensorSingle_d(tec, tbuff, dwibuff)) {
      sprintf(err, "%s: trouble on exp %u/%u", me, II, NN);
      biffAdd(TEN, err); return 1;
    }
    if (randrot) {
      TEN_T2M(matA, tbuff);
      ELL_3M_MUL(matB, matA, rotb);
      ELL_3M_MUL(matA, rotf, matB);
      TEN_M2T(tbuff, matA);
    } /* else we leave tbuff as it is */
    /*
    if (_tenOrig[0] > 0.5) {
      double tdiff[7];
      TEN_T_SUB(tdiff, _tenOrig, tbuff);
      fprintf(stderr, "!%s: %g\n"
              "         (%g) %g,%g,%g  %g,%g  %g\n"
              "         (%g) %g,%g,%g  %g,%g  %g\n", 
              me, TEN_T_NORM(tdiff),
              _tenOrig[0], _tenOrig[1], _tenOrig[2], _tenOrig[3], _tenOrig[4], 
              _tenOrig[5], _tenOrig[6], 
              tbuff[0], tbuff[1], tbuff[2], tbuff[3], tbuff[4],
              tbuff[5], tbuff[6]);
    }
    */
    tbuff += 7;
  }

  /* find mean tensor, and mean R_i */
  tbuff = AIR_CAST(double *, ntbuff->data);
  TEN_T_SET(tm, 0, 0, 0, 0, 0, 0, 0);
  ELL_3V_SET(rm, 0, 0, 0);
  for (II=0; II<NN; II++) {
    TEN_T_INCR(tm, tbuff);
    rm[0] += sqrt(_tenAnisoTen_d[tenAniso_S](tbuff));
    rm[1] += _tenAnisoTen_d[tenAniso_FA](tbuff);
    rm[2] += _tenAnisoTen_d[tenAniso_Mode](tbuff);
    tbuff += 7;
  }
  rm[0] /= NN;
  rm[1] /= NN;
  rm[2] /= NN;
  TEN_T_SCALE(tm, 1.0/NN, tm);

  /* accumulate covariance tensor, and R_i variances */
  for (cc=0; cc<21; cc++) {
    tcov[cc] = 0;
  }
  ELL_3V_SET(rv, 0, 0, 0);
  tbuff = AIR_CAST(double *, ntbuff->data);
  for (II=0; II<NN; II++) {
    double r[3];
    r[0] = sqrt(_tenAnisoTen_d[tenAniso_S](tbuff));
    r[1] = _tenAnisoTen_d[tenAniso_FA](tbuff);
    r[2] = _tenAnisoTen_d[tenAniso_Mode](tbuff);
    cc = 0;
    rv[0] += (r[0] - rm[0])*(r[0] - rm[0])/(NN-1);
    rv[1] += (r[1] - rm[1])*(r[1] - rm[1])/(NN-1);
    rv[2] += (r[2] - rm[2])*(r[2] - rm[2])/(NN-1);
    for (taa=0; taa<6; taa++) {
      for (tbb=taa; tbb<6; tbb++) {
        tcov[cc] += (10000*(tbuff[taa+1]-tm[taa+1])
                     *10000*(tbuff[tbb+1]-tm[tbb+1])/(NN-1));
        cc++;
      }
    }
    tbuff += 7;
  }

  return 0;
}