Beispiel #1
0
void
_nrrdMeasureL1(void *ans, int ansType,
               const void *line, int lineType, size_t len, 
               double axmin, double axmax) {
  double val, S, (*lup)(const void*, size_t);
  size_t ii;

  AIR_UNUSED(axmin);
  AIR_UNUSED(axmax);
  lup = nrrdDLookup[lineType];
  if (nrrdTypeIsIntegral[lineType]) {
    S = 0.0;
    for (ii=0; ii<len; ii++) {
      val = lup(line, ii);
      S += AIR_ABS(val);
    }
  } else {
    S = AIR_NAN;
    for (ii=0; !AIR_EXISTS(S) && ii<len; ii++) {
      S = lup(line, ii);
    }
    S = AIR_ABS(S);
    for (; ii<len; ii++) {
      val = lup(line, ii);
      if (AIR_EXISTS(val)) {
        S += AIR_ABS(val);
      }
    }
  }
  nrrdDStore[ansType](ans, S);
}
Beispiel #2
0
static void
baryFind(double bcoord[3], const double uvp[2],
         const double uv0[2],
         const double uv1[2],
         const double uv2[2]) {
  double mat[9], a, a01, a02, a12;

  ELL_3M_SET(mat,
             uv0[0], uv0[1], 1,
             uv1[0], uv1[1], 1,
             uvp[0], uvp[1], 1);
  a01 = ELL_3M_DET(mat); a01 = AIR_ABS(a01);

  ELL_3M_SET(mat,
             uv0[0], uv0[1], 1,
             uv2[0], uv2[1], 1,
             uvp[0], uvp[1], 1);
  a02 = ELL_3M_DET(mat); a02 = AIR_ABS(a02);

  ELL_3M_SET(mat,
             uv1[0], uv1[1], 1,
             uv2[0], uv2[1], 1,
             uvp[0], uvp[1], 1);
  a12 = ELL_3M_DET(mat); a12 = AIR_ABS(a12);

  a = a01 + a02 + a12;
  ELL_3V_SET(bcoord, a12/a, a02/a, a01/a);
  return;
}
Beispiel #3
0
void
_nrrdMeasureLinf(void *ans, int ansType,
                 const void *line, int lineType, size_t len, 
                 double axmin, double axmax) {
  double val, M, (*lup)(const void*, size_t);
  size_t ii;

  AIR_UNUSED(axmin);
  AIR_UNUSED(axmax);
  lup = nrrdDLookup[lineType];
  if (nrrdTypeIsIntegral[lineType]) {
    val = lup(line, 0);
    M = AIR_ABS(val);
    for (ii=1; ii<len; ii++) {
      val = lup(line, ii);
      val = AIR_ABS(val);
      M = AIR_MAX(M, val);
    }
  } else {
    M = AIR_NAN;
    for (ii=0; !AIR_EXISTS(M) && ii<len; ii++) {
      M = lup(line, ii);
    }
    M = AIR_ABS(M);
    for (; ii<len; ii++) {
      val = lup(line, ii);
      if (AIR_EXISTS(val)) {
        val = AIR_ABS(val);
        M = AIR_MAX(M, val);
      }
    }
  }
  nrrdDStore[ansType](ans, M);
}
Beispiel #4
0
/* XX != AB */
static int
lattXXtoAB(double *dstParm, int srcLatt, const double *srcParm) {
  double AA[2], BB[2], area, theta, radi, scl;
  int ret = 0;

  switch(srcLatt) {
  case rvaLattPRA:  /* PRA -> AB */
    area = AIR_ABS(srcParm[2]);
    theta = AIR_AFFINE(0, srcParm[0], 1, AIR_PI/2, AIR_PI/3);
    radi = srcParm[1];
    ELL_2V_SET(AA, 1.0, 0.0);
    ELL_2V_SET(BB, radi*cos(theta), radi*sin(theta));
    /* area from AA and BB is BB[1], but need to scale
       these to get to requested area */
    scl = sqrt(area/BB[1]);
    ELL_4V_SET(dstParm, scl*AA[0], scl*AA[1], scl*BB[0], scl*BB[1]);
    break;
  case rvaLattAB:  /* UVW -> AB */
    ELL_4V_SET(dstParm, srcParm[2], 0.0, srcParm[0], srcParm[1]);
    break;
  case rvaLattXY:  /* XY -> AB */
    ELL_4V_SET(dstParm, 1.0, 0.0, srcParm[0], srcParm[1]);
    break;
  default: ret = 1; break; /* unimplemented */
  }
  return ret;
}
Beispiel #5
0
/* Calculate the Q-ball profile from DWIs */
void
_tenQball(const double b, const int gradcount, const double svals[],
          const double grads[], double qvals[] ) {
  /* Not an optimal Q-ball implementation! (Taken from submission to
     MICCAI 2006) Should be solved analytically in the future,
     implemented from recent papers. */
  int i,j;
  double d, dist, weight, min, max;

  AIR_UNUSED(b);
  min = max = svals[1] / svals[0];
  for( i = 0; i < gradcount; i++ ) {
    d = svals[i+1] / svals[0];
    if( d > max )
      max = d;
    else if( d < min )
      min = d;
  }

  for( i = 0; i < gradcount; i++ ) {
    qvals[i] = 0;
    for( j = 0; j < gradcount; j++ ) {
      d = AIR_AFFINE( min, svals[j+1] / svals[0], max, 0,1 );
      dist = ELL_3V_DOT(grads + 3*i, grads + 3*j);
      dist = AIR_ABS(dist);
      weight = cos( 0.5 * AIR_PI * dist );
      qvals[i] += d * weight*weight*weight*weight;
    }
  }
  return;
}
Beispiel #6
0
void
_limnSplineWeightsFind_BC(double *wght, limnSpline *spline, double f) {
  double B, C, f0, f1, f2, f3;
  
  B = spline->B;
  C = spline->C;
  f0 = f+1;
  f1 = f;
  f2 = AIR_ABS(f-1);
  f3 = AIR_ABS(f-2);
  ELL_4V_SET(wght,
             _BCCUBIC(f0, B, C),
             _BCCUBIC(f1, B, C),
             _BCCUBIC(f2, B, C),
             _BCCUBIC(f3, B, C));
  return;
}
Beispiel #7
0
/*
** NOTE: profiling showed that about a quarter of the execution time of
** ell_6ms_eigensolve_d() is spent here; so reconsider its need and
** implementation . . . (fabs vs. AIR_ABS() made no difference)
*/
static void
_maxI_sum_find(unsigned int maxI[2], double *sumon, double *sumoff,
               double mat[6][6]) {
  double maxm, tmp;
  unsigned int rrI, ccI;

  /* we hope that all these loops are unrolled by the optimizer */
  *sumon = *sumoff = 0.0;
  for (rrI=0; rrI<6; rrI++) {
    *sumon += AIR_ABS(mat[rrI][rrI]);
  }
  maxm = -1;
  maxI[0] = maxI[1] = 0;
  for (rrI=0; rrI<5; rrI++) {
    for (ccI=rrI+1; ccI<6; ccI++) {
      tmp = AIR_ABS(mat[rrI][ccI]);
      *sumoff += tmp;
      if (tmp > maxm) {
        maxm = tmp;
        maxI[0] = rrI;
        maxI[1] = ccI;
      }
    }
  }

  /*
  if (1) {
    double nrm, trc;
    nrm = trc = 0;
    for (rrI=0; rrI<6; rrI++) {
      trc += mat[rrI][rrI];
      nrm += mat[rrI][rrI]*mat[rrI][rrI];
    }
    for (rrI=0; rrI<5; rrI++) {
      for (ccI=rrI+1; ccI<6; ccI++) {
        nrm += 2*mat[rrI][ccI]*mat[rrI][ccI];
      }
    }
    fprintf(stderr, "---------------- invars = %g %g\n", trc, nrm);
  }
  */

  return;
}
Beispiel #8
0
static int
constraintSatIso(pullTask *task, pullPoint *point,
                 double stepMax, unsigned int iterMax,
                 /* output */
                 int *constrFailP) {
  static const char me[]="constraintSatIso";
  double
    step,         /* current step size */
    val, aval,    /* last and current function values */
    hack,         /* how to control re-tries in the context of a single
                     for-loop, instead of a nested do-while loop */
    grad[4], dir[3], len, state[1 + 1 + 3 + 3];
  unsigned int iter = 0;  /* 0: initial probe, 1..iterMax: probes in loop */

  PROBE(val, aval, grad);
  SAVE(state, aval, val, grad, point->pos);
  hack = 1;
  for (iter=1; iter<=iterMax; iter++) {
    /* consider? http://en.wikipedia.org/wiki/Halley%27s_method */
    NORMALIZE(dir, grad, len);
    if (!len) {
      /* no gradient; back off */
      hack *= task->pctx->sysParm.backStepScale;
      RESTORE(aval, val, grad, point->pos, state);
      continue;
    }
    step = -val/len; /* the newton-raphson step */
    step = step > 0 ? AIR_MIN(stepMax, step) : AIR_MAX(-stepMax, step);
    ELL_3V_SCALE_INCR(point->pos, hack*step, dir);
    _pullPointHistAdd(point, pullCondConstraintSatA);
    PROBE(val, aval, grad);
    if (aval <= state[0]) {  /* we're no further from the root */
      if (AIR_ABS(step) < stepMax*task->pctx->sysParm.constraintStepMin) {
        /* we have converged! */
        break;
      }
      SAVE(state, aval, val, grad, point->pos);
      hack = 1;
    } else { /* oops, try again, don't update dir or len, reset val */
      hack *= task->pctx->sysParm.backStepScale;
      RESTORE(aval, val, grad, point->pos, state);
    }
  }
  if (iter > iterMax) {
    *constrFailP = pullConstraintFailIterMaxed;
  } else {
    *constrFailP = AIR_FALSE;
  }
  return 0;
}
Beispiel #9
0
/*
** UV from Eval
*/
void
tenGlyphBqdUvEval(double uv[2], const double eval[3]) {
  double xx, yy, zz, ax, ay, az, mm;

  ax = AIR_ABS(eval[0]);
  ay = AIR_ABS(eval[1]);
  az = AIR_ABS(eval[2]);
  mm = AIR_MAX(ax, AIR_MAX(ay, az));
  if (mm==0) { /* do not divide */
    uv[0]=uv[1]=0;
    return;
  }
  xx = eval[0]/mm;
  yy = eval[1]/mm;
  zz = eval[2]/mm;
  uv[0] = AIR_AFFINE(-1, yy, 1, 0, 1);
  if (xx > -zz) {
    uv[1] = AIR_AFFINE(-1, zz, 1, 0, 1) - uv[0] + 1;
  } else {
    uv[1] = AIR_AFFINE(-1, xx, 1, -1, 0) - uv[0] + 1;
  }
  return;
}
Beispiel #10
0
/*
** _ell_LU_decomp()
**
** in-place LU decomposition
*/
int
_ell_LU_decomp(double *aa, size_t *indx, size_t NN)  {
  static const char me[]="_ell_LU_decomp";
  int ret=0;
  size_t ii, imax=0, jj, kk;
  double big, sum, tmp;
  double *vv;

  if (!( vv = (double*)calloc(NN, sizeof(double)) )) {
    biffAddf(ELL, "%s: couldn't allocate vv[]!", me);
    ret = 1; goto seeya;
  }

  /* find vv[i]: max of abs of everything in column i */
  for (ii=0; ii<NN; ii++) {
    big = 0.0;
    for (jj=0; jj<NN; jj++) {
      if ((tmp=AIR_ABS(aa[ii*NN + jj])) > big) {
        big = tmp;
      }
    }
    if (!big) {
      char stmp[AIR_STRLEN_SMALL];
      biffAddf(ELL, "%s: singular matrix since column %s all zero", me,
               airSprintSize_t(stmp, ii));
      ret = 1; goto seeya;
    }
    vv[ii] = big;
  }

  for (jj=0; jj<NN; jj++) {
    /* for aa[ii][jj] in lower triangle (below diagonal), subtract from
       aa[ii][jj] the dot product of all elements to its left with elements
       above it (starting at the top) */
    for (ii=0; ii<jj; ii++) {
      sum = aa[ii*NN + jj];
      for (kk=0; kk<ii; kk++) {
        sum -= aa[ii*NN + kk]*aa[kk*NN + jj];
      }
      aa[ii*NN + jj] = sum;
    }

    /* for aa[ii][jj] in upper triangle (including diagonal), subtract from
       aa[ii][jj] the dot product of all elements above it with elements to
       its left (starting from the left) */
    big = 0.0;
    for (ii=jj; ii<NN; ii++) {
      sum = aa[ii*NN + jj];
      for (kk=0; kk<jj; kk++) {
        sum -= aa[ii*NN + kk]*aa[kk*NN + jj];
      }
      aa[ii*NN + jj] = sum;
      /* imax column is one in which abs(aa[i][j])/vv[i] */
      if ((tmp = AIR_ABS(sum)/vv[ii]) >= big) {
        big = tmp;
        imax = ii;
      }
    }

    /* unless we're on the imax column, swap this column the with imax column,
       and permute vv[] accordingly */
    if (jj != imax) {
      /* could record parity # of permutes here */
      for (kk=0; kk<NN; kk++) {
        tmp = aa[imax*NN + kk];
        aa[imax*NN + kk] = aa[jj*NN + kk];
        aa[jj*NN + kk] = tmp;
      }
      tmp = vv[imax];
      vv[imax] = vv[jj];
      vv[jj] = tmp;
    }

    indx[jj] = imax;

    if (aa[jj*NN + jj] == 0.0) {
      aa[jj*NN + jj] = ELL_EPS;
    }

    /* divide everything right of a[jj][jj] by a[jj][jj] */
    if (jj != NN) {
      tmp = 1.0/aa[jj*NN + jj];
      for (ii=jj+1; ii<NN; ii++) {
        aa[ii*NN + jj] *= tmp;
      }
    }
  }
 seeya:
  airFree(vv);
  return ret;
}
Beispiel #11
0
/*
******** tenGradientDistribute
**
** Takes the given list of gradients, normalizes their lengths,
** optionally jitters their positions, does point repulsion, and then
** (optionally) selects a combination of directions with minimum vector sum.
**
** The complicated part of this is the point repulsion, which uses a
** gradient descent with variable set size. The progress of the system
** is measured by decrease in potential (when its measurement doesn't
** overflow to infinity) or an increase in the minimum angle.  When a
** step results in negative progress, the step size is halved, and the
** iteration is attempted again.  Based on the observation that at
** some points the step size must be made very small to get progress,
** the step size is cautiously increased ("nudged") at every
** iteration, to try to avoid using an overly small step.  The amount
** by which the step is nudged is halved everytime the step is halved,
** to avoid endless cycling through step sizes.
*/
int
tenGradientDistribute(Nrrd *nout, const Nrrd *nin,
                      tenGradientParm *tgparm) {
  static const char me[]="tenGradientDistribute";
  char filename[AIR_STRLEN_SMALL];
  unsigned int ii, num, iter, oldIdx, newIdx, edgeShrink;
  airArray *mop;
  Nrrd *npos[2];
  double *pos, len, meanVelocity, pot, potNew, potD,
    edge, edgeMin, angle, angleNew;
  int E;

  if (!nout || tenGradientCheck(nin, nrrdTypeUnknown, 2) || !tgparm) {
    biffAddf(TEN, "%s: got NULL pointer or invalid input", me);
    return 1;
  }

  num = AIR_UINT(nin->axis[1].size);
  mop = airMopNew();
  npos[0] = nrrdNew();
  npos[1] = nrrdNew();
  airMopAdd(mop, npos[0], (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, npos[1], (airMopper)nrrdNuke, airMopAlways);
  if (nrrdConvert(npos[0], nin, nrrdTypeDouble)
      || nrrdConvert(npos[1], nin, nrrdTypeDouble)) {
    biffMovef(TEN, NRRD, "%s: trouble allocating temp buffers", me);
    airMopError(mop); return 1;
  }

  pos = (double*)(npos[0]->data);
  for (ii=0; ii<num; ii++) {
    ELL_3V_NORM(pos, pos, len);
    pos += 3;
  }
  if (tgparm->jitter) {
    if (tenGradientJitter(npos[0], npos[0], tgparm->jitter)) {
      biffAddf(TEN, "%s: problem jittering input", me);
      airMopError(mop); return 1;
    }
  }

  /* initialize things prior to first iteration; have to
     make sure that loop body tests pass 1st time around */
  meanVelocity = 2*tgparm->minVelocity;
  potD = -2*tgparm->minPotentialChange;
  oldIdx = 0;
  newIdx = 1;
  tgparm->step = tgparm->initStep;
  tgparm->nudge = 0.1;
  tenGradientMeasure(&pot, &angle, NULL,
                     npos[oldIdx], tgparm, AIR_TRUE);
  for (iter = 0;
       ((!!tgparm->minIteration && iter < tgparm->minIteration)
        ||
        (iter < tgparm->maxIteration
         && (!tgparm->minPotentialChange
             || !AIR_EXISTS(potD)
             || -potD > tgparm->minPotentialChange)
         && (!tgparm->minVelocity
             || meanVelocity > tgparm->minVelocity)
         && tgparm->step > FLT_MIN));
       iter++) {
    /* copy positions from old to new */
    memcpy(npos[newIdx]->data, npos[oldIdx]->data, 3*num*sizeof(double));
    edge = tenGradientIdealEdge(num, tgparm->single);
    edgeShrink = 0;
    /* try to do a position update, which will fail if repulsion values
       explode, from having an insufficiently small edge normalization,
       so retry with smaller edge next time */
    do {
      E = _tenGradientUpdate(&meanVelocity, &edgeMin,
                             npos[newIdx], edge, tgparm);
      if (E) {
        if (edgeShrink > tgparm->maxEdgeShrink) {
          biffAddf(TEN, "%s: %u > %u edge shrinks (%g), update still failed",
                  me, edgeShrink, tgparm->maxEdgeShrink, edge);
          airMopError(mop); return 1;
        }
        edgeShrink++;
        /* re-initialize positions (HEY ugly code logic) */
        memcpy(npos[newIdx]->data, npos[oldIdx]->data, 3*num*sizeof(double));
        edge = edgeMin;
      }
    } while (E);
    tenGradientMeasure(&potNew, &angleNew, NULL,
                       npos[newIdx], tgparm, AIR_TRUE);
    if ((AIR_EXISTS(pot) && AIR_EXISTS(potNew) && potNew <= pot)
        || angleNew >= angle) {
      /* there was progress of some kind, either through potential
         decrease, or angle increase */
      potD = 2*(potNew - pot)/(potNew + pot);
      if (!(iter % tgparm->report) && tgparm->verbose) {
        fprintf(stderr, "%s(%d): . . . . . . step = %g, edgeShrink = %u\n"
                "   velo = %g<>%g, phi = %g ~ %g<>%g, angle = %g ~ %g\n",
                me, iter, tgparm->step, edgeShrink,
                meanVelocity, tgparm->minVelocity,
                pot, potD, tgparm->minPotentialChange,
                angle, angleNew - angle);
      }
      if (tgparm->snap && !(iter % tgparm->snap)) {
        sprintf(filename, "%05d.nrrd", iter/tgparm->snap);
        if (tgparm->verbose) {
          fprintf(stderr, "%s(%d): . . . . . . saving %s\n",
                  me, iter, filename);
        }
        if (nrrdSave(filename, npos[newIdx], NULL)) {
          char *serr;
          serr = biffGetDone(NRRD);
          if (tgparm->verbose) { /* perhaps shouldn't have this check */
            fprintf(stderr, "%s: iter=%d, couldn't save snapshot:\n%s"
                    "continuing ...\n", me, iter, serr);
          }
          free(serr);
        }
      }
      tgparm->step *= 1 + tgparm->nudge;
      tgparm->step = AIR_MIN(tgparm->initStep, tgparm->step);
      pot = potNew;
      angle = angleNew;
      /* swap buffers */
      newIdx = 1 - newIdx;
      oldIdx = 1 - oldIdx;
    } else {
      /* oops, did not make progress; back off and try again */
      if (tgparm->verbose) {
        fprintf(stderr, "%s(%d): ######## step %g --> %g\n"
                " phi = %g --> %g ~ %g, angle = %g --> %g\n",
                me, iter, tgparm->step, tgparm->step/2,
                pot, potNew, potD, angle, angleNew);
      }
      tgparm->step /= 2;
      tgparm->nudge /= 2;
    }
  }

  /* when the for-loop test fails, we stop before computing the next
     iteration (which starts with copying from npos[oldIdx] to
     npos[newIdx]) ==> the final results are in npos[oldIdx] */

  if (tgparm->verbose) {
    fprintf(stderr, "%s: .......................... done distribution:\n"
            "  (%d && %d) || (%d \n"
            "               && (%d || %d || %d) \n"
            "               && (%d || %d) \n"
            "               && %d) is false\n", me,
            !!tgparm->minIteration, iter < tgparm->minIteration,
            iter < tgparm->maxIteration,
            !tgparm->minPotentialChange,
            !AIR_EXISTS(potD), AIR_ABS(potD) > tgparm->minPotentialChange,
            !tgparm->minVelocity, meanVelocity > tgparm->minVelocity,
            tgparm->step > FLT_MIN);
    fprintf(stderr, "  iter=%d, velo = %g<>%g, phi = %g ~ %g<>%g;\n",
            iter, meanVelocity, tgparm->minVelocity, pot,
            potD, tgparm->minPotentialChange);
    fprintf(stderr, "  minEdge = %g; idealEdge = %g\n",
            2*sin(angle/2), tenGradientIdealEdge(num, tgparm->single));
  }

  tenGradientMeasure(&pot, NULL, NULL, npos[oldIdx], tgparm, AIR_FALSE);
  tgparm->potential = pot;
  tenGradientMeasure(&pot, &angle, &edge, npos[oldIdx], tgparm, AIR_TRUE);
  tgparm->potentialNorm = pot;
  tgparm->angle = angle;
  tgparm->edge = edge;
  tgparm->itersUsed = iter;

  if ((tgparm->minMeanImprovement || tgparm->minMean)
      && !tgparm->single) {
    if (tgparm->verbose) {
      fprintf(stderr, "%s: optimizing balance:\n", me);
    }
    if (tenGradientBalance(nout, npos[oldIdx], tgparm)) {
      biffAddf(TEN, "%s: failed to minimize vector sum of gradients", me);
      airMopError(mop); return 1;
    }
    if (tgparm->verbose) {
      fprintf(stderr, "%s: .......................... done balancing.\n", me);
    }
  } else {
    if (tgparm->verbose) {
      fprintf(stderr, "%s: .......................... (no balancing)\n", me);
    }
    if (nrrdConvert(nout, npos[oldIdx], nrrdTypeDouble)) {
      biffMovef(TEN, NRRD, "%s: couldn't set output", me);
      airMopError(mop); return 1;
    }
  }

  airMopOkay(mop);
  return 0;
}
Beispiel #12
0
int
main() {
  airArray *mop, *submop;
  char *err;

  int typi;
  unsigned int supi, probePass, cti /* context copy index */,
    pvlIdx[NRRD_TYPE_MAX+1], sx, sy, sz, subnum;
  size_t sizes[3] = {42,61,50} /* one of these must be even */,
    ii, nn;
  Nrrd *norigScl, *nucharScl, *nunquant, *nqdiff,
    *nconvScl[NRRD_TYPE_MAX+1];
  unsigned char *ucharScl;
  gageContext *gctx[2][KERN_SIZE_MAX+1];
  gagePerVolume *gpvl[2][NRRD_TYPE_MAX+1][KERN_SIZE_MAX+1];
  const double *vansScl[2][NRRD_TYPE_MAX+1][KERN_SIZE_MAX+1],
    *gansScl[2][NRRD_TYPE_MAX+1][KERN_SIZE_MAX+1],
    *hansScl[2][NRRD_TYPE_MAX+1][KERN_SIZE_MAX+1];
  double *origScl, omin, omax,  dsx, dsy, dsz,
    spcOrig[NRRD_SPACE_DIM_MAX] = {0.0, 0.0, 0.0},
    spcVec[3][NRRD_SPACE_DIM_MAX] = {
      {1.1, 0.0, 0.0},
      {0.0, 2.2, 0.0},
      {0.0, 0.0, 3.3}};

  mop = airMopNew();

#define NRRD_NEW(name, mop)                                     \
  (name) = nrrdNew();                                           \
  airMopAdd((mop), (name), (airMopper)nrrdNuke, airMopAlways)

  /* --------------------------------------------------------------- */
  /* Creating initial volume */
  NRRD_NEW(norigScl, mop);
  if (nrrdMaybeAlloc_nva(norigScl, nrrdTypeDouble, 3, sizes)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "trouble allocating:\n%s", err);
    airMopError(mop); return 1;
  }
  origScl = AIR_CAST(double *, norigScl->data);
  nn = nrrdElementNumber(norigScl);
  airSrandMT(42*42);
  for (ii=0; ii<nn/2; ii++) {
    airNormalRand(origScl + 2*ii + 0, origScl + 2*ii + 1);
  }
  /* learn real range */
  omin = omax = origScl[0];
  for (ii=1; ii<nn; ii++) {
    omin = AIR_MIN(omin, origScl[ii]);
    omax = AIR_MAX(omax, origScl[ii]);
  }
  ELL_3V_SET(spcOrig, 0.0, 0.0, 0.0);
  if (nrrdSpaceSet(norigScl, nrrdSpaceRightAnteriorSuperior)
      || nrrdSpaceOriginSet(norigScl, spcOrig)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "trouble setting space:\n%s", err);
    airMopError(mop); return 1;
  }
  nrrdAxisInfoSet_nva(norigScl, nrrdAxisInfoSpaceDirection, spcVec);
  dsx = AIR_CAST(double, sizes[0]);
  dsy = AIR_CAST(double, sizes[1]);
  dsz = AIR_CAST(double, sizes[2]);
  sx = AIR_CAST(unsigned int, sizes[0]);
  sy = AIR_CAST(unsigned int, sizes[1]);
  sz = AIR_CAST(unsigned int, sizes[2]);
  subnum = AIR_CAST(unsigned int, PROBE_NUM*0.9);


  /* --------------------------------------------------------------- */
  /* Quantizing to 8-bits and checking */
  submop = airMopNew();
  NRRD_NEW(nucharScl, mop);
  NRRD_NEW(nunquant, submop);
  NRRD_NEW(nqdiff, submop);
  if (nrrdQuantize(nucharScl, norigScl, NULL, 8)
      || nrrdUnquantize(nunquant, nucharScl, nrrdTypeDouble)
      || nrrdArithBinaryOp(nqdiff, nrrdBinaryOpSubtract,
                           norigScl, nunquant)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "trouble quantizing and back:\n%s", err);
    airMopError(submop); airMopError(mop); return 1;
  }
  if (!( nucharScl->oldMin == omin
         && nucharScl->oldMax == omax )) {
    fprintf(stderr, "quantization range [%g,%g] != real range [%g,%g]\n",
            nucharScl->oldMin, nucharScl->oldMax, omin, omax);
    airMopError(submop); airMopError(mop); return 1;
  }
  {
    double *qdiff, *unquant;
    /* empirically determined tolerance, which had to be increased in
       order to work under valgrind (!)- perhaps because of a
       difference in the use of 80-bit registers */
    double epsilon=0.50000000000004;
    qdiff = AIR_CAST(double *, nqdiff->data);
    unquant = AIR_CAST(double *, nunquant->data);
    for (ii=0; ii<nn; ii++) {
      double dd;
      /* with infinite precision, the max difference between original and
         quantized values should be exactly half the width (in value)
         of 1/256 of value range  ==> dd = 0.5 */
      dd = qdiff[ii]*256/(omax - omin);
      if (AIR_ABS(dd) > epsilon) {
        unsigned int ui;
        ui = AIR_CAST(unsigned int, ii);
        fprintf(stderr, "|orig[%u]=%.17g - unquant=%.17g|*256/%.17g "
                "= %.17g > %.17g!\n", ui, origScl[ii], unquant[ii],
                omax - omin, AIR_ABS(dd), epsilon);
        airMopError(submop); airMopError(mop); return 1;
      }
    }
  }
