Exemple #1
0
void
washQtoM3(double m[9], double q[4]) {
  double p[4], w, x, y, z, len;

  ELL_4V_COPY(p, q);
  len = ELL_4V_LEN(p);
  ELL_4V_SCALE(p, 1.0/len, p);
  w = p[0];
  x = p[1];
  y = p[2];
  z = p[3];
  /* mathematica work implies that we should be
     setting ROW vectors here */
  ELL_3V_SET(m+0,
             1 - 2*(y*y + z*z),
             2*(x*y - w*z),
             2*(x*z + w*y));
  ELL_3V_SET(m+3,
             2*(x*y + w*z),
             1 - 2*(x*x + z*z),
             2*(y*z - w*x));
  ELL_3V_SET(m+6,
             2*(x*z - w*y),
             2*(y*z + w*x),
             1 - 2*(x*x + y*y));
}
Exemple #2
0
void
ell_q_log_d(double q2[4], const double q1[4]) {
  double a, b, axis[3];

  a = log(ELL_4V_LEN(q1));
  b = ell_q_to_aa_d(axis, q1)/2.0;
  ELL_4V_SET(q2, a, b*axis[0], b*axis[1], b*axis[2]);
}
Exemple #3
0
void
ell_q_pow_d(double q2[4], const double q1[4], const double p) {
  double len, angle, axis[3];

  len = pow(ELL_4V_LEN(q1), p);
  angle = ell_q_to_aa_d(axis, q1);
  ell_aa_to_q_d(q2, p*angle, axis);
  ELL_4V_SCALE(q2, len, q2);
}
Exemple #4
0
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;
}
Exemple #5
0
int
main(int argc, char *argv[]) {
  gageKind *kind;
  char *me, *whatS, *err, *outS, *stackSavePath;
  hestParm *hparm;
  hestOpt *hopt = NULL;
  NrrdKernelSpec *k00, *k11, *k22, *kSS, *kSSblur;
  float pos[3], lineInfo[4];
  double gmc, rangeSS[2], posSS, *scalePos;
  unsigned int ansLen, numSS, ninSSIdx, lineStepNum;
  int what, E=0, renorm, SSrenorm, SSuniform, verbose;
  const double *answer;
  Nrrd *nin, **ninSS=NULL, *nout=NULL;
  gageContext *ctx;
  gagePerVolume *pvl;
  limnPolyData *lpld=NULL;
  airArray *mop;
  int worldSpace;
  Nrrd *ngrad=NULL, *nbmat=NULL;
  double bval, eps;
  unsigned int *skip, skipNum;

  mop = airMopNew();
  me = argv[0];
  hparm = hestParmNew();
  airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways);
  hparm->elideSingleOtherType = AIR_TRUE;
  hestOptAdd(&hopt, "i", "nin", airTypeOther, 1, 1, &nin, NULL,
             "input volume", NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "k", "kind", airTypeOther, 1, 1, &kind, NULL,
             "\"kind\" of volume (\"scalar\", \"vector\", or \"tensor\")",
             NULL, NULL, &probeKindHestCB);
  hestOptAdd(&hopt, "p", "x y z", airTypeFloat, 3, 3, pos, NULL,
             "the position in space at which to probe");
  hestOptAdd(&hopt, "wsp", NULL, airTypeInt, 0, 0, &worldSpace, NULL,
             "if using this option, position (\"-p\") will be in world "
             "space, instead of index space (the default)");
  hestOptAdd(&hopt, "pi", "lpld in", airTypeOther, 1, 1, &lpld, "",
             "input polydata (overrides \"-p\")",
             NULL, NULL, limnHestPolyDataLMPD);
  hestOptAdd(&hopt, "pl", "x y z s", airTypeFloat, 4, 4, lineInfo, "0 0 0 0",
             "probe along line, instead of at point.  "
             "The \"-p\" three coords are the line start point. "
             "If \"s\" is zero, (x,y,z) is the line end point. "
             "If \"s\" is non-zero, (x,y,z) is the line direction, "
             "which is scaled to have length \"s\", "
             "and then used as the step between line samples. ");
  hestOptAdd(&hopt, "pln", "num", airTypeUInt, 1, 1, &lineStepNum, "0",
             "if non-zero, number of steps of probing to do along line, "
             "which overrides \"-p\" and \"-pi\"");
  hestOptAdd(&hopt, "v", "verbosity", airTypeInt, 1, 1, &verbose, "1", 
             "verbosity level");
  hestOptAdd(&hopt, "q", "query", airTypeString, 1, 1, &whatS, NULL,
             "the quantity (scalar, vector, or matrix) to learn by probing");
  hestOptAdd(&hopt, "eps", "epsilon", airTypeDouble, 1, 1, &eps, "0",
             "if non-zero, and if query is a scalar, epsilon around probe "
             "location where we will do discrete differences to find the "
             "gradient and hessian (for debugging)");
  hestOptAdd(&hopt, "k00", "kern00", airTypeOther, 1, 1, &k00,
             "tent", "kernel for gageKernel00",
             NULL, NULL, nrrdHestKernelSpec);
  hestOptAdd(&hopt, "k11", "kern11", airTypeOther, 1, 1, &k11,
             "cubicd:1,0", "kernel for gageKernel11",
             NULL, NULL, nrrdHestKernelSpec);
  hestOptAdd(&hopt, "k22", "kern22", airTypeOther, 1, 1, &k22,
             "cubicdd:1,0", "kernel for gageKernel22",
             NULL, NULL, nrrdHestKernelSpec);

  hestOptAdd(&hopt, "ssn", "SS #", airTypeUInt, 1, 1, &numSS,
             "0", "how many scale-space samples to evaluate, or, "
             "0 to turn-off all scale-space behavior");
  hestOptAdd(&hopt, "ssr", "scale range", airTypeDouble, 2, 2, rangeSS,
             "nan nan", "range of scales in scale-space");
  hestOptAdd(&hopt, "sss", "scale save path", airTypeString, 1, 1,
             &stackSavePath, "",
             "give a non-empty path string (like \"./\") to save out "
             "the pre-blurred volumes computed for the stack");
  hestOptAdd(&hopt, "ssp", "SS pos", airTypeDouble, 1, 1, &posSS, "0",
             "position at which to sample in scale-space");
  hestOptAdd(&hopt, "kssblur", "kernel", airTypeOther, 1, 1, &kSSblur,
             "dgauss:1,5", "blurring kernel, to sample scale space",
             NULL, NULL, nrrdHestKernelSpec);
  hestOptAdd(&hopt, "kss", "kernel", airTypeOther, 1, 1, &kSS,
             "tent", "kernel for reconstructing from scale space samples",
             NULL, NULL, nrrdHestKernelSpec);
  hestOptAdd(&hopt, "ssrn", "ssrn", airTypeInt, 1, 1, &SSrenorm, "0",
             "enable derivative normalization based on scale space");
  hestOptAdd(&hopt, "ssu", NULL, airTypeInt, 0, 0, &SSuniform, NULL,
             "do uniform samples along sigma, and not (by default) "
             "samples according to the logarithm of diffusion time");

  hestOptAdd(&hopt, "rn", NULL, airTypeInt, 0, 0, &renorm, NULL,
             "renormalize kernel weights at each new sample location. "
             "\"Accurate\" kernels don't need this; doing it always "
             "makes things go slower");
  hestOptAdd(&hopt, "gmc", "min gradmag", airTypeDouble, 1, 1, &gmc,
             "0.0", "For curvature-based queries, use zero when gradient "
             "magnitude is below this");
  hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-",
             "output array, when probing on polydata vertices");
  hestParseOrDie(hopt, argc-1, argv+1, hparm,
                 me, probeInfo, AIR_TRUE, AIR_TRUE, AIR_TRUE);
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  what = airEnumVal(kind->enm, whatS);
  if (!what) {
    /* 0 indeed always means "unknown" for any gageKind */
    fprintf(stderr, "%s: couldn't parse \"%s\" as measure of \"%s\" volume\n",
            me, whatS, kind->name);
    hestUsage(stderr, hopt, me, hparm);
    hestGlossary(stderr, hopt, hparm);
    airMopError(mop);
    return 1;
  }
  
  if (ELL_4V_LEN(lineInfo) && !lineStepNum) {
    fprintf(stderr, "%s: gave line info (\"-pl\") but not "
            "# samples (\"-pln\")", me);
    hestUsage(stderr, hopt, me, hparm);
    hestGlossary(stderr, hopt, hparm);
    airMopError(mop);
    return 1;
  }

  /* special set-up required for DWI kind */
  if (!strcmp(TEN_DWI_GAGE_KIND_NAME, kind->name)) {
    if (tenDWMRIKeyValueParse(&ngrad, &nbmat, &bval, &skip, &skipNum, nin)) {
      airMopAdd(mop, err = biffGetDone(TEN), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble parsing DWI info:\n%s\n", me, err);
      airMopError(mop); return 1;
    }
    if (skipNum) {
      fprintf(stderr, "%s: sorry, can't do DWI skipping in tenDwiGage", me);
      airMopError(mop); return 1;
    }
    /* this could stand to use some more command-line arguments */
    if (tenDwiGageKindSet(kind, 50, 1, bval, 0.001, ngrad, nbmat,
                          tenEstimate1MethodLLS,
                          tenEstimate2MethodQSegLLS,
                          /* randSeed */ 7919)) {
      airMopAdd(mop, err = biffGetDone(TEN), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble parsing DWI info:\n%s\n", me, err);
      airMopError(mop); return 1;
    }
  }

  ansLen = kind->table[what].answerLength;

  /* for setting up pre-blurred scale-space samples */
  if (numSS) {
    unsigned int vi;
    ninSS = AIR_CAST(Nrrd **, calloc(numSS, sizeof(Nrrd *)));
    scalePos = AIR_CAST(double *, calloc(numSS, sizeof(double)));
    if (!(ninSS && scalePos)) {
      fprintf(stderr, "%s: couldn't allocate ninSS", me);
      airMopError(mop); return 1;
    }
    for (ninSSIdx=0; ninSSIdx<numSS; ninSSIdx++) {
      ninSS[ninSSIdx] = nrrdNew();
      airMopAdd(mop, ninSS[ninSSIdx], (airMopper)nrrdNuke, airMopAlways);
    }
    if (SSuniform) {
      for (vi=0; vi<numSS; vi++) {
        scalePos[vi] = AIR_AFFINE(0, vi, numSS-1, rangeSS[0], rangeSS[1]);
      }
    } else {
      double rangeTau[2], tau;
      rangeTau[0] = gageTauOfSig(rangeSS[0]);
      rangeTau[1] = gageTauOfSig(rangeSS[1]);
      for (vi=0; vi<numSS; vi++) {
        tau = AIR_AFFINE(0, vi, numSS-1, rangeTau[0], rangeTau[1]);
        scalePos[vi] = gageSigOfTau(tau);
      }
    }
    if (verbose > 2) {
      fprintf(stderr, "%s: sampling scale range %g--%g %suniformly:\n", me,
              rangeSS[0], rangeSS[1], SSuniform ? "" : "non-");
      for (vi=0; vi<numSS; vi++) {
        fprintf(stderr, "    scalePos[%u] = %g\n", vi, scalePos[vi]);
      }
    }
    if (gageStackBlur(ninSS, scalePos, numSS,
                      nin, kind->baseDim, kSSblur, 
                      nrrdBoundaryBleed, AIR_TRUE,
                      verbose)) {
      airMopAdd(mop, err = biffGetDone(GAGE), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble pre-computing blurrings:\n%s\n", me, err);
      airMopError(mop); return 1;
    }
    if (airStrlen(stackSavePath)) {
      char fnform[AIR_STRLEN_LARGE];
      sprintf(fnform, "%s/blur-%%02u.nrrd", stackSavePath);
      fprintf(stderr, "%s: |%s|\n", me, fnform);
      if (nrrdSaveMulti(fnform, AIR_CAST(const Nrrd *const *, ninSS),
                        numSS, 0, NULL)) {
        airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
        fprintf(stderr, "%s: trouble saving blurrings:\n%s\n", me, err);
        airMopError(mop); return 1;
      }
    }
  } else {
Exemple #6
0
/*
** unlike the thing above, this one assumes that the quaternions in qq
** have already been normalized, and, that the sum of wght[] is 1.0
*/
int
ell_q_avgN_d(double mm[4], unsigned int *iterP,
             const double *qq, double *qlog,
             const double *wght, const unsigned int NN,
             const double eps, const unsigned int maxIter) {
  static const char me[]="ell_q_avgN_d";
  double tmp, qdiv[4], elen;
  unsigned int ii, iter;

  /* iterP optional */
  /* wght optional, to signify equal 1/NN weighting for all */
  if (!( mm && qq )) {
    biffAddf(ELL, "%s: got NULL pointer", me);
    return 1;
  }
  if (!( eps >= 0 )) {
    biffAddf(ELL, "%s: need eps >= 0 (not %g)", me, eps);
    return 1;
  }

  /* initialize with euclidean mean */
  ELL_4V_SET(mm, 0, 0, 0, 0);
  for (ii=0; ii<NN; ii++) {
    double ww;
    ww = wght ? wght[ii] : 1.0/NN;
    ELL_4V_SCALE_INCR(mm, ww, qq + 4*ii);
  }
  ELL_4V_NORM(mm, mm, tmp);

  iter = 0;
  do {
    double logavg[4], qexp[4];
    /* take log of everyone */
    for (ii=0; ii<NN; ii++) {
      ell_q_div_d(qdiv, mm, qq + 4*ii); /* div = mm^1 * qq[ii] */
      ell_q_log_d(qlog + 4*ii, qdiv);
    }
    /* average, and find length */
    ELL_4V_SET(logavg, 0, 0, 0, 0);
    for (ii=0; ii<NN; ii++) {
      double ww;
      ww = wght ? wght[ii] : 1.0/NN;
      ELL_4V_SCALE_INCR(logavg, ww, qlog + 4*ii);
    }
    elen = ELL_4V_LEN(logavg);
    /* use exp to put it back on S^3 */
    ell_q_exp_d(qexp, logavg);
    ell_q_mul_d(mm, mm, qexp);
    iter++;
  } while ((!maxIter || iter < maxIter) && elen > eps);
  if (elen > eps) {
    biffAddf(ELL, "%s: still have error %g (> eps %g) after max %d iters", me,
             elen, eps, maxIter);
    return 1;
  }

  if (iterP) {
    *iterP = iter;
  }
  return 0;
}
Exemple #7
0
int
ell_q_avg4_d(double m[4], unsigned int *iterP,
             const double _q1[4], const double _q2[4],
             const double _q3[4], const double _q4[4],
             const double _wght[4],
             const double eps, const unsigned int maxIter) {
  static const char me[]="ell_q_avg4_d";
  double N, elen, a[4], b[4], c[4], d[4],
    tmp[4], la[4], lb[4], lc[4], ld[4], u[4], wght[4];
  unsigned int iter;

  /* *iterP optional */
  if (!( m && _q1 && _q2 && _q3 && _q4 && _wght )) {
    biffAddf(ELL, "%s: got NULL pointer", me);
    return 1;
  }
  if (!( eps >= 0 )) {
    biffAddf(ELL, "%s: need eps >= 0 (not %g)", me, eps);
    return 1;
  }

  /* normalize (wrt L2) all given quaternions */
  ELL_4V_NORM(a, _q1, N);
  ELL_4V_NORM(b, _q2, N);
  ELL_4V_NORM(c, _q3, N);
  ELL_4V_NORM(d, _q4, N);

  /* normalize (wrt L1) the given weights */
  ELL_4V_COPY(wght, _wght);
  N = wght[0] + wght[1] + wght[2] + wght[3];
  ELL_4V_SCALE(wght, 1.0/N, wght);

  /* initialize mean to normalized euclidean mean */
  ELL_4V_SCALE_ADD4(m, wght[0], a, wght[1], b, wght[2], c, wght[3], d);
  ELL_4V_NORM(m, m, N);

  iter = 0;
  do {
    /* take log of everyone */
    ell_q_div_d(tmp, m, a); ell_q_log_d(la, tmp);
    ell_q_div_d(tmp, m, b); ell_q_log_d(lb, tmp);
    ell_q_div_d(tmp, m, c); ell_q_log_d(lc, tmp);
    ell_q_div_d(tmp, m, d); ell_q_log_d(ld, tmp);
    /* average, and find length */
    ELL_4V_SCALE_ADD4(u, wght[0], la, wght[1], lb, wght[2], lc, wght[3], ld);
    elen = ELL_4V_LEN(u);
    /* use exp to put it back on S^3 */
    ell_q_exp_d(tmp, u); ell_q_mul_d(m, m, tmp);
    iter++;
  } while ((!maxIter || iter < maxIter) && elen > eps);
  if (elen > eps) {
    biffAddf(ELL, "%s: still have error %g after max %d iters", me,
             elen, maxIter);
    return 1;
  }

  if (iterP) {
    *iterP = iter;
  }
  return 0;
}
Exemple #8
0
int
_pullPointProcess(pullTask *task, pullBin *bin, pullPoint *point) {
  char me[]="pullPointProcess", err[BIFF_STRLEN];
  double energyOld, energyNew, force[4], distLimit, posOld[4],
    capvec[3], caplen, capscl;  /* related to capping distance traveled
                                   in a per-iteration way */
  int stepBad, giveUp;

  if (!point->stepEnergy) {
    sprintf(err, "%s: whoa, point %u step is zero!", me, point->idtag);
    biffAdd(PULL, err); return 1;
  }

  if (0 && 162 == point->idtag) {
    fprintf(stderr, "!%s: !!!!!!!!!!!! praying ON!\n", me);
    _pullPraying = AIR_TRUE;
    ELL_3V_COPY(_pullPrayCorner[0][0], point->pos);
    _pullPrayCorner[0][0][2] -= 1;
    ELL_3V_COPY(_pullPrayCorner[0][1], point->pos);
    _pullPrayCorner[0][1][2] += 1;
    fprintf(stderr, "!%s: corner[0][0] = %g %g %g\n", me, 
            _pullPrayCorner[0][0][0],
            _pullPrayCorner[0][0][1],
            _pullPrayCorner[0][0][2]);
    fprintf(stderr, "!%s: corner[0][1] = %g %g %g\n", me, 
            _pullPrayCorner[0][1][0],
            _pullPrayCorner[0][1][1],
            _pullPrayCorner[0][1][2]);
  } else {
    _pullPraying = AIR_FALSE;
  }

  if (_pullPraying) {
    fprintf(stderr, "%s: =============================== (%u) hi @ %g %g %g\n",
            me, point->idtag, point->pos[0], point->pos[1], point->pos[2]);
  }
  energyOld = _pullPointEnergyTotal(task, bin, point, force);
  if (_pullPraying) {
    fprintf(stderr, "!%s: =================== point %u has:\n "
            "     energy = %g ; ndist = %g, force %g %g %g %g\n", me,
            point->idtag, energyOld, point->neighDist,
            force[0], force[1], force[2], force[3]);
  }
  if (!( AIR_EXISTS(energyOld) && ELL_4V_EXISTS(force) )) {
    sprintf(err, "%s: point %u non-exist energy or force", me, point->idtag);
    biffAdd(PULL, err); return 1;
  }

  if (task->pctx->constraint) {
    /* we have a constraint, so do something to get the force more
       tangential to the constriant surface */
    double proj[9], pfrc[3];
    _pullConstraintTangent(task, point, proj);
    ELL_3MV_MUL(pfrc, proj, force);
    ELL_3V_COPY(force, pfrc);
  }

  point->status = 0; /* reset status bitflag */
  ELL_4V_COPY(posOld, point->pos);
  _pullPointHistInit(point);
  _pullPointHistAdd(point, pullCondOld);
  
  if (!ELL_4V_LEN(force)) {
    /* this particle has no reason to go anywhere; we're done with it */
    point->energy = energyOld;
    return 0;
  }
  distLimit = _pullDistLimit(task, point);

  /* find capscl */
  ELL_3V_SCALE(capvec, point->stepEnergy, force);
  caplen = ELL_3V_LEN(capvec);
  if (caplen > distLimit) {
    capscl = distLimit/caplen;
  } else {
    capscl = 1;
  }
  if (_pullPraying) {
    fprintf(stderr, "%s: ======= (%u) capscl = %g\n", me,
            point->idtag, capscl);
  }

  if (_pullPraying) {
    double nfrc[3], len, phold[4], ee;
    int cfail;
    ELL_4V_COPY(phold, point->pos);
    
    fprintf(stderr, "!%s(%u,%u): energy(%g,%g,%g) = %f (original)\n",
            me, task->pctx->iter, point->idtag,
            point->pos[0], point->pos[1], point->pos[2], energyOld);
    
    ELL_4V_SCALE_ADD2(point->pos, 1.0, posOld,
                      capscl*point->stepEnergy, force);
    ELL_3V_COPY(_pullPrayCorner[1][0], point->pos);
    _pullPrayCorner[1][0][2] -= 1;
    ELL_3V_COPY(_pullPrayCorner[1][1], point->pos);
    _pullPrayCorner[1][1][2] += 1;
    fprintf(stderr, "!%s: corner[1][0] = %g %g %g\n", me, 
            _pullPrayCorner[1][0][0],
            _pullPrayCorner[1][0][1],
            _pullPrayCorner[1][0][2]);
    fprintf(stderr, "!%s: corner[1][1] = %g %g %g\n", me, 
            _pullPrayCorner[1][1][0],
            _pullPrayCorner[1][1][1],
            _pullPrayCorner[1][1][2]);

#define PROBE(l)  if (_pullProbe(task, point)) {                   \
      sprintf(err, "%s: while praying", me);                       \
      biffAdd(PULL, err); return 1;                                \
    }                                                              \
    (l) = _pullPointScalar(task->pctx, point,                      \
                           pullInfoHeight, NULL, NULL);
    if (1) {
      double *enr, *lpl, uu, vv, vpos[2][3], ll, mid[3];
      unsigned int ui, vi;
      Nrrd *nenr, *nlpl;
      nenr = nrrdNew();
      nlpl = nrrdNew();
      nrrdMaybeAlloc_nva(nenr, nrrdTypeDouble, 2, _pullPrayRes);
      enr = AIR_CAST(double *, nenr->data);
      nrrdMaybeAlloc_nva(nlpl, nrrdTypeDouble, 2, _pullPrayRes);
      lpl = AIR_CAST(double *, nlpl->data);
      for (vi=0; vi<_pullPrayRes[1]; vi++) {
        vv = AIR_AFFINE(0, vi, _pullPrayRes[1]-1, 0, 1);
        ELL_3V_LERP(vpos[0], vv, _pullPrayCorner[0][0], _pullPrayCorner[0][1]);
        ELL_3V_LERP(vpos[1], vv, _pullPrayCorner[1][0], _pullPrayCorner[1][1]);
        for (ui=0; ui<_pullPrayRes[0]; ui++) {
          uu = AIR_AFFINE(0, ui, _pullPrayRes[0]-1, 0, 1);
          ELL_3V_LERP(point->pos, uu, vpos[0], vpos[1]);
          PROBE(ll);
          lpl[ui + _pullPrayRes[0]*vi] = ll;
          enr[ui + _pullPrayRes[0]*vi] = _pullPointEnergyTotal(task, bin,
                                                               point, NULL);
        }
      }
      nrrdSave("nenr.nrrd", nenr, NULL);
      nrrdSave("nlpl.nrrd", nlpl, NULL);
      nenr = nrrdNuke(nenr);
      nlpl = nrrdNuke(nlpl);
    }
#undef PROBE

    ELL_4V_COPY(point->pos, phold);
    _pullPointEnergyTotal(task, bin, point, NULL);
  }
Exemple #9
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;
}
Exemple #10
0
int
main(int argc, char *argv[]) {
  float angleA_f, axisA_f[3], angleB_f, axisB_f[3],
    qA_f[4], qB_f[4], qC_f[4],
    mat3A_f[9], mat4A_f[16], mat3B_f[9], mat4B_f[16], mat3C_f[9], mat4C_f[16],
    pntA_f[4], pntB_f[4], pntC_f[4];
  double angleA_d, axisA_d[3], angleB_d, axisB_d[3],
    qA_d[4], qB_d[4], qC_d[4],
    mat3A_d[9], mat4A_d[16], mat3B_d[9], mat4B_d[16], mat3C_d[9], mat4C_d[16],
    pntA_d[4], pntB_d[4], pntC_d[4];

  int I, N;
  double tmp, det, frob;

  me = argv[0];
  N = 100000;

  AIR_UNUSED(pntA_d);
  AIR_UNUSED(pntB_d);
  AIR_UNUSED(pntC_d);
  AIR_UNUSED(mat4C_d);
  AIR_UNUSED(mat3C_d);
  AIR_UNUSED(mat4B_d);
  AIR_UNUSED(mat3B_d);
  AIR_UNUSED(mat4A_d);
  AIR_UNUSED(mat3A_d);
  AIR_UNUSED(qC_d);
  AIR_UNUSED(qB_d);
  AIR_UNUSED(qA_d);
  AIR_UNUSED(axisB_d);
  AIR_UNUSED(angleB_d);
  AIR_UNUSED(axisA_d);
  AIR_UNUSED(angleA_d);
  AIR_UNUSED(argc);

  for (I=0; I<N; I++) {
    /* make a rotation (as a quaternion) */
    ELL_3V_SET(axisA_f, 2*airDrandMT()-1, 2*airDrandMT()-1, 2*airDrandMT()-1);
    ELL_3V_NORM(axisA_f, axisA_f, tmp); /* yea, not uniform, so what */
    angleA_f = AIR_PI*(2*airDrandMT()-1);
    ell_aa_to_q_f(qA_f, angleA_f, axisA_f);

    /* convert to AA and back, and back */
    angleB_f = ell_q_to_aa_f(axisB_f, qA_f);
    if (ELL_3V_DOT(axisB_f, axisA_f) < 0) {
      ELL_3V_SCALE(axisB_f, -1, axisB_f);
      angleB_f *= -1;
    }
    ELL_3V_SUB(axisA_f, axisA_f, axisB_f);
    printf(" aa -> q -> aa error: %g, %g\n",
           CA + AIR_ABS(angleA_f - angleB_f), CA + ELL_3V_LEN(axisA_f));

    /* convert to 3m and back, and back */
    ell_q_to_3m_f(mat3A_f, qA_f);
    ell_3m_to_q_f(qB_f, mat3A_f);
    if (ELL_4V_DOT(qA_f, qB_f) < 0) {
      ELL_4V_SCALE(qB_f, -1, qB_f);
    }
    ELL_4V_SUB(qC_f, qA_f, qB_f);
    ELL_Q_TO_3M(mat3B_f, qA_f);
    ELL_3M_SUB(mat3C_f, mat3B_f, mat3A_f);
    printf(" q -> 3m -> q error: %g, %g\n",
           CA + ELL_4V_LEN(qC_f), CA + ELL_3M_FROB(mat3C_f));

    /* convert to 4m and back, and back */
    ell_q_to_4m_f(mat4A_f, qA_f);
    ell_4m_to_q_f(qB_f, mat4A_f);
    if (ELL_4V_DOT(qA_f, qB_f) < 0) {
      ELL_4V_SCALE(qB_f, -1, qB_f);
    }
    ELL_4V_SUB(qC_f, qA_f, qB_f);
    ELL_Q_TO_4M(mat4B_f, qA_f);
    ELL_4M_SUB(mat4C_f, mat4B_f, mat4A_f);
    printf(" q -> 4m -> q error: %g, %g\n",
           CA + ELL_4V_LEN(qC_f), CA + ELL_4M_FROB(mat4C_f));

    /* make a point that we'll rotate */
    ELL_3V_SET(pntA_f, 2*airDrandMT()-1, 2*airDrandMT()-1, 2*airDrandMT()-1);
    
    /* effect rotation in two different ways, and compare results */
    ELL_3MV_MUL(pntB_f, mat3A_f, pntA_f);
    ell_q_3v_rotate_f(pntC_f, qA_f, pntA_f);
    ELL_3V_SUB(pntA_f, pntB_f, pntC_f);
    printf("      rotation error = %g\n", CA + ELL_3V_LEN(pntA_f));

    /* mix up inversion with conversion */
    ell_3m_inv_f(mat3C_f, mat3A_f);
    ell_3m_to_q_f(qB_f, mat3C_f);
    ell_q_mul_f(qC_f, qA_f, qB_f);
    if (ELL_4V_DOT(qA_f, qC_f) < 0) {
      ELL_4V_SCALE(qC_f, -1, qC_f);
    }
    printf("    inv mul = %g %g %g %g\n", qC_f[0], 
           CA + qC_f[1], CA + qC_f[2], CA + qC_f[3]);
    ell_q_inv_f(qC_f, qB_f);
    ELL_4V_SUB(qC_f, qB_f, qB_f);
    printf("    inv diff = %g %g %g %g\n", CA + qC_f[0], 
           CA + qC_f[1], CA + qC_f[2], CA + qC_f[3]);

    /* exp and log */
    ell_q_log_f(qC_f, qA_f);
    ell_q_log_f(qB_f, qC_f);
    ell_q_exp_f(qC_f, qB_f);
    ell_q_exp_f(qB_f, qC_f);
    ELL_4V_SUB(qC_f, qB_f, qA_f);
    printf("    exp/log diff = %g %g %g %g\n", CA + qC_f[0], 
           CA + qC_f[1], CA + qC_f[2], CA + qC_f[3]);

    /* pow, not very exhaustive */
    ell_q_to_3m_f(mat3A_f, qA_f);
    ell_3m_post_mul_f(mat3A_f, mat3A_f);
    ell_3m_post_mul_f(mat3A_f, mat3A_f);
    ell_q_pow_f(qB_f, qA_f, 4);
    ell_q_to_3m_f(mat3B_f, qB_f);
    ELL_3M_SUB(mat3B_f, mat3B_f, mat3A_f);
    printf("   pow diff = %g\n", CA + ELL_3M_FROB(mat3B_f));
    if (ELL_3M_FROB(mat3B_f) > 2) {
      printf("  start q = %g %g %g %g\n", qA_f[0], qA_f[1], qA_f[2], qA_f[3]);
      angleA_f = ell_q_to_aa_f(axisA_f, qA_f);
      printf("  --> aa = %g  (%g %g %g)\n", angleA_f, 
             axisA_f[0], axisA_f[1], axisA_f[2]);
      printf("   q^3 = %g %g %g %g\n", qB_f[0], qB_f[1], qB_f[2], qB_f[3]);
      angleA_f = ell_q_to_aa_f(axisA_f, qB_f);
      printf("  --> aa = %g  (%g %g %g)\n", angleA_f, 
             axisA_f[0], axisA_f[1], axisA_f[2]);
      exit(1);
    }

    /* make sure it looks like a rotation matrix */
    ell_q_to_3m_f(mat3A_f, qA_f);
    det = ELL_3M_DET(mat3A_f);
    frob = ELL_3M_FROB(mat3A_f);
    ELL_3M_TRANSPOSE(mat3B_f, mat3A_f);
    ell_3m_inv_f(mat3C_f, mat3A_f);
    ELL_3M_SUB(mat3C_f, mat3B_f, mat3C_f);
    printf("      det = %g; size = %g; err = %g\n", det, frob*frob/3,
           CA + ELL_3M_FROB(mat3C_f));
    
  }

  exit(0);
}