Ejemplo n.º 1
0
/* 
** bins on boundary now extend to infinity; so the only time this 
** returns NULL (indicating error) is for non-existant positions
*/
pullBin *
_pullBinLocate(pullContext *pctx, double *posWorld) {
  char me[]="_pullBinLocate", err[BIFF_STRLEN];
  unsigned int axi, eidx[3], binIdx;

  if (!ELL_3V_EXISTS(posWorld)) {
    sprintf(err, "%s: non-existant position (%g,%g,%g)", me,
            posWorld[0], posWorld[1], posWorld[2]);
    biffAdd(PULL, err); return NULL;
  }

  if (pctx->binSingle) {
    binIdx = 0;
  } else {
    for (axi=0; axi<3; axi++) {
      eidx[axi] = airIndexClamp(pctx->bboxMin[axi],
                                posWorld[axi],
                                pctx->bboxMax[axi],
                                pctx->binsEdge[axi]);
    }
    binIdx = (eidx[0]
              + pctx->binsEdge[0]*(eidx[1] 
                                   + pctx->binsEdge[1]*eidx[2]));
  }
  /*
  fprintf(stderr, "!%s: bin(%g,%g,%g) = %u\n", me, 
          _posWorld[0], _posWorld[1], _posWorld[2], binIdx);
  */

  return pctx->bin + binIdx;
}
Ejemplo n.º 2
0
void
tenTripleConvertSingle_d(double dst[3], int dstType,
                         const double src[3], const int srcType) {
  static const char me[]="tenTripleConvertSingle_d";
  int direct;

  if (airEnumValCheck(tenTripleType, dstType)
      || airEnumValCheck(tenTripleType, srcType)) {
    /* got invalid source or destination type */
    ELL_3V_SET(dst, AIR_NAN, AIR_NAN, AIR_NAN);
    return;
  }

  if (_convert[dstType][srcType]) {
    /* we have a direct converter */
    _convert[dstType][srcType](dst, src);
    direct = AIR_TRUE;
  } else {
    double eval[3];
    /* else, for lack of anything clever, we convert via evals */
    _convert[tenTripleTypeEigenvalue][srcType](eval, src);
    _convert[dstType][tenTripleTypeEigenvalue](dst, eval);
    direct = AIR_FALSE;
  }

  /* warn if conversion created non-existent values from
     existent input */
  if (ELL_3V_EXISTS(src) && !ELL_3V_EXISTS(dst)) {
    fprintf(stderr, "%s: problem? (%s) %g %g %g <-%s- (%s) %g %g %g\n", me,
            airEnumStr(tenTripleType, dstType),
            dst[0], dst[1], dst[2],
            direct ? "-" : "...",
            airEnumStr(tenTripleType, srcType),
            src[0], src[1], src[2]);
  }

  return;
}
Ejemplo n.º 3
0
/*
** bins on boundary now extend to infinity; so the only time this
** returns NULL (indicating error) is for non-existent positions
*/
pushBin *
_pushBinLocate(pushContext *pctx, double *_posWorld) {
  static const char me[]="_pushBinLocate";
  double posWorld[4], posIdx[4];
  unsigned int axi, eidx[3], binIdx;

  if (!ELL_3V_EXISTS(_posWorld)) {
    biffAddf(PUSH, "%s: non-existent position (%g,%g,%g)", me,
             _posWorld[0], _posWorld[1], _posWorld[2]);
    return NULL;
  }

  if (pctx->binSingle) {
    binIdx = 0;
  } else {
    ELL_3V_COPY(posWorld, _posWorld);
    posWorld[3] = 1.0;
    ELL_4MV_MUL(posIdx, pctx->gctx->shape->WtoI, posWorld);
    ELL_34V_HOMOG(posIdx, posIdx);
    for (axi=0; axi<3; axi++) {
      eidx[axi] = airIndexClamp(-0.5,
                                posIdx[axi],
                                pctx->gctx->shape->size[axi]-0.5,
                                pctx->binsEdge[axi]);
    }
    binIdx = (eidx[0]
              + pctx->binsEdge[0]*(eidx[1]
                                   + pctx->binsEdge[1]*eidx[2]));
  }
  /*
  fprintf(stderr, "!%s: bin(%g,%g,%g) = %u\n", me,
          _posWorld[0], _posWorld[1], _posWorld[2], binIdx);
  */

  return pctx->bin + binIdx;
}
Ejemplo n.º 4
0
int
fixproj(Nrrd *nproj[3], Nrrd *nvol) {
  char me[]="fixproj", err[BIFF_STRLEN];
  airArray *mop;
  Nrrd *ntmp[3], *nt;
  int sz[3], ii, map[3], h[3], E, mi;
  size_t rsz[3];
  double vec[3][3], dot[3], sp[3], parm[NRRD_KERNEL_PARMS_NUM];

  mop = airMopNew();

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

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

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

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

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

  airMopOkay(mop);
  return 0;
}
Ejemplo n.º 5
0
/*
** _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;
}