コード例 #1
0
void
_biffFindMaxAndSum(unsigned int *maxP, unsigned int *sumP, _biffEntry *ent) {
  unsigned int ii, len;

  if (!ent->num) {
    /* there's a key, but no error messages.  Odd. */
    *maxP = 1;
    *sumP = 1;
    return;
  }

  *maxP = *sumP = 0;
  for (ii=0; ii<ent->num; ii++) {
    len = (unsigned int)(strlen(ent->err[ii]) + strlen(ent->key) + strlen("[] \n"));
    *sumP += len;
    *maxP = AIR_MAX(*maxP, len);
  }
  *sumP += 1;
  *maxP += 1;
  return;
}
コード例 #2
0
void
_nrrdMeasureHistoSum(void *ans, int ansType,
                     const void *line, int lineType, size_t len, 
                     double axmin, double axmax) {
  double sum, hits, val, (*lup)(const void*, size_t);
  size_t ii;
  
  if (!(AIR_EXISTS(axmin) && AIR_EXISTS(axmax))) {
    axmin = -0.5;
    axmax = len-0.5;
  }
  lup = nrrdDLookup[lineType];
  sum = 0;
  for (ii=0; ii<len; ii++) {
    val = NRRD_CELL_POS(axmin, axmax, len, ii);
    hits = lup(line, ii);
    hits = AIR_MAX(hits, 0);
    sum += hits*val;
  }
  nrrdDStore[ansType](ans, sum);
}
コード例 #3
0
ファイル: qglox.c プロジェクト: CIBC-Internal/teem
/*
** computes (r1 - r0)/(log(r1) - log(r0))
*/
double
_tenQGL_blah(double rr0, double rr1) {
  double bb, ret;

  if (rr1 > rr0) {
    /* the bb calculation below could blow up, so we recurse
       with flipped order */
    ret = _tenQGL_blah(rr1, rr0);
  } else {
    /*   rr1 <= rr0 --> rr1/rr0 <= 1 --> rr1/rr0 - 1 <=  0 --> bb <=  0 */
    /* and rr1 >= 0 --> rr1/rr0 >= 0 --> rr1/rr0 - 1 >= -1 --> bb >= -1 */
    bb = rr0 ? (rr1/rr0 - 1) : 0;
    if (bb > -0.0001) {
      ret = rr0*(1 + bb*(0.5001249976477329
                         - bb*(7.0/6 + bb*(1.0/6 - bb/720.0))));
    } else {
      /* had trouble finding a high-quality approximation for b near -1 */
      bb = AIR_MAX(bb, -1 + 100*FLT_EPSILON);
      ret = rr0*bb/log(bb + 1);
    }
  }
  return ret;
}
コード例 #4
0
ファイル: encodingHex.c プロジェクト: CIBC-Internal/teem
static int
_nrrdEncodingHex_write(FILE *file, const void *_data, size_t elNum,
                       const Nrrd *nrrd, NrrdIoState *nio) {
  /* static const char me[]="_nrrdEncodingHex_write"; */
  const unsigned char *data;
  size_t byteIdx, byteNum;
  unsigned int bytesPerLine;

  bytesPerLine = AIR_MAX(1, nio->charsPerLine/2);
  data = AIR_CAST(const unsigned char*, _data);
  byteNum = elNum*nrrdElementSize(nrrd);
  for (byteIdx=0; byteIdx<byteNum; byteIdx++) {
    fprintf(file, "%c%c",
            _nrrdWriteHexTable[(*data)>>4],
            _nrrdWriteHexTable[(*data)&15]);
    if (bytesPerLine-1 == byteIdx % bytesPerLine) {
      fprintf(file, "\n");
    }
    data++;
  }
  /* just to be sure, we always end with a carraige return */
  fprintf(file, "\n");
  return 0;
}
コード例 #5
0
ファイル: probeMulti.c プロジェクト: BRAINSia/teem
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;
      }
    }
  }