Beispiel #13
0
int
main(int argc, const char **argv) {
  const char *me;
  Nrrd *nscl;
  double *dscl;
  airArray *mop;
  char *fullname;
  gageContext *igctx[INTERP_KERN_NUM], *bgctx[BLUR_KERN_NUM];
  const NrrdKernel *ikern[INTERP_KERN_NUM] = {
    nrrdKernelBox,
    nrrdKernelTent,
    nrrdKernelBCCubic,
    nrrdKernelCatmullRom,
  };
  double ikparm[INTERP_KERN_NUM][NRRD_KERNEL_PARMS_NUM] = {
    {1.0},
    {1.0},
    {1.0, 0.0, 0.5},
    {AIR_NAN},
  };
  const NrrdKernel *bkern[BLUR_KERN_NUM] = {
    nrrdKernelTent,
    nrrdKernelBSpline3,
    nrrdKernelBSpline5,
    nrrdKernelBCCubic,
    nrrdKernelGaussian,
  };
  const NrrdKernel *bkernD[BLUR_KERN_NUM] = {
    nrrdKernelForwDiff,
    nrrdKernelBSpline3D,
    nrrdKernelBSpline5D,
    nrrdKernelBCCubicD,
    nrrdKernelGaussianD,
  };
  const NrrdKernel *bkernDD[BLUR_KERN_NUM] = {
    nrrdKernelZero,
    nrrdKernelBSpline3DD,
    nrrdKernelBSpline5DD,
    nrrdKernelBCCubicDD,
    nrrdKernelGaussianDD,
  };
  double bkparm[BLUR_KERN_NUM][NRRD_KERNEL_PARMS_NUM] = {
    {1.0},
    {AIR_NAN},
    {AIR_NAN},
    {2.0, 1.0, 0.0},
    {1.2, 5.0},
  };
  const double *ivalAns[INTERP_KERN_NUM], *bvalAns[BLUR_KERN_NUM],
    *bgrdAns[BLUR_KERN_NUM], *bhesAns[BLUR_KERN_NUM];
  int E;
  unsigned int sx, sy, sz, ki;

  AIR_UNUSED(argc);
  me = argv[0];
  mop = airMopNew();

  nscl = nrrdNew();
  airMopAdd(mop, nscl, (airMopper)nrrdNuke, airMopAlways);
  fullname = testDataPathPrefix("fmob-c4h.nrrd");
  airMopAdd(mop, fullname, airFree, airMopAlways);
  if (nrrdLoad(nscl, fullname, NULL)) {
    char *err;
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble reading data \"%s\":\n%s",
            me, fullname, err);
    airMopError(mop); return 1;
  }
  /* make sure its a double-type volume (assumed below) */
  if (nrrdTypeDouble != nscl->type) {
    fprintf(stderr, "%s: volume type %s != expected type %s\n", me,
            airEnumStr(nrrdType, nscl->type),
            airEnumStr(nrrdType, nrrdTypeDouble));
    airMopError(mop); return 1;
  }
  dscl = AIR_CAST(double *, nscl->data);
  sx = AIR_CAST(unsigned int, nscl->axis[0].size);
  sy = AIR_CAST(unsigned int, nscl->axis[1].size);
  sz = AIR_CAST(unsigned int, nscl->axis[2].size);

  for (ki=0; ki<INTERP_KERN_NUM; ki++) {
    gagePerVolume *gpvl;
    igctx[ki] = gageContextNew();
    airMopAdd(mop, igctx[ki], (airMopper)gageContextNix, airMopAlways);
    gageParmSet(igctx[ki], gageParmRenormalize, AIR_FALSE);
    gageParmSet(igctx[ki], gageParmCheckIntegrals, AIR_TRUE);
    gageParmSet(igctx[ki], gageParmOrientationFromSpacing, AIR_FALSE);
    E = 0;
    if (!E) E |= !(gpvl = gagePerVolumeNew(igctx[ki], nscl, gageKindScl));
    if (!E) E |= gageKernelSet(igctx[ki], gageKernel00,
                               ikern[ki], ikparm[ki]);
    if (!E) E |= gagePerVolumeAttach(igctx[ki], gpvl);
    if (!E) E |= gageQueryItemOn(igctx[ki], gpvl, gageSclValue);
    if (!E) E |= gageUpdate(igctx[ki]);
    if (E) {
      char *err;
      airMopAdd(mop, err = biffGetDone(GAGE), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble %s set-up:\n%s\n", me,
              ikern[ki]->name, err);
      airMopError(mop); return 1;
    }
    ivalAns[ki] = gageAnswerPointer(igctx[ki], gpvl, gageSclValue);
  }

  /* traverse all samples of volume, probing with the interpolating
     kernels, make sure we recover the original values */
  {
    unsigned int xi, yi, zi;
    double pval[INTERP_KERN_NUM], err, rval;
    int pret;
    for (zi=0; zi<sz; zi++) {
      for (yi=0; yi<sy; yi++) {
        for (xi=0; xi<sx; xi++) {
          rval = dscl[xi + sx*(yi + sy*zi)];
          for (ki=0; ki<INTERP_KERN_NUM; ki++) {
            pret = gageProbeSpace(igctx[ki], xi, yi, zi,
                                  AIR_TRUE /* indexSpace */,
                                  AIR_FALSE /* clamp */);
            if (pret) {
              fprintf(stderr, "%s: %s probe error(%d): %s\n", me,
                      ikern[ki]->name, igctx[ki]->errNum, igctx[ki]->errStr);

              airMopError(mop); return 1;
            }
            pval[ki] = *ivalAns[ki];
            err = AIR_ABS(rval - pval[ki]);
            if (err) {
              fprintf(stderr, "%s: interp's [%u,%u,%u] %s probe %f "
                      "!= true %f (err %f)\n", me, xi, yi, zi,
                      ikern[ki]->name, pval[ki], rval, err);
              airMopError(mop); return 1;
            }
          }
        }
      }
    }
  }

  /* set up contexts for non-interpolating (blurring) kernels,
     and their first and second derivatives */
  for (ki=0; ki<BLUR_KERN_NUM; ki++) {
    gagePerVolume *gpvl;
    bgctx[ki] = gageContextNew();
    airMopAdd(mop, bgctx[ki], (airMopper)gageContextNix, airMopAlways);
    gageParmSet(bgctx[ki], gageParmRenormalize, AIR_TRUE);
    gageParmSet(bgctx[ki], gageParmCheckIntegrals, AIR_TRUE);
    gageParmSet(bgctx[ki], gageParmOrientationFromSpacing, AIR_FALSE);
    E = 0;
    if (!E) E |= !(gpvl = gagePerVolumeNew(bgctx[ki], nscl, gageKindScl));
    if (!E) E |= gageKernelSet(bgctx[ki], gageKernel00,
                               bkern[ki], bkparm[ki]);
    if (!E) E |= gageKernelSet(bgctx[ki], gageKernel11,
                               bkernD[ki], bkparm[ki]);
    if (!E) E |= gageKernelSet(bgctx[ki], gageKernel22,
                               bkernDD[ki], bkparm[ki]);
    if (!E) E |= gagePerVolumeAttach(bgctx[ki], gpvl);
    if (!E) E |= gageQueryItemOn(bgctx[ki], gpvl, gageSclValue);
    if (!E) E |= gageQueryItemOn(bgctx[ki], gpvl, gageSclGradVec);
    if (!E) E |= gageQueryItemOn(bgctx[ki], gpvl, gageSclHessian);
    if (!E) E |= gageUpdate(bgctx[ki]);
    if (E) {
      char *err;
      airMopAdd(mop, err = biffGetDone(GAGE), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble %s set-up:\n%s\n", me,
              bkern[ki]->name, err);
      airMopError(mop); return 1;
    }
    fprintf(stderr, "%s radius = %u\n", bkern[ki]->name, bgctx[ki]->radius);
    bvalAns[ki] = gageAnswerPointer(bgctx[ki], gpvl, gageSclValue);
    bgrdAns[ki] = gageAnswerPointer(bgctx[ki], gpvl, gageSclGradVec);
    bhesAns[ki] = gageAnswerPointer(bgctx[ki], gpvl, gageSclHessian);
  }

  {
#define POS_NUM 12
    double xp[POS_NUM], yp[POS_NUM], zp[POS_NUM],
      pos[POS_NUM*POS_NUM*POS_NUM][3], *prbd,
      offs[POS_NUM/2] = {0, 1.22222, 2.444444, 3.777777, 5.88888, 7.55555};
    Nrrd *nprbd, *ncorr;
    unsigned int ii, jj, kk, qlen = 1 + 3 + 9;
    char *corrfn, explain[AIR_STRLEN_LARGE];
    int pret, differ;

    corrfn = testDataPathPrefix("test/probeSclAns.nrrd");
    airMopAdd(mop, corrfn, airFree, airMopAlways);
    ncorr = nrrdNew();
    airMopAdd(mop, ncorr, (airMopper)nrrdNuke, airMopAlways);
    if (nrrdLoad(ncorr, corrfn, NULL)) {
      char *err;
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble reading data \"%s\":\n%s",
              me, corrfn, err);
      airMopError(mop); return 1;
    }
    for (ii=0; ii<POS_NUM/2; ii++) {
      xp[ii] = yp[ii] = zp[ii] = offs[ii];
      xp[POS_NUM-1-ii] = AIR_CAST(double, sx)-1.0-offs[ii];
      yp[POS_NUM-1-ii] = AIR_CAST(double, sy)-1.0-offs[ii];
      zp[POS_NUM-1-ii] = AIR_CAST(double, sz)-1.0-offs[ii];
    }
    for (kk=0; kk<POS_NUM; kk++) {
      for (jj=0; jj<POS_NUM; jj++) {
        for (ii=0; ii<POS_NUM; ii++) {
          ELL_3V_SET(pos[ii + POS_NUM*(jj + POS_NUM*kk)],
                     xp[ii], yp[jj], zp[kk]);
        }
      }
    }
    nprbd = nrrdNew();
    airMopAdd(mop, nprbd, (airMopper)nrrdNuke, airMopAlways);
    if (nrrdMaybeAlloc_va(nprbd, nrrdTypeDouble, 3,
                          AIR_CAST(size_t, qlen),
                          AIR_CAST(size_t, BLUR_KERN_NUM),
                          AIR_CAST(size_t, POS_NUM*POS_NUM*POS_NUM))) {
      char *err;
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble setting up prbd:\n%s", me, err);
      airMopError(mop); return 1;
    }
    prbd = AIR_CAST(double *, nprbd->data);
    for (ii=0; ii<POS_NUM*POS_NUM*POS_NUM; ii++) {
      for (ki=0; ki<BLUR_KERN_NUM; ki++) {
        pret = gageProbeSpace(bgctx[ki], pos[ii][0], pos[ii][1], pos[ii][2],
                              AIR_TRUE /* indexSpace */,
                              AIR_FALSE /* clamp */);
        if (pret) {
          fprintf(stderr, "%s: %s probe error(%d): %s\n", me,
                  bkern[ki]->name, bgctx[ki]->errNum, bgctx[ki]->errStr);
          airMopError(mop); return 1;
        }
        prbd[0 + qlen*(ki + BLUR_KERN_NUM*(ii))] = bvalAns[ki][0];
        ELL_3V_COPY(prbd + 1 + qlen*(ki + BLUR_KERN_NUM*(ii)), bgrdAns[ki]);
        ELL_9V_COPY(prbd + 4 + qlen*(ki + BLUR_KERN_NUM*(ii)), bhesAns[ki]);
      }
    }
    /* HEY: weirdly, so far its only on Windows (and more than 10 times worse
       on Cygwin) this epsilon needs to be larger than zero, and only for the
       radius 6 Gaussian? */
    if (nrrdCompare(ncorr, nprbd, AIR_FALSE /* onlyData */,
                    8.0e-14 /* epsilon */, &differ, explain)) {
      char *err;
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble comparing:\n%s", me, err);
      airMopError(mop); return 1;
    }
    if (differ) {
      fprintf(stderr, "%s: probed values not correct: %s\n", me, explain);
      airMopError(mop); return 1;
    } else {
      fprintf(stderr, "all good\n");
    }
  }

  airMopOkay(mop);
  return 0;
}
Beispiel #14
0
int
fixproj(Nrrd *nproj[3], Nrrd *nvol) {
  char me[]="fixproj", err[BIFF_STRLEN];
  airArray *mop;
  Nrrd *ntmp[3], *nt;
  int sz[3], ii, map[3], h[3], E, mi;
  size_t rsz[3];
  double vec[3][3], dot[3], sp[3], parm[NRRD_KERNEL_PARMS_NUM];

  mop = airMopNew();

  if (!( ELL_3V_EXISTS(nvol->axis[0].spaceDirection)
         && ELL_3V_EXISTS(nvol->axis[1].spaceDirection)
         && ELL_3V_EXISTS(nvol->axis[2].spaceDirection) )) {
    sprintf(err, "%s: space directions don't exist for all 3 axes", me);
    biffAdd(NINSPECT, err);
    airMopError(mop); return 1;
  }

  airMopAdd(mop, nt = nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, ntmp[0] = nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, ntmp[1] = nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, ntmp[2] = nrrdNew(), (airMopper)nrrdNuke, airMopAlways);

  /*                 RL  AP  SI */
  ELL_3V_SET(vec[0], 1,  0,  0);
  ELL_3V_SET(vec[1], 0,  1,  0);
  ELL_3V_SET(vec[2], 0,  0,  1);
  for (ii=0; ii<3; ii++) {
    dot[0] = ELL_3V_DOT(vec[ii], nvol->axis[0].spaceDirection);
    dot[1] = ELL_3V_DOT(vec[ii], nvol->axis[1].spaceDirection);
    dot[2] = ELL_3V_DOT(vec[ii], nvol->axis[2].spaceDirection);
    dot[0] = AIR_ABS(dot[0]);
    dot[1] = AIR_ABS(dot[1]);
    dot[2] = AIR_ABS(dot[2]);
    map[ii] = ELL_MAX3_IDX(dot[0], dot[1], dot[2]);
  }
  ELL_3V_SET(h, 1, 0, 0);
  E = 0;
  for (ii=0; ii<3; ii++) {
    if (h[map[ii]] != map[h[ii]]) {
      if (!E) E |= nrrdAxesSwap(ntmp[ii], nproj[map[ii]], 1, 2);
    } else {
      if (!E) E |= nrrdCopy(ntmp[ii], nproj[map[ii]]);
    }
  }
  if (E) {
    sprintf(err, "%s: trouble with nrrd operations", me);
    biffMove(NINSPECT, err, NRRD);
    airMopError(mop); return 1;
  }
  E = 0;
  if (nvol->axis[map[0]].spaceDirection[0] > 0) {
    if (!E) E |= nrrdFlip(nt, ntmp[1], 0+1);
    if (!E) E |= nrrdCopy(ntmp[1], nt);
    if (!E) E |= nrrdFlip(nt, ntmp[2], 0+1);
    if (!E) E |= nrrdCopy(ntmp[2], nt);
  }
  if (nvol->axis[map[1]].spaceDirection[1] > 0) {
    if (!E) E |= nrrdFlip(nt, ntmp[0], 0+1);
    if (!E) E |= nrrdCopy(ntmp[0], nt);
    if (!E) E |= nrrdFlip(nt, ntmp[2], 1+1);
    if (!E) E |= nrrdCopy(ntmp[2], nt);
  }
  if (nvol->axis[map[2]].spaceDirection[2] > 0) {
    if (!E) E |= nrrdFlip(nt, ntmp[0], 1+1);
    if (!E) E |= nrrdCopy(ntmp[0], nt);
    if (!E) E |= nrrdFlip(nt, ntmp[1], 1+1);
    if (!E) E |= nrrdCopy(ntmp[1], nt);
  }
  if (E) {
    sprintf(err, "%s: trouble with nrrd operations", me);
    biffMove(NINSPECT, err, NRRD);
    airMopError(mop); return 1;
  }

  for (ii=0; ii<3; ii++) {
    sz[ii] = nvol->axis[map[ii]].size;
    sp[ii] = ELL_3V_LEN(nvol->axis[map[ii]].spaceDirection);
  }
  mi = ELL_MIN3_IDX(sp[0], sp[1], sp[2]);
  sz[0] = (int)(sz[0]*sp[0]/sp[mi]);
  sz[1] = (int)(sz[1]*sp[1]/sp[mi]);
  sz[2] = (int)(sz[2]*sp[2]/sp[mi]);

  parm[0] = 1;
  ELL_3V_SET(rsz, 3, sz[1], sz[2]);
  nrrdSimpleResample(nproj[0], ntmp[0], nrrdKernelBox, parm, rsz, NULL);
  ELL_3V_SET(rsz, 3, sz[0], sz[2]);
  nrrdSimpleResample(nproj[1], ntmp[1], nrrdKernelBox, parm, rsz, NULL);
  ELL_3V_SET(rsz, 3, sz[0], sz[1]);
  nrrdSimpleResample(nproj[2], ntmp[2], nrrdKernelBox, parm, rsz, NULL);

  airMopOkay(mop);
  return 0;
}
Beispiel #15
0
static double _nrrdUnaryOpAbs(double a)        {return AIR_ABS(a);}
Beispiel #16
0
int
tenGlyphGen(limnObject *glyphsLimn, echoScene *glyphsEcho,
            tenGlyphParm *parm,
            const Nrrd *nten, const Nrrd *npos, const Nrrd *nslc) {
  static const char me[]="tenGlyphGen";
  gageShape *shape;
  airArray *mop;
  float *tdata, eval[3], evec[9], *cvec, rotEvec[9], mA_f[16],
    absEval[3], glyphScl[3];
  double pI[3], pW[3], cl, cp, sRot[16], mA[16], mB[16], msFr[9], tmpvec[3],
    R, G, B, qA, qB, qC, glyphAniso, sliceGray;
  unsigned int duh;
  int slcCoord[3], idx, glyphIdx, axis, numGlyphs,
    svRGBAfl=AIR_FALSE;
  limnLook *look; int lookIdx;
  echoObject *eglyph, *inst, *list=NULL, *split, *esquare;
  echoPos_t eM[16], originOffset[3], edge0[3], edge1[3];
  char stmp[AIR_STRLEN_SMALL];
  /*
  int eret;
  double tmp1[3], tmp2[3];
  */

  if (!( (glyphsLimn || glyphsEcho) && nten && parm)) {
    biffAddf(TEN, "%s: got NULL pointer", me);
    return 1;
  }
  mop = airMopNew();
  shape = gageShapeNew();
  shape->defaultCenter = nrrdCenterCell;
  airMopAdd(mop, shape, (airMopper)gageShapeNix, airMopAlways);
  if (npos) {
    if (!( 2 == nten->dim && 7 == nten->axis[0].size )) {
      biffAddf(TEN, "%s: nten isn't 2-D 7-by-N array", me);
      airMopError(mop); return 1;
    }
    if (!( 2 == npos->dim && 3 == npos->axis[0].size
           && nten->axis[1].size == npos->axis[1].size )) {
      biffAddf(TEN, "%s: npos isn't 2-D 3-by-%s array", me,
               airSprintSize_t(stmp, nten->axis[1].size));
      airMopError(mop); return 1;
    }
    if (!( nrrdTypeFloat == nten->type && nrrdTypeFloat == npos->type )) {
      biffAddf(TEN, "%s: nten and npos must be %s, not %s and %s", me,
               airEnumStr(nrrdType, nrrdTypeFloat),
               airEnumStr(nrrdType, nten->type),
               airEnumStr(nrrdType, npos->type));
      airMopError(mop); return 1;
    }
  } else {
    if (tenTensorCheck(nten, nrrdTypeFloat, AIR_TRUE, AIR_TRUE)) {
      biffAddf(TEN, "%s: didn't get a valid DT volume", me);
      airMopError(mop); return 1;
    }
  }
  if (tenGlyphParmCheck(parm, nten, npos, nslc)) {
    biffAddf(TEN, "%s: trouble", me);
    airMopError(mop); return 1;
  }
  if (!npos) {
    if (gageShapeSet(shape, nten, tenGageKind->baseDim)) {
      biffMovef(TEN, GAGE, "%s: trouble", me);
      airMopError(mop); return 1;
    }
  }
  if (parm->doSlice) {
    ELL_3V_COPY(edge0, shape->spacing);
    ELL_3V_COPY(edge1, shape->spacing);
    edge0[parm->sliceAxis] = edge1[parm->sliceAxis] = 0.0;
    switch(parm->sliceAxis) {
    case 0:
      edge0[1] = edge1[2] = 0;
      ELL_4M_ROTATE_Y_SET(sRot, AIR_PI/2);
      break;
    case 1:
      edge0[0] = edge1[2] = 0;
      ELL_4M_ROTATE_X_SET(sRot, AIR_PI/2);
      break;
    case 2: default:
      edge0[0] = edge1[1] = 0;
      ELL_4M_IDENTITY_SET(sRot);
      break;
    }
    ELL_3V_COPY(originOffset, shape->spacing);
    ELL_3V_SCALE(originOffset, -0.5, originOffset);
    originOffset[parm->sliceAxis] *= -2*parm->sliceOffset;
  }
  if (glyphsLimn) {
    /* create limnLooks for diffuse and ambient-only shading */
    /* ??? */
    /* hack: save old value of setVertexRGBAFromLook, and set to true */
    svRGBAfl = glyphsLimn->setVertexRGBAFromLook;
    glyphsLimn->setVertexRGBAFromLook = AIR_TRUE;
  }
  if (glyphsEcho) {
    list = echoObjectNew(glyphsEcho, echoTypeList);
  }
  if (npos) {
    numGlyphs = AIR_UINT(nten->axis[1].size);
  } else {
    numGlyphs = shape->size[0] * shape->size[1] * shape->size[2];
  }
  /* find measurement frame transform */
  if (3 == nten->spaceDim
      && AIR_EXISTS(nten->measurementFrame[0][0])) {
    /*     msFr        nten->measurementFrame
    **   0  1  2      [0][0]   [1][0]   [2][0]
    **   3  4  5      [0][1]   [1][1]   [2][1]
    **   6  7  8      [0][2]   [1][2]   [2][2]
    */
    msFr[0] = nten->measurementFrame[0][0];
    msFr[3] = nten->measurementFrame[0][1];
    msFr[6] = nten->measurementFrame[0][2];
    msFr[1] = nten->measurementFrame[1][0];
    msFr[4] = nten->measurementFrame[1][1];
    msFr[7] = nten->measurementFrame[1][2];
    msFr[2] = nten->measurementFrame[2][0];
    msFr[5] = nten->measurementFrame[2][1];
    msFr[8] = nten->measurementFrame[2][2];
  } else {
    ELL_3M_IDENTITY_SET(msFr);
  }
  for (idx=0; idx<numGlyphs; idx++) {
    tdata = (float*)(nten->data) + 7*idx;
    if (parm->verbose >= 2) {
      fprintf(stderr, "%s: glyph %d/%d: hello %g    %g %g %g %g %g %g\n",
              me, idx, numGlyphs, tdata[0],
              tdata[1], tdata[2], tdata[3],
              tdata[4], tdata[5], tdata[6]);
    }
    if (!( TEN_T_EXISTS(tdata) )) {
      /* there's nothing we can do here */
      if (parm->verbose >= 2) {
        fprintf(stderr, "%s: glyph %d/%d: non-existent data\n",
                me, idx, numGlyphs);
      }
      continue;
    }
    if (npos) {
      ELL_3V_COPY(pW, (float*)(npos->data) + 3*idx);
      if (!( AIR_EXISTS(pW[0]) && AIR_EXISTS(pW[1]) && AIR_EXISTS(pW[2]) )) {
        /* position doesn't exist- perhaps because its from the push
           library, which might kill points by setting coords to nan */
        continue;
      }
    } else {
      NRRD_COORD_GEN(pI, shape->size, 3, idx);
      /* this does take into account full orientation */
      gageShapeItoW(shape, pW, pI);
      if (parm->nmask) {
        if (!( nrrdFLookup[parm->nmask->type](parm->nmask->data, idx)
               >= parm->maskThresh )) {
          if (parm->verbose >= 2) {
            fprintf(stderr, "%s: glyph %d/%d: doesn't meet mask thresh\n",
                    me, idx, numGlyphs);
          }
          continue;
        }
      }
    }
    tenEigensolve_f(eval, evec, tdata);
    /* transform eigenvectors by measurement frame */
    ELL_3MV_MUL(tmpvec, msFr, evec + 0);
    ELL_3V_COPY_TT(evec + 0, float, tmpvec);
    ELL_3MV_MUL(tmpvec, msFr, evec + 3);
    ELL_3V_COPY_TT(evec + 3, float, tmpvec);
    ELL_3MV_MUL(tmpvec, msFr, evec + 6);
    ELL_3V_COPY_TT(evec + 6, float, tmpvec);
    ELL_3V_CROSS(tmpvec, evec + 0, evec + 3);
    if (0 > ELL_3V_DOT(tmpvec, evec + 6)) {
      ELL_3V_SCALE(evec + 6, -1, evec + 6);
    }
    ELL_3M_TRANSPOSE(rotEvec, evec);
    if (parm->doSlice
        && pI[parm->sliceAxis] == parm->slicePos) {
      /* set sliceGray */
      if (nslc) {
        /* we aren't masked by confidence, as anisotropy slice is */
        for (duh=0; duh<parm->sliceAxis; duh++) {
          slcCoord[duh] = (int)(pI[duh]);
        }
        for (duh=duh<parm->sliceAxis; duh<2; duh++) {
          slcCoord[duh] = (int)(pI[duh+1]);
        }
        /* HEY: GLK has no idea what's going here */
        slcCoord[0] = (int)(pI[0]);
        slcCoord[1] = (int)(pI[1]);
        slcCoord[2] = (int)(pI[2]);
        sliceGray =
          nrrdFLookup[nslc->type](nslc->data, slcCoord[0]
                                  + nslc->axis[0].size*slcCoord[1]);
      } else {
        if (!( tdata[0] >= parm->confThresh )) {
          if (parm->verbose >= 2) {
            fprintf(stderr, "%s: glyph %d/%d (slice): conf %g < thresh %g\n",
                    me, idx, numGlyphs, tdata[0], parm->confThresh);
          }
          continue;
        }
        sliceGray = tenAnisoEval_f(eval, parm->sliceAnisoType);
      }
      if (parm->sliceGamma > 0) {
        sliceGray = AIR_AFFINE(0, sliceGray, 1, parm->sliceBias, 1);
        sliceGray = pow(sliceGray, 1.0/parm->sliceGamma);
      } else {
        sliceGray = AIR_AFFINE(0, sliceGray, 1, 0, 1-parm->sliceBias);
        sliceGray = 1.0 - pow(sliceGray, -1.0/parm->sliceGamma);
      }
      /* make slice contribution */
      /* HEY: this is *NOT* aware of shape->fromOrientation */
      if (glyphsLimn) {
        lookIdx = limnObjectLookAdd(glyphsLimn);
        look = glyphsLimn->look + lookIdx;
        ELL_4V_SET_TT(look->rgba, float, sliceGray, sliceGray, sliceGray, 1);
        ELL_3V_SET(look->kads, 1, 0, 0);
        look->spow = 0;
        glyphIdx = limnObjectSquareAdd(glyphsLimn, lookIdx);
        ELL_4M_IDENTITY_SET(mA);
        ell_4m_post_mul_d(mA, sRot);
        if (!npos) {
          ELL_4M_SCALE_SET(mB,
                           shape->spacing[0],
                           shape->spacing[1],
                           shape->spacing[2]);
        }
        ell_4m_post_mul_d(mA, mB);
        ELL_4M_TRANSLATE_SET(mB, pW[0], pW[1], pW[2]);
        ell_4m_post_mul_d(mA, mB);
        ELL_4M_TRANSLATE_SET(mB,
                             originOffset[0],
                             originOffset[1],
                             originOffset[2]);
        ell_4m_post_mul_d(mA, mB);
        ELL_4M_COPY_TT(mA_f, float, mA);
        limnObjectPartTransform(glyphsLimn, glyphIdx, mA_f);
      }
      if (glyphsEcho) {
        esquare = echoObjectNew(glyphsEcho,echoTypeRectangle);
        ELL_3V_ADD2(((echoRectangle*)esquare)->origin, pW, originOffset);
        ELL_3V_COPY(((echoRectangle*)esquare)->edge0, edge0);
        ELL_3V_COPY(((echoRectangle*)esquare)->edge1, edge1);
        echoColorSet(esquare,
                     AIR_CAST(echoCol_t, sliceGray),
                     AIR_CAST(echoCol_t, sliceGray),
                     AIR_CAST(echoCol_t, sliceGray), 1);
        /* this is pretty arbitrary- but I want shadows to have some effect.
           Previously, the material was all ambient: (A,D,S) = (1,0,0),
           which avoided all shadow effects. */
        echoMatterPhongSet(glyphsEcho, esquare, 0.4f, 0.6f, 0, 40);
        echoListAdd(list, esquare);
      }
    }
    if (parm->onlyPositive) {
      if (eval[2] < 0) {
        /* didn't have all positive eigenvalues, its outta here */
        if (parm->verbose >= 2) {
          fprintf(stderr, "%s: glyph %d/%d: not all evals %g %g %g > 0\n",
                  me, idx, numGlyphs, eval[0], eval[1], eval[2]);
        }
        continue;
      }
    }
    if (!( tdata[0] >= parm->confThresh )) {
      if (parm->verbose >= 2) {
        fprintf(stderr, "%s: glyph %d/%d: conf %g < thresh %g\n",
                me, idx, numGlyphs, tdata[0], parm->confThresh);
      }
      continue;
    }
    if (!( tenAnisoEval_f(eval, parm->anisoType) >= parm->anisoThresh )) {
      if (parm->verbose >= 2) {
        fprintf(stderr, "%s: glyph %d/%d: aniso[%d] %g < thresh %g\n",
                me, idx, numGlyphs, parm->anisoType,
                tenAnisoEval_f(eval, parm->anisoType), parm->anisoThresh);
      }
      continue;
    }
    glyphAniso = tenAnisoEval_f(eval, parm->colAnisoType);
    /*
      fprintf(stderr, "%s: eret = %d; evals = %g %g %g\n", me,
      eret, eval[0], eval[1], eval[2]);
      ELL_3V_CROSS(tmp1, evec+0, evec+3); tmp2[0] = ELL_3V_LEN(tmp1);
      ELL_3V_CROSS(tmp1, evec+0, evec+6); tmp2[1] = ELL_3V_LEN(tmp1);
      ELL_3V_CROSS(tmp1, evec+3, evec+6); tmp2[2] = ELL_3V_LEN(tmp1);
      fprintf(stderr, "%s: crosses = %g %g %g\n", me,
      tmp2[0], tmp2[1], tmp2[2]);
    */

    /* set transform (in mA) */
    ELL_3V_ABS(absEval, eval);
    ELL_4M_IDENTITY_SET(mA);                        /* reset */
    ELL_3V_SCALE(glyphScl, parm->glyphScale, absEval); /* scale by evals */
    ELL_4M_SCALE_SET(mB, glyphScl[0], glyphScl[1], glyphScl[2]);

    ell_4m_post_mul_d(mA, mB);
    ELL_43M_INSET(mB, rotEvec);                     /* rotate by evecs */
    ell_4m_post_mul_d(mA, mB);
    ELL_4M_TRANSLATE_SET(mB, pW[0], pW[1], pW[2]);  /* translate */
    ell_4m_post_mul_d(mA, mB);

    /* set color (in R,G,B) */
    cvec = evec + 3*(AIR_CLAMP(0, parm->colEvec, 2));
    R = AIR_ABS(cvec[0]);                           /* standard mapping */
    G = AIR_ABS(cvec[1]);
    B = AIR_ABS(cvec[2]);
    /* desaturate by colMaxSat */
    R = AIR_AFFINE(0.0, parm->colMaxSat, 1.0, parm->colIsoGray, R);
    G = AIR_AFFINE(0.0, parm->colMaxSat, 1.0, parm->colIsoGray, G);
    B = AIR_AFFINE(0.0, parm->colMaxSat, 1.0, parm->colIsoGray, B);
    /* desaturate some by anisotropy */
    R = AIR_AFFINE(0.0, parm->colAnisoModulate, 1.0,
                   R, AIR_AFFINE(0.0, glyphAniso, 1.0, parm->colIsoGray, R));
    G = AIR_AFFINE(0.0, parm->colAnisoModulate, 1.0,
                   G, AIR_AFFINE(0.0, glyphAniso, 1.0, parm->colIsoGray, G));
    B = AIR_AFFINE(0.0, parm->colAnisoModulate, 1.0,
                   B, AIR_AFFINE(0.0, glyphAniso, 1.0, parm->colIsoGray, B));
    /* clamp and do gamma */
    R = AIR_CLAMP(0.0, R, 1.0);
    G = AIR_CLAMP(0.0, G, 1.0);
    B = AIR_CLAMP(0.0, B, 1.0);
    R = pow(R, parm->colGamma);
    G = pow(G, parm->colGamma);
    B = pow(B, parm->colGamma);

    /* find axis, and superquad exponents qA and qB */
    if (eval[2] > 0) {
      /* all evals positive */
      cl = AIR_MIN(0.99, tenAnisoEval_f(eval, tenAniso_Cl1));
      cp = AIR_MIN(0.99, tenAnisoEval_f(eval, tenAniso_Cp1));
      if (cl > cp) {
        axis = 0;
        qA = pow(1-cp, parm->sqdSharp);
        qB = pow(1-cl, parm->sqdSharp);
      } else {
        axis = 2;
        qA = pow(1-cl, parm->sqdSharp);
        qB = pow(1-cp, parm->sqdSharp);
      }
      qC = qB;
    } else if (eval[0] < 0) {
      /* all evals negative */
      float aef[3];
      aef[0] = absEval[2];
      aef[1] = absEval[1];
      aef[2] = absEval[0];
      cl = AIR_MIN(0.99, tenAnisoEval_f(aef, tenAniso_Cl1));
      cp = AIR_MIN(0.99, tenAnisoEval_f(aef, tenAniso_Cp1));
      if (cl > cp) {
        axis = 2;
        qA = pow(1-cp, parm->sqdSharp);
        qB = pow(1-cl, parm->sqdSharp);
      } else {
        axis = 0;
        qA = pow(1-cl, parm->sqdSharp);
        qB = pow(1-cp, parm->sqdSharp);
      }
      qC = qB;
    } else {
#define OOSQRT2 0.70710678118654752440
#define OOSQRT3 0.57735026918962576451
      /* double poleA[3]={OOSQRT3, OOSQRT3, OOSQRT3}; */
      double poleB[3]={1, 0, 0};
      double poleC[3]={OOSQRT2, OOSQRT2, 0};
      double poleD[3]={OOSQRT3, -OOSQRT3, -OOSQRT3};
      double poleE[3]={OOSQRT2, 0, -OOSQRT2};
      double poleF[3]={OOSQRT3, OOSQRT3, -OOSQRT3};
      double poleG[3]={0, -OOSQRT2, -OOSQRT2};
      double poleH[3]={0, 0, -1};
      /* double poleI[3]={-OOSQRT3, -OOSQRT3, -OOSQRT3}; */
      double funk[3]={0,4,2}, thrn[3]={1,4,4};
      double octa[3]={0,2,2}, cone[3]={1,2,2};
      double evalN[3], tmp, bary[3];
      double qq[3];

      ELL_3V_NORM(evalN, eval, tmp);
      if (eval[1] >= -eval[2]) {
        /* inside B-F-C */
        ell_3v_barycentric_spherical_d(bary, poleB, poleF, poleC, evalN);
        ELL_3V_SCALE_ADD3(qq, bary[0], octa, bary[1], thrn, bary[2], cone);
        axis = 2;
      } else if (eval[0] >= -eval[2]) {
        /* inside B-D-F */
        if (eval[1] >= 0) {
          /* inside B-E-F */
          ell_3v_barycentric_spherical_d(bary, poleB, poleE, poleF, evalN);
          ELL_3V_SCALE_ADD3(qq, bary[0], octa, bary[1], funk, bary[2], thrn);
          axis = 2;
        } else {
          /* inside B-D-E */
          ell_3v_barycentric_spherical_d(bary, poleB, poleD, poleE, evalN);
          ELL_3V_SCALE_ADD3(qq, bary[0], cone, bary[1], thrn, bary[2], funk);
          axis = 0;
        }
      } else if (eval[0] < -eval[1]) {
        /* inside D-G-H */
        ell_3v_barycentric_spherical_d(bary, poleD, poleG, poleH, evalN);
        ELL_3V_SCALE_ADD3(qq, bary[0], thrn, bary[1], cone, bary[2], octa);
        axis = 0;
      } else if (eval[1] < 0) {
        /* inside E-D-H */
        ell_3v_barycentric_spherical_d(bary, poleE, poleD, poleH, evalN);
        ELL_3V_SCALE_ADD3(qq, bary[0], funk, bary[1], thrn, bary[2], octa);
        axis = 0;
      } else {
        /* inside F-E-H */
        ell_3v_barycentric_spherical_d(bary, poleF, poleE, poleH, evalN);
        ELL_3V_SCALE_ADD3(qq, bary[0], thrn, bary[1], funk, bary[2], cone);
        axis = 2;
      }
      qA = qq[0];
      qB = qq[1];
      qC = qq[2];
#undef OOSQRT2
#undef OOSQRT3
    }

    /* add the glyph */
    if (parm->verbose >= 2) {
      fprintf(stderr, "%s: glyph %d/%d: the glyph stays!\n",
              me, idx, numGlyphs);
    }
    if (glyphsLimn) {
      lookIdx = limnObjectLookAdd(glyphsLimn);
      look = glyphsLimn->look + lookIdx;
      ELL_4V_SET_TT(look->rgba, float, R, G, B, 1);
      ELL_3V_SET(look->kads, parm->ADSP[0], parm->ADSP[1], parm->ADSP[2]);
      look->spow = 0;
      switch(parm->glyphType) {
      case tenGlyphTypeBox:
        glyphIdx = limnObjectCubeAdd(glyphsLimn, lookIdx);
        break;
      case tenGlyphTypeSphere:
        glyphIdx = limnObjectPolarSphereAdd(glyphsLimn, lookIdx, axis,
                                            2*parm->facetRes, parm->facetRes);
        break;
      case tenGlyphTypeCylinder:
        glyphIdx = limnObjectCylinderAdd(glyphsLimn, lookIdx, axis,
                                         parm->facetRes);
        break;
      case tenGlyphTypeSuperquad:
      default:
        glyphIdx =
          limnObjectPolarSuperquadFancyAdd(glyphsLimn, lookIdx, axis,
                                           AIR_CAST(float, qA),
                                           AIR_CAST(float, qB),
                                           AIR_CAST(float, qC), 0,
                                           2*parm->facetRes,
                                           parm->facetRes);
        break;
      }
      ELL_4M_COPY_TT(mA_f, float, mA);
      limnObjectPartTransform(glyphsLimn, glyphIdx, mA_f);
    }
    if (glyphsEcho) {
      switch(parm->glyphType) {
      case tenGlyphTypeBox:
        eglyph = echoObjectNew(glyphsEcho, echoTypeCube);
        /* nothing else to set */
        break;
      case tenGlyphTypeSphere:
        eglyph = echoObjectNew(glyphsEcho, echoTypeSphere);
        echoSphereSet(eglyph, 0, 0, 0, 1);
        break;
      case tenGlyphTypeCylinder:
        eglyph = echoObjectNew(glyphsEcho, echoTypeCylinder);
        echoCylinderSet(eglyph, axis);
        break;
      case tenGlyphTypeSuperquad:
      default:
        eglyph = echoObjectNew(glyphsEcho, echoTypeSuperquad);
        echoSuperquadSet(eglyph, axis, qA, qB);
        break;
      }
      echoColorSet(eglyph,
                   AIR_CAST(echoCol_t, R),
                   AIR_CAST(echoCol_t, G),
                   AIR_CAST(echoCol_t, B), 1);
      echoMatterPhongSet(glyphsEcho, eglyph,
                         parm->ADSP[0], parm->ADSP[1],
                         parm->ADSP[2], parm->ADSP[3]);
      inst = echoObjectNew(glyphsEcho, echoTypeInstance);
      ELL_4M_COPY(eM, mA);
      echoInstanceSet(inst, eM, eglyph);
      echoListAdd(list, inst);
    }
  }
  if (glyphsLimn) {
    glyphsLimn->setVertexRGBAFromLook = svRGBAfl;
  }
  if (glyphsEcho) {
    split = echoListSplit3(glyphsEcho, list, 10);
    echoObjectAdd(glyphsEcho, split);
  }

  airMopOkay(mop);
  return 0;
}
Beispiel #17
0
int
main(int argc, char *argv[]) {
  char *me, *outS;
  hestOpt *hopt;
  hestParm *hparm;
  airArray *mop;

  char *err, done[13];
  Nrrd *nin, *nblur, *nout;
  NrrdKernelSpec *kb0, *kb1, *k00, *k11, *k22;
  NrrdResampleContext *rsmc;
  int E;
  unsigned int sx, sy, sz, xi, yi, zi, ai;
  gageContext *ctx;
  gagePerVolume *pvl;
  const double *gvec, *gmag, *evec0, *eval;
  double (*ins)(void *v, size_t I, double d);
  double (*lup)(const void *v, size_t I);
  double dotmax, dotpow, gmmax, evalshift, gmpow, _dotmax, _gmmax, scl, clamp;

  me = argv[0];
  mop = airMopNew();
  hparm = hestParmNew();
  hopt = NULL;
  airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways);
  hestOptAdd(&hopt, "i", "nin", airTypeOther, 1, 1, &nin, NULL,
             "input volume", NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "kb0", "kernel", airTypeOther, 1, 1, &kb0,
             "guass:3,5", "kernel to use for pre-process blurring",
             NULL, NULL, nrrdHestKernelSpec);
  hestOptAdd(&hopt, "kb1", "kernel", airTypeOther, 1, 1, &kb1,
             "cubic:1.5,1,0", "kernel to use for pos-process blurring",
             NULL, NULL, nrrdHestKernelSpec);
  hestOptAdd(&hopt, "k00", "kernel", airTypeOther, 1, 1, &k00,
             "cubic:1,0", "k00", NULL, NULL, nrrdHestKernelSpec);
  hestOptAdd(&hopt, "k11", "kernel", airTypeOther, 1, 1, &k11,
             "cubicd:1,0", "k00", NULL, NULL, nrrdHestKernelSpec);
  hestOptAdd(&hopt, "k22", "kernel", airTypeOther, 1, 1, &k22,
             "cubicdd:1,0", "k00", NULL, NULL, nrrdHestKernelSpec);
  hestOptAdd(&hopt, "dotmax", "dot", airTypeDouble, 1, 1, &dotmax, "5",
             "max effective value of dot(gvec, evec0)");
  hestOptAdd(&hopt, "evs", "shift", airTypeDouble, 1, 1, &evalshift, "0",
             "negative shift to avoid changing mostly flat regions");
  hestOptAdd(&hopt, "clamp", "clamp", airTypeDouble, 1, 1, &clamp, "nan",
             "if it exists, data value can't be forced below this");
  hestOptAdd(&hopt, "dotpow", "pow", airTypeDouble, 1, 1, &dotpow, "1",
             "exponent for dot");
  hestOptAdd(&hopt, "gmmax", "dot", airTypeDouble, 1, 1, &gmmax, "2",
             "max effective value of gmag");
  hestOptAdd(&hopt, "gmpow", "pow", airTypeDouble, 1, 1, &gmpow, "1",
             "exponent for gmag");
  hestOptAdd(&hopt, "scl", "scale", airTypeDouble, 1, 1, &scl, "0.1",
             "how much to scale hack to decrease input value");
  hestOptAdd(&hopt, "o", "filename", airTypeString, 1, 1, &outS, "-",
             "fixed volume output");
  hestParseOrDie(hopt, argc-1, argv+1, hparm,
                 me, vhInfo, AIR_TRUE, AIR_TRUE, AIR_TRUE);
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  if (!( 3 == nin->dim
         && nrrdTypeBlock != nin->type )) {
    fprintf(stderr, "%s: need a 3-D scalar nrrd (not %u-D %s)", me,
            nin->dim, airEnumStr(nrrdType, nin->type));
    airMopError(mop); return 1;
  }

  nblur = nrrdNew();
  airMopAdd(mop, nblur, (airMopper)nrrdNuke, airMopAlways);
  if (nrrdCopy(nblur, nin)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: couldn't allocate output:\n%s", me, err);
    airMopError(mop); return 1;
  }

  fprintf(stderr, "%s: pre-blurring ... ", me);
  fflush(stderr);
  rsmc = nrrdResampleContextNew();
  airMopAdd(mop, rsmc, (airMopper)nrrdResampleContextNix, airMopAlways);
  E = AIR_FALSE;
  if (!E) E |= nrrdResampleDefaultCenterSet(rsmc, nrrdCenterCell);
  if (!E) E |= nrrdResampleNrrdSet(rsmc, nin);
  for (ai=0; ai<3; ai++) {
    if (!E) E |= nrrdResampleKernelSet(rsmc, ai, kb0->kernel, kb0->parm);
    if (!E) E |= nrrdResampleSamplesSet(rsmc, ai, nin->axis[ai].size);
    if (!E) E |= nrrdResampleRangeFullSet(rsmc, ai);
  }
  if (!E) E |= nrrdResampleBoundarySet(rsmc, nrrdBoundaryBleed);
  if (!E) E |= nrrdResampleTypeOutSet(rsmc, nrrdTypeDefault);
  if (!E) E |= nrrdResampleRenormalizeSet(rsmc, AIR_TRUE);
  if (!E) E |= nrrdResampleExecute(rsmc, nblur);
  if (E) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: error resampling nrrd:\n%s", me, err);
    airMopError(mop);
    return 1;
  }
  fprintf(stderr, "done.\n");

  ctx = gageContextNew();
  airMopAdd(mop, ctx, (airMopper)gageContextNix, airMopAlways);
  gageParmSet(ctx, gageParmRenormalize, AIR_TRUE);
  gageParmSet(ctx, gageParmCheckIntegrals, AIR_TRUE);
  E = 0;
  if (!E) E |= !(pvl = gagePerVolumeNew(ctx, nblur, gageKindScl));
  if (!E) E |= gagePerVolumeAttach(ctx, pvl);
  if (!E) E |= gageKernelSet(ctx, gageKernel00, k00->kernel, k00->parm);
  if (!E) E |= gageKernelSet(ctx, gageKernel11, k11->kernel, k11->parm);
  if (!E) E |= gageKernelSet(ctx, gageKernel22, k22->kernel, k22->parm);
  if (!E) E |= gageQueryItemOn(ctx, pvl, gageSclGradVec);
  if (!E) E |= gageQueryItemOn(ctx, pvl, gageSclGradMag);
  if (!E) E |= gageQueryItemOn(ctx, pvl, gageSclHessEvec0);
  if (!E) E |= gageQueryItemOn(ctx, pvl, gageSclHessEval);
  if (!E) E |= gageUpdate(ctx);
  if (E) {
    airMopAdd(mop, err = biffGetDone(GAGE), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble:\n%s\n", me, err);
    airMopError(mop); return 1;
  }
  gvec = gageAnswerPointer(ctx, pvl, gageSclGradVec);
  gmag = gageAnswerPointer(ctx, pvl, gageSclGradMag);
  evec0 = gageAnswerPointer(ctx, pvl, gageSclHessEvec0);
  eval = gageAnswerPointer(ctx, pvl, gageSclHessEval);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
  if (nrrdCopy(nout, nin)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: couldn't allocate output:\n%s", me, err);
    airMopError(mop); return 1;
  }

  if (!(nout->type == nin->type && nblur->type == nin->type)) {
    fprintf(stderr, "%s: whoa, types (%s %s %s) not all equal\n", me,
            airEnumStr(nrrdType, nin->type),
            airEnumStr(nrrdType, nblur->type),
            airEnumStr(nrrdType, nout->type));
  }
  ins = nrrdDInsert[nout->type];
  lup = nrrdDLookup[nout->type];
  sx = nin->axis[0].size;
  sy = nin->axis[1].size;
  sz = nin->axis[2].size;

  gageProbe(ctx, 0, 0, 0);
  _dotmax = ELL_3V_DOT(gvec, evec0);
  _gmmax = *gmag;

  fprintf(stderr, "%s: hacking       ", me);
  fflush(stderr);
  for (zi=0; zi<sz; zi++) {
    fprintf(stderr, "%s", airDoneStr(0, zi, sz-1, done));
    fflush(stderr);
    for (yi=0; yi<sy; yi++) {
      for (xi=0; xi<sx; xi++) {
        size_t si;
        double dot, evl, gm, shift, in, out, mode;

        gageProbe(ctx, xi, yi, zi);
        si = xi + sx*(yi + sy*zi);

        dot = ELL_3V_DOT(gvec, evec0);
        _dotmax = AIR_MAX(_dotmax, dot);
        dot = AIR_ABS(dot);
        dot = 1 - AIR_MIN(dot, dotmax)/dotmax;
        dot = pow(dot, dotpow);

        evl = AIR_MAX(0, eval[0] - evalshift);
        mode = airMode3_d(eval);
        evl *= AIR_AFFINE(-1, mode, 1, 0, 1);

        _gmmax = AIR_MAX(_gmmax, *gmag);
        gm = 1 - AIR_MIN(*gmag, gmmax)/gmmax;
        gm = pow(gm, gmpow);

        shift = scl*gm*evl*dot;
        if (AIR_EXISTS(clamp)) {
          in = lup(nin->data, si);
          out = in - shift;
          out = AIR_MAX(out, clamp);
          shift = AIR_MAX(0, in - out);
        }

        ins(nout->data, si, shift);
      }
    }
  }
  fprintf(stderr, "\n");
  fprintf(stderr, "%s: max dot seen: %g\n", me, _dotmax);
  fprintf(stderr, "%s: max gm seen: %g\n", me, _gmmax);

  fprintf(stderr, "%s: post-blurring ... ", me);
  fflush(stderr);
  E = AIR_FALSE;
  if (!E) E |= nrrdResampleNrrdSet(rsmc, nout);
  for (ai=0; ai<3; ai++) {
    if (!E) E |= nrrdResampleKernelSet(rsmc, ai, kb1->kernel, kb1->parm);
    if (!E) E |= nrrdResampleSamplesSet(rsmc, ai, nout->axis[ai].size);
    if (!E) E |= nrrdResampleRangeFullSet(rsmc, ai);
  }
  if (!E) E |= nrrdResampleExecute(rsmc, nblur);
  if (E) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: error resampling nrrd:\n%s", me, err);
    airMopError(mop);
    return 1;
  }
  fprintf(stderr, "done.\n");

  for (zi=0; zi<sz; zi++) {
    for (yi=0; yi<sy; yi++) {
      for (xi=0; xi<sx; xi++) {
        size_t si;
        double in, shift;

        si = xi + sx*(yi + sy*zi);
        in = lup(nin->data, si);
        shift = lup(nblur->data, si);
        ins(nout->data, si, in - shift);
      }
    }
  }

  if (nrrdSave(outS, nout, NULL)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: couldn't save output:\n%s", me, err);
    airMopError(mop); return 1;
  }

  airMopOkay(mop);
  exit(0);
}
Beispiel #18
0
/*
******* ell_6ms_eigensolve_d
**
** uses Jacobi iterations to find eigensystem of 6x6 symmetric matrix,
** given in sym[21], to within convergence threshold eps.  Puts
** eigenvalues, in descending order, in eval[6], and corresponding
** eigenvectors in _evec+0, _evec+6, . . ., _evec+30.  NOTE: you can
** pass a NULL _evec if eigenvectors aren't needed.
**
** does NOT use biff
*/
int
ell_6ms_eigensolve_d(double eval[6], double _evec[36],
                     const double sym[21], const double eps) {
  /* char me[]="ell_6ms_eigensolve_d"; */
  double mat[2][6][6], evec[2][6][6], sumon, sumoff, evtmp[12];
  unsigned int cur, rrI, ccI, maxI[2], iter;

  if (!( eval && sym && eps >= 0 )) {
    return 1;
  }
  /* copy symmetric matrix sym[] into upper tris of mat[0][][] & mat[1][][] */
  mat[0][0][0] = sym[ 0];
  mat[0][0][1] = sym[ 1];
  mat[0][0][2] = sym[ 2];
  mat[0][0][3] = sym[ 3];
  mat[0][0][4] = sym[ 4];
  mat[0][0][5] = sym[ 5];
  mat[0][1][1] = sym[ 6];
  mat[0][1][2] = sym[ 7];
  mat[0][1][3] = sym[ 8];
  mat[0][1][4] = sym[ 9];
  mat[0][1][5] = sym[10];
  mat[0][2][2] = sym[11];
  mat[0][2][3] = sym[12];
  mat[0][2][4] = sym[13];
  mat[0][2][5] = sym[14];
  mat[0][3][3] = sym[15];
  mat[0][3][4] = sym[16];
  mat[0][3][5] = sym[17];
  mat[0][4][4] = sym[18];
  mat[0][4][5] = sym[19];
  mat[0][5][5] = sym[20];
  if (_evec) {
    /* initialize evec[0]; */
    for (rrI=0; rrI<6; rrI++) {
      for (ccI=0; ccI<6; ccI++) {
        evec[0][ccI][rrI] = (rrI == ccI);
      }
    }
  }
  /*
  fprintf(stderr, "!%s(INIT): m = [", me);
  for (rrI=0; rrI<6; rrI++) {
    for (ccI=0; ccI<6; ccI++) {
      fprintf(stderr, "%f%s",
              (rrI <= ccI ? mat[0][rrI][ccI] : mat[0][ccI][rrI]),
              ccI<5 ? "," : (rrI<5 ? ";" : "]"));
    }
    fprintf(stderr, "\n");
  }
  */
  maxI[0] = maxI[1] = UINT_MAX; /* quiet warnings about using maxI unset */
  _maxI_sum_find(maxI, &sumon, &sumoff, mat[0]);
  cur = 1;         /* fake out anticipating first line of loop */
  iter = 0;
  while (sumoff/sumon > eps) {
    double th, tt, cc, ss;
    const unsigned int P = maxI[0];
    const unsigned int Q = maxI[1];
    //make sure that P and Q are within the bounds for mat[2][6][6]
    if(P >=6 || Q >= 6){  
      break;
    }
    /*
    fprintf(stderr, "!%s(%u): sumoff/sumon = %g/%g = %g > %g\n", me, iter,
            sumoff, sumon, sumoff/sumon, eps);
    */
    cur = 1 - cur;

    th = (mat[cur][Q][Q] - mat[cur][P][P])/(2*mat[cur][P][Q]);
    tt = (th > 0 ? +1 : -1)/(AIR_ABS(th) + sqrt(th*th + 1));
    cc = 1/sqrt(tt*tt + 1);
    ss = cc*tt;
    /*
    fprintf(stderr, "!%s(%u): maxI = (P,Q) = (%u,%u) --> ss=%f, cc=%f\n",
            me, iter, P, Q, ss, cc);
    fprintf(stderr, "     r = [");
    for (rrI=0; rrI<6; rrI++) {
      for (ccI=0; ccI<6; ccI++) {
        fprintf(stderr, "%g%s",
                (rrI == ccI
                 ? (rrI == P || rrI == Q ? cc : 1.0)
                 : (rrI == P && ccI == Q
                    ? ss
                    : (rrI == Q && ccI == P
                       ? -ss
                       : 0))),
                ccI<5 ? "," : (rrI<5 ? ";" : "]"));
      }
      fprintf(stderr, "\n");
    }
    */
    /* initialize by copying whole matrix */
    for (rrI=0; rrI<6; rrI++) {
      for (ccI=rrI; ccI<6; ccI++) {
        mat[1-cur][rrI][ccI] = mat[cur][rrI][ccI];
      }
    }
    /* perform Jacobi rotation */
    for (rrI=0; rrI<P; rrI++) {
      mat[1-cur][rrI][P] = cc*mat[cur][rrI][P] - ss*mat[cur][rrI][Q];
    }
    for (ccI=P+1; ccI<6; ccI++) {
      mat[1-cur][P][ccI] = cc*mat[cur][P][ccI] - ss*(Q <= ccI
                                                     ? mat[cur][Q][ccI]
                                                     : mat[cur][ccI][Q]);
    }
    for (rrI=0; rrI<Q; rrI++) {
      mat[1-cur][rrI][Q] = ss*(rrI <= P
                               ? mat[cur][rrI][P]
                               : mat[cur][P][rrI]) + cc*mat[cur][rrI][Q];
    }
    for (ccI=Q+1; ccI<6; ccI++) {
      mat[1-cur][Q][ccI] = ss*mat[cur][P][ccI] + cc*mat[cur][Q][ccI];
    }
    /* set special entries */
    mat[1-cur][P][P] = mat[cur][P][P] - tt*mat[cur][P][Q];
    mat[1-cur][Q][Q] = mat[cur][Q][Q] + tt*mat[cur][P][Q];
    mat[1-cur][P][Q] = 0.0;
    if (_evec) {
      /* NOTE: the eigenvectors use transpose of indexing of mat */
      /* start by copying all */
      for (rrI=0; rrI<6; rrI++) {
        for (ccI=0; ccI<6; ccI++) {
          evec[1-cur][ccI][rrI] = evec[cur][ccI][rrI];
        }
      }
      for (rrI=0; rrI<6; rrI++) {
        evec[1-cur][P][rrI] = cc*evec[cur][P][rrI] - ss*evec[cur][Q][rrI];
        evec[1-cur][Q][rrI] = ss*evec[cur][P][rrI] + cc*evec[cur][Q][rrI];
      }
    }

    _maxI_sum_find(maxI, &sumon, &sumoff, mat[1-cur]);

    /*
    fprintf(stderr, "!%s(%u): m = [", me, iter);
    for (rrI=0; rrI<6; rrI++) {
      for (ccI=0; ccI<6; ccI++) {
        fprintf(stderr, "%f%s",
                (rrI <= ccI ? mat[1-cur][rrI][ccI] : mat[1-cur][ccI][rrI]),
                ccI<5 ? "," : (rrI<5 ? ";" : "]"));
      }
      fprintf(stderr, "\n");
    }
    */
    iter++;
  }
  /* 1-cur is index of final solution */

  /* sort evals */
  for (ccI=0; ccI<6; ccI++) {
    evtmp[0 + 2*ccI] = mat[1-cur][ccI][ccI];
    evtmp[1 + 2*ccI] = ccI;
  }
  qsort(evtmp, 6, 2*sizeof(double), _compar);

  /* copy out solution */
  for (ccI=0; ccI<6; ccI++) {
    eval[ccI] = evtmp[0 + 2*ccI];
    if (_evec) {
      unsigned eeI;
      for (rrI=0; rrI<6; rrI++) {
        eeI = AIR_CAST(unsigned int, evtmp[1 + 2*ccI]);
        _evec[rrI + 6*ccI] = evec[1-cur][eeI][rrI];
      }
    }
  }

  return 0;
}
Beispiel #19
0
static int
constraintSatHght(pullTask *task, pullPoint *point,
                  int tang1Use, int tang2Use,
                  int negtang1Use, int negtang2Use,
                  double stepMax, unsigned int iterMax,
                  int *constrFailP) {
  static const char me[]="constraintSatHght";
  double val, grad[3], hess[9], posproj[9], negproj[9],
    state[1+3+9+9+9+3], hack, step,
    d1, d2, pdir[3], plen, pgrad[3];
#if PRAYING
  double _tmpv[3]={0,0,0};
#endif
  int havePos, haveNeg, haveNada;
  unsigned int iter = 0;  /* 0: initial probe, 1..iterMax: probes in loop */
  /* http://en.wikipedia.org/wiki/Newton%27s_method_in_optimization */

  havePos = tang1Use || tang2Use;
  haveNeg = negtang1Use || negtang2Use;
  haveNada = !havePos && !haveNeg;
#if PRAYING
  {
    double stpmin;
    /* HEY: shouldn't stpmin also be used later in this function? */
    stpmin = task->pctx->voxelSizeSpace*task->pctx->sysParm.constraintStepMin;
    fprintf(stderr, "!%s(%u): starting at %g %g %g %g\n", me, point->idtag,
            point->pos[0], point->pos[1], point->pos[2], point->pos[3]);
    fprintf(stderr, "!%s: pt %d %d nt %d %d (nada %d) "
            "stepMax %g, iterMax %u\n", me,
            tang1Use, tang2Use, negtang1Use, negtang2Use, haveNada,
            stepMax, iterMax);
    fprintf(stderr, "!%s: stpmin = %g = voxsize %g * parm.stepmin %g\n", me,
            stpmin, task->pctx->voxelSizeSpace,
            task->pctx->sysParm.constraintStepMin);
  }
#endif
  _pullPointHistAdd(point, pullCondOld);
  PROBE(val, grad, hess, posproj, negproj);
#if PRAYING
  PRINT("initial probe");
#endif
  SAVE(state, val, grad, hess, posproj, negproj, point->pos);
  hack = 1;
  for (iter=1; iter<=iterMax; iter++) {
#if PRAYING
    fprintf(stderr, "!%s: =============== begin iter %u\n", me, iter);
#endif
    /* HEY: no opportunistic increase of hack? */
    if (havePos || haveNada) {
      POSNORM(d1, d2, pdir, plen, pgrad, grad, hess, posproj);
      if (!plen) {
        /* this use to be a biff error, which got to be annoying */
        *constrFailP = pullConstraintFailProjGradZeroA;
        return 0;
      }
      step = (d2 <= 0 ? -plen : -d1/d2);
#if PRAYING
      fprintf(stderr, "!%s: (+) iter %u step = (%g <= 0 ? %g : %g) --> %g\n",
              me, iter, d2, -plen, -d1/d2, step);
#endif
      step = step > 0 ? AIR_MIN(stepMax, step) : AIR_MAX(-stepMax, step);
      if (AIR_ABS(step) < stepMax*task->pctx->sysParm.constraintStepMin) {
        /* no further iteration needed; we're converged */
#if PRAYING
        fprintf(stderr, "     |step| %g < %g*%g = %g ==> converged!\n",
                AIR_ABS(step),
                stepMax, task->pctx->sysParm.constraintStepMin,
                stepMax*task->pctx->sysParm.constraintStepMin);
#endif
        if (!haveNeg) {
          break;
        } else {
          goto nextstep;
        }
      }
      /* else we have to take a significant step */
#if PRAYING
      fprintf(stderr, "       -> step %g, |pdir| = %g\n",
              step, ELL_3V_LEN(pdir));
      ELL_3V_COPY(_tmpv, point->pos);
      fprintf(stderr, "       ->  pos (%g,%g,%g,%g) += %g * %g * (%g,%g,%g)\n",
              point->pos[0], point->pos[1], point->pos[2], point->pos[3],
              hack, step, pdir[0], pdir[1], pdir[2]);
#endif
      ELL_3V_SCALE_INCR(point->pos, hack*step, pdir);
#if PRAYING
      ELL_3V_SUB(_tmpv, _tmpv, point->pos);
      fprintf(stderr, "       -> moved to %g %g %g %g\n",
              point->pos[0], point->pos[1], point->pos[2], point->pos[3]);
      fprintf(stderr, "       (moved %g)\n", ELL_3V_LEN(_tmpv));
#endif
      _pullPointHistAdd(point, pullCondConstraintSatA);
      PROBE(val, grad, hess, posproj, negproj);
#if PRAYING
      fprintf(stderr, "  (+) probed at (%g,%g,%g,%g)\n",
              point->pos[0], point->pos[1], point->pos[2], point->pos[3]);
      PRINT("after move");
      fprintf(stderr, "  val(%g,%g,%g,%g)=%g %s state[0]=%g\n",
              point->pos[0], point->pos[1], point->pos[2], point->pos[3],
              val, val <= state[0] ? "<=" : ">", state[0]);
#endif
      if (val <= state[0]) {
        /* we made progress */
#if PRAYING
        fprintf(stderr, "  (+) progress!\n");
#endif
        SAVE(state, val, grad, hess, posproj, negproj, point->pos);
        hack = 1;
      } else {
        /* oops, we went uphill instead of down; try again */
#if PRAYING
        fprintf(stderr, "  val *increased*; backing hack from %g to %g\n",
                hack, hack*task->pctx->sysParm.backStepScale);
#endif
        hack *= task->pctx->sysParm.backStepScale;
        RESTORE(val, grad, hess, posproj, negproj, point->pos, state);
#if PRAYING
        fprintf(stderr, "  restored to pos (%g,%g,%g,%g)\n",
                point->pos[0], point->pos[1], point->pos[2], point->pos[3]);
#endif
      }
    }
  nextstep:
    if (haveNeg) {
      /* HEY: copy and paste from above, minus fluff */
      NEGNORM(d1, d2, pdir, plen, pgrad, grad, hess, negproj);
      if (!plen && !haveNeg) {
        /* this use to be a biff error, which got to be annoying */
        *constrFailP = pullConstraintFailProjGradZeroA;
        return 0;
      }
      step = (d2 <= 0 ? -plen : -d1/d2);
#if PRAYING
      fprintf(stderr, "!%s: -+) iter %u step = (%g <= 0 ? %g : %g) --> %g\n",
              me, iter, d2, -plen, -d1/d2, step);
#endif
      step = step > 0 ? AIR_MIN(stepMax, step) : AIR_MAX(-stepMax, step);
      if (AIR_ABS(step) < stepMax*task->pctx->sysParm.constraintStepMin) {
#if PRAYING
        fprintf(stderr, "     |step| %g < %g*%g = %g ==> converged!\n",
                AIR_ABS(step),
                stepMax, task->pctx->sysParm.constraintStepMin,
                stepMax*task->pctx->sysParm.constraintStepMin);
#endif
        /* no further iteration needed; we're converged */
        break;
      }
      /* else we have to take a significant step */
#if PRAYING
      fprintf(stderr, "       -> step %g, |pdir| = %g\n",
              step, ELL_3V_LEN(pdir));
      ELL_3V_COPY(_tmpv, point->pos);
      fprintf(stderr, "       ->  pos (%g,%g,%g,%g) += %g * %g * (%g,%g,%g)\n",
              point->pos[0], point->pos[1], point->pos[2], point->pos[3],
              hack, step, pdir[0], pdir[1], pdir[2]);
#endif
      ELL_3V_SCALE_INCR(point->pos, hack*step, pdir);
#if PRAYING
      ELL_3V_SUB(_tmpv, _tmpv, point->pos);
      fprintf(stderr, "       -> moved to %g %g %g %g\n",
              point->pos[0], point->pos[1], point->pos[2], point->pos[3]);
      fprintf(stderr, "       (moved %g)\n", ELL_3V_LEN(_tmpv));
#endif
      _pullPointHistAdd(point, pullCondConstraintSatA);
      PROBE(val, grad, hess, posproj, negproj);
#if PRAYING
      fprintf(stderr, "  (-) probed at (%g,%g,%g,%g)\n",
              point->pos[0], point->pos[1], point->pos[2], point->pos[3]);
      PRINT("after move");
      fprintf(stderr, "  val(%g,%g,%g,%g)=%g %s state[0]=%g\n",
              point->pos[0], point->pos[1], point->pos[2], point->pos[3],
              val, val >= state[0] ? ">=" : "<", state[0]);
#endif
      if (val >= state[0]) {
        /* we made progress */
#if PRAYING
        fprintf(stderr, "  (-) progress!\n");
#endif
        SAVE(state, val, grad, hess, posproj, negproj, point->pos);
        hack = 1;
      } else {
        /* oops, we went uphill instead of down; try again */
#if PRAYING
        fprintf(stderr, "  val *increased*; backing hack from %g to %g\n",
                hack, hack*task->pctx->sysParm.backStepScale);
#endif
        hack *= task->pctx->sysParm.backStepScale;
        RESTORE(val, grad, hess, posproj, negproj, point->pos, state);
#if PRAYING
        fprintf(stderr, "  restored to pos (%g,%g,%g,%g)\n",
                point->pos[0], point->pos[1], point->pos[2], point->pos[3]);
#endif
      }
    }
  }
  if (iter > iterMax) {
    *constrFailP = pullConstraintFailIterMaxed;
  } else {
    *constrFailP = AIR_FALSE;
  }
  /*
  printf("!%s: %d %s\n", me, *constrFailP,
         *constrFailP ? "FAILED!" : "ok");
          */
  return 0;
}
Beispiel #20
0
static int
constraintSatLapl(pullTask *task, pullPoint *point,
                  double stepMax, unsigned int iterMax,
                  /* output */
                  int *constrFailP) {
  static const char me[]="constraintSatLapl";
  double
    step,         /* current step size */
    valLast, val, /* last and current function values */
    grad[4], dir[3], len,
    posOld[3], posNew[3], tmpv[3];
  double a=0, b=1, s, fa, fb, fs, tmp, diff;
  int side = 0;
  unsigned int iter = 0;  /* 0: initial probe, 1..iterMax: probes in loop */

  step = stepMax/2;
  PROBEG(val, grad);
  if (0 == val) {
    /* already exactly at the zero, we're done. This actually happens! */
    /* printf("!%s: a lapl == 0!\n", me); */
    return 0;
  }
  valLast = val;
  NORMALIZE(dir, grad, len);
  /* first phase: follow normalized gradient until laplacian sign change */
  for (iter=1; iter<=iterMax; iter++) {
    double sgn;
    ELL_3V_COPY(posOld, point->pos);
    sgn = airSgn(val); /* lapl < 0 => downhill; lapl > 0 => uphill */
    ELL_3V_SCALE_INCR(point->pos, sgn*step, dir);
    _pullPointHistAdd(point, pullCondConstraintSatA);
    PROBEG(val, grad);
    if (val*valLast < 0) {
      /* laplacian has changed sign; stop looking */
      break;
    }
    valLast = val;
    NORMALIZE(dir, grad, len);
  }
  if (iter > iterMax) {
    *constrFailP = pullConstraintFailIterMaxed;
    return 0;
  }
  /* second phase: find the zero-crossing, looking between
     f(posOld)=valLast and f(posNew)=val */
  ELL_3V_COPY(posNew, point->pos);
  ELL_3V_SUB(tmpv, posNew, posOld);
  len = ELL_3V_LEN(tmpv);
  fa = valLast;
  fb = val;
  if (AIR_ABS(fa) < AIR_ABS(fb)) {
    ELL_SWAP2(a, b, tmp); ELL_SWAP2(fa, fb, tmp);
  }
  for (iter=1; iter<=iterMax; iter++) {
    s = AIR_AFFINE(fa, 0, fb, a, b);
    ELL_3V_LERP(point->pos, s, posOld, posNew);
    _pullPointHistAdd(point, pullCondConstraintSatB);
    PROBE(fs);
    if (0 == fs) {
      /* exactly nailed the zero, we're done. This actually happens! */
      printf("!%s: b lapl == 0!\n", me);
      break;
    }
    /* "Illinois" false-position. Dumb, but it works. */
    if (fs*fb > 0) { /* not between s and b */
      b = s;
      fb = fs;
      if (+1 == side) {
        fa /= 2;
      }
      side = +1;
    } else { /* not between a and s */
      a = s;
      fa = fs;
      if (-1 == side) {
        fb /= 2;
      }
      side = -1;
    }
    diff = (b - a)*len;
    if (AIR_ABS(diff) < stepMax*task->pctx->sysParm.constraintStepMin) {
      /* converged! */
      break;
    }
  }
  if (iter > iterMax) {
    *constrFailP = pullConstraintFailIterMaxed;
  } else {
    *constrFailP = AIR_FALSE;
  }
  return 0;
}
Beispiel #21
0
double
miteSample(miteThread *mtt, miteRender *mrr, miteUser *muu,
           int num, double rayT, int inside,
           double samplePosWorld[3],
           double samplePosIndex[3]) {
  static const char me[]="miteSample";
  mite_t R, G, B, A;
  double *NN;
  double NdotV, kn[3], knd[3], ref[3], len, *dbg=NULL;

  if (!inside) {
    return mtt->rayStep;
  }

  if (mtt->skip) {
    /* we have one verbose pixel, but we're not on it */
    return 0.0;
  }

  /* early ray termination */
  if (1-mtt->TT >= muu->opacNear1) {
    mtt->TT = 0.0;
    return 0.0;
  }

  /* set (fake) view based on fake from */
  if (AIR_EXISTS(muu->fakeFrom[0])) {
    ELL_3V_SUB(mtt->V, samplePosWorld, muu->fakeFrom);
    ELL_3V_NORM(mtt->V, mtt->V, len);
  }

  /* do probing at this location to determine values of everything
     that might appear in the txf domain */
  if (gageProbe(mtt->gctx,
                samplePosIndex[0],
                samplePosIndex[1],
                samplePosIndex[2])) {
    biffAddf(MITE, "%s: gage trouble: %s (%d)", me,
             mtt->gctx->errStr, mtt->gctx->errNum);
    return AIR_NAN;
  }

  if (mrr->queryMiteNonzero) {
    /* There is some optimal trade-off between slowing things down
       with too many branches on all possible checks of queryMite,
       and slowing things down with doing the work of setting them all.
       This code has not been profiled whatsoever */
    mtt->directAnsMiteVal[miteValXw][0] = samplePosWorld[0];
    mtt->directAnsMiteVal[miteValXi][0] = samplePosIndex[0];
    mtt->directAnsMiteVal[miteValYw][0] = samplePosWorld[1];
    mtt->directAnsMiteVal[miteValYi][0] = samplePosIndex[1];
    mtt->directAnsMiteVal[miteValZw][0] = samplePosWorld[2];
    mtt->directAnsMiteVal[miteValZi][0] = samplePosIndex[2];
    mtt->directAnsMiteVal[miteValRw][0] = ELL_3V_LEN(samplePosWorld);
    mtt->directAnsMiteVal[miteValRi][0] = ELL_3V_LEN(samplePosIndex);
    mtt->directAnsMiteVal[miteValTw][0] = rayT;
    mtt->directAnsMiteVal[miteValTi][0] = num;
    ELL_3V_COPY(mtt->directAnsMiteVal[miteValView], mtt->V);
    NN = mtt->directAnsMiteVal[miteValNormal];
    if (mtt->_normal) {
      if (1 == muu->normalSide) {
        ELL_3V_SCALE(NN, -1, mtt->_normal);
      } else {
        ELL_3V_COPY(NN, mtt->_normal);
      }
    }

    if ((GAGE_QUERY_ITEM_TEST(mrr->queryMite, miteValNdotV)
         || GAGE_QUERY_ITEM_TEST(mrr->queryMite, miteValNdotL)
         || GAGE_QUERY_ITEM_TEST(mrr->queryMite, miteValVrefN))) {
      mtt->directAnsMiteVal[miteValNdotV][0] = ELL_3V_DOT(NN, mtt->V);
      mtt->directAnsMiteVal[miteValNdotL][0] =
        ELL_3V_DOT(NN, muu->lit->dir[0]);
      if (!muu->normalSide) {
        mtt->directAnsMiteVal[miteValNdotV][0] =
          AIR_ABS(mtt->directAnsMiteVal[miteValNdotV][0]);
        mtt->directAnsMiteVal[miteValNdotL][0] =
          AIR_ABS(mtt->directAnsMiteVal[miteValNdotL][0]);
      }
      NdotV = mtt->directAnsMiteVal[miteValNdotV][0];
      ELL_3V_SCALE_ADD2(ref, 2*NdotV, NN, -1, mtt->V);
      ELL_3V_NORM(mtt->directAnsMiteVal[miteValVrefN], ref, len);
    }

    if (GAGE_QUERY_ITEM_TEST(mrr->queryMite, miteValGTdotV)) {
      ELL_3MV_MUL(kn, mtt->nPerp, mtt->V);
      ELL_3V_NORM(kn, kn, len);
      ELL_3MV_MUL(knd, mtt->geomTens, kn);
      mtt->directAnsMiteVal[miteValGTdotV][0] = ELL_3V_DOT(knd, kn);
    }
  }


  /* initialize txf range quantities, and apply all txfs */
  if (mtt->verbose) {
    muu->debugIdx = airArrayLenIncr(muu->debugArr, muu->ndebug->axis[0].size);
  }

  memcpy(mtt->range, muu->rangeInit, MITE_RANGE_NUM*sizeof(mite_t));
  _miteStageRun(mtt, muu);

  /* if there's opacity, do shading and compositing */
  if (mtt->range[miteRangeAlpha]) {
    /* fprintf(stderr, "%s: mtt->TT = %g\n", me, mtt->TT); */
    /*
    if (mtt->verbose) {
      fprintf(stderr, "%s: before compositing: RGBT = %g,%g,%g,%g\n",
              me, mtt->RR, mtt->GG, mtt->BB, mtt->TT);
    }
    */
    _miteRGBACalc(&R, &G, &B, &A, mtt, mrr, muu);
    mtt->RR += mtt->TT*A*R;
    mtt->GG += mtt->TT*A*G;
    mtt->BB += mtt->TT*A*B;
    mtt->TT *= 1-A;
    /*
    if (mtt->verbose) {
      fprintf(stderr, "%s: after compositing: RGBT = %g,%g,%g,%g\n",
              me, mtt->RR, mtt->GG, mtt->BB, mtt->TT);
    }
    */
    /* fprintf(stderr, "%s: mtt->TT = %g\n", me, mtt->TT); */
  } else {
    R = G = B = A = 0;
  }
  if (mtt->verbose) {
    dbg = muu->debug + muu->debugIdx;
    dbg[0 + 2*mtt->stageNum] = R;
    dbg[1 + 2*mtt->stageNum] = G;
    dbg[2 + 2*mtt->stageNum] = B;
    dbg[3 + 2*mtt->stageNum] = A;
    dbg[4 + 2*mtt->stageNum] = rayT;
  }

  /* set Z if it hasn't been set already */
  if (1-mtt->TT >= muu->opacMatters && !AIR_EXISTS(mtt->ZZ)) {
    mtt->ZZ = rayT;
  }

  /* this is used to index mtt->debug */
  mtt->raySample += 1;

  return mtt->rayStep;
}
int
_echoRayIntx_Superquad(RAYINTX_ARGS(Superquad)) {
  char me[]="_echoRayIntx_Superquad";
  echoPos_t TT=0, Tmin, Tmax, t0, t1, t2, t3, v1, v2, diff, tol,
    saveTmin, Vmin, Vmax, VV=0, dV, dVmin, dVmax, tmp,
    (*v)(echoPos_t, echoPos_t, echoPos_t,
         echoPos_t, echoPos_t),
    (*vg)(echoPos_t[3],
          echoPos_t, echoPos_t, echoPos_t,
          echoPos_t, echoPos_t),
    (*lvg)(echoPos_t[3],
           echoPos_t, echoPos_t, echoPos_t,
           echoPos_t, echoPos_t),
    from[3], grad[3], pos[3];  /* these two used only by macros */
  int iter;
  
  if (!_echoRayIntx_CubeSolid(&Tmin, &Tmax,
                              -1-2*ECHO_EPSILON, 1+2*ECHO_EPSILON,
                              -1-2*ECHO_EPSILON, 1+2*ECHO_EPSILON,
                              -1-2*ECHO_EPSILON, 1+2*ECHO_EPSILON, ray)) {
    return AIR_FALSE;
  }
  switch(obj->axis) {
    case 0:
      v = _echo_SuperquadX_v;
      vg = _echo_SuperquadX_vg;
      lvg = _echo_SuperquadX_lvg;
      break;
    case 1:
      v = _echo_SuperquadY_v;
      vg = _echo_SuperquadY_vg;
      lvg = _echo_SuperquadY_lvg;
      break;
    case 2: default:
      v = _echo_SuperquadZ_v;
      vg = _echo_SuperquadZ_vg;
      lvg = _echo_SuperquadZ_lvg;
      break;
  }
  if (tstate->verbose) {
    fprintf(stderr, "%s%s: Tmin, Tmax = %g, %g, ax = %d\n",
            _echoDot(tstate->depth), me, Tmin, Tmax, obj->axis);
  }

#define VAL(TT)                               \
  (ELL_3V_SCALE_ADD2(pos, 1, from, (TT), ray->dir),  \
   v(pos[0], pos[1], pos[2], obj->A, obj->B))

#define VALGRAD(VV, DV, TT)                                \
  ELL_3V_SCALE_ADD2(pos, 1, from, (TT), ray->dir);                \
  (VV) = vg(grad, pos[0], pos[1], pos[2], obj->A, obj->B); \
  (DV) = ELL_3V_DOT(grad, ray->dir)

#define LVALGRAD(VV, DV, TT)                                \
  ELL_3V_SCALE_ADD2(pos, 1, from, (TT), ray->dir);                 \
  (VV) = lvg(grad, pos[0], pos[1], pos[2], obj->A, obj->B); \
  (DV) = ELL_3V_DOT(grad, ray->dir)

#define RR 0.61803399
#define CC (1.0-RR)
#define SHIFT3(a,b,c,d) (a)=(b); (b)=(c); (c)=(d)
#define SHIFT2(a,b,c)   (a)=(b); (b)=(c)

  /* testing */
  ELL_3V_SCALE_ADD2(from, 1, ray->from, Tmin, ray->dir);
  saveTmin = Tmin;
  Tmin = 0;
  Tmax -= saveTmin;
  /*
  ELL_3V_COPY(from, ray->from);
  saveTmin = 0;
  */

  /* evaluate value and derivatives at Tmin and Tmax */
  VALGRAD(Vmin, dVmin, Tmin);
  VALGRAD(Vmax, dVmax, Tmax);

  /* if the segment start and end are both positive or both negative,
     and if the derivatives also don't change sign, there's no root.
     Also, due to convexity, if values at start and end are negative,
     then there is no root */
  if ( (Vmin*Vmax >= 0 && dVmin*dVmax >= 0) 
       || (Vmin <= 0 && Vmax <= 0) ) {
    return AIR_FALSE;
  }
  if (tstate->verbose) {
    fprintf(stderr, "%s%s: dVmin = %g, dVmax = %g, Vmin = %g, Vmax = %g\n",
            _echoDot(tstate->depth), me, dVmin, dVmax, Vmin, Vmax);
  }

  /* either the value changed sign, or the derivative changed sign, or
     both.  If, as is common, the derivatives changed sign, but the
     values didn't (which means they are both positive, due to a test
     above), we need to limit the interval by minimizing the value
     until either we see a negative value, or until the minimization
     converged.  Based on Golden Section Search, NR pg.401 */
  if (dVmin*dVmax < 0 && Vmin*Vmax >= 0) {
    t0 = Tmin;
    t1 = RR*Tmin + CC*Tmax;
    t2 = CC*Tmin + RR*Tmax;
    t3 = Tmax;
    v1 = VAL(t1);
    v2 = VAL(t2);
    if (tstate->verbose) {
      fprintf(stderr, "%s%s: \n"
              "     t0 = % 31.15f\n"
              "     t1 = % 31.15f  -> v1 = % 31.15f\n"
              "     t2 = % 31.15f  -> v2 = % 31.15f\n"
              "     t3 = % 31.15f\n",
              _echoDot(tstate->depth), me,
              t0, t1, v1, t2, v2, t3);
    }
    tol = sqrt(ECHO_POS_EPS);
    while ( (t3-t0 > tol*(t1+t2))         /* still haven't converged */
            && (v1 > 0 && v2 > 0) ) {     /* v1 and v2 both positive */
      diff = v2 - v1;
      if (v1 < v2) {
        SHIFT3(t3, t2, t1, CC*t0 + RR*t2);
        SHIFT2(v2, v1, VAL(t1));
      } else {
        SHIFT3(t0, t1, t2, RR*t1 + CC*t3);
        SHIFT2(v1, v2, VAL(t2));
      }
      if (tstate->verbose) {
        fprintf(stderr, "%s%s: %s ---> \n"
                "     t0 = % 31.15f\n"
                "     t1 = % 31.15f  -> v1 = % 31.15f\n"
                "     t2 = % 31.15f  -> v2 = % 31.15f\n"
                "     t3 = % 31.15f\n",
                _echoDot(tstate->depth), me,
                diff > 0 ? "v1 < v2" : "v1 > v2",
                t0, t1, v1, t2, v2, t3);
      }
    }
    if (v1 > 0 && v2 > 0) {
      /* the minimization stopped, yet both v1 and v2 are still positive,
         so there's no way we can have a root */
      if (tstate->verbose) {
        fprintf(stderr, "%s%s: minimization found no root\n",
                _echoDot(tstate->depth), me);
      }
      return AIR_FALSE;
    }
    /* else either v1 or v2 <= 0, so there is a root (actually two).
       By construction, f(t0) is positive, so we can now bracket the
       root between t0 and t1 or t2, whichever one is associated with
       a smaller value */
    Tmin = t0;
    Tmax = v1 < v2 ? t1 : t2;  /* HEY: shouldn't I just be using whichever one is closer? */
    Vmin = VAL(Tmin);
    Vmax = VAL(Tmax);
  }

  /* the value isn't necessarily monotonic between Tmin and Tmax, but
     we know that there is only one root. Find it with newton-raphson,
     using the log of function, both for values and for derivatives */
  iter = 0;
  TT = (Tmin + Tmax)/2;
  LVALGRAD(VV, dV, TT);

  while (iter < parm->sqNRI && AIR_ABS(VV) > parm->sqTol
         && AIR_EXISTS(VV) && AIR_EXISTS(dV)) {
    if (tstate->verbose) {
      fprintf(stderr, "%s%s: iter = %d: TT = %g, VV = %g, dV = %g\n",
              _echoDot(tstate->depth), me, iter, TT, VV, dV);
    }
    TT -= VV/dV;
    if (!AIR_IN_OP(Tmin, TT, Tmax)) {
      /* newton-raphson sent us flying out of bounds; find a tighter
         [Tmin,Tmax] bracket with bisection and try again */
      TT = (Tmin + Tmax)/2;
      VV = VAL(TT);
      if (Vmin*VV < 0) {
        Tmax = TT;
        Vmax = VV;
      } else {
        Tmin = TT;
        Vmin = VV;
      }
      TT = (Tmin + Tmax)/2;
    }
    LVALGRAD(VV, dV, TT);
    iter++;
  }

  if (!( AIR_EXISTS(VV) && AIR_EXISTS(dV) )) {
    /* we bailed out of the loop above because
       we got screwed by numerical errors
       --> pretend that there was no intersection,
       and HEY this will have to be debugged later */
    return AIR_FALSE;
  }

  /* else we succeedded in finding the intersection */
  intx->t = TT + saveTmin;
  VALGRAD(VV, dV, TT);   /* puts gradient into grad */
  ELL_3V_NORM(intx->norm, grad, tmp);
  intx->obj = OBJECT(obj);
  /* set in intx:
     yes: t, norm
     no: u, v
  */
  return AIR_TRUE;
}
Beispiel #23
0
int
baneGkms_txfMain(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *perr, err[BIFF_STRLEN];
  Nrrd *nout;
  airArray *mop;
  int pret, E, res[2], vi, gi, step;
  float min[2], max[2], top[2], v0, g0, *data, v, g,
    gwidth, width, mwidth, 
    tvl, tvr, vl, vr, tmp, maxa;

  hestOptAdd(&opt, "r", "Vres Gres", airTypeInt, 2, 2, res, "256 256",
             "resolution of the transfer function in value and gradient "
             "magnitude");
  hestOptAdd(&opt, "min", "Vmin Gmin", airTypeFloat, 2, 2, min, "0.0 0.0",
             "minimum value and grad mag in txf");
  hestOptAdd(&opt, "max", "Vmax Gmax", airTypeFloat, 2, 2, max, NULL,
             "maximum value and grad mag in txf");
  hestOptAdd(&opt, "v", "base value", airTypeFloat, 1, 1, &v0, NULL,
             "data value at which to position bottom of triangle");
  hestOptAdd(&opt, "g", "gthresh", airTypeFloat, 1, 1, &g0, "0.0",
             "lowest grad mag to receive opacity");
  hestOptAdd(&opt, "gw", "gwidth", airTypeFloat, 1, 1, &gwidth, "0.0",
             "range of grad mag values over which to apply threshold "
             "at low gradient magnitudes");
  hestOptAdd(&opt, "top", "Vtop Gtop", airTypeFloat, 2, 2, top, NULL,
             "data value and grad mag at center of top of triangle");
  hestOptAdd(&opt, "w", "value width", airTypeFloat, 1, 1, &width, NULL,
             "range of values to be spanned at top of triangle");
  hestOptAdd(&opt, "mw", "value width", airTypeFloat, 1, 1, &mwidth, "0",
             "range of values to be spanned at BOTTOM of triangle");
  hestOptAdd(&opt, "step", NULL, airTypeInt, 0, 0, &step, NULL,
             "instead of assigning opacity inside a triangular region, "
             "make it more like a step function, in which opacity never "
             "decreases in increasing data value");
  hestOptAdd(&opt, "a", "max opac", airTypeFloat, 1, 1, &maxa, "1.0",
             "highest opacity to assign");
  hestOptAdd(&opt, "o", "opacOut", airTypeString, 1, 1, &out, NULL,
             "output opacity function filename");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);
  USAGE(_baneGkms_txfInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
  E = 0;
  if (!E) E |= nrrdMaybeAlloc_va(nout, nrrdTypeFloat, 3,
                                 AIR_CAST(size_t, 1),
                                 AIR_CAST(size_t, res[0]),
                                 AIR_CAST(size_t, res[1]));
  if (!E) E |= !(nout->axis[0].label = airStrdup("A"));
  if (!E) E |= !(nout->axis[1].label = airStrdup("gage(scalar:v)"));
  if (!E) nrrdAxisInfoSet_va(nout, nrrdAxisInfoMin,
                             AIR_NAN, (double)min[0], (double)min[1]);
  if (!E) nrrdAxisInfoSet_va(nout, nrrdAxisInfoMax,
                             AIR_NAN, (double)max[0], (double)max[1]);
  if (!E) E |= !(nout->axis[2].label = airStrdup("gage(scalar:gm)"));
  if (E) {
    sprintf(err, "%s: trouble creating opacity function nrrd", me);
    biffMove(BANE, err, NRRD); airMopError(mop); return 1;
  }
  data = (float *)nout->data;
  tvl = top[0] - width/2; 
  tvr = top[0] + width/2;
  mwidth /= 2;
  for (gi=0; gi<res[1]; gi++) {
    g = AIR_CAST(float, NRRD_CELL_POS(min[1], max[1], res[1], gi));
    for (vi=0; vi<res[0]; vi++) {
      v = AIR_CAST(float, NRRD_CELL_POS(min[0], max[0], res[0], vi));
      vl = AIR_CAST(float, AIR_AFFINE(0, g, top[1], v0-mwidth, tvl));
      vr = AIR_CAST(float, AIR_AFFINE(0, g, top[1], v0+mwidth, tvr));
      if (g > top[1]) {
        data[vi + res[0]*gi] = 0;
        continue;
      }
      tmp = AIR_CAST(float, (v - vl)/(0.00001 + vr - vl));
      tmp = 1 - AIR_ABS(2*tmp - 1);
      if (step && v > (vr + vl)/2) {
        tmp = 1;
      }
      tmp = AIR_MAX(0, tmp);
      data[vi + res[0]*gi] = tmp*maxa;
      tmp = AIR_CAST(float, AIR_AFFINE(g0 - gwidth/2, g, g0 + gwidth/2,
                                       0.0, 1.0));
      tmp = AIR_CLAMP(0, tmp, 1);
      data[vi + res[0]*gi] *= tmp;
    }
  }
  if (nrrdSave(out, nout, NULL)) {
    sprintf(err, "%s: trouble saving opacity function", me);
    biffMove(BANE, err, NRRD); airMopError(mop); return 1;
  }
  
  airMopOkay(mop);
  return 0;
}
Beispiel #24
0
int
baneGkms_pvgMain(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *outS, *perr, err[BIFF_STRLEN], *mapS;
  Nrrd *ninfo, *nposA, *nposB, *ndon, *npvg;
  NrrdIoState *nio;
  airArray *mop;
  int i, pret, invert, sv, sg, smlI;
  float *pos, p, min, max, sml, newsml, newmin, newmax;
  NrrdRange *range;

  hestOptAdd(&opt, "inv", NULL, airTypeInt, 0, 0, &invert, NULL,
             "Draw on white background, instead of black");
  hestOptAdd(&opt, "m", "mapOut", airTypeString, 1, 1, &mapS, "",
             "save out the colormap used here, so that it can be applied "
             "to other nrrds with \"unu imap -r\"");
  hestOptAdd(&opt, "i", "infoIn", airTypeOther, 1, 1, &ninfo, NULL,
             "input info file (from \"gkms info\")",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&opt, "o", "imageOut", airTypeString, 1, 1, &outS, NULL,
             "output image, in PPM format");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);
  USAGE(_baneGkms_pvgInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);
  airMopAdd(mop, ndon=_baneGkmsDonNew(invert),
            (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, nposA=nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, nposB=nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, npvg=nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, nio=nrrdIoStateNew(), (airMopper)nrrdIoStateNix,
            airMopAlways);

  if (airStrlen(mapS)) {
    if (nrrdSave(mapS, ndon, NULL)) {
      sprintf(err, "%s: trouble saving colormap", me);
      biffMove(BANE, err, NRRD); airMopError(mop); return 1;
    }
  }

  /* we use sigma = 1.0: different sigmas will scale the position,
     which will not change the coloring
     gthresh = 0.0: we want to see everything, and Simian has taught
     us that there can be boundaries at extremely low gradients */
  if (banePosCalc(nposA, 1.0, 0.0, ninfo)) {
    sprintf(err, "%s: trouble calculating position", me);
    biffAdd(BANE, err); airMopError(mop); return 1;
  }
  sv = nposA->axis[0].size;
  sg = nposA->axis[1].size;
  pos = (float *)nposA->data;

  /* find min, max, sml, smlI: histo-eq will warp values around such
     that min-->min and max-->max, but 0-->??.  So, find smallest
     magnitide position (sml) as a stand-in for 0.0 and its index
     (smlI) */
  sml = 0;
  smlI = 0;
  min = max = AIR_NAN;
  for (i=0; i<sv*sg; i++) {
    p = pos[i];
    if (!AIR_EXISTS(p))
      continue;
    if (!AIR_EXISTS(min)) {
      min = max = p;
      sml = AIR_ABS(p);
      smlI = i;
      continue;
    }
    min = AIR_MIN(p, min);
    max = AIR_MAX(p, max);
    if (AIR_ABS(p) < sml) {
      sml = AIR_ABS(p);
      smlI = i;
    }
  }
  if (!AIR_EXISTS(min)) {
    sprintf(err, "%s: didn't see any real data in position array", me);
    biffAdd(BANE, err); airMopError(mop); return 1;
  }
  if (nrrdHistoEq(nposB, nposA, NULL, PVG_HISTEQ_BINS, 3, 1.0)) {
    sprintf(err, "%s: trouble doing histo-eq on p(v,g)", me);
    biffMove(BANE, err, NRRD); airMopError(mop); return 1;
  }

  /* warp position values that pos[smlI] gets mapped back to zero,
     and so that [newmin,newmax] is centered on zero */
  pos = (float *)nposB->data;
  newsml = pos[smlI];
  if (min < -max) {
    newmin = min;
    newmax = -min;
  } else {
    newmin = -max;
    newmax = max;
  }
  for (i=0; i<sv*sg; i++) {
    if (!AIR_EXISTS(pos[i])) {
      continue;
    }
    if (pos[i] < newsml) {
      pos[i] = AIR_CAST(float, AIR_AFFINE(min, pos[i], newsml, newmin, 0.0));
    } else {
Beispiel #25
0
void *
_alanTuringWorker(void *_task) {
  alan_t *tendata, *ten, react,
    conf, Dxx, Dxy, Dyy, /* Dxz, Dyz, */
    *tpx, *tmx, *tpy, *tmy, /* *tpz, *tmz, */
    *lev0, *lev1, *parm, deltaT, alpha, beta, A, B,
    *v[27], lapA, lapB, corrA, corrB, 
    deltaA, deltaB, diffA, diffB, change;
  int dim, iter, stop, startW, endW, idx,
    px, mx, py, my, pz, mz,
    startY, endY, startZ, endZ, sx, sy, sz, x, y, z;
  alanTask *task;

  task = (alanTask *)_task;
  dim = task->actx->dim;
  sx = task->actx->size[0];
  sy = task->actx->size[1];
  sz = (2 == dim ? 1 : task->actx->size[2]);
  parm = (alan_t*)(task->actx->nparm->data);
  diffA = AIR_CAST(alan_t, task->actx->diffA/pow(task->actx->deltaX, dim));
  diffB = AIR_CAST(alan_t, task->actx->diffB/pow(task->actx->deltaX, dim));
  startW = task->idx*sy/task->actx->numThreads;
  endW = (task->idx+1)*sy/task->actx->numThreads;
  tendata = task->actx->nten ? (alan_t *)task->actx->nten->data : NULL;
  react = task->actx->react;

  if (2 == dim) {
    startZ = 0;
    endZ = 1;
    startY = startW;
    endY = endW;
  } else {
    startZ = startW;
    endZ = endW;
    startY = 0;
    endY = sy;
  }

  for (iter = 0; 
       (alanStopNot == task->actx->stop 
        && (0 == task->actx->maxIteration
            || iter < task->actx->maxIteration)); 
       iter++) {

    if (0 == task->idx) {
      task->actx->iter = iter;
      task->actx->nlev = task->actx->_nlev[(iter+1) % 2];
    }
    lev0 = (alan_t*)(task->actx->_nlev[iter % 2]->data);
    lev1 = (alan_t*)(task->actx->_nlev[(iter+1) % 2]->data);
    stop = alanStopNot;
    change = 0;
    conf = 1;  /* if you have no data; this will stay 1 */
    for (z = startZ; z < endZ; z++) {
      if (task->actx->wrap) {
        pz = AIR_MOD(z+1, sz);
        mz = AIR_MOD(z-1, sz);
      } else {
        pz = AIR_MIN(z+1, sz-1);
        mz = AIR_MAX(z-1, 0);
      }
      for (y = startY; y < endY; y++) {
        if (task->actx->wrap) {
          py = AIR_MOD(y+1, sy);
          my = AIR_MOD(y-1, sy);
        } else {
          py = AIR_MIN(y+1, sy-1);
          my = AIR_MAX(y-1, 0);
        }
        for (x = 0; x < sx; x++) {
          if (task->actx->wrap) {
            px = AIR_MOD(x+1, sx);
            mx = AIR_MOD(x-1, sx);
          } else {
            px = AIR_MIN(x+1, sx-1);
            mx = AIR_MAX(x-1, 0);
          }
          idx = x + sx*(y + sy*z);
          A = lev0[0 + 2*idx];
          B = lev0[1 + 2*idx];
          deltaT = parm[0 + 3*idx];
          alpha = parm[1 + 3*idx];
          beta = parm[2 + 3*idx];
          lapA = lapB = corrA = corrB = 0;
          if (2 == dim) {
            /*
            **  0 1 2 ----> X
            **  3 4 5
            **  6 7 8
            **  |
            **  v Y
            */
            v[1] = lev0 + 2*( x + sx*(my));
            v[3] = lev0 + 2*(mx + sx*( y));
            v[5] = lev0 + 2*(px + sx*( y));
            v[7] = lev0 + 2*( x + sx*(py));
            if (tendata) {
              /*
              **  0 1 2    Dxy/2          Dyy        -Dxy/2
              **  3 4 5     Dxx     -2*(Dxx + Dyy)     Dxx
              **  6 7 8   -Dxy/2          Dyy         Dxy/2
              */
              v[0] = lev0 + 2*(mx + sx*(my));
              v[2] = lev0 + 2*(px + sx*(my));
              v[6] = lev0 + 2*(mx + sx*(py));
              v[8] = lev0 + 2*(px + sx*(py));
              ten = tendata + 4*idx;
              conf = AIR_CAST(alan_t, (AIR_CLAMP(0.3, ten[0], 1) - 0.3)/0.7);
              if (conf) {
                Dxx = ten[1];
                Dxy = ten[2];
                Dyy = ten[3];
                lapA = (Dxy*(v[0][0] + v[8][0] - v[2][0] - v[6][0])/2
                        + Dxx*(v[3][0] + v[5][0]) + Dyy*(v[1][0] + v[7][0])
                        - 2*(Dxx + Dyy)*A);
                lapB = (Dxy*(v[0][1] + v[8][1] - v[2][1] - v[6][1])/2
                        + Dxx*(v[3][1] + v[5][1]) + Dyy*(v[1][1] + v[7][1])
                        - 2*(Dxx + Dyy)*B);
                if (!(task->actx->homogAniso)) {
                  tpx = tendata + 4*(px + sx*( y + sy*( z)));
                  tmx = tendata + 4*(mx + sx*( y + sy*( z)));
                  tpy = tendata + 4*( x + sx*(py + sy*( z)));
                  tmy = tendata + 4*( x + sx*(my + sy*( z)));
                  corrA = ((tpx[1]-tmx[1])*(v[5][0]-v[3][0])/4+ /* Dxx,x*A,x */
                           (tpx[2]-tmx[2])*(v[7][0]-v[1][0])/4+ /* Dxy,x*A,y */
                           (tpy[2]-tmy[2])*(v[5][0]-v[3][0])/4+ /* Dxy,y*A,x */
                           (tpy[3]-tmy[3])*(v[7][0]-v[1][0]));  /* Dyy,y*A,y */
                  corrB = ((tpx[1]-tmx[1])*(v[5][1]-v[3][1])/4+ /* Dxx,x*B,x */
                           (tpx[2]-tmx[2])*(v[7][1]-v[1][1])/4+ /* Dxy,x*B,y */
                           (tpy[2]-tmy[2])*(v[5][1]-v[3][1])/4+ /* Dxy,y*B,x */
                           (tpy[3]-tmy[3])*(v[7][1]-v[1][1]));  /* Dyy,y*B,y */
                }
              } else {
                /* no confidence; you diffuse */
                lapA = v[1][0] + v[3][0] + v[5][0] + v[7][0] - 4*A;
                lapB = v[1][1] + v[3][1] + v[5][1] + v[7][1] - 4*B;
              }
            } else {
              /* no data; you diffuse */
              lapA = v[1][0] + v[3][0] + v[5][0] + v[7][0] - 4*A;
              lapB = v[1][1] + v[3][1] + v[5][1] + v[7][1] - 4*B;
            }
          } else {
            /* 3 == dim */
            /*
            **          0   1   2   ---- X
            **        3   4   5
            **      6   7   8
            **    /
            **  /       9  10  11
            ** Y     12  13  14
            **     15  16  17
            **
            **         18  19  20
            **       21  22  23
            **     24  25  26
            **         |
            **         |
            **         Z
            */
            v[ 4] = lev0 + 2*( x + sx*( y + sy*(mz)));
            v[10] = lev0 + 2*( x + sx*(my + sy*( z)));
            v[12] = lev0 + 2*(mx + sx*( y + sy*( z)));
            v[14] = lev0 + 2*(px + sx*( y + sy*( z)));
            v[16] = lev0 + 2*( x + sx*(py + sy*( z)));
            v[22] = lev0 + 2*( x + sx*( y + sy*(pz)));
            if (tendata) {

              if (!(task->actx->homogAniso)) {
                
              }
            } else {
              lapA = (v[ 4][0] + v[10][0] + v[12][0]
                      + v[14][0] + v[16][0] + v[22][0] - 6*A);
              lapB = (v[ 4][1] + v[10][1] + v[12][1]
                      + v[14][1] + v[16][1] + v[22][1] - 6*B);
            }
          }
          
          deltaA = deltaT*(react*conf*task->actx->K*(alpha - A*B) 
                           + diffA*(lapA + corrA));
          if (AIR_ABS(deltaA) > task->actx->maxPixelChange) {
            stop = alanStopDiverged;
          }
          change += AIR_ABS(deltaA);
          deltaB = deltaT*(react*conf*task->actx->K*(A*B - B - beta)
                           + diffB*(lapB + corrB));
          if (!( AIR_EXISTS(deltaA) && AIR_EXISTS(deltaB) )) {
            stop = alanStopNonExist;
          }
          
          A += deltaA;
          B = AIR_MAX(0, B + deltaB);
          lev1[0 + 2*idx] = A;
          lev1[1 + 2*idx] = B; 
        }
      }
    }
    
    /* add change to global sum in a threadsafe way */
    airThreadMutexLock(task->actx->changeMutex);
    task->actx->averageChange += change/(sx*sy*sz);
    task->actx->changeCount += 1;
    if (task->actx->changeCount == task->actx->numThreads) {
      /* I must be the last thread to reach this point; all 
         others must have passed the mutex unlock, and are
         sitting at the barrier */
      if (alanStopNot != stop) {
        /* there was some problem in going from lev0 to lev1, which
           we deal with now by setting actx->stop */
        task->actx->stop = stop;
      } else if (task->actx->averageChange < task->actx->minAverageChange) {
        /* we converged */
        task->actx->stop = alanStopConverged;
      } else {
        /* we keep going */
        _alanPerIteration(task->actx, iter);
        if (task->actx->perIteration) {
          task->actx->perIteration(task->actx, iter);
        }
      }
      task->actx->averageChange = 0;
      task->actx->changeCount = 0;
    }
    airThreadMutexUnlock(task->actx->changeMutex);

    /* force all threads to line up here, once per iteration */
    airThreadBarrierWait(task->actx->iterBarrier);
  }
  
  if (iter == task->actx->maxIteration) {
    /* HEY: all threads will agree on this, right? */
    task->actx->stop = alanStopMaxIteration;
  }
  /* else: the non-alanStopNot value of task->actx->stop made us stop */
  return _task;
}
Beispiel #26
0
int
main(int argc, char *argv[]) {
  int i;
  Nrrd *nrrd;
  double diff, idx, idx2, idx3, idx4, lo, hi, pos, pos2, pos3, pos4;

  AIR_UNUSED(argc);
  AIR_UNUSED(argv);
  if (nrrdAlloc_va(nrrd=nrrdNew(), nrrdTypeFloat, 2,
                   AIR_CAST(size_t, 4),
                   AIR_CAST(size_t, 4))) {
    printf("trouble:\n%s\n", biffGet(NRRD));
    exit(1);
  }
  nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMin, 10.0, 10.0);
  nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMax, 12.0, 12.0);
  nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoCenter, nrrdCenterNode, nrrdCenterCell);

  idx = 0;
  printf("\n");
  pos = nrrdAxisInfoPos(nrrd, 0, idx);
  printf("pos(0, %g) == %g --> %g\n",
         idx, pos, nrrdAxisInfoIdx(nrrd, 0, pos));
  pos = nrrdAxisInfoPos(nrrd, 1, idx);
  printf("pos(1, %g) == %g --> %g\n",
         idx, pos, nrrdAxisInfoIdx(nrrd, 1, pos));

  idx = 1;
  printf("\n");
  pos = nrrdAxisInfoPos(nrrd, 0, idx);
  printf("pos(0, %g) == %g --> %g\n",
         idx, pos, nrrdAxisInfoIdx(nrrd, 0, pos));
  pos = nrrdAxisInfoPos(nrrd, 1, idx);
  printf("pos(1, %g) == %g --> %g\n",
         idx, pos, nrrdAxisInfoIdx(nrrd, 1, pos));

  idx = 2;
  printf("\n");
  pos = nrrdAxisInfoPos(nrrd, 0, idx);
  printf("pos(0, %g) == %g --> %g\n",
         idx, pos, nrrdAxisInfoIdx(nrrd, 0, pos));
  pos = nrrdAxisInfoPos(nrrd, 1, idx);
  printf("pos(1, %g) == %g --> %g\n",
         idx, pos, nrrdAxisInfoIdx(nrrd, 1, pos));

  idx = 0; idx2 = 0;
  printf("\n");
  nrrdAxisInfoPosRange(&lo, &hi, nrrd, 0, idx, idx2);
  nrrdAxisInfoIdxRange(&idx3, &idx4, nrrd, 0, lo, hi);
  printf("range(0, %g -- %g) == (%g -- %g) --> (%g -- %g)\n",
         idx, idx2, lo, hi, idx3, idx4);
  nrrdAxisInfoPosRange(&lo, &hi, nrrd, 1, idx, idx2);
  nrrdAxisInfoIdxRange(&idx3, &idx4, nrrd, 1, lo, hi);
  printf("range(1, %g -- %g) == (%g -- %g) --> (%g -- %g)\n",
         idx, idx2, lo, hi, idx3, idx4);

  idx = 0; idx2 = 1;
  printf("\n");
  nrrdAxisInfoPosRange(&lo, &hi, nrrd, 0, idx, idx2);
  nrrdAxisInfoIdxRange(&idx3, &idx4, nrrd, 0, lo, hi);
  printf("range(0, %g -- %g) == (%g -- %g) --> (%g -- %g)\n",
         idx, idx2, lo, hi, idx3, idx4);
  nrrdAxisInfoPosRange(&lo, &hi, nrrd, 1, idx, idx2);
  nrrdAxisInfoIdxRange(&idx3, &idx4, nrrd, 1, lo, hi);
  printf("range(1, %g -- %g) == (%g -- %g) --> (%g -- %g)\n",
         idx, idx2, lo, hi, idx3, idx4);

  idx = 1; idx2 = 0;
  printf("\n");
  nrrdAxisInfoPosRange(&lo, &hi, nrrd, 0, idx, idx2);
  nrrdAxisInfoIdxRange(&idx3, &idx4, nrrd, 0, lo, hi);
  printf("range(0, %g -- %g) == (%g -- %g) --> (%g -- %g)\n",
         idx, idx2, lo, hi, idx3, idx4);
  nrrdAxisInfoPosRange(&lo, &hi, nrrd, 1, idx, idx2);
  nrrdAxisInfoIdxRange(&idx3, &idx4, nrrd, 1, lo, hi);
  printf("range(1, %g -- %g) == (%g -- %g) --> (%g -- %g)\n",
         idx, idx2, lo, hi, idx3, idx4);

  nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMin, 12.0, 12.0);
  nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMax, 10.0, 10.0);
  printf("\n(axis min,max flipped)\n");

  idx = 0;
  printf("\n");
  pos = nrrdAxisInfoPos(nrrd, 0, idx);
  printf("pos(0, %g) == %g --> %g\n",
         idx, pos, nrrdAxisInfoIdx(nrrd, 0, pos));
  pos = nrrdAxisInfoPos(nrrd, 1, idx);
  printf("pos(1, %g) == %g --> %g\n",
         idx, pos, nrrdAxisInfoIdx(nrrd, 1, pos));

  idx = 1;
  printf("\n");
  pos = nrrdAxisInfoPos(nrrd, 0, idx);
  printf("pos(0, %g) == %g --> %g\n",
         idx, pos, nrrdAxisInfoIdx(nrrd, 0, pos));
  pos = nrrdAxisInfoPos(nrrd, 1, idx);
  printf("pos(1, %g) == %g --> %g\n",
         idx, pos, nrrdAxisInfoIdx(nrrd, 1, pos));

  idx = 2;
  printf("\n");
  pos = nrrdAxisInfoPos(nrrd, 0, idx);
  printf("pos(0, %g) == %g --> %g\n",
         idx, pos, nrrdAxisInfoIdx(nrrd, 0, pos));
  pos = nrrdAxisInfoPos(nrrd, 1, idx);
  printf("pos(1, %g) == %g --> %g\n",
         idx, pos, nrrdAxisInfoIdx(nrrd, 1, pos));

  idx = 0; idx2 = 0;
  printf("\n");
  nrrdAxisInfoPosRange(&lo, &hi, nrrd, 0, idx, idx2);
  nrrdAxisInfoIdxRange(&idx3, &idx4, nrrd, 0, lo, hi);
  printf("range(0, %g -- %g) == (%g -- %g) --> (%g -- %g)\n",
         idx, idx2, lo, hi, idx3, idx4);
  nrrdAxisInfoPosRange(&lo, &hi, nrrd, 1, idx, idx2);
  nrrdAxisInfoIdxRange(&idx3, &idx4, nrrd, 1, lo, hi);
  printf("range(1, %g -- %g) == (%g -- %g) --> (%g -- %g)\n",
         idx, idx2, lo, hi, idx3, idx4);

  idx = 0; idx2 = 2;
  printf("\n");
  nrrdAxisInfoPosRange(&lo, &hi, nrrd, 0, idx, idx2);
  nrrdAxisInfoIdxRange(&idx3, &idx4, nrrd, 0, lo, hi);
  printf("range(0, %g -- %g) == (%g -- %g) --> (%g -- %g)\n",
         idx, idx2, lo, hi, idx3, idx4);
  nrrdAxisInfoPosRange(&lo, &hi, nrrd, 1, idx, idx2);
  nrrdAxisInfoIdxRange(&idx3, &idx4, nrrd, 1, lo, hi);
  printf("range(1, %g -- %g) == (%g -- %g) --> (%g -- %g)\n",
         idx, idx2, lo, hi, idx3, idx4);

  idx = 2; idx2 = 0;
  printf("\n");
  nrrdAxisInfoPosRange(&lo, &hi, nrrd, 0, idx, idx2);
  nrrdAxisInfoIdxRange(&idx3, &idx4, nrrd, 0, lo, hi);
  printf("range(0, %g -- %g) == (%g -- %g) --> (%g -- %g)\n",
         idx, idx2, lo, hi, idx3, idx4);
  nrrdAxisInfoPosRange(&lo, &hi, nrrd, 1, idx, idx2);
  nrrdAxisInfoIdxRange(&idx3, &idx4, nrrd, 1, lo, hi);
  printf("range(1, %g -- %g) == (%g -- %g) --> (%g -- %g)\n",
         idx, idx2, lo, hi, idx3, idx4);

  nrrd->axis[0].center = nrrdCenterCell;
  nrrd->axis[0].size = 4;
  nrrd->axis[0].min = -4;
  nrrd->axis[0].max = 4;
  pos = 0;
  pos2 = 1;
  nrrdAxisInfoIdxRange(&idx, &idx2, nrrd, 0, pos, pos2);
  nrrdAxisInfoPosRange(&pos3, &pos4, nrrd, 0, idx, idx2);
  printf("min, max = %g, %g\n", nrrd->axis[0].min, nrrd->axis[0].max);
  printf("pos, pos2 = %g, %g\n", pos, pos2);
  printf("idx, idx2 = %g, %g\n", idx, idx2);
  printf("pos3, pos4 = %g, %g\n", pos3, pos4);
  exit(1);


  /* and now for random-ness */
  airSrandMT((int)airTime());
  nrrd->axis[0].center = nrrdCenterNode;
  nrrd->axis[0].center = nrrdCenterCell;
  for (i=0; i<=1000000; i++) {
    nrrd->axis[0].min = frand(-3.0, 3.0);
    nrrd->axis[0].max = frand(-3.0, 3.0);
    idx = frand(-3.0, 3.0);
    pos = nrrdAxisInfoPos(nrrd, 0, idx);
    diff = idx - nrrdAxisInfoIdx(nrrd, 0, pos);
    if (AIR_ABS(diff) > 0.00000001) { printf("PANIC 0\n"); exit(2); }
    pos = frand(-3.0, 3.0);
    idx = nrrdAxisInfoIdx(nrrd, 0, pos);
    diff = pos - nrrdAxisInfoPos(nrrd, 0, idx);
    if (AIR_ABS(diff) > 0.00000001) { printf("PANIC 1\n"); exit(2); }

    nrrd->axis[0].min = (int)frand(-3.0, 3.0);
    nrrd->axis[0].max = (int)frand(-3.0, 3.0);
    idx = (int)frand(-10.0, 10.0);
    idx2 = (int)frand(-10.0, 10.0);
    nrrdAxisInfoPosRange(&pos, &pos2, nrrd, 0, idx, idx2);
    nrrdAxisInfoIdxRange(&idx3, &idx4, nrrd, 0, pos, pos2);
    diff = AIR_ABS(idx - idx3) + AIR_ABS(idx2 - idx4);
    if (AIR_ABS(diff) > 0.00000001) { printf("PANIC 2\n"); exit(2); }
    pos = (int)frand(-3.0, 3.0);
    pos2 = (int)frand(-3.0, 3.0);
    nrrdAxisInfoIdxRange(&idx, &idx2, nrrd, 0, pos, pos2);
    nrrdAxisInfoPosRange(&pos3, &pos4, nrrd, 0, idx, idx2);
    diff = AIR_ABS(pos - pos3) + AIR_ABS(pos2 - pos4);
    if (AIR_ABS(diff) > 0.00000001) {
      printf("min, max = %g, %g\n", nrrd->axis[0].min, nrrd->axis[0].max);
      printf("pos, pos2 = %g, %g\n", pos, pos2);
      printf("idx, idx2 = %g, %g\n", idx, idx2);
      printf("pos3, pos4 = %g, %g\n", pos3, pos4);
      printf("PANIC (%d) 3 %g\n", (int)nrrd->axis[0].size, diff); exit(2);
    }
  }

  exit(0);
}
Beispiel #27
0
void
tend_helixDoit(Nrrd *nout, double bnd,
               double orig[3], double i2w[9], double mf[9],
               double r, double R, double S, double angle, int incrtwist,
               double ev[3], double bgEval) {
  int sx, sy, sz, xi, yi, zi;
  double th, t0, t1, t2, t3, v1, v2,
    wpos[3], vpos[3], mfT[9],
    W2H[9], H2W[9], H2C[9], C2H[9], fv[3], rv[3], uv[3], mA[9], mB[9], inside,
    tmp[3], len;
  float *out;

  sx = nout->axis[1].size;
  sy = nout->axis[2].size;
  sz = nout->axis[3].size;
  out = (float*)nout->data;
  ELL_3M_TRANSPOSE(mfT, mf);
  for (zi=0; zi<sz; zi++) {
    fprintf(stderr, "zi = %d/%d\n", zi, sz);
    for (yi=0; yi<sy; yi++) {
      for (xi=0; xi<sx; xi++) {
        ELL_3V_SET(tmp, xi, yi, zi);
        ELL_3MV_MUL(vpos, i2w, tmp);
        ELL_3V_INCR(vpos, orig);

#define WPOS(pos, th) ELL_3V_SET((pos),R*cos(th), R*sin(th), S*(th)/(2*AIR_PI))
#define VAL(th) (WPOS(wpos, th), ELL_3V_DIST(wpos, vpos))
#define RR 0.61803399
#define CC (1.0-RR)
#define SHIFT3(a,b,c,d) (a)=(b); (b)=(c); (c)=(d)
#define SHIFT2(a,b,c)   (a)=(b); (b)=(c)
        
        th = atan2(vpos[1], vpos[0]);
        th += 2*AIR_PI*floor(0.5 + vpos[2]/S - th/(2*AIR_PI));
        if (S*th/(2*AIR_PI) > vpos[2]) {
          t0 = th - AIR_PI; t3 = th;
        } else {
          t0 = th; t3 = th + AIR_PI;
        }
        t1 = RR*t0 + CC*t3;
        t2 = CC*t0 + RR*t3;
        v1 = VAL(t1);
        v2 = VAL(t2);
        while ( t3-t0 > 0.000001*(AIR_ABS(t1)+AIR_ABS(t2)) ) {
          if (v1 < v2) {
            SHIFT3(t3, t2, t1, CC*t0 + RR*t2);
            SHIFT2(v2, v1, VAL(t1));
          } else {
            SHIFT3(t0, t1, t2, RR*t1 + CC*t3);
            SHIFT2(v1, v2, VAL(t2));
          }
        }
        /* t1 (and t2) are now the th for which the point on the helix
           (R*cos(th), R*sin(th), S*(th)/(2*AIR_PI)) is closest to vpos */

        WPOS(wpos, t1);
        ELL_3V_SUB(wpos, vpos, wpos);
        ELL_3V_SET(fv, -R*sin(t1), R*cos(t1), S/AIR_PI);  /* helix tangent */
        ELL_3V_NORM(fv, fv, len);
        ELL_3V_COPY(rv, wpos);
        ELL_3V_NORM(rv, rv, len);
        len = ELL_3V_DOT(rv, fv);
        ELL_3V_SCALE(tmp, -len, fv);
        ELL_3V_ADD2(rv, rv, tmp);
        ELL_3V_NORM(rv, rv, len);  /* rv now normal to helix, closest to 
                                      pointing to vpos */
        ELL_3V_CROSS(uv, rv, fv);
        ELL_3V_NORM(uv, uv, len);  /* (rv,fv,uv) now right-handed frame */
        ELL_3MV_ROW0_SET(W2H, uv); /* as is (uv,rv,fv) */
        ELL_3MV_ROW1_SET(W2H, rv);
        ELL_3MV_ROW2_SET(W2H, fv);
        ELL_3M_TRANSPOSE(H2W, W2H);
        inside = 0.5 - 0.5*airErf((ELL_3V_LEN(wpos)-r)/(bnd + 0.0001));
        if (incrtwist) {
          th = angle*ELL_3V_LEN(wpos)/r;
        } else {
          th = angle;
        }
        ELL_3M_ROTATE_Y_SET(H2C, th);
        ELL_3M_TRANSPOSE(C2H, H2C);
        ELL_3M_SCALE_SET(mA,
                         AIR_LERP(inside, bgEval, ev[1]),
                         AIR_LERP(inside, bgEval, ev[2]),
                         AIR_LERP(inside, bgEval, ev[0]));
        ELL_3M_MUL(mB, mA, H2C);
        ELL_3M_MUL(mA, mB, W2H);
        ELL_3M_MUL(mB, mA, mf);
        ELL_3M_MUL(mA, C2H, mB);
        ELL_3M_MUL(mB, H2W, mA);
        ELL_3M_MUL(mA, mfT, mB);
        
        TEN_M2T_TT(out, float, mA);
        out[0] = 1.0;
        out += 7;
      }
    }
  }
  return;
}
Beispiel #28
0
/*
** Thanks to:
** http://jgt.akpeters.com/papers/MollerHughes99/code.html
*/
void
ell_3m_rotate_between_d(double rot[9], double from[3], double to[3]) {
  double vv[3];
  double e, h, f;

  if (!( rot && from && to)) {
    return;
  }
  ELL_3V_CROSS(vv, from, to);
  e = ELL_3V_DOT(from, to);
  f = AIR_ABS(e);
  if (f > 0.9999999) {   /* "from" and "to"-vector almost parallel */
    double tu[3], tv[3]; /* temporary storage vectors */
    double xx[3];        /* vector most nearly orthogonal to "from" */
    double c1, c2, c3;   /* coefficients for later use */
    int i, j;

    xx[0] = AIR_ABS(from[0]);
    xx[1] = AIR_ABS(from[1]);
    xx[2] = AIR_ABS(from[2]);

    if (xx[0] < xx[1]) {
      if (xx[0] < xx[2]) {
        xx[0] = 1.0; xx[1] = xx[2] = 0.0;
      } else {
        xx[2] = 1.0; xx[0] = xx[1] = 0.0;
      }
    } else {
      if (xx[1] < xx[2]) {
        xx[1] = 1.0; xx[0] = xx[2] = 0.0;
      } else {
        xx[2] = 1.0; xx[0] = xx[1] = 0.0;
      }
    }

    tu[0] = xx[0] - from[0]; tu[1] = xx[1] - from[1]; tu[2] = xx[2] - from[2];
    tv[0] = xx[0] - to[0];   tv[1] = xx[1] - to[1];   tv[2] = xx[2] - to[2];

    c1 = 2.0 / ELL_3V_DOT(tu, tu);
    c2 = 2.0 / ELL_3V_DOT(tv, tv);
    c3 = c1 * c2  * ELL_3V_DOT(tu, tv);

    for (i = 0; i < 3; i++) {
      for (j = 0; j < 3; j++) {
        rot[3*i + j] =  - c1 * tu[i] * tu[j]
                     - c2 * tv[i] * tv[j]
                     + c3 * tv[i] * tu[j];
      }
      rot[3*i + i] += 1.0;
    }
  } else { /* the most common case, unless "from"="to", or "from"=-"to" */
    double hvx, hvz, hvxy, hvxz, hvyz;
    h = 1.0/(1.0 + e);      /* optimization by Gottfried Chen */
    hvx = h * vv[0];
    hvz = h * vv[2];
    hvxy = hvx * vv[1];
    hvxz = hvx * vv[2];
    hvyz = hvz * vv[1];
    rot[3*0 + 0] = e + hvx * vv[0];
    rot[3*0 + 1] = hvxy - vv[2];
    rot[3*0 + 2] = hvxz + vv[1];

    rot[3*1 + 0] = hvxy + vv[2];
    rot[3*1 + 1] = e + h * vv[1] * vv[1];
    rot[3*1 + 2] = hvyz - vv[0];

    rot[3*2 + 0] = hvxz - vv[1];
    rot[3*2 + 1] = hvyz + vv[0];
    rot[3*2 + 2] = e + hvz * vv[2];
  }
  return;
}
Beispiel #29
0
int
_nrrdHestIterParse(void *ptr, char *str, char err[AIR_STRLEN_HUGE]) {
  char me[]="_nrrdHestIterParse", *nerr;
  Nrrd *nrrd;
  NrrdIter **iterP;
  airArray *mop;
  double val;
  int ret;

  if (!(ptr && str)) {
    sprintf(err, "%s: got NULL pointer", me);
    return 1;
  }
  iterP = (NrrdIter **)ptr;
  mop = airMopNew();
  *iterP = nrrdIterNew();
  airMopAdd(mop, *iterP, (airMopper)nrrdIterNix, airMopOnError);

  /* the challenge here is determining if a given string represents a
     filename or a number.  Obviously there are cases where it could
     be both, so we'll assume its a filename first.  Because: there
     are different ways of writing the same number, such as "3" -->
     "+3", "3.1" --> "3.10", so someone accidently using the file when
     they mean to use the number has easy ways of changing the number
     representation, since these trivial transformations will probably
     not all result in valid filenames. Another problem is that one
     really wants a general robust test to see if a given string is a
     valid number representation AND NOTHING BUT THAT, and sscanf() is
     not that test.  In any case, if there are to be improved smarts
     about this matter, they need to be implemented below and nowhere
     else. */

  nrrd = nrrdNew();
  ret = nrrdLoad(nrrd, str, NULL);
  if (!ret) {
    /* first attempt at nrrdLoad() was SUCCESSFUL */
    nrrdIterSetOwnNrrd(*iterP, nrrd);
  } else {
    /* so it didn't load as a nrrd- if its because fopen() failed,
       then we'll try it as a number.  If its for another reason,
       then we complain */
    nrrdNuke(nrrd);
    if (2 != ret) {
      /* it failed because of something besides the fopen(), so complain */
      nerr = biffGetDone(NRRD);
      airStrcpy(err, AIR_STRLEN_HUGE, nerr);
      airMopError(mop); return 1;
    } else {
      /* fopen() failed, so it probably wasn't meant to be a filename */
      free(biffGetDone(NRRD));
      ret = airSingleSscanf(str, "%lf", &val);
      if (_nrrdLooksLikeANumber(str)
          || (1 == ret && (!AIR_EXISTS(val)
                           || AIR_ABS(AIR_PI - val) < 0.0001))) {
        /* either it patently looks like a number, or,
           it already parsed as a number and it is a special value */
        if (1 == ret) {
          nrrdIterSetValue(*iterP, val);
        } else {
          /* oh, this is bad. */
          fprintf(stderr, "%s: PANIC, is it a number or not?", me);
          exit(1);
        }
      } else {
        /* it doesn't look like a number, but the fopen failed, so
           we'll let it fail again and pass back the error messages */
        if (nrrdLoad(nrrd = nrrdNew(), str, NULL)) {
          nerr = biffGetDone(NRRD);
          airStrcpy(err, AIR_STRLEN_HUGE, nerr);
          airMopError(mop); return 1;
        } else {
          /* what the hell? */
          fprintf(stderr, "%s: PANIC, is it a nrrd or not?", me);
          exit(1);
        }
      }
    }
  }
  airMopAdd(mop, iterP, (airMopper)airSetNull, airMopOnError);
  airMopOkay(mop);
  return 0;
}
Beispiel #30
0
void
_miteRGBACalc(mite_t *R, mite_t *G, mite_t *B, mite_t *A,
              miteThread *mtt, miteRender *mrr, miteUser *muu) {
  static const char me[]="_miteRGBACalc";
  mite_t tmp,
    ad[3],                          /* ambient+diffuse light contribution */
    s[3] = {0,0,0},                 /* specular light contribution */
    col[3], E, ka, kd, ks, sp,      /* txf-determined rendering variables */
    LdotN=0, HdotN, H[3], N[3];     /* for lighting calculation */

  col[0] = mtt->range[miteRangeRed];
  col[1] = mtt->range[miteRangeGreen];
  col[2] = mtt->range[miteRangeBlue];
  E = mtt->range[miteRangeEmissivity];
  ka = mtt->range[miteRangeKa];
  kd = mtt->range[miteRangeKd];
  ks = mtt->range[miteRangeKs];
  ELL_3V_SCALE(ad, ka, muu->lit->amb);
  switch (mrr->shadeSpec->method) {
  case miteShadeMethodNone:
    /* nothing to do */
    break;
  case miteShadeMethodPhong:
    if (kd || ks) {
      ELL_3V_NORM(N, mtt->shadeVec0, tmp);
      if (1 == muu->normalSide) {
        ELL_3V_SCALE(N, -1, N);
      }
      /* else -1==side --> N = -1*-1*N = N
         or 0==side --> N = N, so there's nothing to do */
      if (kd) {
        LdotN = ELL_3V_DOT(muu->lit->dir[0], N);
        if (!muu->normalSide) {
          LdotN = AIR_ABS(LdotN);
        }
        if (LdotN > 0) {
          ELL_3V_SCALE_INCR(ad, LdotN*kd, muu->lit->col[0]);
        }
      }
      if (ks) {
        sp = mtt->range[miteRangeSP];
        ELL_3V_ADD2(H, muu->lit->dir[0], mtt->V);
        ELL_3V_NORM(H, H, tmp);
        HdotN = ELL_3V_DOT(H, N);
        if (!muu->normalSide) {
          HdotN = AIR_ABS(HdotN);
        }
        if (HdotN > 0) {
          HdotN = pow(HdotN, sp);
          ELL_3V_SCALE(s, HdotN*ks, muu->lit->col[0]);
        }
      }
    }
    break;
  case miteShadeMethodLitTen:
    fprintf(stderr, "!%s: lit-tensor not yet implemented\n", me);
    break;
  default:
    fprintf(stderr, "!%s: PANIC, shadeMethod %d unimplemented\n",
            me, mrr->shadeSpec->method);
    exit(1);
    break;
  }
  *R = (E - 1 + ad[0])*col[0] + s[0];
  *G = (E - 1 + ad[1])*col[1] + s[1];
  *B = (E - 1 + ad[2])*col[2] + s[2];
  *A = mtt->range[miteRangeAlpha];
  *A = AIR_CLAMP(0.0, *A, 1.0);
  /*
  if (mtt->verbose) {
    fprintf(stderr, "%s: col[] = %g,%g,%g; A,E = %g,%g; Kads = %g,%g,%g\n", me,
            col[0], col[1], col[2], mtt->range[miteRangeAlpha], E, ka, kd, ks);
    fprintf(stderr, "%s: N = (%g,%g,%g), L = (%g,%g,%g) ---> LdotN = %g\n",
            me, N[0], N[1], N[2], muu->lit->dir[0][0], muu->lit->dir[0][1],
            muu->lit->dir[0][2], LdotN);
    fprintf(stderr, "%s: ad[] = %g,%g,%g\n", me, ad[0], ad[1], ad[2]);
    fprintf(stderr, "%s:  --> R,G,B,A = %g,%g,%g,%g\n", me, *R, *G, *B, *A);
  }
  */
  return;
}