Esempio n. 1
0
void
_ra2t(Nrrd *nten, double rad, double angle, 
      double mRI[9], double mRF[9], double hack) {
  double x, y, xyz[3], XX[3], YY[3], CC[3], EE[3], VV[3], tmp, mD[9], mT[9];
  float *tdata;
  int xi, yi, sx, sy;

  sx = nten->axis[1].size;
  sy = nten->axis[2].size;
  x = rad*sin(AIR_PI*angle/180);
  y = rad*cos(AIR_PI*angle/180);
  xi = airIndexClamp(0.0, x, sqrt(3.0)/2.0, sx);
  yi = airIndexClamp(0.0, y, 0.5, sy);
  ELL_3V_SET(VV, 0, 3, 0);
  ELL_3V_SET(EE, 1.5, 1.5, 0);
  ELL_3V_SET(CC, 1, 1, 1);
  ELL_3V_SUB(YY, EE, CC);
  ELL_3V_SUB(XX, VV, EE);
  ELL_3V_NORM(XX, XX, tmp);
  ELL_3V_NORM(YY, YY, tmp);
  ELL_3V_SCALE_ADD3(xyz, 1.0, CC, hack*x, XX, hack*y, YY);
  
  ELL_3M_IDENTITY_SET(mD);
  ELL_3M_DIAG_SET(mD, xyz[0], xyz[1], xyz[2]);
  ELL_3M_IDENTITY_SET(mT);
  ell_3m_post_mul_d(mT, mRI);
  ell_3m_post_mul_d(mT, mD);
  ell_3m_post_mul_d(mT, mRF);
  tdata = (float*)(nten->data) + 7*(xi + sx*(yi + 1*sy));
  tdata[0] = 1.0;
  TEN_M2T(tdata, mT);
}
Esempio n. 2
0
File: tg.c Progetto: BRAINSia/teem
int
main(int argc, const char *argv[]) {
  const char *me;
  char *err, *outS;
  hestOpt *hopt=NULL;
  airArray *mop;

  int xi, yi, zi, samp;
  float *tdata;
  double clp[2], xyz[3], q[4], len;
  double mD[9], mRF[9], mRI[9], mT[9];
  Nrrd *nten;
  mop = airMopNew();

  me = argv[0];
  hestOptAdd(&hopt, "n", "# samples", airTypeInt, 1, 1, &samp, "4",
             "number of samples along each edge of cube");
  hestOptAdd(&hopt, "c", "cl cp", airTypeDouble, 2, 2, clp, NULL,
             "shape of tensor to use; \"cl\" and \"cp\" are cl1 "
             "and cp1 values, both in [0.0,1.0]");
  hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-",
             "output file to save tensors into");
  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);

  nten = nrrdNew();
  airMopAdd(mop, nten, (airMopper)nrrdNuke, airMopAlways);

  _clp2xyz(xyz, clp);
  fprintf(stderr, "%s: want evals = %g %g %g\n", me, xyz[0], xyz[1], xyz[2]);

  if (nrrdMaybeAlloc_va(nten, nrrdTypeFloat, 4,
                        AIR_CAST(size_t, 7),
                        AIR_CAST(size_t, samp),
                        AIR_CAST(size_t, samp),
                        AIR_CAST(size_t, samp))) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: couldn't allocate output:\n%s\n", me, err);
    airMopError(mop);
    return 1;
  }
  ELL_3M_IDENTITY_SET(mD);
  ELL_3M_DIAG_SET(mD, xyz[0], xyz[1], xyz[2]);
  tdata = (float*)nten->data;
  for (zi=0; zi<samp; zi++) {
    for (yi=0; yi<samp; yi++) {
      for (xi=0; xi<samp; xi++) {
        q[0] = 1.0;
        q[1] = AIR_AFFINE(-0.5, (float)xi, samp-0.5, -1, 1);
        q[2] = AIR_AFFINE(-0.5, (float)yi, samp-0.5, -1, 1);
        q[3] = AIR_AFFINE(-0.5, (float)zi, samp-0.5, -1, 1);
        len = ELL_4V_LEN(q);
        ELL_4V_SCALE(q, 1.0/len, q);
        washQtoM3(mRF, q);
        ELL_3M_TRANSPOSE(mRI, mRF);

        ELL_3M_IDENTITY_SET(mT);
        ell_3m_post_mul_d(mT, mRI);
        ell_3m_post_mul_d(mT, mD);
        ell_3m_post_mul_d(mT, mRF);

        tdata[0] = 1.0;
        TEN_M2T(tdata, mT);
        tdata += 7;
      }
    }
  }

  if (nrrdSave(outS, nten, NULL)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: couldn't save output:\n%s\n", me, err);
    airMopError(mop);
    return 1;
  }
  airMopOkay(mop);
  return 0;
}
Esempio n. 3
0
int
main(int argc, const char *argv[]) {
  const char *me;
  char *err, *outS;
  double eval[3], matA[9], matB[9], sval[3], uu[9], vv[9], escl[5],
    view[3];
  float matAf[9], matBf[16];
  float pp[3], qq[4], mR[9], len, gamma;
  float os, vs, rad, AB[2], ten[7];
  hestOpt *hopt=NULL;
  airArray *mop;
  limnObject *obj;
  limnLook *look; int lookRod, lookSoid;
  float kadsRod[3], kadsSoid[3];
  int gtype, partIdx=-1; /* sssh */
  int res;
  FILE *file;

  me = argv[0];
  hestOptAdd(&hopt, "sc", "evals", airTypeDouble, 3, 3, eval, "1 1 1",
             "original eigenvalues of tensor to be visualized");
  hestOptAdd(&hopt, "AB", "A, B exponents", airTypeFloat, 2, 2, AB, "nan nan",
             "Directly set the A, B parameters to the superquadric surface, "
             "over-riding the default behavior of determining them from the "
             "scalings \"-sc\" as superquadric tensor glyphs");
  hestOptAdd(&hopt, "os", "over-all scaling", airTypeFloat, 1, 1, &os, "1",
             "over-all scaling (multiplied by scalings)");
  hestOptAdd(&hopt, "vs", "view-dir scaling", airTypeFloat, 1, 1, &vs, "1",
             "scaling along view-direction (to show off bas-relief "
             "ambibuity of ellipsoids versus superquads)");
  hestOptAdd(&hopt, "es", "extra scaling", airTypeDouble, 5, 5, escl,
             "2 1 0 0 1", "extra scaling specified with five values "
             "0:tensor|1:geometry|2:none vx vy vz scaling");
  hestOptAdd(&hopt, "fr", "from (eye) point", airTypeDouble, 3, 3, &view,
             "4 4 4", "eye point, needed for non-unity \"-vs\"");
  hestOptAdd(&hopt, "gamma", "superquad sharpness", airTypeFloat, 1, 1,
             &gamma, "0",
             "how much to sharpen edges as a "
             "function of differences between eigenvalues");
  hestOptAdd(&hopt, "g", "glyph shape", airTypeEnum, 1, 1, &gtype, "sqd",
             "glyph to use; not all are implemented here",
             NULL, tenGlyphType);
  hestOptAdd(&hopt, "pp", "x y z", airTypeFloat, 3, 3, pp, "0 0 0",
             "transform: rotation identified by"
             "location in quaternion quotient space");
  hestOptAdd(&hopt, "r", "radius", airTypeFloat, 1, 1, &rad, "0.015",
             "black axis cylinder radius (or 0.0 to not drawn these)");
  hestOptAdd(&hopt, "res", "resolution", airTypeInt, 1, 1, &res, "25",
             "tesselation resolution for both glyph and axis cylinders");
  hestOptAdd(&hopt, "pg", "ka kd ks", airTypeFloat, 3, 3, kadsSoid,
             "0.2 0.8 0.0",
             "phong coefficients for glyph");
  hestOptAdd(&hopt, "pr", "ka kd ks", airTypeFloat, 3, 3, kadsRod, "1 0 0",
             "phong coefficients for black rods (if being drawn)");
  hestOptAdd(&hopt, "o", "output OFF", airTypeString, 1, 1, &outS, "out.off",
             "output file to save OFF into");
  hestParseOrDie(hopt, argc-1, argv+1, NULL,
                 me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
  mop = airMopNew();
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  obj = limnObjectNew(1000, AIR_TRUE);
  airMopAdd(mop, obj, (airMopper)limnObjectNix, airMopAlways);

  if (!( 0 == escl[0] || 1 == escl[0] || 2 == escl[0] )) {
    fprintf(stderr, "%s: escl[0] %g not 0, 1 or 2\n", me, escl[0]);
    airMopError(mop); return 1;
  }
  if (!(tenGlyphTypeBox == gtype ||
        tenGlyphTypeSphere == gtype ||
        tenGlyphTypeSuperquad == gtype)) {
    fprintf(stderr, "%s: got %s %s, but here only do %s, %s, or %s\n", me,
            tenGlyphType->name,
            airEnumStr(tenGlyphType, gtype),
            airEnumStr(tenGlyphType, tenGlyphTypeBox),
            airEnumStr(tenGlyphType, tenGlyphTypeSphere),
            airEnumStr(tenGlyphType, tenGlyphTypeSuperquad));
    airMopError(mop); return 1;
  }

  /* create limnLooks for glyph and for rods */
  lookSoid = limnObjectLookAdd(obj);
  look = obj->look + lookSoid;
  ELL_4V_SET(look->rgba, 1, 1, 1, 1);
  ELL_3V_COPY(look->kads, kadsSoid);

  look->spow = 0;
  lookRod = limnObjectLookAdd(obj);
  look = obj->look + lookRod;
  ELL_4V_SET(look->rgba, 0, 0, 0, 1);
  ELL_3V_COPY(look->kads, kadsRod);
  look->spow = 0;

  ELL_3M_IDENTITY_SET(matA); /* A = I */
  ELL_3V_SCALE(eval, os, eval);
  ELL_3M_SCALE_SET(matB, eval[0], eval[1], eval[2]); /* B = diag(eval) */
  ell_3m_post_mul_d(matA, matB); /* A = B*A = diag(eval) */

  if (0 == escl[0]) {
    scalingMatrix(matB, escl + 1, escl[4]);
    ell_3m_post_mul_d(matA, matB);
  }

  if (1 != vs) {
    if (!ELL_3V_LEN(view)) {
      fprintf(stderr, "%s: need non-zero view for vs %g != 1\n", me, vs);
      airMopError(mop); return 1;
    }
    scalingMatrix(matB, view, vs);
    /* the scaling along the view direction is a symmetric matrix,
       but applying that scaling to the symmetric input tensor
       is not necessarily symmetric */
    ell_3m_post_mul_d(matA, matB);  /* A = B*A */
  }
  /* so we do an SVD to get rotation U and the scalings sval[] */
  /* U * diag(sval) * V */
  ell_3m_svd_d(uu, sval, vv, matA, AIR_TRUE);

  /*
  fprintf(stderr, "%s: ____________________________________\n", me);
  fprintf(stderr, "%s: mat = \n", me);
  ell_3m_print_d(stderr, matA);
  fprintf(stderr, "%s: uu = \n", me);
  ell_3m_print_d(stderr, uu);
  ELL_3M_TRANSPOSE(matC, uu);
  ELL_3M_MUL(matB, uu, matC);
  fprintf(stderr, "%s: uu * uu^T = \n", me);
  ell_3m_print_d(stderr, matB);
  fprintf(stderr, "%s: sval = %g %g %g\n", me, sval[0], sval[1], sval[2]);
  fprintf(stderr, "%s: vv = \n", me);
  ell_3m_print_d(stderr, vv);
  ELL_3M_MUL(matB, vv, vv);
  fprintf(stderr, "%s: vv * vv^T = \n", me);
  ELL_3M_TRANSPOSE(matC, vv);
  ELL_3M_MUL(matB, vv, matC);
  ell_3m_print_d(stderr, matB);
  ELL_3M_IDENTITY_SET(matA);
  ell_3m_pre_mul_d(matA, uu);
  ELL_3M_SCALE_SET(matB, sval[0], sval[1], sval[2]);
  ell_3m_pre_mul_d(matA, matB);
  ell_3m_pre_mul_d(matA, vv);
  fprintf(stderr, "%s: uu * diag(sval) * vv = \n", me);
  ell_3m_print_d(stderr, matA);
  fprintf(stderr, "%s: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", me);
  */

  /* now create symmetric matrix out of U and sval */
  /* A = I */
  ELL_3M_IDENTITY_SET(matA);
  ell_3m_pre_mul_d(matA, uu);   /* A = A*U = I*U = U */
  ELL_3M_SCALE_SET(matB, sval[0], sval[1], sval[2]); /* B = diag(sval) */
  ell_3m_pre_mul_d(matA, matB); /* A = U*diag(sval) */
  ELL_3M_TRANSPOSE(matB, uu);
  ell_3m_pre_mul_d(matA, matB); /* A = U*diag(sval)*U^T */
  TEN_M2T(ten, matA);

  partIdx = soidDoit(obj, lookSoid,
                     gtype, gamma, res,
                     (AIR_EXISTS(AB[0]) && AIR_EXISTS(AB[1])) ? AB : NULL,
                     ten);

  if (1 == escl[0]) {
    scalingMatrix(matB, escl + 1, escl[4]);
    ELL_43M_INSET(matBf, matB);
    limnObjectPartTransform(obj, partIdx, matBf);
  }
  /* this is a rotate on the geomtry; nothing to do with the tensor */
  ELL_4V_SET(qq, 1, pp[0], pp[1], pp[2]);
  ELL_4V_NORM(qq, qq, len);
  ell_q_to_3m_f(mR, qq);
  ELL_43M_INSET(matBf, mR);
  limnObjectPartTransform(obj, partIdx, matBf);

  if (rad) {
    partIdx = limnObjectCylinderAdd(obj, lookRod, 0, res);
    ELL_4M_IDENTITY_SET(matAf);
    ELL_4M_SCALE_SET(matBf, (1-eval[0])/2, rad, rad);
    ell_4m_post_mul_f(matAf, matBf);
    ELL_4M_TRANSLATE_SET(matBf, (1+eval[0])/2, 0.0, 0.0);
    ell_4m_post_mul_f(matAf, matBf);
    limnObjectPartTransform(obj, partIdx, matAf);

    partIdx = limnObjectCylinderAdd(obj, lookRod, 0, res);
    ELL_4M_IDENTITY_SET(matAf);
    ELL_4M_SCALE_SET(matBf, (1-eval[0])/2, rad, rad);
    ell_4m_post_mul_f(matAf, matBf);
    ELL_4M_TRANSLATE_SET(matBf, -(1+eval[0])/2, 0.0, 0.0);
    ell_4m_post_mul_f(matAf, matBf);
    limnObjectPartTransform(obj, partIdx, matAf);

    partIdx = limnObjectCylinderAdd(obj, lookRod, 1, res);
    ELL_4M_IDENTITY_SET(matAf);
    ELL_4M_SCALE_SET(matBf, rad, (1-eval[1])/2, rad);
    ell_4m_post_mul_f(matAf, matBf);
    ELL_4M_TRANSLATE_SET(matBf, 0.0, (1+eval[1])/2, 0.0);
    ell_4m_post_mul_f(matAf, matBf);
    limnObjectPartTransform(obj, partIdx, matAf);

    partIdx = limnObjectCylinderAdd(obj, lookRod, 1, res);
    ELL_4M_IDENTITY_SET(matAf);
    ELL_4M_SCALE_SET(matBf, rad, (1-eval[1])/2, rad);
    ell_4m_post_mul_f(matAf, matBf);
    ELL_4M_TRANSLATE_SET(matBf, 0.0, -(1+eval[1])/2, 0.0);
    ell_4m_post_mul_f(matAf, matBf);
    limnObjectPartTransform(obj, partIdx, matAf);

    partIdx = limnObjectCylinderAdd(obj, lookRod, 2, res);
    ELL_4M_IDENTITY_SET(matAf);
    ELL_4M_SCALE_SET(matBf, rad, rad, (1-eval[2])/2);
    ell_4m_post_mul_f(matAf, matBf);
    ELL_4M_TRANSLATE_SET(matBf, 0.0, 0.0, (1+eval[2])/2);
    ell_4m_post_mul_f(matAf, matBf);
    limnObjectPartTransform(obj, partIdx, matAf);

    partIdx = limnObjectCylinderAdd(obj, lookRod, 2, res);
    ELL_4M_IDENTITY_SET(matAf);
    ELL_4M_SCALE_SET(matBf, rad, rad, (1-eval[2])/2);
    ell_4m_post_mul_f(matAf, matBf);
    ELL_4M_TRANSLATE_SET(matBf, 0.0, 0.0, -(1+eval[2])/2);
    ell_4m_post_mul_f(matAf, matBf);
    limnObjectPartTransform(obj, partIdx, matAf);
  }

  file = airFopen(outS, stdout, "w");
  airMopAdd(mop, file, (airMopper)airFclose, airMopAlways);

  if (limnObjectWriteOFF(file, obj)) {
    airMopAdd(mop, err = biffGetDone(LIMN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble:\n%s\n", me, err);
    airMopError(mop); return 1;
  }

  airMopOkay(mop);
  return 0;
}
Esempio n. 4
0
int
main(int argc, const char *argv[]) {
  const char *me;
  char *err, *outS;
  double scale[3], matA[9], matB[9], matC[9], sval[3], uu[9], vv[9];
  float matAf[9], matBf[16];
  float p[3], q[4], mR[9], len, gamma;
  float os, vs, rad, AB[2], ten[7], view[3];
  hestOpt *hopt=NULL;
  airArray *mop;
  limnObject *obj;
  limnLook *look; int lookRod, lookSoid;
  int partIdx=-1; /* sssh */
  int res, sphere;
  FILE *file;

  me = argv[0];
  hestOptAdd(&hopt, "sc", "scalings", airTypeDouble, 3, 3, scale, "1 1 1",
             "axis-aligned scaling to do on ellipsoid");
  hestOptAdd(&hopt, "AB", "A, B exponents", airTypeFloat, 2, 2, AB, "nan nan",
             "Directly set the A, B parameters to the superquadric surface, "
             "over-riding the default behavior of determining them from the "
             "scalings \"-sc\" as superquadric tensor glyphs");
  hestOptAdd(&hopt, "os", "over-all scaling", airTypeFloat, 1, 1, &os, "1",
             "over-all scaling (multiplied by scalings)");
  hestOptAdd(&hopt, "vs", "over-all scaling", airTypeFloat, 1, 1, &vs, "1",
             "scaling along view-direction (to show off bas-relief "
             "ambibuity of ellipsoids versus superquads)");
  hestOptAdd(&hopt, "fr", "from (eye) point", airTypeFloat, 3, 3, &view,
             "4 4 4", "eye point, needed for non-unity \"-vs\"");
  hestOptAdd(&hopt, "gamma", "superquad sharpness", airTypeFloat, 1, 1,
             &gamma, "0",
             "how much to sharpen edges as a "
             "function of differences between eigenvalues");
  hestOptAdd(&hopt, "sphere", NULL, airTypeInt, 0, 0, &sphere, NULL,
             "use a sphere instead of a superquadric");
  hestOptAdd(&hopt, "p", "x y z", airTypeFloat, 3, 3, p, "0 0 0",
             "location in quaternion quotient space");
  hestOptAdd(&hopt, "r", "radius", airTypeFloat, 1, 1, &rad, "0.015",
             "black axis cylinder radius (or 0.0 to not drawn these)");
  hestOptAdd(&hopt, "res", "resolution", airTypeInt, 1, 1, &res, "25",
             "tesselation resolution for both glyph and axis cylinders");
  hestOptAdd(&hopt, "o", "output OFF", airTypeString, 1, 1, &outS, "out.off",
             "output file to save OFF into");
  hestParseOrDie(hopt, argc-1, argv+1, NULL,
                 me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
  mop = airMopNew();
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  obj = limnObjectNew(1000, AIR_TRUE);
  airMopAdd(mop, obj, (airMopper)limnObjectNix, airMopAlways);

  /* create limnLooks for ellipsoid and for rods */
  lookSoid = limnObjectLookAdd(obj);
  look = obj->look + lookSoid;
  ELL_4V_SET(look->rgba, 1, 1, 1, 1);
  ELL_3V_SET(look->kads, 0.2, 0.8, 0);
  look->spow = 0;
  lookRod = limnObjectLookAdd(obj);
  look = obj->look + lookRod;
  ELL_4V_SET(look->rgba, 0, 0, 0, 1);
  ELL_3V_SET(look->kads, 1, 0, 0);
  look->spow = 0;

  ELL_3M_IDENTITY_SET(matA);
  ELL_3V_SCALE(scale, os, scale);
  ELL_3M_SCALE_SET(matB, scale[0], scale[1], scale[2]);
  ell_3m_post_mul_d(matA, matB);
  if (1 != vs) {
    ELL_3V_NORM(view, view, len);
    if (!len) {
      /* HEY: perhaps do more diplomatic error message here */
      fprintf(stderr, "%s: stupido!\n", me);
      exit(1);
    }
    ELL_3MV_OUTER(matB, view, view);
    ELL_3M_SCALE(matB, vs-1, matB);
    ELL_3M_IDENTITY_SET(matC);
    ELL_3M_ADD2(matB, matC, matB);
    ell_3m_post_mul_d(matA, matB);
  }
  ell_3m_svd_d(uu, sval, vv, matA, AIR_TRUE);

  /*
  fprintf(stderr, "%s: ____________________________________\n", me);
  fprintf(stderr, "%s: mat = \n", me);
  ell_3m_print_d(stderr, matA);
  fprintf(stderr, "%s: uu = \n", me);
  ell_3m_print_d(stderr, uu);
  ELL_3M_TRANSPOSE(matC, uu);
  ELL_3M_MUL(matB, uu, matC);
  fprintf(stderr, "%s: uu * uu^T = \n", me);
  ell_3m_print_d(stderr, matB);
  fprintf(stderr, "%s: sval = %g %g %g\n", me, sval[0], sval[1], sval[2]);
  fprintf(stderr, "%s: vv = \n", me);
  ell_3m_print_d(stderr, vv);
  ELL_3M_MUL(matB, vv, vv);
  fprintf(stderr, "%s: vv * vv^T = \n", me);
  ELL_3M_TRANSPOSE(matC, vv);
  ELL_3M_MUL(matB, vv, matC);
  ell_3m_print_d(stderr, matB);
  ELL_3M_IDENTITY_SET(matA);
  ell_3m_pre_mul_d(matA, uu);
  ELL_3M_SCALE_SET(matB, sval[0], sval[1], sval[2]);
  ell_3m_pre_mul_d(matA, matB);
  ell_3m_pre_mul_d(matA, vv);
  fprintf(stderr, "%s: uu * diag(sval) * vv = \n", me);
  ell_3m_print_d(stderr, matA);
  fprintf(stderr, "%s: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", me);
  */

  ELL_3M_IDENTITY_SET(matA);
  ell_3m_pre_mul_d(matA, uu);
  ELL_3M_SCALE_SET(matB, sval[0], sval[1], sval[2]);
  ell_3m_pre_mul_d(matA, matB);
  ELL_3M_TRANSPOSE(matB, uu);
  ell_3m_pre_mul_d(matA, matB);
  TEN_M2T(ten, matA);

  partIdx = soidDoit(obj, lookSoid,
                     sphere, gamma, res,
                     (AIR_EXISTS(AB[0]) && AIR_EXISTS(AB[1])) ? AB : NULL,
                     ten);

  ELL_4V_SET(q, 1, p[0], p[1], p[2]);
  ELL_4V_NORM(q, q, len);
  ell_q_to_3m_f(mR, q);
  ELL_43M_INSET(matBf, mR);
  limnObjectPartTransform(obj, partIdx, matBf);

  if (rad) {
    partIdx = limnObjectCylinderAdd(obj, lookRod, 0, res);
    ELL_4M_IDENTITY_SET(matAf);
    ELL_4M_SCALE_SET(matBf, (1-scale[0])/2, rad, rad);
    ell_4m_post_mul_f(matAf, matBf);
    ELL_4M_TRANSLATE_SET(matBf, (1+scale[0])/2, 0.0, 0.0);
    ell_4m_post_mul_f(matAf, matBf);
    limnObjectPartTransform(obj, partIdx, matAf);

    partIdx = limnObjectCylinderAdd(obj, lookRod, 0, res);
    ELL_4M_IDENTITY_SET(matAf);
    ELL_4M_SCALE_SET(matBf, (1-scale[0])/2, rad, rad);
    ell_4m_post_mul_f(matAf, matBf);
    ELL_4M_TRANSLATE_SET(matBf, -(1+scale[0])/2, 0.0, 0.0);
    ell_4m_post_mul_f(matAf, matBf);
    limnObjectPartTransform(obj, partIdx, matAf);

    partIdx = limnObjectCylinderAdd(obj, lookRod, 1, res);
    ELL_4M_IDENTITY_SET(matAf);
    ELL_4M_SCALE_SET(matBf, rad, (1-scale[1])/2, rad);
    ell_4m_post_mul_f(matAf, matBf);
    ELL_4M_TRANSLATE_SET(matBf, 0.0, (1+scale[1])/2, 0.0);
    ell_4m_post_mul_f(matAf, matBf);
    limnObjectPartTransform(obj, partIdx, matAf);

    partIdx = limnObjectCylinderAdd(obj, lookRod, 1, res);
    ELL_4M_IDENTITY_SET(matAf);
    ELL_4M_SCALE_SET(matBf, rad, (1-scale[1])/2, rad);
    ell_4m_post_mul_f(matAf, matBf);
    ELL_4M_TRANSLATE_SET(matBf, 0.0, -(1+scale[1])/2, 0.0);
    ell_4m_post_mul_f(matAf, matBf);
    limnObjectPartTransform(obj, partIdx, matAf);

    partIdx = limnObjectCylinderAdd(obj, lookRod, 2, res);
    ELL_4M_IDENTITY_SET(matAf);
    ELL_4M_SCALE_SET(matBf, rad, rad, (1-scale[2])/2);
    ell_4m_post_mul_f(matAf, matBf);
    ELL_4M_TRANSLATE_SET(matBf, 0.0, 0.0, (1+scale[2])/2);
    ell_4m_post_mul_f(matAf, matBf);
    limnObjectPartTransform(obj, partIdx, matAf);

    partIdx = limnObjectCylinderAdd(obj, lookRod, 2, res);
    ELL_4M_IDENTITY_SET(matAf);
    ELL_4M_SCALE_SET(matBf, rad, rad, (1-scale[2])/2);
    ell_4m_post_mul_f(matAf, matBf);
    ELL_4M_TRANSLATE_SET(matBf, 0.0, 0.0, -(1+scale[2])/2);
    ell_4m_post_mul_f(matAf, matBf);
    limnObjectPartTransform(obj, partIdx, matAf);
  }

  file = airFopen(outS, stdout, "w");
  airMopAdd(mop, file, (airMopper)airFclose, airMopAlways);

  if (limnObjectWriteOFF(file, obj)) {
    airMopAdd(mop, err = biffGetDone(LIMN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble:\n%s\n", me, err);
    airMopError(mop); return 1;
  }

  airMopOkay(mop);
  return 0;
}
Esempio n. 5
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;
}
Esempio n. 6
0
int
main(int argc, char *argv[]) {
  char *me, *err, *outS;
  hestOpt *hopt=NULL;
  airArray *mop;
  
  int sx, sy, xi, yi, samp, version, whole, right;
  float *tdata;
  double p[3], xyz[3], q[4], len, hackcp=0, maxca;
  double ca, cp, mD[9], mRF[9], mRI[9], mT[9], hack;
  Nrrd *nten;
  mop = airMopNew();
  
  me = argv[0];
  hestOptAdd(&hopt, "n", "# samples", airTypeInt, 1, 1, &samp, "4",
             "number of glyphs along each edge of triangle");
  hestOptAdd(&hopt, "p", "x y z", airTypeDouble, 3, 3, p, NULL,
             "location in quaternion quotient space");
  hestOptAdd(&hopt, "ca", "max ca", airTypeDouble, 1, 1, &maxca, "0.8",
             "maximum ca to use at bottom edge of triangle");
  hestOptAdd(&hopt, "r", NULL, airTypeInt, 0, 0, &right, NULL,
             "sample a right-triangle-shaped region, instead of "
             "a roughly equilateral triangle. ");
  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, "hack", "hack", airTypeDouble, 1, 1, &hack, "0.04",
             "this is a hack");
  hestOptAdd(&hopt, "v", "version", airTypeInt, 1, 1, &version, "1",
             "which version of the Westin metrics to use to parameterize "
             "triangle; \"1\" for ISMRM 97, \"2\" for MICCAI 99");
  hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-",
             "output file to save tensors into");
  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);
  
  nten = nrrdNew();
  airMopAdd(mop, nten, (airMopper)nrrdNuke, airMopAlways);

  if (!( 1 == version || 2 == version )) {
    fprintf(stderr, "%s: version must be 1 or 2 (not %d)\n", me, version);
    airMopError(mop); 
    return 1;
  }
  if (right) {
    sx = samp;
    sy = (int)(1.0*samp/sqrt(3.0));
  } else {
    sx = 2*samp-1;
    sy = samp;
  }
  if (nrrdMaybeAlloc_va(nten, nrrdTypeFloat, 4,
                        AIR_CAST(size_t, 7),
                        AIR_CAST(size_t, sx),
                        AIR_CAST(size_t, sy),
                        AIR_CAST(size_t, 3))) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: couldn't allocate output:\n%s\n", me, err);
    airMopError(mop); 
    return 1;
  }
  q[0] = 1.0;
  q[1] = p[0];
  q[2] = p[1];
  q[3] = p[2];
  len = ELL_4V_LEN(q);
  ELL_4V_SCALE(q, 1.0/len, q);
  washQtoM3(mRF, q);
  ELL_3M_TRANSPOSE(mRI, mRF);
  if (right) {
    _ra2t(nten, 0.00, 0.0, mRI, mRF, hack);

    _ra2t(nten, 0.10, 0.0, mRI, mRF, hack);
    _ra2t(nten, 0.10, 60.0, mRI, mRF, hack);

    _ra2t(nten, 0.20, 0.0, mRI, mRF, hack);
    _ra2t(nten, 0.20, 30.0, mRI, mRF, hack);
    _ra2t(nten, 0.20, 60.0, mRI, mRF, hack);

    _ra2t(nten, 0.30, 0.0, mRI, mRF, hack);
    _ra2t(nten, 0.30, 20.0, mRI, mRF, hack);
    _ra2t(nten, 0.30, 40.0, mRI, mRF, hack);
    _ra2t(nten, 0.30, 60.0, mRI, mRF, hack);

    _ra2t(nten, 0.40, 0.0, mRI, mRF, hack);
    _ra2t(nten, 0.40, 15.0, mRI, mRF, hack);
    _ra2t(nten, 0.40, 30.0, mRI, mRF, hack);
    _ra2t(nten, 0.40, 45.0, mRI, mRF, hack);
    _ra2t(nten, 0.40, 60.0, mRI, mRF, hack);

    _ra2t(nten, 0.50, 0.0, mRI, mRF, hack);
    _ra2t(nten, 0.50, 12.0, mRI, mRF, hack);
    _ra2t(nten, 0.50, 24.0, mRI, mRF, hack);
    _ra2t(nten, 0.50, 36.0, mRI, mRF, hack);
    _ra2t(nten, 0.50, 48.0, mRI, mRF, hack);
    _ra2t(nten, 0.50, 60.0, mRI, mRF, hack);

    /* _ra2t(nten, 0.60, 30.0, mRI, mRF, hack); */
    _ra2t(nten, 0.60, 40.0, mRI, mRF, hack);
    _ra2t(nten, 0.60, 50.0, mRI, mRF, hack);
    _ra2t(nten, 0.60, 60.0, mRI, mRF, hack);

    /* _ra2t(nten, 0.70, 34.3, mRI, mRF, hack); */
    /* _ra2t(nten, 0.70, 42.8, mRI, mRF, hack); */
    _ra2t(nten, 0.70, 51.4, mRI, mRF, hack);
    _ra2t(nten, 0.70, 60.0, mRI, mRF, hack);

    /* _ra2t(nten, 0.80, 45.0, mRI, mRF, hack); */
    _ra2t(nten, 0.80, 52.5, mRI, mRF, hack);
    _ra2t(nten, 0.80, 60.0, mRI, mRF, hack);

    _ra2t(nten, 0.90, 60.0, mRI, mRF, hack);

    _ra2t(nten, 1.00, 60.0, mRI, mRF, hack);
    /*
    _ra2t(nten, 0.000, 0.0, mRI, mRF, hack);

    _ra2t(nten, 0.125, 0.0, mRI, mRF, hack);
    _ra2t(nten, 0.125, 60.0, mRI, mRF, hack);

    _ra2t(nten, 0.250, 0.0, mRI, mRF, hack);
    _ra2t(nten, 0.250, 30.0, mRI, mRF, hack);
    _ra2t(nten, 0.250, 60.0, mRI, mRF, hack);

    _ra2t(nten, 0.375, 0.0, mRI, mRF, hack);
    _ra2t(nten, 0.375, 20.0, mRI, mRF, hack);
    _ra2t(nten, 0.375, 40.0, mRI, mRF, hack);
    _ra2t(nten, 0.375, 60.0, mRI, mRF, hack);

    _ra2t(nten, 0.500, 0.0, mRI, mRF, hack);
    _ra2t(nten, 0.500, 15.0, mRI, mRF, hack);
    _ra2t(nten, 0.500, 30.0, mRI, mRF, hack);
    _ra2t(nten, 0.500, 45.0, mRI, mRF, hack);
    _ra2t(nten, 0.500, 60.0, mRI, mRF, hack);

    _ra2t(nten, 0.625, 37.0, mRI, mRF, hack);
    _ra2t(nten, 0.625, 47.5, mRI, mRF, hack);
    _ra2t(nten, 0.625, 60.0, mRI, mRF, hack);

    _ra2t(nten, 0.750, 49.2, mRI, mRF, hack);
    _ra2t(nten, 0.750, 60.0, mRI, mRF, hack);

    _ra2t(nten, 0.875, 60.0, mRI, mRF, hack);

    _ra2t(nten, 1.000, 60.0, mRI, mRF, hack);
    */
    nten->axis[1].spacing = 1;
    nten->axis[2].spacing = (sx-1)/(sqrt(3.0)*(sy-1));
    nten->axis[3].spacing = 1;
  } else {
    for (yi=0; yi<samp; yi++) {
      if (whole) {
        ca = AIR_AFFINE(0, yi, samp-1, 0.0, 1.0);
      } else {
        ca = AIR_AFFINE(0, yi, samp-1, hack, maxca);
        hackcp = AIR_AFFINE(0, yi, samp-1, hack, 0);
      }
      for (xi=0; xi<=yi; xi++) {
        if (whole) {
          cp = AIR_AFFINE(0, xi, samp-1, 0.0, 1.0);
        } else {
          cp = AIR_AFFINE(0, xi, samp-1, hackcp, maxca-hack/2.0);
        }
        _cap2xyz(xyz, ca, cp, version, whole);
        /*
          fprintf(stderr, "%s: (%d,%d) -> (%g,%g) -> %g %g %g\n", me,
          yi, xi, ca, cp, xyz[0], xyz[1], xyz[2]);
        */
        ELL_3M_IDENTITY_SET(mD);
        ELL_3M_DIAG_SET(mD, xyz[0], xyz[1], xyz[2]);
        ELL_3M_IDENTITY_SET(mT);
        ell_3m_post_mul_d(mT, mRI);
        ell_3m_post_mul_d(mT, mD);
        ell_3m_post_mul_d(mT, mRF);
        
        tdata = (float*)nten->data + 
          7*(2*(samp-1-xi) - (samp-1-yi) + (2*samp-1)*((samp-1-yi) + samp));
        tdata[0] = 1.0;
        TEN_M2T(tdata, mT);
      }
    }
    nten->axis[1].spacing = 1;
    nten->axis[2].spacing = 1.5;
    nten->axis[3].spacing = 1;
  }
  
  if (nrrdSave(outS, nten, NULL)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: couldn't save output:\n%s\n", me, err);
    airMopError(mop); 
    return 1;
  }
  airMopOkay(mop);
  return 0;
}
Esempio n. 7
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
  }
Esempio n. 8
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;
}