コード例 #6
0
ファイル: constraints.c プロジェクト: CIBC-Internal/teem
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;
}
コード例 #7
0
ファイル: coreAlan.c プロジェクト: SCIInstitute/Cleaver
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;
}
コード例 #8
0
ファイル: mod.c プロジェクト: BRAINSia/teem
static int
theFunc(Nrrd *nout, const Nrrd *nin, int func, funcParm *parm) {
  static const char me[]="theFunc";
  float *tin, *tout, eval[3], evec[9], weight[3], size, mean;
  size_t NN, II;
  unsigned int ri;

  if (!AIR_IN_OP(funcUnknown, func, funcLast)) {
    biffAddf(TEN, "%s: given func %d out of range [%d,%d]", me, func,
             funcUnknown+1, funcLast-1);
    return 1;
  }
  if (!(nout && nin && parm)) {
    biffAddf(TEN, "%s: got NULL pointer", me);
    return 1;
  }
  if (tenTensorCheck(nin, nrrdTypeFloat, AIR_FALSE, AIR_TRUE)) {
    biffAddf(TEN, "%s: didn't get a tensor nrrd", me);
    return 1;
  }
  if (nout != nin) {
    if (nrrdCopy(nout, nin)) {
      biffMovef(TEN, NRRD, "%s: couldn't allocate output", me);
      return 1;
    }
  }

  tin = (float*)(nin->data);
  tout = (float*)(nout->data);
  NN = nrrdElementNumber(nin)/7;
  switch(func) {
  case funcSizeNormalize:
    ELL_3V_COPY_TT(weight, float, parm->weight);
    size = weight[0] + weight[1] + weight[2];
    if (!size) {
      biffAddf(TEN, "%s: some of eigenvalue weights is zero", me);
      return 1;
    }
    weight[0] /= size;
    weight[1] /= size;
    weight[2] /= size;
    for (II=0; II<=NN-1; II++) {
      tenEigensolve_f(eval, evec, tin);
      size = (weight[0]*AIR_ABS(eval[0])
              + weight[1]*AIR_ABS(eval[1])
              + weight[2]*AIR_ABS(eval[2]));
      ELL_3V_SET_TT(eval, float,
                    AIR_AFFINE(0, parm->amount, 1,
                               eval[0], parm->target*eval[0]/size),
                    AIR_AFFINE(0, parm->amount, 1,
                               eval[1], parm->target*eval[1]/size),
                    AIR_AFFINE(0, parm->amount, 1,
                               eval[2], parm->target*eval[2]/size));
      tenMakeSingle_f(tout, tin[0], eval, evec);
      tin += 7;
      tout += 7;
    }
    break;
  case funcSizeScale:
    for (II=0; II<=NN-1; II++) {
      TEN_T_SET_TT(tout, float,
                   tin[0],
                   parm->amount*tin[1],
                   parm->amount*tin[2],
                   parm->amount*tin[3],
                   parm->amount*tin[4],
                   parm->amount*tin[5],
                   parm->amount*tin[6]);
      tin += 7;
      tout += 7;
    }
    break;
  case funcAnisoScale:
    for (II=0; II<=NN-1; II++) {
      tenEigensolve_f(eval, evec, tin);
      if (parm->fixDet) {
        eval[0] = AIR_MAX(eval[0], 0.00001f);
        eval[1] = AIR_MAX(eval[1], 0.00001f);
        eval[2] = AIR_MAX(eval[2], 0.00001f);
        ELL_3V_SET_TT(eval, float, log(eval[0]), log(eval[1]), log(eval[2]));
      }
      mean = (eval[0] + eval[1] + eval[2])/3.0f;
      ELL_3V_SET_TT(eval, float,
                    AIR_LERP(parm->scale, mean, eval[0]),
                    AIR_LERP(parm->scale, mean, eval[1]),
                    AIR_LERP(parm->scale, mean, eval[2]));
      if (parm->fixDet) {
        ELL_3V_SET_TT(eval, float, exp(eval[0]), exp(eval[1]), exp(eval[2]));
      }
      if (eval[2] < 0 && parm->makePositive) {
        eval[0] = AIR_MAX(eval[0], 0.0f);
        eval[1] = AIR_MAX(eval[1], 0.0f);
        eval[2] = AIR_MAX(eval[2], 0.0f);
      }
      tenMakeSingle_f(tout, tin[0], eval, evec);
      tin += 7;
      tout += 7;
    }
    break;
  case funcEigenvalueClamp:
    for (II=0; II<=NN-1; II++) {
      tenEigensolve_f(eval, evec, tin);
      if (AIR_EXISTS(parm->min)) {
        ELL_3V_SET_TT(eval, float,
                      AIR_MAX(eval[0], parm->min),
                      AIR_MAX(eval[1], parm->min),
                      AIR_MAX(eval[2], parm->min));
      }
      if (AIR_EXISTS(parm->max)) {
        ELL_3V_SET_TT(eval, float,
                      AIR_MIN(eval[0], parm->max),
                      AIR_MIN(eval[1], parm->max),
                      AIR_MIN(eval[2], parm->max));
      }
      tenMakeSingle_f(tout, tin[0], eval, evec);
      tin += 7;
      tout += 7;
    }
コード例 #9
0
ファイル: formatNRRD.c プロジェクト: SCIInstitute/Cleaver
/*
** this is responsible for the header-relative path processing
**
** NOTE: if the filename is "-", then because it does not start with '/',
** it would normally be prefixed by nio->path, so it needs special handling
**
** NOTE: this should work okay with nio->headerStringRead, I think ...
*/
int
nrrdIoStateDataFileIterNext(FILE **fileP, NrrdIoState *nio, int reading) {
  char me[]="nrrdIoStateDataFileIterNext", *err;
  char *fname=NULL;
  int ii, needPath;
  unsigned int num, fi;
  size_t maxl;
  airArray *mop;

  mop = airMopNew();
  airMopAdd(mop, (void*)fileP, (airMopper)airSetNull, airMopOnError);

  if (!fileP) {
    if ((err = (char*)malloc(BIFF_STRLEN))) {
      sprintf(err, "%s: got NULL pointer", me);
      biffAdd(NRRD, err); free(err);
    }
    airMopError(mop); return 1;
  }
  if (!_nrrdDataFNNumber(nio)) {
    if ((err = (char*)malloc(BIFF_STRLEN))) {
      sprintf(err, "%s: there appear to be zero datafiles!", me);
      biffAdd(NRRD, err); free(err);
    }
    airMopError(mop); return 1;
  }

  nio->dataFNIndex++;
  if (nio->dataFNIndex >= (int)_nrrdDataFNNumber(nio)) {
    /* there is no next data file, but we don't make that an error */
    nio->dataFNIndex = _nrrdDataFNNumber(nio);
    airMopOkay(mop);
    *fileP = NULL;
    return 0;
  }

  /* HEY: some of this error checking is done far more often than needed */
  if (nio->dataFNFormat || nio->dataFNArr->len) {
    needPath = AIR_FALSE;
    maxl = 0;
    if (nio->dataFNFormat) {
      needPath = _NEED_PATH(nio->dataFNFormat);
      /* assuming 10-digit integers is plenty big */
      maxl = 10 + strlen(nio->dataFNFormat);
    } else {
      for (fi=0; fi<nio->dataFNArr->len; fi++) {
        needPath |= _NEED_PATH(nio->dataFN[fi]);
        maxl = AIR_MAX(maxl, strlen(nio->dataFN[fi]));
      }
    }
    if (needPath && !airStrlen(nio->path)) {
      if ((err = (char*)malloc(BIFF_STRLEN))) {
        sprintf(err, "%s: need nio->path for header-relative datafiles", me);
        biffAdd(NRRD, err); free(err);
      }
      airMopError(mop); return 1;
    }
    fname = (char*)malloc(airStrlen(nio->path) + strlen("/") + maxl + 1);
    if (!fname) {
      if ((err = (char*)malloc(BIFF_STRLEN))) {
        sprintf(err, "%s: couldn't allocate filename buffer", me);
        biffAdd(NRRD, err); free(err);
      }
      airMopError(mop); return 1;
    }
    airMopAdd(mop, fname, airFree, airMopAlways);
  }

  if (nio->dataFNFormat) {
    /* ---------------------------------------------------------- */
    /* --------- base.%d <min> <max> <step> [<dim>] ------------- */
    /* ---------------------------------------------------------- */
    num = 0;
    for (ii = nio->dataFNMin; 
         ((nio->dataFNStep > 0 && ii <= nio->dataFNMax)
          || (nio->dataFNStep < 0 && ii >= nio->dataFNMax));
         ii += nio->dataFNStep) {
      if ((int)num == nio->dataFNIndex) {  /* HEY scrutinize cast */
        break;
      }
      num += 1;
    }
    if (_NEED_PATH(nio->dataFNFormat)) {
      strcpy(fname, nio->path);
      strcat(fname, "/");
      sprintf(fname + strlen(nio->path) + strlen("/"), nio->dataFNFormat, ii);
    } else {
      sprintf(fname, nio->dataFNFormat, ii);
    }
  } else if (nio->dataFNArr->len) {
    /* ---------------------------------------------------------- */
    /* ------------------- LIST or single ----------------------- */
    /* ---------------------------------------------------------- */
    if (_NEED_PATH(nio->dataFN[nio->dataFNIndex])) {
      sprintf(fname, "%s/%s", nio->path, nio->dataFN[nio->dataFNIndex]);
    } else {
      strcpy(fname, nio->dataFN[nio->dataFNIndex]);
    }
  }
  /* else data file is attached */
  
  if (nio->dataFNFormat || nio->dataFNArr->len) {
    *fileP = airFopen(fname, reading ? stdin : stdout, reading ? "rb" : "wb");
    if (!(*fileP)) {
      if ((err = (char*)malloc(strlen(fname) + BIFF_STRLEN))) {
        sprintf(err, "%s: couldn't open \"%s\" (data file %d of %d) for %s",
                me, fname, nio->dataFNIndex+1, (int)_nrrdDataFNNumber(nio),
                reading ? "reading" : "writing");
        biffAdd(NRRD, err); free(err);
      }
      airMopError(mop); return 1;
    }
  } else {
    /* data file is attached */
    if (nio->headerStringRead) {
      /* except we were never reading from a file to begin with, but this
         isn't an error */
      *fileP = NULL;
    } else {
      *fileP = nio->headerFile;
    }
  }
  
  airMopOkay(mop);
  return 0;
}
コード例 #10
0
ファイル: write.c プロジェクト: guo2004131/freesurfer
/*
** _nrrdSprintFieldInfo
**
** this prints "<prefix><field>: <info>" into *strP (after allocating it for
** big enough, usually with a stupidly big margin of error), in a form
** suitable to be written to NRRD or other image headers.  This will always
** print something (for valid inputs), even stupid <info>s like
** "(unknown endian)".  It is up to the caller to decide which fields
** are worth writing, via _nrrdFieldInteresting().
**
** NOTE: some of these fields make sense in non-NRRD files (e.g. all
** the per-axis information), but many only make sense in NRRD files.
** This is just one example of NRRD-format-specific stuff that is not
** in formatNRRD.c
*/
void
_nrrdSprintFieldInfo(char **strP, char *prefix,
                     const Nrrd *nrrd, NrrdIoState *nio, int field)
{
    char me[]="_nrrdSprintFieldInfo", buff[AIR_STRLEN_MED], *fnb;
    double colvec[NRRD_SPACE_DIM_MAX];
    const char *fs;
    unsigned int ii, dd,
             uintStrlen = 11,
             size_tStrlen = 33,
             doubleStrlen = 513;
    int fslen, fdlen, endi, maxl;

    if (!( strP && prefix
            && nrrd
            && AIR_IN_CL(1, nrrd->dim, NRRD_DIM_MAX)
            && AIR_IN_OP(nrrdField_unknown, field, nrrdField_last) ))
    {
        return;
    }
    if (!_nrrdFieldInteresting(nrrd, nio, field))
    {
        *strP = airStrdup("");
    }

    fs = airEnumStr(nrrdField, field);
    fslen = strlen(prefix) + strlen(fs) + strlen(": ") + 1;
    switch (field)
    {
    case nrrdField_comment:
    case nrrdField_keyvalue:
        fprintf(stderr, "%s: CONFUSION: why are you calling me on \"%s\"?\n", me,
                airEnumStr(nrrdField, nrrdField_comment));
        *strP = airStrdup("");
        break;
    case nrrdField_content:
        airOneLinify(nrrd->content);
        *strP = (char *)calloc(fslen + strlen(nrrd->content), sizeof(char));
        sprintf(*strP, "%s%s: %s", prefix, fs, nrrd->content);
        break;
    case nrrdField_number:
        *strP = (char *)calloc(fslen + size_tStrlen, sizeof(char));
        sprintf(*strP, "%s%s: " _AIR_SIZE_T_CNV, prefix, fs,
                nrrdElementNumber(nrrd));
        break;
    case nrrdField_type:
        *strP = (char *)calloc(fslen + strlen(airEnumStr(nrrdType, nrrd->type)),
                               sizeof(char));
        sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdType, nrrd->type));
        break;
    case nrrdField_block_size:
        *strP = (char *)calloc(fslen + size_tStrlen, sizeof(char));
        sprintf(*strP, "%s%s: " _AIR_SIZE_T_CNV, prefix, fs, nrrd->blockSize);
        break;
    case nrrdField_dimension:
        *strP = (char *)calloc(fslen + uintStrlen, sizeof(char));
        sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->dim);
        break;
    case nrrdField_space:
        *strP = (char *)calloc(fslen + strlen(airEnumStr(nrrdSpace, nrrd->space)),
                               sizeof(char));
        sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdSpace, nrrd->space));
        break;
    case nrrdField_space_dimension:
        *strP = (char *)calloc(fslen + uintStrlen, sizeof(char));
        sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->spaceDim);
        break;
    /* ---- begin per-axis fields ---- */
    case nrrdField_sizes:
        *strP = (char *)calloc(fslen + nrrd->dim*(size_tStrlen + 1), sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            sprintf(buff, " " _AIR_SIZE_T_CNV, nrrd->axis[ii].size);
            strcat(*strP, buff);
        }
        break;
    case nrrdField_spacings:
        *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].spacing);
            strcat(*strP, buff);
        }
        break;
    case nrrdField_thicknesses:
        *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].thickness);
            strcat(*strP, buff);
        }
        break;
    case nrrdField_axis_mins:
        *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].min);
            strcat(*strP, buff);
        }
        break;
    case nrrdField_axis_maxs:
        *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].max);
            strcat(*strP, buff);
        }
        break;
    case nrrdField_space_directions:
        *strP = (char *)calloc(fslen +
                               nrrd->dim*nrrd->spaceDim*(doubleStrlen
                                       + strlen("(,) ")),
                               sizeof(char));
        sprintf(*strP, "%s%s: ", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim,
                                   nrrd->axis[ii].spaceDirection);
            if (ii < nrrd->dim-1)
            {
                strcat(*strP, " ");
            }
        }
        break;
    case nrrdField_centers:
        fdlen = 0;
        for (ii=0; ii<nrrd->dim; ii++)
        {
            fdlen += 1 + airStrlen(nrrd->axis[ii].center
                                   ? airEnumStr(nrrdCenter, nrrd->axis[ii].center)
                                   : NRRD_UNKNOWN);
        }
        *strP = (char *)calloc(fslen + fdlen, sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            sprintf(buff, " %s",
                    (nrrd->axis[ii].center
                     ? airEnumStr(nrrdCenter, nrrd->axis[ii].center)
                     : NRRD_UNKNOWN));
            strcat(*strP, buff);
        }
        break;
    case nrrdField_kinds:
        fdlen = 0;
        for (ii=0; ii<nrrd->dim; ii++)
        {
            fdlen += 1 + airStrlen(nrrd->axis[ii].kind
                                   ? airEnumStr(nrrdKind, nrrd->axis[ii].kind)
                                   : NRRD_UNKNOWN);
        }
        *strP = (char *)calloc(fslen + fdlen, sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            sprintf(buff, " %s",
                    (nrrd->axis[ii].kind
                     ? airEnumStr(nrrdKind, nrrd->axis[ii].kind)
                     : NRRD_UNKNOWN));
            strcat(*strP, buff);
        }
        break;
    case nrrdField_labels:
        fdlen = 0;
        for (ii=0; ii<nrrd->dim; ii++)
        {
            fdlen += airStrlen(nrrd->axis[ii].label) + 4;
        }
        *strP = (char *)calloc(fslen + fdlen, sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            strcat(*strP, " \"");
            if (airStrlen(nrrd->axis[ii].label))
            {
                strcat(*strP, nrrd->axis[ii].label);
            }
            strcat(*strP, "\"");
        }
        break;
    case nrrdField_units:
        fdlen = 0;
        for (ii=0; ii<nrrd->dim; ii++)
        {
            fdlen += airStrlen(nrrd->axis[ii].units) + 4;
        }
        *strP = (char *)calloc(fslen + fdlen, sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            strcat(*strP, " \"");
            if (airStrlen(nrrd->axis[ii].units))
            {
                strcat(*strP, nrrd->axis[ii].units);
            }
            strcat(*strP, "\"");
        }
        break;
    /* ---- end per-axis fields ---- */
    case nrrdField_min:
    case nrrdField_max:
        /* we're basically a no-op, now that these fields became meaningless */
        *strP = (char *)calloc(fslen + doubleStrlen, sizeof(char));
        sprintf(*strP, "%s%s: 0.0", prefix, fs);
        strcat(*strP, buff);
        break;
    case nrrdField_old_min:
        *strP = (char *)calloc(fslen + doubleStrlen, sizeof(char));
        sprintf(*strP, "%s%s: ", prefix, fs);
        airSinglePrintf(NULL, buff, "%g", nrrd->oldMin);
        strcat(*strP, buff);
        break;
    case nrrdField_old_max:
        *strP = (char *)calloc(fslen + doubleStrlen, sizeof(char));
        sprintf(*strP, "%s%s: ", prefix, fs);
        airSinglePrintf(NULL, buff, "%g", nrrd->oldMax);
        strcat(*strP, buff);
        break;
    case nrrdField_endian:
        if (airEndianUnknown != nio->endian)
        {
            /* we know a specific endianness because either it was recorded as
               part of "unu make -h", or it was set (and data was possibly
               altered) as part of "unu save" */
            endi = nio->endian;
        }
        else
        {
            /* we record our current architecture's endian because we're
               going to writing out data */
            endi = AIR_ENDIAN;
        }
        *strP = (char *)calloc(fslen + strlen(airEnumStr(airEndian, endi)),
                               sizeof(char));
        sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(airEndian, endi));
        break;
    case nrrdField_encoding:
        *strP = (char *)calloc(fslen + strlen(nio->encoding->name),
                               sizeof(char));
        sprintf(*strP, "%s%s: %s", prefix, fs, nio->encoding->name);
        break;
    case nrrdField_line_skip:
        *strP = (char *)calloc(fslen + uintStrlen, sizeof(char));
        sprintf(*strP, "%s%s: %d", prefix, fs, nio->lineSkip);
        break;
    case nrrdField_byte_skip:
        *strP = (char *)calloc(fslen + uintStrlen, sizeof(char));
        sprintf(*strP, "%s%s: %d", prefix, fs, nio->byteSkip);
        break;
    case nrrdField_sample_units:
        airOneLinify(nrrd->sampleUnits);
        *strP = (char *)calloc(fslen + strlen(nrrd->sampleUnits), sizeof(char));
        sprintf(*strP, "%s%s: \"%s\"", prefix, fs, nrrd->sampleUnits);
        break;
    case nrrdField_space_units:
        fdlen = 0;
        for (ii=0; ii<nrrd->spaceDim; ii++)
        {
            fdlen += airStrlen(nrrd->spaceUnits[ii]) + 4;
        }
        *strP = (char *)calloc(fslen + fdlen, sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->spaceDim; ii++)
        {
            strcat(*strP, " \"");
            if (airStrlen(nrrd->spaceUnits[ii]))
            {
                strcat(*strP, nrrd->spaceUnits[ii]);
            }
            strcat(*strP, "\"");
        }
        break;
    case nrrdField_space_origin:
        *strP = (char *)calloc(fslen + nrrd->spaceDim*(doubleStrlen
                               + strlen("(,) ")),
                               sizeof(char));
        sprintf(*strP, "%s%s: ", prefix, fs);
        _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, nrrd->spaceOrigin);
        break;
    case nrrdField_measurement_frame:
        *strP = (char *)calloc(fslen + (nrrd->spaceDim*
                                        nrrd->spaceDim*(doubleStrlen
                                                + strlen("(,) "))),
                               sizeof(char));
        sprintf(*strP, "%s%s: ", prefix, fs);
        for (dd=0; dd<nrrd->spaceDim; dd++)
        {
            for (ii=0; ii<nrrd->spaceDim; ii++)
            {
                colvec[ii] = nrrd->measurementFrame[dd][ii];
            }
            _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, colvec);
            if (dd < nrrd->spaceDim-1)
            {
                strcat(*strP, " ");
            }
        }
        break;
    case nrrdField_data_file:
        /* NOTE: this comes last (nrrdField_data_file is the highest-valued
           member of the nrrdField* enum) because the "LIST" form of the
           data file specification requires that the following lines be
           the filenames */
        /* error checking elsewhere: assumes there is data file info */
        if (nio->dataFNFormat)
        {
            *strP = (char *)calloc(fslen + strlen(nio->dataFNFormat) + 4*uintStrlen,
                                   sizeof(char));
            if (nio->dataFileDim == nrrd->dim-1)
            {
                sprintf(*strP, "%s%s: %s %d %d %d", prefix, fs, nio->dataFNFormat,
                        nio->dataFNMin, nio->dataFNMax, nio->dataFNStep);
            }
            else
            {
                sprintf(*strP, "%s%s: %s %d %d %d %d", prefix, fs, nio->dataFNFormat,
                        nio->dataFNMin, nio->dataFNMax, nio->dataFNStep,
                        nio->dataFileDim);
            }
        }
        else if (nio->dataFNArr->len > 1)
        {
            maxl = 0;
            for (ii=0; ii<nio->dataFNArr->len; ii++)
            {
                maxl = AIR_MAX(maxl, (int)strlen(nio->dataFN[ii]));
            }
            *strP = (char *)calloc(fslen + strlen(NRRD_LIST_FLAG)
                                   + uintStrlen + nio->dataFNArr->len * (maxl + 1),
                                   sizeof(char));
            fnb = (char *)calloc(fslen + strlen(NRRD_LIST_FLAG)
                                 + uintStrlen + maxl + 1,
                                 sizeof(char));
            if (nio->dataFileDim == nrrd->dim-1)
            {
                sprintf(*strP, "%s%s: LIST\n", prefix, fs);
            }
            else
            {
                sprintf(*strP, "%s%s: LIST %d\n", prefix, fs, nio->dataFileDim);
            }
            for (ii=0; ii<nio->dataFNArr->len; ii++)
            {
                sprintf(fnb, "%s%s", nio->dataFN[ii],
                        ii<nio->dataFNArr->len-1 ? "\n" : "");
                strcat(*strP, fnb);
            }
            free(fnb);
        }
        else
        {
            /* there is some ambiguity between a "LIST" of length one,
               and a single explicit data filename, but that's harmless */
            *strP = (char *)calloc(fslen + strlen("./")
                                   + strlen(nio->dataFN[0]) + 1,
                                   sizeof(char));
            sprintf(*strP, "%s%s: %s%s", prefix, fs,
                    /* this is a favor to older readers that can deal with
                       this NRRD file because its being saved in a NRRD0003
                       (or below) version, so we don't want to confuse them
                       by not having the old explicit header-relative flag */
                    (_nrrdFormatNRRD_whichVersion(nrrd, nio) < 4 ? "./" : ""),
                    nio->dataFN[0]);
        }
        break;
    default:
        fprintf(stderr, "%s: CONFUSION: field %d unrecognized\n", me, field);
        break;
    }

    return;
}
コード例 #11
0
ファイル: gkmsPvg.c プロジェクト: SCIInstitute/Cleaver
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 {
コード例 #12
0
ファイル: tenDwiGage.c プロジェクト: ryanfb/teem-parallel
void
_tenDwiGageAnswer(gageContext *ctx, gagePerVolume *pvl) {
  char me[]="_tenDwiGageAnswer";
  unsigned int dwiIdx;
  tenDwiGageKindData *kindData;
  tenDwiGagePvlData *pvlData;
  double *dwiAll, dwiMean=0, tentmp[7];

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

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

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

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

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

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

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

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

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

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

    guess[2] = AIR_PI/4;
    guess[3] = -AIR_PI/4;
    /*
    guess[2] = AIR_AFFINE(0, airDrandMT_r(pvlData->randState), 1,
                          AIR_PI/6, AIR_PI/3);
    guess[3] = AIR_AFFINE(0, airDrandMT_r(pvlData->randState), 1,
                          -AIR_PI/6, -AIR_PI/3);
    */
    /* Fill in the constraints for the LM optimization, 
       the threshold of error difference */
    opts[0] = pvlData->levmarTau;
    opts[1] = pvlData->levmarEps1;
    opts[2] = pvlData->levmarEps2;
    opts[3] = pvlData->levmarEps3;
    /* Very imp to set this opt, note that only forward
       differences are used to approx Jacobian */
    opts[4] = pvlData->levmarDelta;
    
    /* run NLLS, results are stored back into guess[] */
    pvlData->levmarUseFastExp = AIR_FALSE;
    lmret = dlevmar_bc_dif(_tenLevmarPeledCB, guess, pvlData->tec2->dwi,
                           PARAMS, pvlData->tec2->dwiNum, loBnd, upBnd,
                           pvlData->levmarMaxIter, opts,
                           pvlData->levmarInfo,
                           NULL, NULL, pvlData);
    if (-1 == lmret) {
      ctx->errNum = 1;
      sprintf(ctx->errStr, "%s: dlevmar_bc_dif() failed!", me);
    } else {
      /* Get the AIC for the two tensor fit, use the levmarinfo
         to get the residual */
      /*
        residual = pvlData->levmarInfo[1]/pvlData->tec2->dwiNum;
        AICTwoFit = _tenComputeAIC(residual, pvlData->tec2->dwiNum, 12);
      */
      /* Form the tensors using the estimated pp, returned in guess */
      _tenPeledRotate2D(tenA, guess[0], pvlData->ten1Eval[2], guess[2]);
      _tenPeledRotate2D(tenB, guess[0], pvlData->ten1Eval[2], guess[3]);
      TEN_T2M(matA, tenA);
      TEN_T2M(matB, tenB);
      
      ELL_3M_TRANSPOSE(rott, pvlData->ten1Evec);
      ELL_3M_MUL(matTmp, matA, pvlData->ten1Evec);
      ELL_3M_MUL(matA, rott, matTmp);
      ELL_3M_MUL(matTmp, matB, pvlData->ten1Evec);
      ELL_3M_MUL(matB, rott, matTmp);
      
      /* Copy two two tensors */
      /* guess[1] is population fraction of first tensor */
      if (guess[1] > 0.5) {
        twoTen[7] = guess[1];
        TEN_M2T(twoTen + 0, matA);
        TEN_M2T(twoTen + 7, matB);
      } else {
        twoTen[7] = 1 - guess[1];
        TEN_M2T(twoTen + 0, matB);
        TEN_M2T(twoTen + 7, matA);
      }
      twoTen[0] = 1;
    }
#undef PARAMS
#else
    double *twoTen;
    twoTen = pvl->directAnswer[tenDwiGage2TensorPeled];
    TEN_T_SET(twoTen + 0, AIR_NAN, AIR_NAN, AIR_NAN, AIR_NAN,
              AIR_NAN, AIR_NAN, AIR_NAN);
    TEN_T_SET(twoTen + 7, AIR_NAN, AIR_NAN, AIR_NAN, AIR_NAN,
              AIR_NAN, AIR_NAN, AIR_NAN);
    fprintf(stderr, "%s: sorry, not compiled with TEEM_LEVMAR\n", me);
#endif
  }
コード例 #13
0
ファイル: qglox.c プロジェクト: CIBC-Internal/teem
/*
** This does (non-optionally) use biff, to report convergence failures
**
** we do in fact require non-NULL tip, because it holds the buffers we need
*/
int
_tenQGLInterpNEvec(double evecOut[9],
                   const double *evecIn, /* size 9 -by- NN */
                   const double *wght,   /* size NN */
                   unsigned int NN,
                   tenInterpParm *tip) {
  static const char me[]="_tenQGLInterpNEvec";
  double qOut[4], maxWght, len, /* odsum, */ dsum, rot[9];
  unsigned int ii, centerIdx=0, fix, qiter;

  if (!( evecOut && evecIn && tip )) {
    biffAddf(TEN, "%s: got NULL pointer", me);
    return 1;
  }
  /* convert to quaternions */
  for (ii=0; ii<NN; ii++) {
    ELL_3M_TRANSPOSE(rot, evecIn + 9*ii);
    ell_3m_to_q_d(tip->qIn + 4*ii, rot);
  }
  /* HEY: what should this be used for?  variable odsum set but not used */
  /* odsum = _tenQGL_q_interdot(&centerIdx, tip->qIn, tip->qInter, NN); */

  /* find quaternion with maximal weight, use it as is (decree that
     its the right representative), and then align rest with that.
     This is actually principled; symmetry allows it */
  centerIdx = 0;
  if (wght) {
    maxWght = wght[centerIdx];
    for (ii=1; ii<NN; ii++) {
      if (wght[ii] > maxWght) {
        centerIdx = ii;
        maxWght = wght[centerIdx];
      }
    }
  }
  for (ii=0; ii<NN; ii++) {
    if (ii == centerIdx) {
      continue;
    }
    _tenQGL_q_align(tip->qIn + 4*ii, tip->qIn + 4*centerIdx, tip->qIn + 4*ii);
  }
  dsum = _tenQGL_q_interdot(&centerIdx, tip->qIn, tip->qInter, NN);

  /* try to settle on tightest set of representatives */
  qiter = 0;
  do {
    fix = 0;
    for (ii=0; ii<NN; ii++) {
      unsigned int ff;
      if (ii == centerIdx) {
        continue;
      }
      ff = _tenQGL_q_align(tip->qIn + 4*ii, tip->qIn + 4*centerIdx,
                           tip->qIn + 4*ii);
      fix = AIR_MAX(fix, ff);
    }
    dsum = _tenQGL_q_interdot(&centerIdx, tip->qIn, tip->qInter, NN);
    if (tip->maxIter && qiter > tip->maxIter) {
      biffAddf(TEN, "%s: q tightening unconverged after %u iters; "
               "interdot = %g -> maxfix = %u; center = %u\n",
               me, tip->maxIter, dsum, fix, centerIdx);
      return 1;
    }
    qiter++;
  } while (fix);
  /*
  fprintf(stderr, "!%s: dsum %g --%u--> %g\n", me, odsum, qiter, dsum);
  */
  /* make sure they're normalized */
  for (ii=0; ii<NN; ii++) {
    ELL_4V_NORM(tip->qIn + 4*ii, tip->qIn + 4*ii, len);
  }

  /* compute iterated weighted mean, stored in qOut */
  if (ell_q_avgN_d(qOut, &qiter, tip->qIn, tip->qBuff, wght,
                   NN, tip->convEps, tip->maxIter)) {
    biffMovef(TEN, ELL, "%s: problem doing quaternion mean", me);
    return 1;
  }
  /*
  fprintf(stderr, "!%s: q avg converged in %u\n", me, qiter);
  */

  /* finish, convert back to evec */
  ell_q_to_3m_d(rot, qOut);
  ELL_3M_TRANSPOSE(evecOut, rot);

  return 0;
}
コード例 #14
0
ファイル: vh.c プロジェクト: SCIInstitute/Cleaver
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);
}
コード例 #15
0
ファイル: shape.c プロジェクト: ryanfb/teem-parallel
/*
** _gageShapeSet
**
** we are serving two masters here.  If ctx is non-NULL, we are being called
** from within gage, and we are to be lax or strict according to the settings
** of ctx->parm.requireAllSpacings and ctx->parm.requireEqualCenters.  If
** ctx is NULL, gageShapeSet was called, in which case we go with lax
** behavior (nothing "required")
**
** This function has subsumed the old gageVolumeCheck, and hence has 
** become this weird beast- part error checker and part (gageShape)
** initializer.  Oh well...
*/
int
_gageShapeSet(const gageContext *ctx, gageShape *shape,
              const Nrrd *nin, unsigned int baseDim) {
  char me[]="_gageShapeSet", err[BIFF_STRLEN];
  int ai, cx, cy, cz, defCenter, statCalc[3];
  unsigned int minsize, sx, sy, sz;
  const NrrdAxisInfo *ax[3];
  double maxLen, defSpacing,
    vecA[4], vecB[3], vecC[3], vecD[4], matA[9],
    spcCalc[3], vecCalc[3][NRRD_SPACE_DIM_MAX], orig[NRRD_SPACE_DIM_MAX];

  /* ------ basic error checking */
  if (!( shape && nin )) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(GAGE, err);  if (shape) { gageShapeReset(shape); }
    return 1;
  }
  if (nrrdCheck(nin)) {
    sprintf(err, "%s: basic nrrd validity check failed", me);
    biffMove(GAGE, err, NRRD); gageShapeReset(shape);
    return 1;
  }
  if (nrrdTypeBlock == nin->type) {
    sprintf(err, "%s: need a non-block type nrrd", me);
    biffAdd(GAGE, err); gageShapeReset(shape);
    return 1;
  }
  if (!(nin->dim == 3 + baseDim)) {
    sprintf(err, "%s: nrrd should be %u-D, not %u-D",
            me, 3 + baseDim, nin->dim);
    biffAdd(GAGE, err); gageShapeReset(shape);
    return 1;
  }
  ax[0] = &(nin->axis[baseDim+0]);
  ax[1] = &(nin->axis[baseDim+1]);
  ax[2] = &(nin->axis[baseDim+2]);
  /*
  if (1) {
    unsigned int ai;
    for (ai=0; ai<3; ai++) {
      fprintf(stderr, "!%s: ax[%u] spc = %g, sd = %g %g %g\n", me, ai,
              ax[ai]->spacing,
              ax[ai]->spaceDirection[0],
              ax[ai]->spaceDirection[1],
              ax[ai]->spaceDirection[2]);
    }
  }
  */
  statCalc[0] = nrrdSpacingCalculate(nin, baseDim + 0,
                                     spcCalc + 0, vecCalc[0]);
  statCalc[1] = nrrdSpacingCalculate(nin, baseDim + 1,
                                     spcCalc + 1, vecCalc[1]);
  statCalc[2] = nrrdSpacingCalculate(nin, baseDim + 2,
                                     spcCalc + 2, vecCalc[2]);
  /*
  fprintf(stderr, "!%s: axis stat %d %d %d\n", me,
          statCalc[0], statCalc[1], statCalc[2]);
  */
  /* see if nrrdSpacingCalculate ever *failed* */
  if (nrrdSpacingStatusUnknown == statCalc[0]
      || nrrdSpacingStatusUnknown == statCalc[1]
      || nrrdSpacingStatusUnknown == statCalc[2]) {
    sprintf(err, "%s: nrrdSpacingCalculate trouble on axis %d, %d, or %d",
            me, baseDim + 0, baseDim + 1, baseDim + 2);
    biffAdd(GAGE, err); gageShapeReset(shape);
    return 1;
  }
  /* see if nrrdSpacingCalculate encountered an axis with no space
     direction in a nrrd that nominally has a surrounding space */
  if (nrrdSpacingStatusScalarWithSpace == statCalc[0]
      || nrrdSpacingStatusScalarWithSpace == statCalc[1]
      || nrrdSpacingStatusScalarWithSpace == statCalc[2]) {
    sprintf(err, "%s: nrrdSpacingCalculate weirdness on axis %d, %d, or %d",
            me, baseDim + 0, baseDim + 1, baseDim + 2);
    biffAdd(GAGE, err); gageShapeReset(shape);
    return 1;
  }
  if (!( (   nrrdSpacingStatusDirection == statCalc[0]
          && nrrdSpacingStatusDirection == statCalc[1]
          && nrrdSpacingStatusDirection == statCalc[2])
         ||
         (   nrrdSpacingStatusDirection != statCalc[0]
          && nrrdSpacingStatusDirection != statCalc[1]
          && nrrdSpacingStatusDirection != statCalc[2])
         )) {
    sprintf(err, "%s: inconsistent space directions use "
            "in axis %d, %d, and %d",
            me, baseDim + 0, baseDim + 1, baseDim + 2);
    biffAdd(GAGE, err); gageShapeReset(shape);
    return 1;
  }
  if (   nrrdSpacingStatusDirection == statCalc[0]
      && nrrdSpacingStatusDirection == statCalc[1]
      && nrrdSpacingStatusDirection == statCalc[2]) {
    /* this will get reset to false in case of error */
    shape->fromOrientation = AIR_TRUE;
  } else {
    shape->fromOrientation = AIR_FALSE;
  }
  /* oh yea, we should make sure the space dimension is right! */
  if (shape->fromOrientation && 3 != nin->spaceDim) {
    sprintf(err, "%s: orientation space dimension %d != 3",
            me, nin->spaceDim);
    biffAdd(GAGE, err); gageShapeReset(shape);
    return 1;
  }

  /* ------ find centering (set shape->center) */
  /* HEY: when we have full orientation information (via spaceDirections
     and spaceOrigin) the centering information is moot for determining
     shape, but until all usage of gageShape stuff is properly overhauled
     to take orientation into account, we'll still set shape->center */
  cx = ax[0]->center;
  cy = ax[1]->center;
  cz = ax[2]->center;
  if (ctx && ctx->parm.requireEqualCenters) {
    if (!( cx == cy && cx == cz )) {
      sprintf(err, "%s: axes %d,%d,%d centerings (%s,%s,%s) not equal", me,
              baseDim+0, baseDim+1, baseDim+2,
              airEnumStr(nrrdCenter, cx),
              airEnumStr(nrrdCenter, cy),
              airEnumStr(nrrdCenter, cz));
      biffAdd(GAGE, err); gageShapeReset(shape);
      return 1;
    }
  } else {
    if (   (nrrdCenterUnknown != cx && nrrdCenterUnknown != cy && cx != cy) 
        || (nrrdCenterUnknown != cy && nrrdCenterUnknown != cz && cy != cz) 
        || (nrrdCenterUnknown != cx && nrrdCenterUnknown != cz && cx != cz) ) {
      sprintf(err, "%s: two known centerings (of %s,%s,%s) are unequal", me,
              airEnumStr(nrrdCenter, cx),
              airEnumStr(nrrdCenter, cy),
              airEnumStr(nrrdCenter, cz));
      biffAdd(GAGE, err); gageShapeReset(shape);
      return 1;
    }
  }
  defCenter = ctx ? ctx->parm.defaultCenter : shape->defaultCenter;
  shape->center = (nrrdCenterUnknown != cx ? cx
                   : (nrrdCenterUnknown != cy ? cy
                      : (nrrdCenterUnknown != cz ? cz
                         : defCenter)));

  /* ------ find sizes (set shape->size[0,1,2]) */
  sx = ax[0]->size;
  sy = ax[1]->size;
  sz = ax[2]->size;
  minsize = (nrrdCenterCell == shape->center ? 1 : 2);
  /* HEY: perhaps this should be relaxed if we have full orientation info */
  if (!(sx >= minsize && sy >= minsize && sz >= minsize )) {
    sprintf(err, "%s: sizes (%u,%u,%u) must all be >= %u "
            "(min number of %s-centered samples)", me, 
            sx, sy, sz, minsize, airEnumStr(nrrdCenter, shape->center));
    biffAdd(GAGE, err); gageShapeReset(shape);
    return 1;
  }
  shape->size[0] = sx;
  shape->size[1] = sy;
  shape->size[2] = sz;

  /* ------ find spacings (set shape->spacing[0,1,2]) */
  if (shape->fromOrientation) {
    shape->spacing[0] = AIR_ABS(spcCalc[0]);
    shape->spacing[1] = AIR_ABS(spcCalc[1]);
    shape->spacing[2] = AIR_ABS(spcCalc[2]);
    for (ai=0; ai<=2; ai++) {
      shape->volHalfLen[ai] = AIR_NAN;
      shape->voxLen[ai] = AIR_NAN;
    }
  } else {
    double xs, ys, zs;
    unsigned int num[3];
    xs = ax[0]->spacing;
    ys = ax[1]->spacing;
    zs = ax[2]->spacing;
    if (ctx && ctx->parm.requireAllSpacings) {
      if (!( AIR_EXISTS(xs) && AIR_EXISTS(ys) && AIR_EXISTS(zs) )) {
        sprintf(err, "%s: spacings for axes %d,%d,%d don't all exist",
                me, baseDim+0, baseDim+1, baseDim+2);
        biffAdd(GAGE, err); gageShapeReset(shape);
        return 1;
      }
    }
    /* there is no shape->defaultSpacing, we'll go out on a limb ... */
    defSpacing = ctx ? ctx->parm.defaultSpacing : nrrdDefaultSpacing;
    xs = AIR_EXISTS(xs) ? xs : defSpacing;
    ys = AIR_EXISTS(ys) ? ys : defSpacing;
    zs = AIR_EXISTS(zs) ? zs : defSpacing;
    if (!( xs != 0 && ys != 0 && zs != 0 )) {
      sprintf(err, "%s: spacings (%g,%g,%g) for axes %d,%d,%d not all "
              "non-zero", me, xs, ys, zs, baseDim+0, baseDim+1, baseDim+2);
      biffAdd(GAGE, err); gageShapeReset(shape);
      return 1;
    }
    /* ------ learn lengths for bounding nrrd in bi-unit cube
       (set shape->volHalfLen[0,1,2] and shape->voxLen[0,1,2]) */
    shape->spacing[0] = AIR_ABS(xs);
    shape->spacing[1] = AIR_ABS(ys);
    shape->spacing[2] = AIR_ABS(zs);
    maxLen = 0.0;
    for (ai=0; ai<=2; ai++) {
      num[ai] = (nrrdCenterNode == shape->center
                 ? shape->size[ai]-1
                 : shape->size[ai]);
      shape->volHalfLen[ai] = num[ai]*shape->spacing[ai];
      maxLen = AIR_MAX(maxLen, shape->volHalfLen[ai]);
    }
    /* Thu Dec 13 02:45:01 EST 2007
       fixed long-standing bug in handling vols without full orientation info:
       spacing[ai] was never scaled to account for being crammed into
       the bi-unit cube!! */
    for (ai=0; ai<=2; ai++) {
      shape->volHalfLen[ai] /= maxLen;
      shape->spacing[ai] = shape->voxLen[ai] = 2*shape->volHalfLen[ai]/num[ai];
    }
  }
  
  /* ------ set transform matrices */
  if (shape->fromOrientation) {
    /* find translation vector (we check above that spaceDim == 3) */
    nrrdSpaceOriginGet(nin, orig);
    if (!( AIR_EXISTS(orig[0]) &&
           AIR_EXISTS(orig[1]) && 
           AIR_EXISTS(orig[2]) )) {
      /* don't have origin, so set it to come from the middle of volume */
      ELL_3V_SET(orig, 0.0f, 0.0f, 0.0f);
      ELL_3V_SCALE_INCR(orig, -(shape->size[0] - 1.0f)*spcCalc[0]/2.0f,
                        vecCalc[0]);
      ELL_3V_SCALE_INCR(orig, -(shape->size[1] - 1.0f)*spcCalc[1]/2.0f,
                        vecCalc[1]);
      ELL_3V_SCALE_INCR(orig, -(shape->size[2] - 1.0f)*spcCalc[2]/2.0f,
                        vecCalc[2]);
    }
    vecD[3] = 0;
    ELL_3V_SCALE(vecD, spcCalc[0], vecCalc[0]);
    ELL_4MV_COL0_SET(shape->ItoW, vecD);
    ELL_3V_SCALE(vecD, spcCalc[1], vecCalc[1]);
    ELL_4MV_COL1_SET(shape->ItoW, vecD);
    ELL_3V_SCALE(vecD, spcCalc[2], vecCalc[2]);
    ELL_4MV_COL2_SET(shape->ItoW, vecD);
    vecD[3] = 1;
    ELL_3V_COPY(vecD, orig);
    ELL_4MV_COL3_SET(shape->ItoW, vecD);
    /*
    fprintf(stderr, "%s: %g (%g,%g,%g)\n", me,
            spcCalc[0], vecCalc[0][0], vecCalc[0][1], vecCalc[0][2]);
    fprintf(stderr, "%s: %g (%g,%g,%g)\n", me,
            spcCalc[1], vecCalc[1][0], vecCalc[1][1], vecCalc[1][2]);
    fprintf(stderr, "%s: %g (%g,%g,%g)\n", me,
            spcCalc[2], vecCalc[2][0], vecCalc[2][1], vecCalc[2][2]);
    */
  } else {
    ELL_3V_SET(vecC, 0, 0, 0);
    _gageShapeUnitItoW(shape, vecA, vecC);
    ELL_3V_SET(vecC, 1, 0, 0);
    _gageShapeUnitItoW(shape, vecB, vecC);
    ELL_3V_SUB(vecD, vecB, vecA);
    vecD[3] = 0;
    ELL_4MV_COL0_SET(shape->ItoW, vecD);

    ELL_3V_SET(vecC, 0, 1, 0);
    _gageShapeUnitItoW(shape, vecB, vecC);
    ELL_3V_SUB(vecD, vecB, vecA);
    vecD[3] = 0;
    ELL_4MV_COL1_SET(shape->ItoW, vecD);

    ELL_3V_SET(vecC, 0, 0, 1);
    _gageShapeUnitItoW(shape, vecB, vecC);
    ELL_3V_SUB(vecD, vecB, vecA);
    vecD[3] = 0;
    ELL_4MV_COL2_SET(shape->ItoW, vecD);

    vecA[3] = 1;
    ELL_4MV_COL3_SET(shape->ItoW, vecA);
  }
  ell_4m_inv_d(shape->WtoI, shape->ItoW);

  ELL_34M_EXTRACT(matA, shape->ItoW);
  ell_3m_inv_d(shape->ItoWSubInv, matA);
  ELL_3M_TRANSPOSE(shape->ItoWSubInvTransp, shape->ItoWSubInv);

  return 0;
}
コード例 #16
0
ファイル: arith.c プロジェクト: BRAINSia/teem
int
nrrdArithIterAffine(Nrrd *nout, NrrdIter *minIn,
                    NrrdIter *in, NrrdIter *maxIn,
                    NrrdIter *minOut, NrrdIter *maxOut, int clamp) {
  static const char me[]="nrrdArithInterAffine";
  double (*ins)(void *v, size_t I, double d),
    mini, vin, maxi, mino, maxo, vout;
  const Nrrd *nin;
  char *contA, *contB, *contC, *contD, *contE;
  size_t I, N;

  if (!(nout && minIn && in && maxIn && minOut && maxOut)) {
    biffAddf(NRRD, "%s: got NULL pointer", me);
    return 1;
  }
  nin = (_NRRD_ITER_NRRD(in)
         ? _NRRD_ITER_NRRD(in)
         : (_NRRD_ITER_NRRD(minIn)
            ? _NRRD_ITER_NRRD(minIn)
            : (_NRRD_ITER_NRRD(maxIn)
               ? _NRRD_ITER_NRRD(maxIn)
               : (_NRRD_ITER_NRRD(minOut)
                  ? _NRRD_ITER_NRRD(minOut)
                  : _NRRD_ITER_NRRD(maxOut)))));
  if (!nin) {
    biffAddf(NRRD, "%s: can't operate solely on fixed values", me);
    return 1;
  }
  if (nrrdCopy(nout, nin)) {
    biffAddf(NRRD, "%s: couldn't initialize output", me);
    return 1;
  }
  N = nrrdElementNumber(nin);
  ins = nrrdDInsert[nout->type];
  for (I=0; I<N; I++) {
    mini = nrrdIterValue(minIn);
    vin = nrrdIterValue(in);
    maxi = nrrdIterValue(maxIn);
    mino = nrrdIterValue(minOut);
    maxo = nrrdIterValue(maxOut);
    vout = AIR_AFFINE(mini, vin, maxi, mino, maxo);
    if (clamp) {
      double mmin = AIR_MIN(mino, maxo);
      double mmax = AIR_MAX(mino, maxo);
      vout = AIR_CLAMP(mmin, vout, mmax);
    }
    ins(nout->data, I, vout);
  }
  contA = nrrdIterContent(in);
  contB = nrrdIterContent(minIn);
  contC = nrrdIterContent(maxIn);
  contD = nrrdIterContent(maxOut);
  contE = nrrdIterContent(maxOut);
  /* HEY: same annoyance about order of arguments as in function above */
  if (_nrrdContentSet_va(nout, "affine", contA, "%s,%s,%s,%s",
                         contB, contC, contD, contE)) {
    biffAddf(NRRD, "%s:", me);
    free(contA); free(contB); free(contC); free(contD); free(contE); return 1;
  }
  free(contA); free(contB); free(contC); free(contD); free(contE);

  return 0;
}
コード例 #17
0
ファイル: arith.c プロジェクト: BRAINSia/teem
static double _nrrdTernaryOpMax(double a, double b, double c) {
  b = AIR_MAX(b, c);
  return AIR_MAX(a, b);
}
コード例 #18
0
ファイル: arith.c プロジェクト: BRAINSia/teem
static double _nrrdBinaryOpMax(double a, double b)       {return AIR_MAX(a,b);}
コード例 #19
0
ファイル: flotsam.c プロジェクト: BRAINSia/teem
/*
******** unrrduCmdMain
**
** A "main" function for unu-like programs, which is very similar to
** teem/src/bin/unu.c:main(), and
** teem/src/bin/tend.c:main(), and
** teem/src/limn/test/lpu.c:main().
** With more time (and a major Teem release), this function may change,
** and those programs may use this.
**
** A sneaky but basic issue is the const-correctness of how the hestParm
** is used; we'd like to take a const hestParm* to communicate parameters
** the caller has set, but the show-stopper is that unrrduCmd->main()
** takes a non-const hestParm, and it has to be that way, because some
** unu commands alter the given hparm (which probably shouldn't happen).
** Until that's fixed, we have a non-const hestParm* coming in here.
*/
int
unrrduCmdMain(int argc, const char **argv,
              const char *cmd, const char *title,
              const unrrduCmd *const *cmdList,
              hestParm *_hparm, FILE *fusage) {
  int i, ret;
  const char *me;
  char *argv0 = NULL;
  hestParm *hparm;
  airArray *mop;

  me = argv[0];

  /* parse environment variables first, in case they break nrrdDefault*
     or nrrdState* variables in a way that nrrdSanity() should see */
  nrrdDefaultGetenv();
  nrrdStateGetenv();

  /* unu does some unu-specific environment-variable handling here */

  nrrdSanityOrDie(me);

  mop = airMopNew();
  if (_hparm) {
    hparm = _hparm;
  } else {
    hparm = hestParmNew();
    airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways);
    hparm->elideSingleEnumType = AIR_TRUE;
    hparm->elideSingleOtherType = AIR_TRUE;
    hparm->elideSingleOtherDefault = AIR_FALSE;
    hparm->elideSingleNonExistFloatDefault = AIR_TRUE;
    hparm->elideMultipleNonExistFloatDefault = AIR_TRUE;
    hparm->elideSingleEmptyStringDefault = AIR_TRUE;
    hparm->elideMultipleEmptyStringDefault = AIR_TRUE;
    hparm->cleverPluralizeOtherY = AIR_TRUE;
    /* learning columns from current window; if ioctl is available
    if (1) {
      struct winsize ws;
      ioctl(1, TIOCGWINSZ, &ws);
      hparm->columns = ws.ws_col - 1;
    }
    */
    hparm->columns = 78;
  }

  /* if there are no arguments, then we give general usage information */
  if (1 >= argc) {
    /* this is like unrrduUsageUnu() */
    unsigned int ii, maxlen = 0;
    char *buff, *fmt, tdash[] = "--- %s ---";
    for (ii=0; cmdList[ii]; ii++) {
      if (cmdList[ii]->hidden) {
        continue;
      }
      maxlen = AIR_MAX(maxlen, AIR_UINT(strlen(cmdList[ii]->name)));
    }
    if (!maxlen) {
      fprintf(fusage, "%s: problem: maxlen = %u\n", me, maxlen);
      airMopError(mop); return 1;
    }
    buff = AIR_CALLOC(strlen(tdash) + strlen(title) + 1, char);
    airMopAdd(mop, buff, airFree, airMopAlways);
    sprintf(buff, tdash, title);
    fmt = AIR_CALLOC(hparm->columns + strlen(buff) + 1, char); /* generous */
    airMopAdd(mop, buff, airFree, airMopAlways);
    sprintf(fmt, "%%%us\n",
            AIR_UINT((hparm->columns-strlen(buff))/2 + strlen(buff) - 1));
    fprintf(fusage, fmt, buff);

    for (ii=0; cmdList[ii]; ii++) {
      unsigned int cc, len;
      if (cmdList[ii]->hidden) {
        continue;
      }
      len = AIR_UINT(strlen(cmdList[ii]->name));
      strcpy(buff, "");
      for (cc=len; cc<maxlen; cc++)
        strcat(buff, " ");
      strcat(buff, cmd);
      strcat(buff, " ");
      strcat(buff, cmdList[ii]->name);
      strcat(buff, " ... ");
      len = strlen(buff);
      fprintf(fusage, "%s", buff);
      _hestPrintStr(fusage, len, len, hparm->columns,
                    cmdList[ii]->info, AIR_FALSE);
    }
    airMopError(mop);
    return 1;
  }
