Пример #1
0
void
tenTripleCalcSingle_d(double dst[3], int ttype, double ten[7]) {
  double eval[3];

  /* in time this can become more efficient ... */
  switch (ttype) {
  case tenTripleTypeEigenvalue:
    tenEigensolve_d(dst, NULL, ten);
    break;
  case tenTripleTypeMoment:
  case tenTripleTypeXYZ:
  case tenTripleTypeRThetaZ:
  case tenTripleTypeRThetaPhi:
  case tenTripleTypeK:
  case tenTripleTypeJ:
  case tenTripleTypeWheelParm:
    tenEigensolve_d(eval, NULL, ten);
    tenTripleConvertSingle_d(dst, ttype, eval, tenTripleTypeEigenvalue);
    break;
  case tenTripleTypeR:
    dst[0] = sqrt(_tenAnisoTen_d[tenAniso_S](ten));
    dst[1] = _tenAnisoTen_d[tenAniso_FA](ten);
    dst[2] = _tenAnisoTen_d[tenAniso_Mode](ten);
    break;
  default:
    /* what on earth? */
    ELL_3V_SET(dst, AIR_NAN, AIR_NAN, AIR_NAN);
  }
  return;
}
Пример #2
0
void
_coilKind7TensorFilterFinish(coil_t *delta, coil_t **iv3, 
                             double spacing[3],
                             double parm[COIL_PARMS_NUM]) {
  coil_t rspX, rspY, rspZ,
    rspsqX, rspsqY, rspsqZ;
  double eval[3], evec[9], tens[7], tengrad[21], grad[3], LL, KK,
    cnd,
    dmu1[7], dmu2[7], dskw[7], phi3[7];

  rspX = AIR_CAST(coil_t, 1.0/spacing[0]); rspsqX = rspX*rspX;
  rspY = AIR_CAST(coil_t, 1.0/spacing[1]); rspsqY = rspY*rspY;
  rspZ = AIR_CAST(coil_t, 1.0/spacing[2]); rspsqZ = rspZ*rspZ;
  TENS(tens, iv3);
  TENGRAD(tengrad, iv3, rspX, rspY, rspZ);
  tenEigensolve_d(eval, evec, tens);
  tenInvariantGradientsK_d(dmu1, dmu2, dskw, tens, 0.000001);
  tenRotationTangents_d(NULL, NULL, phi3, evec);
  /* \midhat{\nabla} \mu_1 ----------------- */
  ELL_3V_SET(grad,
             TEN_T_DOT(dmu1, tengrad + 0*7),
             TEN_T_DOT(dmu1, tengrad + 1*7),
             TEN_T_DOT(dmu1, tengrad + 2*7));
  LL = ELL_3V_DOT(grad,grad);
  KK = parm[1]*parm[1];
  cnd = _COIL_CONDUCT(LL, KK);
  /* \midhat{\nabla} \mu_2 ----------------- */
  ELL_3V_SET(grad,
             TEN_T_DOT(dmu2, tengrad + 0*7),
             TEN_T_DOT(dmu2, tengrad + 1*7),
             TEN_T_DOT(dmu2, tengrad + 2*7));
  LL = ELL_3V_DOT(grad,grad);
  KK = parm[2]*parm[2];
  cnd *= _COIL_CONDUCT(LL, KK);
  /* \midhat{\nabla} \skw and twist! ----------------- */
  ELL_3V_SET(grad,
             TEN_T_DOT(dskw, tengrad + 0*7),
             TEN_T_DOT(dskw, tengrad + 1*7),
             TEN_T_DOT(dskw, tengrad + 2*7));
  LL = ELL_3V_DOT(grad,grad);
  ELL_3V_SET(grad,
             TEN_T_DOT(phi3, tengrad + 0*7),
             TEN_T_DOT(phi3, tengrad + 1*7),
             TEN_T_DOT(phi3, tengrad + 2*7));
  LL += ELL_3V_DOT(grad,grad);
  KK = AIR_CAST(coil_t, parm[3]*parm[3]);
  cnd *= _COIL_CONDUCT(LL, KK); 
  delta[0]= 0.0f;
  delta[1]= AIR_CAST(coil_t, parm[0]*cnd*LAPL(iv3, 1, rspsqX, rspsqY, rspsqZ));
  delta[2]= AIR_CAST(coil_t, parm[0]*cnd*LAPL(iv3, 2, rspsqX, rspsqY, rspsqZ));
  delta[3]= AIR_CAST(coil_t, parm[0]*cnd*LAPL(iv3, 3, rspsqX, rspsqY, rspsqZ));
  delta[4]= AIR_CAST(coil_t, parm[0]*cnd*LAPL(iv3, 4, rspsqX, rspsqY, rspsqZ));
  delta[5]= AIR_CAST(coil_t, parm[0]*cnd*LAPL(iv3, 5, rspsqX, rspsqY, rspsqZ));
  delta[6]= AIR_CAST(coil_t, parm[0]*cnd*LAPL(iv3, 6, rspsqX, rspsqY, rspsqZ));
}
Пример #3
0
void
tenQGLInterpTwo(double oten[7],
                const double tenA[7], const double tenB[7],
                int ptype, double tt, tenInterpParm *tip) {
  double oeval[3], evalA[3], evalB[3], oevec[9], evecA[9], evecB[9], cc;

  AIR_UNUSED(tip);
  tenEigensolve_d(evalA, evecA, tenA);
  tenEigensolve_d(evalB, evecB, tenB);
  cc = AIR_LERP(tt, tenA[0], tenB[0]);

  if (tenInterpTypeQuatGeoLoxK == ptype) {
    tenQGLInterpTwoEvalK(oeval, evalA, evalB, tt);
  } else {
    tenQGLInterpTwoEvalR(oeval, evalA, evalB, tt);
  }
  tenQGLInterpTwoEvec(oevec, evecA, evecB, tt);
  tenMakeSingle_d(oten, cc, oeval, oevec);

  return;
}
Пример #4
0
int
main(int argc, const char *argv[]) {
  const char *me;
  hestOpt *hopt=NULL;
  airArray *mop;

  double _tt[6], tt[7], ss, pp[3], qq[4], rot[9], mat1[9], mat2[9], tmp,
    evalA[3], evecA[9], evalB[3], evecB[9];
  int roots;

  mop = airMopNew();
  me = argv[0];
  hestOptAdd(&hopt, NULL, "m00 m01 m02 m11 m12 m22",
             airTypeDouble, 6, 6, _tt, NULL, "symmtric matrix coeffs");
  hestOptAdd(&hopt, "p", "vec", airTypeDouble, 3, 3, pp, "0 0 0",
             "rotation as P vector");
  hestOptAdd(&hopt, "s", "scl", airTypeDouble, 1, 1, &ss, "1.0",
             "scaling");
  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);

  ELL_6V_COPY(tt + 1, _tt);
  tt[0] = 1.0;
  TEN_T_SCALE(tt, ss, tt);

  ELL_4V_SET(qq, 1, pp[0], pp[1], pp[2]);
  ELL_4V_NORM(qq, qq, tmp);
  ell_q_to_3m_d(rot, qq);
  printf("%s: rot\n", me);
  printf("  %g %g %g\n", rot[0], rot[1], rot[2]);
  printf("  %g %g %g\n", rot[3], rot[4], rot[5]);
  printf("  %g %g %g\n", rot[6], rot[7], rot[8]);

  TEN_T2M(mat1, tt);
  ell_3m_mul_d(mat2, rot, mat1);
  ELL_3M_TRANSPOSE_IP(rot, tmp);
  ell_3m_mul_d(mat1, mat2, rot);
  TEN_M2T(tt, mat1);

  printf("input matrix = \n %g %g %g\n %g %g\n %g\n",
          tt[1], tt[2], tt[3], tt[4], tt[5], tt[6]);

  printf("================== tenEigensolve_d ==================\n");
  roots = tenEigensolve_d(evalA, evecA, tt);
  printf("%s roots\n", airEnumStr(ell_cubic_root, roots));
  testeigen(tt, evalA, evecA);

  printf("================== new eigensolve ==================\n");
  roots = evals(evalB, tt[1], tt[2], tt[3], tt[4], tt[5], tt[6]);
  printf("%s roots: %g %g %g\n", airEnumStr(ell_cubic_root, roots),
         evalB[0], evalB[1], evalB[2]);
  roots = evals_evecs(evalB, evecB,
                      tt[1], tt[2], tt[3], tt[4], tt[5], tt[6]);
  printf("%s roots\n", airEnumStr(ell_cubic_root, roots));
  testeigen(tt, evalB, evecB);

  airMopOkay(mop);
  return 0;
}
Пример #5
0
void
_tenGageAnswer (gageContext *ctx, gagePerVolume *pvl) {
  /* char me[]="_tenGageAnswer"; */
  gage_t epsilon=1.0E-10f;
  gage_t *tenAns, *evalAns, *evecAns, *vecTmp=NULL,
    *gradDtA=NULL, *gradDtB=NULL, *gradDtC=NULL,
    *gradDtD=NULL, *gradDtE=NULL, *gradDtF=NULL,
    gradDdXYZ[21]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    *gradCbS=NULL, *gradCbB=NULL, *gradCbQ=NULL, *gradCbR=NULL;
  gage_t tmp0, tmp1, magTmp=0,
    gradCbA[3]={0,0,0}, gradCbC[3]={0,0,0},
    dtA=0, dtB=0, dtC=0, dtD=0, dtE=0, dtF=0,
    cbQQQ=0, cbQ=0, cbR=0, cbA=0, cbB=0, cbC=0, cbS=0;

#if !GAGE_TYPE_FLOAT
  int ci;
  float evalAnsF[3], aniso[TEN_ANISO_MAX+1];
#endif

  tenAns = pvl->directAnswer[tenGageTensor];
  evalAns = pvl->directAnswer[tenGageEval];
  evecAns = pvl->directAnswer[tenGageEvec];
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTensor)) {
    /* done if doV */
    tenAns[0] = AIR_CLAMP(0.0f, tenAns[0], 1.0f);
    dtA = tenAns[1];
    dtB = tenAns[2];
    dtC = tenAns[3];
    dtD = tenAns[4];
    dtE = tenAns[5];
    dtF = tenAns[6];
    if (ctx->verbose) {
      fprintf(stderr, "tensor = (%g) %g %g %g   %g %g   %g\n", tenAns[0],
              dtA, dtB, dtC, dtD, dtE, dtF);
    }
  }
  /* done if doV 
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageConfidence)) {
  }
  */
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTrace)) {
    cbA = -(pvl->directAnswer[tenGageTrace][0] = dtA + dtD + dtF);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageB)) {
    cbB = pvl->directAnswer[tenGageB][0] = 
      dtA*dtD + dtA*dtF + dtD*dtF - dtB*dtB - dtC*dtC - dtE*dtE;
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageDet)) {
    cbC = -(pvl->directAnswer[tenGageDet][0] = 
            2.0f*dtB*dtC*dtE + dtA*dtD*dtF 
            - dtC*dtC*dtD - dtA*dtE*dtE - dtB*dtB*dtF);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageS)) {
    cbS = (pvl->directAnswer[tenGageS][0] = 
           dtA*dtA + dtD*dtD + dtF*dtF
           + 2.0f*dtB*dtB + 2.0f*dtC*dtC + 2.0f*dtE*dtE);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageQ)) {
    cbQ = pvl->directAnswer[tenGageQ][0] = (cbS - cbB)/9.0f;
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageFA)) {
    pvl->directAnswer[tenGageFA][0] =
      AIR_CAST(gage_t, 3*sqrt(cbQ/(epsilon + cbS)));
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageR)) {
    cbR = pvl->directAnswer[tenGageR][0] =
      (5.0f*cbA*cbB - 27.0f*cbC - 2.0f*cbA*cbS)/54.0f;
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTheta)) {
    cbQQQ = cbQ*cbQ*cbQ;
    tmp0 = AIR_CAST(gage_t, cbR/(epsilon + sqrt(cbQQQ)));
    tmp0 = AIR_CLAMP(-1.0f, tmp0, 1.0f);
    pvl->directAnswer[tenGageTheta][0] = AIR_CAST(gage_t, acos(tmp0)/AIR_PI);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageEvec)) {
    /* we do the longer process to get eigenvectors, and in the process
       we always find the eigenvalues, whether or not they were asked for */
#if GAGE_TYPE_FLOAT
    tenEigensolve_f(evalAns, evecAns, tenAns);
#else
    tenEigensolve_d(evalAns, evecAns, tenAns);
#endif
  } else if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageEval)) {
    /* else eigenvectors are NOT needed, but eigenvalues ARE needed */
#if GAGE_TYPE_FLOAT
    tenEigensolve_f(evalAns, NULL, tenAns);
#else
    tenEigensolve_d(evalAns, NULL, tenAns);
#endif
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTensorGrad)) {
    /* done if doD1 */
    /* still have to set up pointer variables that item answers
       below will rely on as short-cuts */
    vecTmp = pvl->directAnswer[tenGageTensorGrad];
    gradDtA = vecTmp + 1*3;
    gradDtB = vecTmp + 2*3;
    gradDtC = vecTmp + 3*3;
    gradDtD = vecTmp + 4*3;
    gradDtE = vecTmp + 5*3;
    gradDtF = vecTmp + 6*3;
    TEN_T_SET(gradDdXYZ + 0*7, tenAns[0],
              gradDtA[0], gradDtB[0], gradDtC[0],
              gradDtD[0], gradDtE[0],
              gradDtF[0]);
    TEN_T_SET(gradDdXYZ + 1*7, tenAns[0],
              gradDtA[1], gradDtB[1], gradDtC[1],
              gradDtD[1], gradDtE[1],
              gradDtF[1]);
    TEN_T_SET(gradDdXYZ + 2*7, tenAns[0],
              gradDtA[2], gradDtB[2], gradDtC[2],
              gradDtD[2], gradDtE[2],
              gradDtF[2]);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTensorGradMag)) {
    vecTmp = pvl->directAnswer[tenGageTensorGradMag];
    vecTmp[0] = AIR_CAST(gage_t, sqrt(TEN_T_DOT(gradDdXYZ + 0*7,
                                                gradDdXYZ + 0*7)));
    vecTmp[1] = AIR_CAST(gage_t, sqrt(TEN_T_DOT(gradDdXYZ + 1*7,
                                                gradDdXYZ + 1*7)));
    vecTmp[2] = AIR_CAST(gage_t, sqrt(TEN_T_DOT(gradDdXYZ + 2*7,
                                                gradDdXYZ + 2*7)));
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTensorGradMag)) {
    pvl->directAnswer[tenGageTensorGradMagMag][0] =
      AIR_CAST(gage_t, ELL_3V_LEN(vecTmp));
  }

  /* --- Trace --- */
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTraceGradVec)) {
    vecTmp = pvl->directAnswer[tenGageTraceGradVec];
    ELL_3V_ADD3(vecTmp, gradDtA, gradDtD, gradDtF);
    ELL_3V_SCALE(gradCbA, -1, vecTmp);

  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTraceGradMag)) {
    magTmp = pvl->directAnswer[tenGageTraceGradMag][0] =
      AIR_CAST(gage_t, ELL_3V_LEN(vecTmp));
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTraceNormal)) {
    ELL_3V_SCALE(pvl->directAnswer[tenGageTraceNormal],
                 1.0f/(epsilon + magTmp), vecTmp);
  }
  /* --- B --- */
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageBGradVec)) {
    gradCbB = vecTmp = pvl->directAnswer[tenGageBGradVec];
    ELL_3V_SCALE_ADD6(vecTmp, 
                      dtD + dtF, gradDtA,
                      -2.0f*dtB, gradDtB,
                      -2.0f*dtC, gradDtC,
                      dtA + dtF, gradDtD,
                      -2.0f*dtE, gradDtE,
                      dtA + dtD, gradDtF);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageBGradMag)) {
    magTmp = pvl->directAnswer[tenGageBGradMag][0] =
      AIR_CAST(gage_t, ELL_3V_LEN(vecTmp));
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageBNormal)) {
    ELL_3V_SCALE(pvl->directAnswer[tenGageBNormal],
                 1.0f/(epsilon + magTmp), vecTmp);
  }
  /* --- Det --- */
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageDetGradVec)) {
    vecTmp = pvl->directAnswer[tenGageDetGradVec];
    ELL_3V_SCALE_ADD6(vecTmp,
                      dtD*dtF - dtE*dtE, gradDtA,
                      2.0f*(dtC*dtE - dtB*dtF), gradDtB,
                      2.0f*(dtB*dtE - dtC*dtD), gradDtC,
                      dtA*dtF - dtC*dtC, gradDtD,
                      2.0f*(dtB*dtC - dtA*dtE), gradDtE,
                      dtA*dtD - dtB*dtB, gradDtF);
    ELL_3V_SCALE(gradCbC, -1, vecTmp);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageDetGradMag)) {
    magTmp = pvl->directAnswer[tenGageDetGradMag][0] =
      AIR_CAST(float, ELL_3V_LEN(vecTmp));
  }
Пример #6
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
  }
Пример #7
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;
}