コード例 #20
0
ファイル: aalias.c プロジェクト: rblake/seg3d2
int
main(int argc, char *argv[]) {
  char *me, *outS;
  hestOpt *hopt;
  hestParm *hparm;
  airArray *mop;

  char *err, done[13];
  Nrrd *nin, *ndist, *nmask, *nupdate, *nout;
  NrrdKernelSpec *k00, *k11, *k22;
  int E;
  unsigned int sx, sy, sz, xi, yi, zi, si, iter, maxIter;
  gageContext *ctx;
  gagePerVolume *pvl;
  double dt, *dist, *mask, *update, thresh, eps, rmsMin;
  const double *valu, *gmag, *mcrv;

  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, "k00", "kernel", airTypeOther, 1, 1, &k00,
             "tent", "k00", NULL, NULL, nrrdHestKernelSpec);
  hestOptAdd(&hopt, "k11", "kernel", airTypeOther, 1, 1, &k11,
             "cubicd:0,0.5", "k00", NULL, NULL, nrrdHestKernelSpec);
  hestOptAdd(&hopt, "k22", "kernel", airTypeOther, 1, 1, &k22,
             "cubicdd:1,0", "k00", NULL, NULL, nrrdHestKernelSpec);
  hestOptAdd(&hopt, "dt", "step", airTypeDouble, 1, 1, &dt, "0.17",
             "time step size");
  hestOptAdd(&hopt, "th", "val", airTypeDouble, 1, 1, &thresh, "0.0",
             "the value to use for thresholding the input "
             "volume, to create the binary constraint image.");
  hestOptAdd(&hopt, "eps", "val", airTypeDouble, 1, 1, &eps, "0.05",
             "width of value bracket around threshold, to constrain the "
             "the update from letting to value, originally on either "
             "side of the threshold, from getting too close.");
  hestOptAdd(&hopt, "rms", "thresh", airTypeDouble, 1, 1, &rmsMin, "0.01",
             "RMS change below this terminates updates.");
  hestOptAdd(&hopt, "mi", "max", airTypeUInt, 1, 1, &maxIter, "100",
             "maximum # iterations");
  hestOptAdd(&hopt, "o", "filename", airTypeString, 1, 1, &outS, "-",
             "fixed volume output");
  hestParseOrDie(hopt, argc-1, argv+1, hparm,
                 me, aaliasInfo, AIR_TRUE, AIR_TRUE, AIR_TRUE);
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  ndist = nrrdNew();
  nmask = nrrdNew();
  nupdate = nrrdNew();
  airMopAdd(mop, ndist, (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, nmask, (airMopper)nrrdNuke, airMopAlways);
  airMopAdd(mop, nupdate, (airMopper)nrrdNuke, airMopAlways);
  if (nrrdConvert(ndist, nin, nrrdTypeDouble)
      || nrrdConvert(nmask, nin, nrrdTypeDouble)
      || nrrdConvert(nupdate, nin, nrrdTypeDouble)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: couldn't allocate buffers:\n%s", me, err);
    airMopError(mop); return 1;
  }
  dist = AIR_CAST(double *, ndist->data);
  mask = AIR_CAST(double *, nmask->data);
  update = AIR_CAST(double *, nupdate->data);

  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, ndist, 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, gageSclValue);
  if (!E) E |= gageQueryItemOn(ctx, pvl, gageSclGradMag);
  if (!E) E |= gageQueryItemOn(ctx, pvl, gageSclMeanCurv);
  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;
  }
  valu = gageAnswerPointer(ctx, pvl, gageSclValue);
  gmag = gageAnswerPointer(ctx, pvl, gageSclGradMag);
  mcrv = gageAnswerPointer(ctx, pvl, gageSclMeanCurv);

  sx = nin->axis[0].size;
  sy = nin->axis[1].size;
  sz = nin->axis[2].size;

  for (iter=0; iter<maxIter; iter++) {
    double rms;
    unsigned count;
    fprintf(stderr, "%s: iter %u:      ", me, iter);
    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++) {
          si = xi + sx*(yi + sy*zi);
          gageProbe(ctx, xi, yi, zi);
          update[si] = -dt*(*gmag)*(*mcrv);
        }
      }
    }
    rms = 0;
    count = 0;
    for (si=0; si<sx*sy*sz; si++) {
      double newval;
      if (update[si]) {
        /* NOTE: this update behavior is only slightly different than
           what's described in Equation 18 of the paper. That update
           rule ensures that the value never changes "sign" (with
           respect to the threshold value), by clamping the values
           above or below to 0.0.  But worst-case scenario is that two
           adjacent samples that were on other side of the threshold
           (i.e. 0), could then equal the threshold, which would
           confuse a marching-cubes type algorithm.  So the "eps"
           enforces a small value range around the treshold, and keeps
           the values on either side of it. */
        newval = dist[si] + update[si];
        if (mask[si] > thresh) {
          newval = AIR_MAX(newval, thresh+eps/2);
        } else {
          newval = AIR_MIN(newval, thresh-eps/2);
        }
        rms += (dist[si] - newval)*(dist[si] - newval);
        dist[si] = newval;
        count++;
      }
    }
    fprintf(stderr, "%s", airDoneStr(0, zi, sz-1, done));
    rms /= count;
    rms = sqrt(rms);
    if (rms < rmsMin) {
      fprintf(stderr, "\n%s: RMS %g below threshold %g\n", me, rms, rmsMin);
      break;
    } else {
      fprintf(stderr, " rms = %g > %g\n", rms, rmsMin);
    }
  }
  if (iter == maxIter) {
    fprintf(stderr, "%s: hit max iter %u\n", me, maxIter);
  }

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
  if (nrrdCopy(nout, ndist)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: couldn't allocate output:\n%s", me, err);
    airMopError(mop); return 1;
  }
  
  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);
}
コード例 #21
0
ファイル: gkmsTxf.c プロジェクト: SCIInstitute/Cleaver
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;
}
コード例 #22
0
ファイル: deconvolve.c プロジェクト: BRAINSia/teem
int
gageDeconvolveSeparable(Nrrd *nout, const Nrrd *nin,
                        const gageKind *kind,
                        const NrrdKernelSpec *ksp,
                        int typeOut) {
  static const char me[]="gageDeconvolveSeparable";
  double *line, (*lup)(const void *, size_t),
    (*ins)(void *, size_t, double);
  airArray *mop;
  size_t lineLen, sx, sy, sz, idx, ii, jj;
  unsigned int vi, valLen;

  if (!(nout && nin && kind && ksp)) {
    biffAddf(GAGE, "%s: got NULL pointer", me);
    return 1;
  }
  if (!(nrrdTypeDefault == typeOut
        || !airEnumValCheck(nrrdType, typeOut))) {
    biffAddf(GAGE, "%s: typeOut %d not valid", me, typeOut);
    return 1;
  }
  if (!gageDeconvolveSeparableKnown(ksp)) {
    biffAddf(GAGE, "%s: separable deconv not known for %s kernel",
             me, ksp->kernel->name);
    return 1;
  }
  if (gageKindVolumeCheck(kind, nin)) {
    biffAddf(GAGE, "%s: given volume doesn't fit %s kind",
             me, kind->name);
    return 1;
  }
  if (nrrdTypeDefault == typeOut
      ? nrrdCopy(nout, nin)
      : nrrdConvert(nout, nin, typeOut)) {
    biffMovef(GAGE, NRRD, "%s: problem allocating output", me);
    return 1;
  }
  if (deconvTrivial(ksp)) {
    /* if there's no real work for the deconvolution, then by
       copying the values we're already done; bye */
    return 0;
  }

  valLen = kind->valLen;
  sx = nin->axis[kind->baseDim + 0].size;
  sy = nin->axis[kind->baseDim + 1].size;
  sz = nin->axis[kind->baseDim + 2].size;
  lineLen = sx;
  lineLen = AIR_MAX(lineLen, sy);
  lineLen = AIR_MAX(lineLen, sz);
  lup = nrrdDLookup[nin->type];
  ins = nrrdDInsert[nout->type];

  mop = airMopNew();
  line = AIR_CALLOC(lineLen*valLen, double);
  airMopAdd(mop, line, airFree, airMopAlways);

  /* process along X scanlines */
  for (jj=0; jj<sy*sz; jj++) {
    /* xi = 0, yi = jj%sy, zi = jj/sy
       ==> xi + sx*(yi + sy*zi)
       == 0 + sx*(jj%sy + sy*(jj/sy)) == 0 + sx*jj */
    idx = 0 + valLen*(0 + sx*jj);
    for (ii=0; ii<sx; ii++) {
      for (vi=0; vi<valLen; vi++) {
        line[ii + sx*vi] = lup(nin->data, idx + vi + valLen*ii);
      }
    }
    for (vi=0; vi<valLen; vi++) {
      deconvLine(line + sx*vi, sx, ksp);
    }
    for (ii=0; ii<sx; ii++) {
      for (vi=0; vi<valLen; vi++) {
        ins(nout->data, idx + vi + valLen*ii, line[ii + sx*vi]);
      }
    }
  }

  /* process along Y scanlines */
  for (jj=0; jj<sx*sz; jj++) {
    /* xi = jj%sx, yi = 0, zi = jj/sx
       ==> xi + sx*(yi + sy*zi)
       == jj%sx + sx*(0 + sy*jj/sx) */
    idx = 0 + valLen*((jj%sx) + sx*(0 + sy*(jj/sx)));
    for (ii=0; ii<sy; ii++) {
      for (vi=0; vi<valLen; vi++) {
        line[ii + sy*vi] = lup(nin->data, idx + vi + valLen*sx*ii);
      }
    }
    for (vi=0; vi<valLen; vi++) {
      deconvLine(line + sy*vi, sy, ksp);
    }
    for (ii=0; ii<sx; ii++) {
      for (vi=0; vi<valLen; vi++) {
        ins(nout->data, idx + vi + valLen*sx*ii, line[ii + sy*vi]);
      }
    }
  }

  /* process along Z scanlines */
  for (jj=0; jj<sx*sy; jj++) {
    /* xi = jj%sx, yi = jj/sx, zi = 0
       ==> xi + sx*(yi + sy*zi)
       == jj%sx + sx*(jj/sx + sy*0)
       == jj%sx + sx*(jj/sx) == jj */
    idx = 0 + valLen*jj;
    for (ii=0; ii<sz; ii++) {
      for (vi=0; vi<valLen; vi++) {
        line[ii + sz*vi] = lup(nin->data, idx + vi + valLen*sx*sy*ii);
      }
    }
    for (vi=0; vi<valLen; vi++) {
      deconvLine(line + sz*vi, sz, ksp);
    }
    for (ii=0; ii<sx; ii++) {
      for (vi=0; vi<valLen; vi++) {
        ins(nout->data, idx + vi + valLen*sx*sy*ii, line[ii + sz*vi]);
      }
    }
  }

  airMopOkay(mop);
  return 0;
}
コード例 #23
0
int
main(int argc, char *argv[]) {
  char *me, *outS;
  hestOpt *hopt;
  hestParm *hparm;
  airArray *mop;

  char *err;
  Nrrd *nin, *nhist;
  double vmin, vmax, rmax, val, cent[2], rad;
  int bins[2], sx, sy, xi, yi, ridx, hidx, rbins, hbins;
  NrrdRange *range;
  double (*lup)(const void *v, size_t I), *hist;
  
  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 image", NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "b", "rbins hbins", airTypeInt, 2, 2, bins, NULL,
             "# of histogram bins: radial and value");
  hestOptAdd(&hopt, "min", "value", airTypeDouble, 1, 1, &vmin, "nan",
             "Value at low end of histogram. Defaults to lowest value "
             "found in input nrrd.");
  hestOptAdd(&hopt, "max", "value", airTypeDouble, 1, 1, &vmax, "nan",
             "Value at high end of histogram. Defaults to highest value "
             "found in input nrrd.");
  hestOptAdd(&hopt, "rmax", "max radius", airTypeDouble, 1, 1, &rmax, "nan",
             "largest radius to include in histogram");
  hestOptAdd(&hopt, "c", "center x, y", airTypeDouble, 2, 2, cent, NULL,
             "The center point around which to build radial histogram");
  hestOptAdd(&hopt, "o", "filename", airTypeString, 1, 1, &outS, "-",
             "file to write histogram to");
  hestParseOrDie(hopt, argc-1, argv+1, hparm,
                 me, histradInfo, AIR_TRUE, AIR_TRUE, AIR_TRUE);
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  if (2 != nin->dim) {
    fprintf(stderr, "%s: need 2-D input (not %d-D)\n", me, nin->dim);
    airMopError(mop); return 1;
  }

  rbins = bins[0];
  hbins = bins[1];
  nhist = nrrdNew();
  airMopAdd(mop, nhist, (airMopper)nrrdNuke, airMopAlways);
  if (nrrdMaybeAlloc_va(nhist, nrrdTypeDouble, 2,
                        AIR_CAST(size_t, rbins),
                        AIR_CAST(size_t, hbins))) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: couldn't allocate histogram:\n%s", me, err);
    airMopError(mop); return 1;
  }

  if (!( AIR_EXISTS(vmin) && AIR_EXISTS(vmax) )) {
    range = nrrdRangeNewSet(nin, nrrdStateBlind8BitRange);
    airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
    vmin = AIR_EXISTS(vmin) ? vmin : range->min;
    vmax = AIR_EXISTS(vmax) ? vmax : range->max;
  }

#define DIST(x0, y0, x1, y1) (sqrt((x0-x1)*(x0-x1) + (y0-y1)*(y0-y1)))

  sx = nin->axis[0].size;
  sy = nin->axis[1].size;
  if (!AIR_EXISTS(rmax)) {
    rmax = 0;
    rmax = AIR_MAX(rmax, DIST(cent[0], cent[1], 0, 0));
    rmax = AIR_MAX(rmax, DIST(cent[0], cent[1], sx-1, 0));
    rmax = AIR_MAX(rmax, DIST(cent[0], cent[1], 0, sy-1));
    rmax = AIR_MAX(rmax, DIST(cent[0], cent[1], sx-1, sy-1));
  }
  
  lup = nrrdDLookup[nin->type];
  hist = (double*)(nhist->data);
  for (xi=0; xi<sx; xi++) {
    for (yi=0; yi<sy; yi++) {
      rad = DIST(cent[0], cent[1], xi, yi);
      if (!AIR_IN_OP(0, rad, rmax)) {
        continue;
      }
      val = lup(nin->data, xi + sx*yi);
      if (!AIR_IN_OP(vmin, val, vmax)) {
        continue;
      }
      ridx = airIndex(0, rad, rmax, rbins);
      hidx = airIndex(vmin, val, vmax, hbins);
      hist[ridx + rbins*hidx] += 1;
    }
  }
  
  nhist->axis[0].min = 0;
  nhist->axis[0].max = rmax;
  nhist->axis[1].min = vmin;
  nhist->axis[1].max = vmax;
  if (nrrdSave(outS, nhist, 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);
}
コード例 #24
0
ファイル: sclanswer.c プロジェクト: SCIInstitute/Cleaver
void
_gageSclAnswer (gageContext *ctx, gagePerVolume *pvl) {
  char me[]="_gageSclAnswer";
  double gmag=0, *hess, *norm, *gvec, *gten, *k1, *k2, curv=0, 
    sHess[9]={0,0,0,0,0,0,0,0,0};
  double tmpMat[9], tmpVec[3], hevec[9], heval[3];
  double len, gp1[3], gp2[3], *nPerp, ncTen[9], nProj[9]={0,0,0,0,0,0,0,0,0};
  double alpha = 0.5;
  double beta = 0.5;
  double gamma = 5;
  double cc = 1e-6;
#define FD_MEDIAN_MAX 16
  int fd, nidx, xi, yi, zi;
  double *fw, iv3wght[2*FD_MEDIAN_MAX*FD_MEDIAN_MAX*FD_MEDIAN_MAX],
    wghtSum, wght;

  /* convenience pointers for work below */
  hess = pvl->directAnswer[gageSclHessian];
  gvec = pvl->directAnswer[gageSclGradVec];
  norm = pvl->directAnswer[gageSclNormal];
  nPerp = pvl->directAnswer[gageSclNPerp];
  gten = pvl->directAnswer[gageSclGeomTens];
  k1 = pvl->directAnswer[gageSclK1];
  k2 = pvl->directAnswer[gageSclK2];
  
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclValue)) {
    /* done if doV */
    if (ctx->verbose) {
      fprintf(stderr, "%s: val = % 15.7f\n", me, 
              (double)(pvl->directAnswer[gageSclValue][0]));
    }
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclGradVec)) {
    /* done if doD1 */
    if (ctx->verbose) {
      fprintf(stderr, "%s: gvec = ", me);
      ell_3v_print_d(stderr, gvec);
    }
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclGradMag)) {
    /* this is the true value of gradient magnitude */
    gmag = pvl->directAnswer[gageSclGradMag][0] = sqrt(ELL_3V_DOT(gvec, gvec));
  }

  /* NB: it would seem that gageParmGradMagMin is completely ignored ... */

  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclNormal)) {
    if (gmag) {
      ELL_3V_SCALE(norm, 1/gmag, gvec);
      /* polishing ... 
      len = sqrt(ELL_3V_DOT(norm, norm));
      ELL_3V_SCALE(norm, 1/len, norm);
      */
    } else {
      ELL_3V_COPY(norm, gageZeroNormal);
    }
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclNPerp)) {
    /* nPerp = I - outer(norm, norm) */
    /* NB: this sets both nPerp and nProj */
    ELL_3MV_OUTER(nProj, norm, norm);
    ELL_3M_SCALE(nPerp, -1, nProj);
    nPerp[0] += 1;
    nPerp[4] += 1;
    nPerp[8] += 1;
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclHessian)) {
    /* done if doD2 */
    if (ctx->verbose) {
      fprintf(stderr, "%s: hess = \n", me);
      ell_3m_print_d(stderr, hess);
    }
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclLaplacian)) {
    pvl->directAnswer[gageSclLaplacian][0] = hess[0] + hess[4] + hess[8];
    if (ctx->verbose) {
      fprintf(stderr, "%s: lapl = %g + %g + %g  = %g\n", me,
              hess[0], hess[4], hess[8], 
              pvl->directAnswer[gageSclLaplacian][0]);
    }
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclHessFrob)) {
    pvl->directAnswer[gageSclHessFrob][0] = ELL_3M_FROB(hess);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclHessEval)) {
    /* HEY: look at the return value for root multiplicity? */
    ell_3m_eigensolve_d(heval, hevec, hess, AIR_TRUE);
    ELL_3V_COPY(pvl->directAnswer[gageSclHessEval], heval);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclHessEvec)) {
    ELL_3M_COPY(pvl->directAnswer[gageSclHessEvec], hevec);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclHessRidgeness)) {
    double A, B, S;
    if (heval[1] >0 || heval[2]>0) {
      pvl->directAnswer[gageSclHessRidgeness][0] = 0;
    }
    else if (AIR_ABS(heval[1])<1e-10 || AIR_ABS(heval[2])<1e-10) {
      pvl->directAnswer[gageSclHessRidgeness][0] = 0;
    }
    else {
      double *ans;
      A = AIR_ABS(heval[1])/AIR_ABS(heval[2]);
      B = AIR_ABS(heval[0])/sqrt(AIR_ABS(heval[1]*heval[2]));
      S = sqrt(heval[0]*heval[0] + heval[1]*heval[1] + heval[2]*heval[2]);
      ans = pvl->directAnswer[gageSclHessRidgeness];
      ans[0] = (1-exp(-A*A/(2*alpha*alpha))) *
        exp(-B*B/(2*beta*beta)) *
        (1-exp(-S*S/(2*gamma*gamma))) *
        exp(-2*cc*cc/(AIR_ABS(heval[1])*heval[2]*heval[2]));
    }
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclHessValleyness)) {
    double A, B, S;
    if (heval[0] <0 || heval[1]<0) {
      pvl->directAnswer[gageSclHessValleyness][0] = 0;
    }
    else if (AIR_ABS(heval[0])<1e-10 || AIR_ABS(heval[1])<1e-10) {
      pvl->directAnswer[gageSclHessValleyness][0] = 0;
    }
    else {
      double *ans;
      A = AIR_ABS(heval[1])/AIR_ABS(heval[0]);
      B = AIR_ABS(heval[2])/sqrt(AIR_ABS(heval[1]*heval[0]));
      S = sqrt(heval[0]*heval[0] + heval[1]*heval[1] + heval[2]*heval[2]);
      ans = pvl->directAnswer[gageSclHessValleyness];
      ans[0] = (1-exp(-A*A/(2*alpha*alpha))) *
        exp(-B*B/(2*beta*beta)) *
        (1-exp(-S*S/(2*gamma*gamma))) *
        exp(-2*cc*cc/(AIR_ABS(heval[1])*heval[0]*heval[0]));
    }
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclHessMode)) {
    pvl->directAnswer[gageSclHessMode][0] = airMode3_d(heval);
  }

  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageScl2ndDD)) {
    ELL_3MV_MUL(tmpVec, hess, norm);
    pvl->directAnswer[gageScl2ndDD][0] = ELL_3V_DOT(norm, tmpVec);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclGeomTens)) {
    if (gmag > ctx->parm.gradMagCurvMin) {
      /* parm.curvNormalSide applied here to determine the sense of the
         normal when doing all curvature calculations */
      ELL_3M_SCALE(sHess, -(ctx->parm.curvNormalSide)/gmag, hess);
      
      /* gten = nPerp * sHess * nPerp */
      ELL_3M_MUL(tmpMat, sHess, nPerp);
      ELL_3M_MUL(gten, nPerp, tmpMat);

      if (ctx->verbose) {
        fprintf(stderr, "%s: gten: \n", me);
        ell_3m_print_d(stderr, gten);
        ELL_3MV_MUL(tmpVec, gten, norm);
        len = ELL_3V_LEN(tmpVec);
        fprintf(stderr, "%s: should be small: %30.15f\n", me, (double)len);
        ell_3v_perp_d(gp1, norm);
        ELL_3MV_MUL(tmpVec, gten, gp1);
        len = ELL_3V_LEN(tmpVec);
        fprintf(stderr, "%s: should be bigger: %30.15f\n", me, (double)len);
        ELL_3V_CROSS(gp2, gp1, norm);
        ELL_3MV_MUL(tmpVec, gten, gp2);
        len = ELL_3V_LEN(tmpVec);
        fprintf(stderr, "%s: should (also) be bigger: %30.15f\n",
                me, (double)len);
      }
    } else {
      ELL_3M_ZERO_SET(gten);
    }
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query,  gageSclTotalCurv)) {
    curv = pvl->directAnswer[gageSclTotalCurv][0] = ELL_3M_FROB(gten);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query,  gageSclShapeTrace)) {
    pvl->directAnswer[gageSclShapeTrace][0] = (curv
                                               ? ELL_3M_TRACE(gten)/curv
                                               : 0);
  }
  if ( (GAGE_QUERY_ITEM_TEST(pvl->query,  gageSclK1)) ||
       (GAGE_QUERY_ITEM_TEST(pvl->query,  gageSclK2)) ){
    double T, N, D;
    T = ELL_3M_TRACE(gten);
    N = curv;
    D = 2*N*N - T*T;
    /*
    if (D < -0.0000001) {
      fprintf(stderr, "%s: %g %g\n", me, T, N);
      fprintf(stderr, "%s: !!! D curv determinant % 22.10f < 0.0\n", me, D);
      fprintf(stderr, "%s: gten: \n", me);
      ell_3m_print_d(stderr, gten);
    }
    */
    D = AIR_MAX(D, 0);
    D = sqrt(D);
    k1[0] = 0.5*(T + D);
    k2[0] = 0.5*(T - D);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query,  gageSclMeanCurv)) {
    pvl->directAnswer[gageSclMeanCurv][0] = (*k1 + *k2)/2;
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query,  gageSclGaussCurv)) {
    pvl->directAnswer[gageSclGaussCurv][0] = (*k1)*(*k2);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query,  gageSclShapeIndex)) {
    pvl->directAnswer[gageSclShapeIndex][0] = 
      -(2/AIR_PI)*atan2(*k1 + *k2, *k1 - *k2);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclCurvDir1)) {
    /* HEY: this only works when K1, K2, 0 are all well mutually distinct,
       since these are the eigenvalues of the geometry tensor, and this
       code assumes that the eigenspaces are all one-dimensional */
    ELL_3M_COPY(tmpMat, gten);
    ELL_3M_DIAG_SET(tmpMat, gten[0] - *k1, gten[4]- *k1, gten[8] - *k1);
    ell_3m_1d_nullspace_d(tmpVec, tmpMat);
    ELL_3V_COPY(pvl->directAnswer[gageSclCurvDir1], tmpVec);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclCurvDir2)) {
    /* HEY: this only works when K1, K2, 0 are all well mutually distinct,
       since these are the eigenvalues of the geometry tensor, and this
       code assumes that the eigenspaces are all one-dimensional */
    ELL_3M_COPY(tmpMat, gten);
    ELL_3M_DIAG_SET(tmpMat, gten[0] - *k2, gten[4] - *k2, gten[8] - *k2);
    ell_3m_1d_nullspace_d(tmpVec, tmpMat);
    ELL_3V_COPY(pvl->directAnswer[gageSclCurvDir2], tmpVec);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclFlowlineCurv)) {
    if (gmag >= ctx->parm.gradMagCurvMin) {
      /* because of the gageSclGeomTens prerequisite, sHess, nPerp, and
         nProj are all already set */
      /* ncTen = nPerp * sHess * nProj */
      ELL_3M_MUL(tmpMat, sHess, nProj);
      ELL_3M_MUL(ncTen, nPerp, tmpMat);
    } else {
      ELL_3M_ZERO_SET(ncTen);
    }
    /* there used to be a wrong extra sqrt() here */
    pvl->directAnswer[gageSclFlowlineCurv][0] = ELL_3M_FROB(ncTen);
  }
  if (GAGE_QUERY_ITEM_TEST(pvl->query, gageSclMedian)) {
    /* this item is currently a complete oddball in that it does not
       benefit from anything done in the "filter" stage, which is in
       fact a waste of time if the query consists only  of this item */
    fd = 2*ctx->radius;
    if (fd > FD_MEDIAN_MAX) {
      fprintf(stderr, "%s: PANIC: current filter diameter = %d "
              "> FD_MEDIAN_MAX = %d\n", me, fd, FD_MEDIAN_MAX);
      exit(1);
    }
    fw = ctx->fw + fd*3*gageKernel00;
    /* HEY: this needs some optimization help */
    wghtSum = 0;
    nidx = 0;
    for (xi=0; xi<fd; xi++) {
      for (yi=0; yi<fd; yi++) {
        for (zi=0; zi<fd; zi++) {
          iv3wght[0 + 2*nidx] = pvl->iv3[nidx];
          iv3wght[1 + 2*nidx] = fw[xi + 0*fd]*fw[yi + 1*fd]*fw[zi + 2*fd];
          wghtSum += iv3wght[1 + 2*nidx];
          nidx++;
        }
      }
    }
    qsort(iv3wght, fd*fd*fd, 2*sizeof(double), nrrdValCompare[nrrdTypeDouble]);
    wght = 0;
    for (nidx=0; nidx<fd*fd*fd; nidx++) {
      wght += iv3wght[1 + 2*nidx];
      if (wght > wghtSum/2) {
        break;
      }
    }
    pvl->directAnswer[gageSclMedian][0] = iv3wght[0 + 2*nidx];
  }
  return;
}
コード例 #25
0
ファイル: usage.c プロジェクト: rblake/seg3d2
void
hestGlossary(FILE *f, hestOpt *opt, hestParm *_parm) {
  int i, j, len, maxlen, numOpts;
  char buff[2*AIR_STRLEN_HUGE], tmpS[AIR_STRLEN_HUGE];
  hestParm *parm;

  parm = !_parm ? hestParmNew() : _parm;

  if (_hestPanic(opt, NULL, parm)) {
    /* we can't continue; the opt array is botched */
    parm = !_parm ? hestParmFree(parm) : NULL;
    return;
  }
    
  numOpts = _hestNumOpts(opt);

  maxlen = 0;
  if (numOpts) {
    fprintf(f, "\n");
  }
  for (i=0; i<numOpts; i++) {
    strcpy(buff, "");
    _hestSetBuff(buff, opt + i, parm, AIR_TRUE, AIR_FALSE);
    maxlen = AIR_MAX((int)strlen(buff), maxlen);
  }
  if (parm && parm->respFileEnable) {
    sprintf(buff, "%cfile ...", parm->respFileFlag);
    len = strlen(buff);
    for (j=len; j<maxlen; j++) {
      fprintf(f, " ");
    }
    fprintf(f, "%s = ", buff);
    strcpy(buff, "response file(s) containing command-line arguments");
    _hestPrintStr(f, maxlen + 3, maxlen + 3, parm->columns, buff, AIR_FALSE);
  }
  for (i=0; i<numOpts; i++) {
    strcpy(buff, "");
    _hestSetBuff(buff, opt + i, parm, AIR_TRUE, AIR_FALSE);
    airOneLinify(buff);
    len = strlen(buff);
    for (j=len; j<maxlen; j++) {
      fprintf(f, " ");
    }
    fprintf(f, "%s", buff);
    strcpy(buff, "");
#if 1
    if (opt[i].flag && strchr(opt[i].flag, parm->multiFlagSep)) {
      /* there is a long-form flag as well as short */
      _hestSetBuff(buff, opt + i, parm, AIR_FALSE, AIR_TRUE);
      strcat(buff, " = ");
      fprintf(f, " , ");
    } else {
      /* there is only a short-form flag */
      fprintf(f, " = ");
    }
#else
    fprintf(f, " = ");
#endif
    if (opt[i].info) {
      strcat(buff, opt[i].info);
    }
    if ((opt[i].min || _hestMax(opt[i].max))
        && (!( 2 == opt[i].kind
               && airTypeEnum == opt[i].type 
               && parm->elideSingleEnumType )) 
        && (!( 2 == opt[i].kind
               && airTypeOther == opt[i].type 
               && parm->elideSingleOtherType )) 
        ) {
      /* if there are newlines in the info, then we want to clarify the
         type by printing it on its own line */
      if (opt[i].info && strchr(opt[i].info, '\n')) {
        strcat(buff, "\n ");
      }
      else {
        strcat(buff, " ");
      }
      strcat(buff, "(");
      if (opt[i].min == 0 && _hestMax(opt[i].max) == 1) {
        strcat(buff, "optional\t");
      }
      else {
        if ((int)opt[i].min == _hestMax(opt[i].max) && _hestMax(opt[i].max) > 1) { /* HEY scrutinize casts */
          sprintf(tmpS, "%d\t", _hestMax(opt[i].max));
          strcat(buff, tmpS);
        }
        else if ((int)opt[i].min < _hestMax(opt[i].max)) { /* HEY scrutinize casts */
          if (-1 == opt[i].max) {
            sprintf(tmpS, "%d\tor\tmore\t", opt[i].min);
          }
          else {
            sprintf(tmpS, "%d..%d\t", opt[i].min, _hestMax(opt[i].max));
          }
          strcat(buff, tmpS);
        }
      }
      sprintf(tmpS, "%s%s", 
              (airTypeEnum == opt[i].type
               ? opt[i].enm->name
               : (airTypeOther == opt[i].type
                  ? opt[i].CB->type
                  : airTypeStr[opt[i].type])),
              (_hestMax(opt[i].max) > 1 
               ? (airTypeOther == opt[i].type
                  && 'y' == opt[i].CB->type[airStrlen(opt[i].CB->type)-1]
                  && parm->cleverPluralizeOtherY
                  ? "\bies" 
                  : "s")
               : ""));
      strcat(buff, tmpS);
      strcat(buff, ")");
    }
    /*
    fprintf(stderr, "!%s: parm->elideSingleOtherDefault = %d\n",
            "hestGlossary", parm->elideSingleOtherDefault);
    */
    if (opt[i].dflt 
        && (opt[i].min || _hestMax(opt[i].max))
        && (!( 2 == opt[i].kind
               && (airTypeFloat == opt[i].type || airTypeDouble == opt[i].type)
               && !AIR_EXISTS(airAtod(opt[i].dflt)) 
               && parm->elideSingleNonExistFloatDefault ))
        && (!( (3 == opt[i].kind || 5 == opt[i].kind) 
               && (airTypeFloat == opt[i].type || airTypeDouble == opt[i].type)
               && !AIR_EXISTS(airAtod(opt[i].dflt)) 
               && parm->elideMultipleNonExistFloatDefault ))
        && (!( 2 == opt[i].kind
               && airTypeOther == opt[i].type
               && parm->elideSingleOtherDefault ))
        && (!( 2 == opt[i].kind
               && airTypeString == opt[i].type
               && parm->elideSingleEmptyStringDefault 
               && 0 == airStrlen(opt[i].dflt) ))
        && (!( (3 == opt[i].kind || 5 == opt[i].kind) 
               && airTypeString == opt[i].type
               && parm->elideMultipleEmptyStringDefault 
               && 0 == airStrlen(opt[i].dflt) ))
        ) {
      /* if there are newlines in the info, then we want to clarify the
         default by printing it on its own line */
      if (opt[i].info && strchr(opt[i].info, '\n')) {
        strcat(buff, "\n ");
      }
      else {
        strcat(buff, "; ");
      }
      strcat(buff, "default:\t");
      strcpy(tmpS, opt[i].dflt);
      airStrtrans(tmpS, ' ', '\t');
      strcat(buff, "\"");
      strcat(buff, tmpS);
      strcat(buff, "\"");
    }
    _hestPrintStr(f, maxlen + 3, maxlen + 3, parm->columns, buff, AIR_FALSE);
  }
  parm = !_parm ? hestParmFree(parm) : NULL;

  return;
}
コード例 #26
0
ファイル: shape.c プロジェクト: CIBC-Internal/teem
/*
** _gageShapeSet
**
** we are serving two masters here.  If ctx is non-NULL, we are being called
** from within gage, and we are to be lax or strict according to the settings
** of ctx->parm.requireAllSpacings and ctx->parm.requireEqualCenters.  If
** ctx is NULL, gageShapeSet was called, in which case we go with lax
** behavior (nothing "required")
**
** This function has subsumed the contents of the old gageVolumeCheck,
** and hence has become this weird beast- part error checker and part
** (gageShape) initializer.  Oh well...
*/
int
_gageShapeSet(const gageContext *ctx, gageShape *shape,
              const Nrrd *nin, unsigned int baseDim) {
  static const char me[]="_gageShapeSet";
  int ai, cx, cy, cz, statCalc[3], status, ofspc;
  unsigned int minsize;
  const NrrdAxisInfo *ax[3];
  double vecA[4], vecB[3], vecC[3], vecD[4], matA[9],
    spcCalc[3], vecCalc[3][NRRD_SPACE_DIM_MAX], orig[NRRD_SPACE_DIM_MAX];
  airArray *mop;

  /*
  fprintf(stderr, "!%s: ctx = %p (%s, %s)\n", me, ctx,
          (ctx
           ? (ctx->shape->fromOrientation
              ? "YES from orient"
              : "not from orient")
           : "???"),
          (ctx
           ? (ctx->parm.orientationFromSpacing
              ? "YES ofs"
              : "not ofs")
           : "???"));
  */
  /* ------ basic error checking */
  mop = airMopNew();
  airMopAdd(mop, shape, _mopShapeReset, airMopOnError);
  if (!( shape && nin )) {
    biffAddf(GAGE, "%s: got NULL pointer", me);
    airMopError(mop); return 1;
  }
  if (nrrdCheck(nin)) {
    biffMovef(GAGE, NRRD, "%s: basic nrrd validity check failed", me);
    airMopError(mop); return 1;
  }
  if (nrrdTypeBlock == nin->type) {
    biffAddf(GAGE, "%s: need a non-block type nrrd", me);
    airMopError(mop); return 1;
  }
  if (!(nin->dim == 3 + baseDim)) {
    biffAddf(GAGE, "%s: nrrd should be %u-D, not %u-D",
             me, 3 + baseDim, nin->dim);
    airMopError(mop); return 1;
  }
  ax[0] = &(nin->axis[baseDim+0]);
  ax[1] = &(nin->axis[baseDim+1]);
  ax[2] = &(nin->axis[baseDim+2]);

  statCalc[0] = nrrdSpacingCalculate(nin, baseDim + 0,
                                     spcCalc + 0, vecCalc[0]);
  statCalc[1] = nrrdSpacingCalculate(nin, baseDim + 1,
                                     spcCalc + 1, vecCalc[1]);
  statCalc[2] = nrrdSpacingCalculate(nin, baseDim + 2,
                                     spcCalc + 2, vecCalc[2]);
  /* see if nrrdSpacingCalculate ever *failed* */
  if (nrrdSpacingStatusUnknown == statCalc[0]
      || nrrdSpacingStatusUnknown == statCalc[1]
      || nrrdSpacingStatusUnknown == statCalc[2]) {
    biffAddf(GAGE, "%s: nrrdSpacingCalculate trouble on axis %d, %d, or %d",
             me, baseDim + 0, baseDim + 1, baseDim + 2);
    airMopError(mop); return 1;
  }
  if (!( statCalc[0] == statCalc[1] && statCalc[1] == statCalc[2] )) {
    biffAddf(GAGE, "%s: inconsistent spacing information on axes "
             "%u (%s), %u (%s), and %u (%s)", me,
             baseDim + 0, airEnumDesc(nrrdSpacingStatus, statCalc[0]),
             baseDim + 1, airEnumDesc(nrrdSpacingStatus, statCalc[1]),
             baseDim + 2, airEnumDesc(nrrdSpacingStatus, statCalc[2]));
    airMopError(mop); return 1;
  }
  /* this simplifies reasoning in the code that follows */
  status = statCalc[0];
  /* zero spacing would be problematic */
  if (0 == spcCalc[0] && 0 == spcCalc[1] && 0 == spcCalc[2]) {
    biffAddf(GAGE, "%s: spacings (%g,%g,%g) for axes %d,%d,%d not all "
             "non-zero", me, spcCalc[1], spcCalc[1], spcCalc[2],
             baseDim+0, baseDim+1, baseDim+2);
    airMopError(mop); return 1;
  }

  /* error checking based on status */
  if (nrrdSpacingStatusScalarWithSpace == status) {
    biffAddf(GAGE, "%s: sorry, can't handle per-axis spacing that isn't part "
             "of a surrounding world space (%s)",
             me, airEnumStr(nrrdSpacingStatus, status));
    airMopError(mop); return 1;
  }
  /* we no longer allow a nrrd to come in with no spacing info at all */
  if (nrrdSpacingStatusNone == status) {
    biffAddf(GAGE, "%s: sorry, need some spacing info for spatial axes "
             "%u, %u, %u", me,
             baseDim+0, baseDim+1, baseDim+2);
    airMopError(mop); return 1;
  }
  /* actually, there shouldn't be any other options for spacing status
     besides these too; this is just being careful */
  if (!( nrrdSpacingStatusDirection == status
         || nrrdSpacingStatusScalarNoSpace == status )) {
    biffAddf(GAGE, "%s: sorry, can only handle spacing status %d (%s) "
             "or %d (%s), not %d (%s)", me,
             nrrdSpacingStatusDirection,
             airEnumStr(nrrdSpacingStatus, nrrdSpacingStatusDirection),
             nrrdSpacingStatusScalarNoSpace,
             airEnumStr(nrrdSpacingStatus, nrrdSpacingStatusScalarNoSpace),
             status, airEnumStr(nrrdSpacingStatus, status));
    airMopError(mop); return 1;
  }

  if (nrrdSpacingStatusDirection == status) {
    shape->fromOrientation = AIR_TRUE;
    if (3 != nin->spaceDim) {
      biffAddf(GAGE, "%s: orientation space dimension %d != 3",
               me, nin->spaceDim);
      airMopError(mop); return 1;
    }
  } else {
    shape->fromOrientation = AIR_FALSE;
  }

  /* ------ find centering (set shape->center) */
  /* NOTE: when the volume is being crammed in a bi-unit cube, the centering
     will actually affect the positions of the samples.  Otherwise,
     (having full orientation, or using orientationFromSpacing), the
     centering will only affect the probe-able bounds of the volume, but
     the sample positions in space don't depend on centering */
  cx = ax[0]->center;
  cy = ax[1]->center;
  cz = ax[2]->center;
  if (!( cx == cy && cy == cz )) {
    biffAddf(GAGE,
             "%s: axes %d,%d,%d centerings (%s,%s,%s) not all equal",
             me, baseDim+0, baseDim+1, baseDim+2,
             airEnumStr(nrrdCenter, cx),
             airEnumStr(nrrdCenter, cy),
             airEnumStr(nrrdCenter, cz));
    airMopError(mop); return 1;
  }
  /* Hopefully, ctx->parm.defaultCenter == shape->defaultCenter; and this
     worry will be moot if ctx->parm.defaultCenter goes away */
  shape->center = (nrrdCenterUnknown != cx
                   ? cx /* cx == cy == cz, by above */
                   : (ctx
                      ? ctx->parm.defaultCenter
                      : shape->defaultCenter));

  /* ------ find sizes (set shape->size[0,1,2]) */
  shape->size[0] = ax[0]->size;
  shape->size[1] = ax[1]->size;
  shape->size[2] = ax[2]->size;
  minsize = (nrrdCenterCell == shape->center ? 1 : 2);
  /* this can't be relaxed in the face of having full orientation info,
     because even then, you can't have a non-zero probe-able volume if
     there's only one sample along a node-centered axis */
  if (!(shape->size[0] >= minsize
        && shape->size[1] >= minsize
        && shape->size[2] >= minsize )) {
    biffAddf(GAGE, "%s: sizes (%u,%u,%u) must all be >= %u "
             "(min number of %s-centered samples)", me,
             shape->size[0], shape->size[1], shape->size[2],
             minsize, airEnumStr(nrrdCenter, shape->center));
    airMopError(mop); return 1;
  }

  /* ------ find spacings[0,1,2] and ItoW matrix */
  /* Hopefully, ctx->parm.orientationFromSpacing and
     shape->orientationFromSpacing don't represent competing interests;
     this worry will be moot if ctx->parm.orientationFromSpacing goes away */
  ofspc = ((ctx && ctx->parm.orientationFromSpacing)
           || shape->orientationFromSpacing);
  if (shape->fromOrientation || ofspc) {
    if (ofspc) {
      /* need abs() in case an axis had negative spacing */
      ELL_3V_ABS(shape->spacing, spcCalc);
      ELL_3V_SET(vecCalc[0], airSgn(spcCalc[0]), 0.0, 0.0);
      ELL_3V_SET(vecCalc[1], 0.0, airSgn(spcCalc[1]), 0.0);
      ELL_3V_SET(vecCalc[2], 0.0, 0.0, airSgn(spcCalc[2]));
    } else {
      ELL_3V_COPY(shape->spacing, spcCalc);
      /* vecCalc set by nrrdSpacingCalculate */
    }
    if (shape->fromOrientation) {
      /* if the spaceOrigin isn't set, this will be all NaNs */
      nrrdSpaceOriginGet(nin, orig);
    } else {
      /* sorry, if you want to specify an image origin that over-rides the
         behavior of centering the volume at (0,0,0), then it has to be
         done through the full orientation info.  That is, we don't want
         to use nrrdOriginCalculate() because otherwise the logic gets
         too complicated */
      ELL_3V_SET(orig, AIR_NAN, AIR_NAN, AIR_NAN);
    }
    if (!ELL_3V_EXISTS(orig)) {
      /* don't have origin, for whatever reason; center volume on (0,0,0) */
      ELL_3V_SET(orig, 0.0, 0.0, 0.0);
      ELL_3V_SCALE_INCR(orig, -(shape->size[0] - 1.0)*shape->spacing[0]/2.0,
                        vecCalc[0]);
      ELL_3V_SCALE_INCR(orig, -(shape->size[1] - 1.0)*shape->spacing[1]/2.0,
                        vecCalc[1]);
      ELL_3V_SCALE_INCR(orig, -(shape->size[2] - 1.0)*shape->spacing[2]/2.0,
                        vecCalc[2]);
    }
    vecD[3] = 0;
    ELL_3V_SCALE(vecD, spcCalc[0], vecCalc[0]);
    ELL_4MV_COL0_SET(shape->ItoW, vecD);
    ELL_3V_SCALE(vecD, spcCalc[1], vecCalc[1]);
    ELL_4MV_COL1_SET(shape->ItoW, vecD);
    ELL_3V_SCALE(vecD, spcCalc[2], vecCalc[2]);
    ELL_4MV_COL2_SET(shape->ItoW, vecD);
    vecD[3] = 1;
    ELL_3V_COPY(vecD, orig);
    ELL_4MV_COL3_SET(shape->ItoW, vecD);
    /*
    fprintf(stderr, "%s: %g (%g,%g,%g)\n", me,
            spcCalc[0], vecCalc[0][0], vecCalc[0][1], vecCalc[0][2]);
    fprintf(stderr, "%s: %g (%g,%g,%g)\n", me,
            spcCalc[1], vecCalc[1][0], vecCalc[1][1], vecCalc[1][2]);
    fprintf(stderr, "%s: %g (%g,%g,%g)\n", me,
            spcCalc[2], vecCalc[2][0], vecCalc[2][1], vecCalc[2][2]);
    */
    /*
    fprintf(stderr, "%s: ItoW = %g %g %g %g\n", me,
           shape->ItoW[ 0], shape->ItoW[ 1], shape->ItoW[ 2], shape->ItoW[ 3]);
    fprintf(stderr, "%s:        %g %g %g %g\n", me,
           shape->ItoW[ 4], shape->ItoW[ 5], shape->ItoW[ 6], shape->ItoW[ 7]);
    fprintf(stderr, "%s:        %g %g %g %g\n", me,
           shape->ItoW[ 8], shape->ItoW[ 9], shape->ItoW[10], shape->ItoW[11]);
    fprintf(stderr, "%s:        %g %g %g %g\n", me,
           shape->ItoW[12], shape->ItoW[13], shape->ItoW[14], shape->ItoW[15]);
    */
  } else { /* not (shape->fromOrientation || ofspc) */
    double maxLen, volHalfLen[3];
    size_t num[3];
    /* ------ learn lengths for bounding nrrd in bi-unit cube */
    ELL_3V_ABS(shape->spacing, spcCalc);
    maxLen = 0.0;
    for (ai=0; ai<=2; ai++) {
      num[ai] = (nrrdCenterNode == shape->center
                 ? shape->size[ai]-1
                 : shape->size[ai]);
      volHalfLen[ai] = num[ai]*shape->spacing[ai];
      maxLen = AIR_MAX(maxLen, volHalfLen[ai]);
    }
    /* Thu Dec 13 02:45:01 EST 2007
       fixed long-standing bug in handling vols without full orientation info:
       spacing[ai] was never scaled to account for being crammed into
       the bi-unit cube!! */
    for (ai=0; ai<=2; ai++) {
      volHalfLen[ai] /= maxLen;
      shape->spacing[ai] = 2*volHalfLen[ai]/num[ai];
    }
    ELL_3V_SET(vecC, 0, 0, 0);
    shapeUnitItoW(shape, vecA, vecC, volHalfLen);
    ELL_3V_SET(vecC, 1, 0, 0);
    shapeUnitItoW(shape, vecB, vecC, volHalfLen);
    ELL_3V_SUB(vecD, vecB, vecA);
    vecD[3] = 0;
    ELL_4MV_COL0_SET(shape->ItoW, vecD);

    ELL_3V_SET(vecC, 0, 1, 0);
    shapeUnitItoW(shape, vecB, vecC, volHalfLen);
    ELL_3V_SUB(vecD, vecB, vecA);
    vecD[3] = 0;
    ELL_4MV_COL1_SET(shape->ItoW, vecD);

    ELL_3V_SET(vecC, 0, 0, 1);
    shapeUnitItoW(shape, vecB, vecC, volHalfLen);
    ELL_3V_SUB(vecD, vecB, vecA);
    vecD[3] = 0;
    ELL_4MV_COL2_SET(shape->ItoW, vecD);

    vecA[3] = 1;
    ELL_4MV_COL3_SET(shape->ItoW, vecA);
  }

  /* ------ set the rest of the matrices */
  ell_4m_inv_d(shape->WtoI, shape->ItoW);
  ELL_34M_EXTRACT(matA, shape->ItoW);
  ell_3m_inv_d(shape->ItoWSubInv, matA);
  ELL_3M_TRANSPOSE(shape->ItoWSubInvTransp, shape->ItoWSubInv);

  airMopOkay(mop);
  return 0;
}
コード例 #27
0
ファイル: simple.c プロジェクト: ryanfb/teem-parallel
/*
******** nrrdSanity()
**
** makes sure that all the basic assumptions of nrrd hold for
** the architecture/etc which we're currently running on.  
** 
** returns 1 if all is okay, 0 if there is a problem
*/
int
nrrdSanity(void) {
  char me[]="nrrdSanity", err[BIFF_STRLEN];
  int aret, type;
  size_t maxsize;
  airLLong tmpLLI;
  airULLong tmpULLI;
  static int _nrrdSanity = 0;

  if (_nrrdSanity) {
    /* we've been through this once before and things looked okay ... */
    /* Is this thread-safe?  I think so.  If we assume that any two
       threads are going to compute the same value, isn't it the case
       that, at worse, both of them will go through all the tests and
       then set _nrrdSanity to the same thing? */
    return 1;
  }
  
  aret = airSanity();
  if (aret != airInsane_not) {
    sprintf(err, "%s: airSanity() failed: %s", me, airInsaneErr(aret));
    biffAdd(NRRD, err); return 0;
  }

  if (airEnumValCheck(nrrdEncodingType, nrrdDefaultWriteEncodingType)) {
    sprintf(err, "%s: nrrdDefaultWriteEncodingType (%d) not in valid "
            "range [%d,%d]", me, nrrdDefaultWriteEncodingType,
            nrrdEncodingTypeUnknown+1, nrrdEncodingTypeLast-1);
    biffAdd(NRRD, err); return 0;
  }
  if (airEnumValCheck(nrrdCenter, nrrdDefaultCenter)) {
    sprintf(err, "%s: nrrdDefaultCenter (%d) not in valid range [%d,%d]",
            me, nrrdDefaultCenter,
            nrrdCenterUnknown+1, nrrdCenterLast-1);
    biffAdd(NRRD, err); return 0;
  }
  /* ---- BEGIN non-NrrdIO */
  if (!( nrrdTypeDefault == nrrdDefaultResampleType
         || !airEnumValCheck(nrrdType, nrrdDefaultResampleType) )) {
    sprintf(err, "%s: nrrdDefaultResampleType (%d) not in valid range [%d,%d]",
            me, nrrdDefaultResampleType,
            nrrdTypeUnknown, nrrdTypeLast-1);
    biffAdd(NRRD, err); return 0;
  }
  if (airEnumValCheck(nrrdBoundary, nrrdDefaultResampleBoundary)) {
    sprintf(err, "%s: nrrdDefaultResampleBoundary (%d) "
            "not in valid range [%d,%d]",
            me, nrrdDefaultResampleBoundary,
            nrrdBoundaryUnknown+1, nrrdBoundaryLast-1);
    biffAdd(NRRD, err); return 0;
  }
  if (airEnumValCheck(nrrdType, nrrdStateMeasureType)) {
    sprintf(err, "%s: nrrdStateMeasureType (%d) not in valid range [%d,%d]",
            me, nrrdStateMeasureType,
            nrrdTypeUnknown+1, nrrdTypeLast-1);
    biffAdd(NRRD, err); return 0;
  }
  if (airEnumValCheck(nrrdType, nrrdStateMeasureHistoType)) {
    sprintf(err,
            "%s: nrrdStateMeasureHistoType (%d) not in valid range [%d,%d]",
            me, nrrdStateMeasureType,
            nrrdTypeUnknown+1, nrrdTypeLast-1);
    biffAdd(NRRD, err); return 0;
  }
  /* ---- END non-NrrdIO */

  if (!( nrrdTypeSize[nrrdTypeChar] == sizeof(char)
         && nrrdTypeSize[nrrdTypeUChar] == sizeof(unsigned char)
         && nrrdTypeSize[nrrdTypeShort] == sizeof(short)
         && nrrdTypeSize[nrrdTypeUShort] == sizeof(unsigned short)
         && nrrdTypeSize[nrrdTypeInt] == sizeof(int)
         && nrrdTypeSize[nrrdTypeUInt] == sizeof(unsigned int)
         && nrrdTypeSize[nrrdTypeLLong] == sizeof(airLLong)
         && nrrdTypeSize[nrrdTypeULLong] == sizeof(airULLong)
         && nrrdTypeSize[nrrdTypeFloat] == sizeof(float)
         && nrrdTypeSize[nrrdTypeDouble] == sizeof(double) )) {
    sprintf(err, "%s: sizeof() for nrrd types has problem: "
            "expected (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d) "
            "but got (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)", me,
            (int)nrrdTypeSize[nrrdTypeChar],
            (int)nrrdTypeSize[nrrdTypeUChar],
            (int)nrrdTypeSize[nrrdTypeShort],
            (int)nrrdTypeSize[nrrdTypeUShort],
            (int)nrrdTypeSize[nrrdTypeInt],
            (int)nrrdTypeSize[nrrdTypeUInt],
            (int)nrrdTypeSize[nrrdTypeLLong],
            (int)nrrdTypeSize[nrrdTypeULLong],
            (int)nrrdTypeSize[nrrdTypeFloat],
            (int)nrrdTypeSize[nrrdTypeDouble],
            (int)sizeof(char),
            (int)sizeof(unsigned char),
            (int)sizeof(short),
            (int)sizeof(unsigned short),
            (int)sizeof(int),
            (int)sizeof(unsigned int),
            (int)sizeof(airLLong),
            (int)sizeof(airULLong),
            (int)sizeof(float),
            (int)sizeof(double));
    biffAdd(NRRD, err); return 0;
  }

  /* check on NRRD_TYPE_SIZE_MAX */
  maxsize = 0;
  for (type=nrrdTypeUnknown+1; type<=nrrdTypeLast-2; type++) {
    maxsize = AIR_MAX(maxsize, nrrdTypeSize[type]);
  }
  if (maxsize != NRRD_TYPE_SIZE_MAX) {
    sprintf(err, "%s: actual max type size is %d != %d == NRRD_TYPE_SIZE_MAX",
            me, (int)maxsize, NRRD_TYPE_SIZE_MAX);
    biffAdd(NRRD, err); return 0;
  }

  /* check on NRRD_TYPE_BIGGEST */
  if (maxsize != sizeof(NRRD_TYPE_BIGGEST)) {
    sprintf(err, "%s: actual max type size is %d != "
            "%d == sizeof(NRRD_TYPE_BIGGEST)",
            me, (int)maxsize, (int)sizeof(NRRD_TYPE_BIGGEST));
    biffAdd(NRRD, err); return 0;
  }
  
  /* nrrd-defined type min/max values */
  tmpLLI = NRRD_LLONG_MAX;
  if (tmpLLI != NRRD_LLONG_MAX) {
    sprintf(err, "%s: long long int can't hold NRRD_LLONG_MAX ("
            AIR_ULLONG_FMT ")", me,
            NRRD_LLONG_MAX);
    biffAdd(NRRD, err); return 0;
  }
  tmpLLI += 1;
  if (NRRD_LLONG_MIN != tmpLLI) {
    sprintf(err, "%s: long long int min (" AIR_LLONG_FMT ") or max ("
            AIR_LLONG_FMT ") incorrect", me,
            NRRD_LLONG_MIN, NRRD_LLONG_MAX);
    biffAdd(NRRD, err); return 0;
  }
  tmpULLI = NRRD_ULLONG_MAX;
  if (tmpULLI != NRRD_ULLONG_MAX) {
    sprintf(err, 
            "%s: unsigned long long int can't hold NRRD_ULLONG_MAX ("
            AIR_ULLONG_FMT ")",
            me, NRRD_ULLONG_MAX);
    biffAdd(NRRD, err); return 0;
  }
  tmpULLI += 1;
  if (tmpULLI != 0) {
    sprintf(err, "%s: unsigned long long int max (" AIR_ULLONG_FMT 
            ") incorrect", me,
            NRRD_ULLONG_MAX);
    biffAdd(NRRD, err); return 0;
  }

  if (_nrrdCheckEnums()) {
    sprintf(err, "%s: problem with enum definition", me);
    biffAdd(NRRD, err); return 0;
  }
  
  if (!( NRRD_DIM_MAX >= 3 )) {
    sprintf(err, "%s: NRRD_DIM_MAX == %d seems awfully small, doesn't it?",
            me, NRRD_DIM_MAX);
    biffAdd(NRRD, err); return 0;
  }

  if (!nrrdTypeIsIntegral[nrrdTypeBlock]) {
    sprintf(err, "%s: nrrdTypeInteger[nrrdTypeBlock] is not true, things "
            "could get wacky", me);
    biffAdd(NRRD, err); return 0;
  }

  /* HEY: any other assumptions built into Teem? */

  _nrrdSanity = 1;
  return 1;
}
コード例 #28
0
ファイル: affine.c プロジェクト: BRAINSia/teem
int
unrrdu_affineMain(int argc, const char **argv, const char *me,
                  hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err;
  NrrdIter *minIn, *in, *maxIn, *minOut, *maxOut, *args[5];
  Nrrd *nout, *ntmp=NULL;
  int type, E, pret, clamp;
  airArray *mop;
  unsigned int ai, nn;

  hestOptAdd(&opt, NULL, "minIn", airTypeOther, 1, 1, &minIn, NULL,
             "Lower end of input value range.",
             NULL, NULL, nrrdHestIter);
  hestOptAdd(&opt, NULL, "in", airTypeOther, 1, 1, &in, NULL,
             "Input value.",
             NULL, NULL, nrrdHestIter);
  hestOptAdd(&opt, NULL, "maxIn", airTypeOther, 1, 1, &maxIn, NULL,
             "Upper end of input value range.",
             NULL, NULL, nrrdHestIter);
  hestOptAdd(&opt, NULL, "minOut", airTypeOther, 1, 1, &minOut, NULL,
             "Lower end of output value range.",
             NULL, NULL, nrrdHestIter);
  hestOptAdd(&opt, NULL, "maxOut", airTypeOther, 1, 1, &maxOut, NULL,
             "Upper end of output value range.",
             NULL, NULL, nrrdHestIter);
  hestOptAdd(&opt, "t,type", "type", airTypeOther, 1, 1, &type, "default",
             "type to convert all nrrd inputs to, prior to "
             "doing operation.  This also determines output type. "
             "By default (not using this option), the types of the input "
             "nrrds are left unchanged.",
             NULL, NULL, &unrrduHestMaybeTypeCB);
  hestOptAdd(&opt, "clamp", "bool", airTypeBool, 1, 1, &clamp, "false",
             "clamp output values to specified output range");
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_affineInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

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

  args[0] = minIn;
  args[1] = in;
  args[2] = maxIn;
  args[3] = minOut;
  args[4] = maxOut;
  nn = 0;
  for (ai=0; ai<5; ai++) {
    nn += !!args[ai]->ownNrrd;
  }
  if (nrrdTypeDefault != type) {
    /* they wanted to convert nrrds to some other type first */
    E = 0;
    for (ai=0; ai<5; ai++) {
      if (args[ai]->ownNrrd) {
        if (!E) E |= nrrdConvert(ntmp=nrrdNew(), args[ai]->ownNrrd, type);
        if (!E) nrrdIterSetOwnNrrd(args[ai], ntmp);
      }
    }
    if (E) {
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: error converting input nrrd(s):\n%s", me, err);
      airMopError(mop);
      return 1;
    }
  }

  if (0 == nn) {
    /* actually, there are no nrrds; we represent the functionality
       of the previous stand-alone binary "affine" */
    double valOut;
    valOut = AIR_AFFINE(minIn->val, in->val, maxIn->val,
                        minOut->val, maxOut->val);
    if (clamp) {
      double mmin = AIR_MIN(minOut->val, maxOut->val);
      double mmax = AIR_MAX(minOut->val, maxOut->val);
      valOut = AIR_CLAMP(mmin, valOut, mmax);
    }
    printf("%g\n", valOut);
  } else {
    /* we have a nrrd output */
    if (1 == nn && in->ownNrrd) {
      E = nrrdArithAffine(nout, minIn->val, in->ownNrrd, maxIn->val,
                          minOut->val, maxOut->val, clamp);
    } else {
      E = nrrdArithIterAffine(nout, minIn, in, maxIn, minOut, maxOut, clamp);
    }
    if (E) {
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: error doing ternary operation:\n%s", me, err);
      airMopError(mop);
      return 1;
    }
    SAVE(out, nout, NULL);
  }

  airMopOkay(mop);
  return 0;
}
コード例 #29
0
ファイル: polyshapes.c プロジェクト: SCIInstitute/Cleaver
int
limnPolyDataCylinder(limnPolyData *pld,
                     unsigned int infoBitFlag,
                     unsigned int thetaRes, int sharpEdge) {
  char me[]="limnPolyDataCylinder", err[BIFF_STRLEN];
  unsigned int vertNum, primNum, primIdx, indxNum, thetaIdx, vertIdx, blah;
  double theta, cth, sth, sq2;

  /* sanity bounds */
  thetaRes = AIR_MAX(3, thetaRes);

  vertNum = sharpEdge ? 4*thetaRes : 2*thetaRes;
  primNum = 3;
  indxNum = 2*thetaRes + 2*(thetaRes+1);  /* 2 fans + 1 strip */
  if (limnPolyDataAlloc(pld, infoBitFlag, vertNum, indxNum, primNum)) {
    sprintf(err, "%s: couldn't allocate output", me); 
    biffAdd(LIMN, err); return 1;
  }
  
  vertIdx = 0;
  for (blah=0; blah < (sharpEdge ? 2u : 1u); blah++) {
    for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
      theta = AIR_AFFINE(0, thetaIdx, thetaRes, 0, 2*AIR_PI);
      ELL_4V_SET_TT(pld->xyzw + 4*vertIdx, float,
                    cos(theta), sin(theta), 1, 1);
      /*
      fprintf(stderr, "!%s: vert[%u] = %g %g %g\n", me, vertIdx,
              (pld->xyzw + 4*vertIdx)[0],
              (pld->xyzw + 4*vertIdx)[1],
              (pld->xyzw + 4*vertIdx)[2]);
      */
      ++vertIdx;
    }
  }
  for (blah=0; blah < (sharpEdge ? 2u : 1u); blah++) {
    for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
      theta = AIR_AFFINE(0, thetaIdx, thetaRes, 0, 2*AIR_PI);
      ELL_4V_SET_TT(pld->xyzw + 4*vertIdx, float,
                    cos(theta), sin(theta), -1, 1);
      /*
      fprintf(stderr, "!%s: vert[%u] = %g %g %g\n", me, vertIdx,
              (pld->xyzw + 4*vertIdx)[0],
              (pld->xyzw + 4*vertIdx)[1],
              (pld->xyzw + 4*vertIdx)[2]);
      */
      ++vertIdx;
    }
  }

  primIdx = 0;
  vertIdx = 0;
  /* fan on top */
  for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
    pld->indx[vertIdx++] = thetaIdx;
  }
  pld->type[primIdx] = limnPrimitiveTriangleFan;
  pld->icnt[primIdx] = thetaRes;
  primIdx++;

  /* single strip around */
  for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
    pld->indx[vertIdx++] = (sharpEdge ? 1 : 0)*thetaRes + thetaIdx;
    pld->indx[vertIdx++] = (sharpEdge ? 2 : 1)*thetaRes + thetaIdx;
  }
  pld->indx[vertIdx++] = (sharpEdge ? 1 : 0)*thetaRes;
  pld->indx[vertIdx++] = (sharpEdge ? 2 : 1)*thetaRes;
  pld->type[primIdx] = limnPrimitiveTriangleStrip;
  pld->icnt[primIdx] = 2*(thetaRes+1);
  primIdx++;

  /* fan on bottom */
  for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
    pld->indx[vertIdx++] = (sharpEdge ? 3 : 1)*thetaRes + thetaIdx;
  }
  pld->type[primIdx] = limnPrimitiveTriangleFan;
  pld->icnt[primIdx] = thetaRes;
  primIdx++;

  if ((1 << limnPolyDataInfoNorm) & infoBitFlag) {
    sq2 = sqrt(2.0);
    if (sharpEdge) {
      for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
        theta = AIR_AFFINE(0, thetaIdx, thetaRes, 0, 2*AIR_PI);
        cth = cos(theta);
        sth = sin(theta);
        ELL_3V_SET_TT(pld->norm + 3*(thetaIdx + 0*thetaRes),
                      float, 0, 0, 1);
        ELL_3V_SET_TT(pld->norm + 3*(thetaIdx + 1*thetaRes),
                      float, cth, sth, 0);
        ELL_3V_SET_TT(pld->norm + 3*(thetaIdx + 2*thetaRes),
                      float, cth, sth, 0);
        ELL_3V_SET_TT(pld->norm + 3*(thetaIdx + 3*thetaRes),
                      float, 0, 0, -1);
      }
    } else {
      for (thetaIdx=0; thetaIdx<thetaRes; thetaIdx++) {
コード例 #30
0
int
main(int argc, char *argv[]) {
  char *me;
  hestOpt *hopt=NULL;
  airArray *mop;

  char *errS, *outS, *covarS;
  Nrrd *_nodf, *nvec, *nhist, *ncovar;
  int bins;
  size_t size[NRRD_DIM_MAX];
  float min;
  
  mop = airMopNew();
  me = argv[0];

  hestOptAdd(&hopt, "i", "odf", airTypeOther, 1, 1, &_nodf, NULL,
             "ODF volume to analyze", NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "v", "odf", airTypeOther, 1, 1, &nvec, NULL,
             "list of vectors by which odf is sampled",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "min", "min", airTypeFloat, 1, 1, &min, "0.0",
             "ODF values below this are ignored, and per-voxel ODF is "
             "normalized to have sum 1.0.  Use \"nan\" to subtract out "
             "the per-voxel min.");
  hestOptAdd(&hopt, "b", "bins", airTypeInt, 1, 1, &bins, "128",
             "number of bins in histograms");
  hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-",
             "output file");
  hestOptAdd(&hopt, "co", "covariance out", airTypeString, 1, 1,
             &covarS, "covar.nrrd", "covariance output file");
  hestParseOrDie(hopt, argc-1, argv+1, NULL,
                 me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);
  
  if (!( nrrdTypeFloat == nvec->type )) {
    fprintf(stderr, "%s vector type (%s) not %s\n", me,
            airEnumStr(nrrdType, nvec->type),
            airEnumStr(nrrdType, nrrdTypeFloat));
    airMopError(mop); return 1;
  }
  if (!( 2 == nvec->dim && 3 == nvec->axis[0].size )) {
    fprintf(stderr, "%s: nvec not a 2-D 3-by-N array\n", me);
    airMopError(mop); return 1;
  }
  if (!( _nodf->axis[0].size == nvec->axis[1].size )) {
    fprintf(stderr, "%s mismatch of _nodf->axis[0].size (%d) vs. "
            "nvec->axis[1].size (%d)\n", me, 
            (int)_nodf->axis[0].size, (int)nvec->axis[1].size);
    airMopError(mop); return 1;
  }
  nrrdAxisInfoGet_nva(_nodf, nrrdAxisInfoSize, size);
  size[0] = bins;
  nhist = nrrdNew();
  airMopAdd(mop, nhist, (airMopper)nrrdNuke, airMopAlways);
  if (nrrdMaybeAlloc_nva(nhist, nrrdTypeFloat, _nodf->dim, size)) {
    airMopAdd(mop, errS = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble allocating output:\n%s", me, errS);
    airMopError(mop); return 1;
  }
  ncovar = nrrdNew();
  airMopAdd(mop, ncovar, (airMopper)nrrdNuke, airMopAlways);
  if (nrrdMaybeAlloc_va(ncovar, nrrdTypeFloat, 2,
                        AIR_CAST(size_t, bins),
                        AIR_CAST(size_t, bins))) {
    airMopAdd(mop, errS = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble allocating covariance output:\n%s", me, errS);
    airMopError(mop); return 1;
  }

  {
    /* we modify the lengths of the vectors here */
    int NN, VV, ii, jj=0, kk, *anglut;
    float *odf, *hist, *covar, *vec, *vi, *vj, tmp, pvmin;
    double *mean;
    Nrrd *nodf, *nanglut;

    VV = nvec->axis[1].size;
    NN = nrrdElementNumber(_nodf)/VV;

    nanglut = nrrdNew();
    airMopAdd(mop, nanglut, (airMopper)nrrdNuke, airMopAlways);
    if (nrrdMaybeAlloc_va(nanglut, nrrdTypeInt, 2,
                          AIR_CAST(size_t, VV),
                          AIR_CAST(size_t, VV))) {
      airMopAdd(mop, errS = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble allocating lookup table:\n%s", me, errS);
      airMopError(mop); return 1;
    }
    if (nrrdTypeFloat == _nodf->type) {
      nodf = _nodf;
    } else {
      nodf = nrrdNew();
      airMopAdd(mop, nodf, (airMopper)nrrdNuke, airMopAlways);
      if (nrrdConvert(nodf, _nodf, nrrdTypeFloat)) {
        airMopAdd(mop, errS = biffGetDone(NRRD), airFree, airMopAlways);
        fprintf(stderr, "%s: trouble converting input:\n%s", me, errS);
        airMopError(mop); return 1;
      }
    }      
    
    /* normalize lengths (MODIFIES INPUT) */
    vec = (float*)nvec->data;
    for (ii=0; ii<=jj; ii++) {
      vi = vec + 3*ii;
      ELL_3V_NORM(vi, vi, tmp);
    }
    
    /* pre-compute pair-wise angles */
    anglut = (int*)nanglut->data;
    for (jj=0; jj<VV; jj++) {
      vj = vec + 3*jj;
      for (ii=0; ii<=jj; ii++) {
        vi = vec + 3*ii;
        tmp = ELL_3V_DOT(vi, vj);
        tmp = AIR_ABS(tmp);
        tmp = acos(tmp)/(AIR_PI/2.0);
        anglut[ii + VV*jj] = airIndex(0.0, tmp, 1.0, bins);
      }
    }

    /* process all samples (MODIFIES INPUT if input was already float) */
    odf = (float*)nodf->data;
    hist = (float*)nhist->data;
    for (kk=0; kk<NN; kk++) {
      if (!(kk % 100)) {
        fprintf(stderr, "%d/%d\n", kk, NN);
      }
      tmp = 0;
      if (AIR_EXISTS(min)) {
        for (ii=0; ii<VV; ii++) {
          odf[ii] = AIR_MAX(0.0, odf[ii]-min);
          tmp += odf[ii];
        }
      } else {
        /* we do the more sketchy per-voxel min subtraction */
        pvmin = airFPGen_f(airFP_POS_INF);
        for (ii=0; ii<VV; ii++) {
          pvmin = AIR_MIN(pvmin, odf[ii]);
        }
        for (ii=0; ii<VV; ii++) {
          odf[ii] -= pvmin;
          tmp += odf[ii];
        }
      }
      if (tmp) {
        /* something left after subtracting out baseline isotropic */
        for (ii=0; ii<VV; ii++) {
          odf[ii] /= tmp;
        }
        /* odf[] is normalized to 1.0 sum */
        for (jj=0; jj<VV; jj++) {
          for (ii=0; ii<=jj; ii++) {
            tmp = odf[ii]*odf[jj];
            hist[anglut[ii + VV*jj]] += tmp;
          }
        }
      }
      odf += VV;
      hist += bins;
    }
    odf = NULL;
    hist = NULL;

    /* find mean value of each bin (needed for covariance) */
    mean = (double*)calloc(bins, sizeof(double));
    if (!mean) {
      fprintf(stderr, "%s: couldn't allocate mean array", me);
      airMopError(mop); return 1;
    }
    hist = (float*)nhist->data;
    for (kk=0; kk<NN; kk++) {
      for (ii=0; ii<bins; ii++) {
        mean[ii] += hist[ii];
      }
      hist += bins;
    }
    hist = NULL;
    for (ii=0; ii<bins; ii++) {
      mean[ii] /= NN;
    }

    /* make covariance matrix of from all histograms */
    covar = (float*)ncovar->data;
    hist = (float*)nhist->data;
    for (kk=0; kk<NN; kk++) {
      for (jj=0; jj<bins; jj++) {
        for (ii=0; ii<jj; ii++) {
          tmp = (hist[ii] - mean[ii])*(hist[jj] - mean[jj]);
          covar[ii + bins*jj] += tmp;
          covar[jj + bins*ii] += tmp;
        }
        covar[jj + bins*jj] += (hist[jj] - mean[jj])*(hist[jj] - mean[jj]);
      }
      hist += bins;
    }
    hist = NULL;
  }

  if (nrrdSave(outS, nhist, NULL)) {
    airMopAdd(mop, errS = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: couldn't save output:\n%s\n", me, errS);
    airMopError(mop); return 1;
  }
  if (nrrdSave(covarS, ncovar, NULL)) {
    airMopAdd(mop, errS = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: couldn't save covariance output:\n%s\n", me, errS);
    airMopError(mop); return 1;
  }
  airMopOkay(mop);
  return 0;
}