Esempio n. 1
0
int
unrrdu_axdeleteMain(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err;
  Nrrd *nin, *nout, *ntmp;
  int pret, _axis;
  unsigned axis;
  airArray *mop;

  hestOptAdd(&opt, "a,axis", "axis", airTypeInt, 1, 1, &_axis, NULL, 
             "dimension (axis index) of the axis to remove");
  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

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

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

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

  if (-1 == _axis) {
    ntmp = nrrdNew();
    airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways);
    if (nrrdCopy(nout, nin)) {
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: error copying axis:\n%s", me, err);
      airMopError(mop); return 1;
    }
    for (axis=0;
         axis<nout->dim && nout->axis[axis].size > 1;
         axis++);
    while (axis<nout->dim) {
      if (nrrdAxesDelete(ntmp, nout, axis)
          || nrrdCopy(nout, ntmp)) {
        airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
        fprintf(stderr, "%s: error deleting axis:\n%s", me, err);
        airMopError(mop); return 1;
      }
      for (axis=0;
           axis<nout->dim && nout->axis[axis].size > 1;
           axis++);
    }
  } else {
    if (nrrdAxesDelete(nout, nin, _axis)) {
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: error deleting axis:\n%s", me, err);
      airMopError(mop); return 1;
    }
  }

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
Esempio n. 2
0
int
_baneClipAnswer_Percentile(int *countP, Nrrd *hvol, double *clipParm) {
  static const char me[]="_baneClipAnswer_Percentile";
  Nrrd *ncopy;
  int *hits, clip;
  size_t num, sum, out, outsofar, hi;

  if (nrrdCopy(ncopy=nrrdNew(), hvol)) {
    biffMovef(BANE, NRRD, "%s: couldn't create copy of histovol", me);
    return 1;
  }
  hits = (int *)ncopy->data;
  num = nrrdElementNumber(ncopy);
  qsort(hits, num, sizeof(int), nrrdValCompare[nrrdTypeInt]);
  sum = 0;
  for (hi=0; hi<num; hi++) {
    sum += hits[hi];
  }
  out = (size_t)(sum*clipParm[0]/100);
  outsofar = 0;
  hi = num-1;
  do {
    outsofar += hits[hi--];
  } while (outsofar < out);
  clip = hits[hi];
  nrrdNuke(ncopy);

  *countP = clip;
  return 0;
}
Esempio n. 3
0
int
alanUpdate(alanContext *actx) {
  char me[]="alanUpdate", err[BIFF_STRLEN];
  int ret;

  if (_alanCheck(actx)) {
    sprintf(err, "%s: ", me);
    biffAdd(ALAN, err); return 1;
  }
  if (actx->_nlev[0] || actx->_nlev[0]) {
    sprintf(err, "%s: confusion: _nlev[0,1] already allocated?", me);
    biffAdd(ALAN, err); return 1;
  }
  actx->_nlev[0] = nrrdNew();
  actx->_nlev[1] = nrrdNew();
  actx->nparm = nrrdNew();
  if (2 == actx->dim) {
    ret = (nrrdMaybeAlloc_va(actx->_nlev[0], alan_nt, 3,
                             AIR_CAST(size_t, 2),
                             AIR_CAST(size_t, actx->size[0]),
                             AIR_CAST(size_t, actx->size[1]))
           || nrrdCopy(actx->_nlev[1], actx->_nlev[0])
           || nrrdMaybeAlloc_va(actx->nparm, alan_nt, 3,
                                AIR_CAST(size_t, 3),
                                AIR_CAST(size_t, actx->size[0]),
                                AIR_CAST(size_t, actx->size[1])));
  } else {
    ret = (nrrdMaybeAlloc_va(actx->_nlev[0], alan_nt, 4,
                             AIR_CAST(size_t, 2),
                             AIR_CAST(size_t, actx->size[0]),
                             AIR_CAST(size_t, actx->size[1]),
                             AIR_CAST(size_t, actx->size[2]))
           || nrrdCopy(actx->_nlev[1], actx->_nlev[0])
           || nrrdMaybeAlloc_va(actx->nparm, alan_nt, 4,
                                AIR_CAST(size_t, 3),
                                AIR_CAST(size_t, actx->size[0]),
                                AIR_CAST(size_t, actx->size[1]),
                                AIR_CAST(size_t, actx->size[2])));
  }
  if (ret) {
    sprintf(err, "%s: trouble allocating buffers", me);
    biffMove(ALAN, err, NRRD); return 1;
  }
  
  return 0;
}
Esempio n. 4
0
int
_miteNtxfCopy(miteRender *mrr, miteUser *muu) {
  static const char me[]="_miteNtxfCopy";
  int ni, E;

  mrr->ntxf = AIR_CALLOC(muu->ntxfNum, Nrrd *);
  if (!mrr->ntxf) {
    biffAddf(MITE, "%s: couldn't calloc %d ntxf pointers", me, muu->ntxfNum);
    return 1;
  }
  mrr->ntxfNum = muu->ntxfNum;
  airMopAdd(mrr->rmop, mrr->ntxf, airFree, airMopAlways);
  E = 0;
  for (ni=0; ni<mrr->ntxfNum; ni++) {
    mrr->ntxf[ni] = nrrdNew();
    if (!E) airMopAdd(mrr->rmop, mrr->ntxf[ni],
                      (airMopper)nrrdNuke, airMopAlways);
    if (!( nrrdTypeUChar == muu->ntxf[ni]->type
           || nrrdTypeFloat == muu->ntxf[ni]->type
           || nrrdTypeDouble == muu->ntxf[ni]->type )) {
      biffAddf(MITE,
               "%s: sorry, can't handle txf of type %s (only %s, %s, %s)",
               me, airEnumStr(nrrdType, muu->ntxf[ni]->type),
               airEnumStr(nrrdType, nrrdTypeUChar),
               airEnumStr(nrrdType, nrrdTypeFloat),
               airEnumStr(nrrdType, nrrdTypeDouble));
      return 1;
    }
    /* note that key/values need to be copied for the sake of
       identifying a non-default miteStageOp */
    switch(muu->ntxf[ni]->type) {
    case nrrdTypeUChar:
      if (!E) E |= nrrdUnquantize(mrr->ntxf[ni], muu->ntxf[ni], nrrdTypeUChar);
      if (!E) E |= nrrdKeyValueCopy(mrr->ntxf[ni], muu->ntxf[ni]);
      break;
    case mite_nt:
      if (!E) E |= nrrdCopy(mrr->ntxf[ni], muu->ntxf[ni]);
      break;
    default:  /* will be either float or double (whatever mite_nt isn't) */
      if (!E) E |= nrrdConvert(mrr->ntxf[ni], muu->ntxf[ni], mite_nt);
      if (!E) E |= nrrdKeyValueCopy(mrr->ntxf[ni], muu->ntxf[ni]);
      break;
    }
  }
  if (E) {
    biffMovef(MITE, NRRD, "%s: troubling copying/converting all ntxfs", me);
    return 1;
  }
  return 0;
}
Esempio n. 5
0
int
tenTripleConvert(Nrrd *nout, int dstType,
                 const Nrrd *nin, int srcType) {
  static const char me[]="tenTripleConvert";
  size_t II, NN;
  double (*ins)(void *, size_t, double), (*lup)(const void *, size_t);

  if (!( nout && nin )) {
    biffAddf(TEN, "%s: got NULL pointer", me);
    return 1;
  }
  if ( airEnumValCheck(tenTripleType, dstType) ||
       airEnumValCheck(tenTripleType, srcType) ) {
    biffAddf(TEN, "%s: got invalid %s dst (%d) or src (%d)", me,
             tenTripleType->name, dstType, srcType);
    return 1;
  }
  if (3 != nin->axis[0].size) {
    char stmp[AIR_STRLEN_SMALL];
    biffAddf(TEN, "%s: need axis[0].size 3, not %s", me,
             airSprintSize_t(stmp, nin->axis[0].size));
    return 1;
  }
  if (nrrdTypeBlock == nin->type) {
    biffAddf(TEN, "%s: input has non-scalar %s type",
             me, airEnumStr(nrrdType, nrrdTypeBlock));
    return 1;
  }

  if (nrrdCopy(nout, nin)) {
    biffMovef(TEN, NRRD, "%s: couldn't initialize output", me);
    return 1;
  }
  lup = nrrdDLookup[nin->type];
  ins = nrrdDInsert[nout->type];
  NN = nrrdElementNumber(nin)/3;
  for (II=0; II<NN; II++) {
    double src[3], dst[3];
    src[0] = lup(nin->data, 0 + 3*II);
    src[1] = lup(nin->data, 1 + 3*II);
    src[2] = lup(nin->data, 2 + 3*II);
    tenTripleConvertSingle_d(dst, dstType, src, srcType);
    ins(nout->data, 0 + 3*II, dst[0]);
    ins(nout->data, 1 + 3*II, dst[1]);
    ins(nout->data, 2 + 3*II, dst[2]);
  }

  return 0;
}
Esempio n. 6
0
int
nrrdArithUnaryOp(Nrrd *nout, int op, const Nrrd *nin) {
  static const char me[]="nrrdArithUnaryOp";
  size_t N, I;
  int size[NRRD_DIM_MAX];
  double (*insert)(void *v, size_t I, double d),
    (*lookup)(const void *v, size_t I), (*uop)(double), val;

  if (!(nout && nin)) {
    biffAddf(NRRD, "%s: got NULL pointer", me);
    return 1;
  }
  if (nrrdTypeBlock == nin->type) {
    biffAddf(NRRD, "%s: can't operate on type %s", me,
             airEnumStr(nrrdType, nrrdTypeBlock));
    return 1;
  }
  if (airEnumValCheck(nrrdUnaryOp, op)) {
    biffAddf(NRRD, "%s: unary op %d invalid", me, op);
    return 1;
  }
  if (nout != nin) {
    if (nrrdCopy(nout, nin)) {
      biffAddf(NRRD, "%s:", me);
      return 1;
    }
  }
  nrrdAxisInfoGet_nva(nin, nrrdAxisInfoSize, size);
  uop = _nrrdUnaryOp[op];

  N = nrrdElementNumber(nin);
  lookup = nrrdDLookup[nin->type];
  insert = nrrdDInsert[nin->type];
  for (I=0; I<N; I++) {
    val = lookup(nin->data, I);
    insert(nout->data, I, uop(val));
  }
  if (nrrdContentSet_va(nout, airEnumStr(nrrdUnaryOp, op), nin, "")) {
    biffAddf(NRRD, "%s:", me);
    return 1;
  }
  nrrdBasicInfoInit(nout,
                    NRRD_BASIC_INFO_ALL ^ (NRRD_BASIC_INFO_OLDMIN_BIT
                                           | NRRD_BASIC_INFO_OLDMAX_BIT));
  return 0;
}
Esempio n. 7
0
/*
** note that if tgparm->insertZeroVec, there will be one sample more
** along axis 1 of nout than the requested #gradients "num"
*/
int
tenGradientGenerate(Nrrd *nout, unsigned int num, tenGradientParm *tgparm) {
  static const char me[]="tenGradientGenerate";
  Nrrd *nin;
  airArray *mop;

  if (!(nout && tgparm)) {
    biffAddf(TEN, "%s: got NULL pointer", me);
    return 1;
  }
  if (!( num >= 3 )) {
    biffAddf(TEN, "%s: can generate minimum of 3 gradient directions "
            "(not %d)", me, num);
    return 1;
  }
  mop = airMopNew();
  nin = nrrdNew();
  airMopAdd(mop, nin, (airMopper)nrrdNuke, airMopAlways);

  if (tenGradientRandom(nin, num, tgparm->seed)
      || tenGradientDistribute(nout, nin, tgparm)) {
    biffAddf(TEN, "%s: trouble", me);
    airMopError(mop); return 1;
  }
  if (tgparm->insertZeroVec) {
    /* this is potentially confusing: the second axis (axis 1)
       is going to come back one longer than the requested
       number of gradients! */
    Nrrd *ntmp;
    ptrdiff_t padMin[2] = {0, -1}, padMax[2];
    padMax[0] = AIR_CAST(ptrdiff_t, nout->axis[0].size-1);
    padMax[1] = AIR_CAST(ptrdiff_t, num-1);
    ntmp = nrrdNew();
    airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways);
    if (nrrdPad_nva(ntmp, nout, padMin, padMax,
                    nrrdBoundaryPad, 0.0)
        || nrrdCopy(nout, ntmp)) {
      biffMovef(TEN, NRRD, "%s: trouble adding zero vector", me);
      airMopError(mop); return 1;
    }
  }

  airMopOkay(mop);
  return 0;
}
Esempio n. 8
0
int
nrrdArithAffine(Nrrd *nout, double minIn,
                const Nrrd *nin, double maxIn,
                double minOut, double maxOut, int clamp) {
  static const char me[]="nrrdArithAffine";
  size_t I, N;
  double (*ins)(void *v, size_t I, double d),
    (*lup)(const void *v, size_t I), mmin, mmax;

  if ( !nout || nrrdCheck(nin) ) {
    biffAddf(NRRD, "%s: got NULL pointer or invalid input", me);
    return 1;
  }
  if (nout != nin) {
    if (nrrdCopy(nout, nin)) {
      biffAddf(NRRD, "%s: couldn't initialize output", me);
      return 1;
    }
  }
  N = nrrdElementNumber(nin);
  ins = nrrdDInsert[nout->type];
  lup = nrrdDLookup[nin->type];
  mmin = AIR_MIN(minOut, maxOut);
  mmax = AIR_MAX(minOut, maxOut);
  for (I=0; I<N; I++) {
    double val;
    val = lup(nin->data, I);
    val = AIR_AFFINE(minIn, val, maxIn, minOut, maxOut);
    if (clamp) {
      val = AIR_CLAMP(mmin, val, mmax);
    }
    ins(nout->data, I, val);
  }
  /* HEY: it would be much better if the ordering here was the same as in
     AIR_AFFINE, but that's not easy with the way the content functions are
     now set up */
  if (nrrdContentSet_va(nout, "affine", nin,
                        "%g,%g,%g,%g", minIn, maxIn,
                        minOut, maxOut)) {
    biffAddf(NRRD, "%s:", me);
  }
  return 0;
}
Esempio n. 9
0
int
_baneClipAnswer_TopN(int *countP, Nrrd *hvol, double *clipParm) {
  static const char me[]="_baneClipAnwer_TopN";
  Nrrd *copy;
  int *hits, tmp;
  size_t num;

  if (nrrdCopy(copy=nrrdNew(), hvol)) {
    biffMovef(BANE, NRRD, "%s: couldn't create copy of histovol", me);
    return 1;
  }
  hits = (int *)copy->data;
  num = nrrdElementNumber(copy);
  qsort(hits, num, sizeof(int), nrrdValCompare[nrrdTypeInt]);
  tmp = AIR_CLAMP(0, (int)clipParm[0], (int)num-1);
  *countP = hits[num-tmp-1];
  nrrdNuke(copy);

  return 0;
}
Esempio n. 10
0
int
nrrdOrientationReduce(Nrrd *nout, const Nrrd *nin,
                      int setMinsFromOrigin) {
  char me[]="nrrdOrientationReduce", err[BIFF_STRLEN];
  unsigned int spatialAxisNum, spatialAxisIdx[NRRD_DIM_MAX], saxii;
  NrrdAxisInfo *axis;

  if (!(nout && nin)) {
    sprintf(err, "%s: got NULL spacing", me);
    biffAdd(NRRD, err); return 1;
  }

  if (nout != nin) {
    if (nrrdCopy(nout, nin)) {
      sprintf(err, "%s: trouble doing initial copying", me);
      biffAdd(NRRD, err); return 1;
    }

  }
  if (!nout->spaceDim) {
    /* we're done! */
    return 0;
  }
  spatialAxisNum = nrrdSpatialAxesGet(nout, spatialAxisIdx);
  for (saxii=0; saxii<spatialAxisNum; saxii++) {
    axis = nout->axis + spatialAxisIdx[saxii];
    axis->spacing = nrrdSpaceVecNorm(nout->spaceDim,
                                     axis->spaceDirection);
    if (setMinsFromOrigin) {
      axis->min = (saxii < nout->spaceDim 
                   ? nout->spaceOrigin[saxii]
                   : AIR_NAN);
    }
  }
  nrrdSpaceSet(nout, nrrdSpaceUnknown);
  
  return 0;
}
Esempio n. 11
0
/*
** DOES use biff
*/
meetPullVol *
meetPullVolCopy(const meetPullVol *mpv) {
  static const char me[]="meetPullVolCopy";
  meetPullVol *ret;
  unsigned int si;
  airArray *mop;

  mop = airMopNew();
  ret = meetPullVolNew();
  airMopAdd(mop, ret, (airMopper)meetPullVolNix, airMopOnError);
  /* HEY: hope this is okay for dynamic kinds */
  ret->kind = mpv->kind;
  ret->fileName = airStrdup(mpv->fileName);
  ret->volName = airStrdup(mpv->volName);
  if (mpv->sbp) {
    ret->sbp = gageStackBlurParmNew();
    if (gageStackBlurParmCopy(ret->sbp, mpv->sbp)) {
      biffMovef(MEET, GAGE, "%s: problem", me);
      airMopError(mop); return NULL;
    }
  }
  ret->leeching = AIR_FALSE;
  ret->derivNormSS = mpv->derivNormSS;
  ret->recomputedSS = AIR_FALSE;
  ret->derivNormBiasSS = mpv->derivNormBiasSS;
  if (mpv->sbp) {
    ret->nin = NULL;
    ret->ninSS = AIR_CALLOC(ret->sbp->num, Nrrd *);
    for (si=0; si<mpv->sbp->num; si++) {
      ret->ninSS[si] = nrrdNew();
      if (nrrdCopy(ret->ninSS[si], mpv->ninSS[si])) {
        biffMovef(MEET, NRRD, "%s: problem with ninSS[%u]", me, si);
        airMopError(mop); return NULL;
      }
    }
  } else {
Esempio n. 12
0
int
main(int argc, char *argv[]) {
  char *me, *errS, *outS;
  hestOpt *hopt=NULL;
  hestParm *hparm;
  airArray *mop;
  Nrrd *nin, *nout;
  NrrdKernelSpec *ksp;
  mossSampler *msp;
  double mat[6], **matList, *origInfo, origMat[6], origInvMat[6], ox, oy,
    min[2], max[2];
  int d, bound, ax0, size[2];
  unsigned int matListLen, _bkgLen, i, avgNum;
  float *bkg, *_bkg, scale[4];
  
  me = argv[0];
  mop = airMopNew();
  hparm = hestParmNew();
  airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways);
  hparm->elideSingleEnumType = AIR_TRUE;
  hparm->elideSingleOtherType = AIR_TRUE;
  hparm->elideSingleOtherDefault = AIR_FALSE;
  hparm->elideMultipleNonExistFloatDefault = AIR_TRUE;
  hparm->respFileEnable = AIR_TRUE;
  
  hestOptAdd(&hopt, "i", "image", airTypeOther, 1, 1, &nin, "-",
             "input image", NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "0", "origin", airTypeOther, 1, 1, &origInfo, "p:0,0",
             "where to location (0,0) prior to applying transforms.\n "
             "\b\bo \"u:<float>,<float>\" locate origin in a unit box "
             "[0,1]x[0,1] which covers the original image\n "
             "\b\bo \"p:<float>,<float>\" locate origin at a particular "
             "pixel location, in the index space of the image",
             NULL, NULL, mossHestOrigin);
  hestOptAdd(&hopt, "t", "xform0", airTypeOther, 1, -1, &matList, NULL,
             "transform(s) to apply to image.  Transforms "
             "are applied in the order in which they appear.\n "
             "\b\bo \"identity\": no geometric transform, just resampling\n "
             "\b\bo \"translate:x,y\": shift image by vector (x,y), as "
             "measured in pixels\n "
             "\b\bo \"rotate:ang\": rotate CCW by ang degrees\n "
             "\b\bo \"scale:xs,ys\": scale by xs in X, and ys in Y\n "
             "\b\bo \"shear:fix,amnt\": shear by amnt, keeping fixed "
             "the pixels along a direction <fix> degrees from the X axis\n "
             "\b\bo \"flip:ang\": flip along axis an angle <ang> degrees from "
             "the X axis\n "
             "\b\bo \"a,b,tx,c,d,ty\": specify the transform explicitly "
             "in row-major order (opposite of PostScript) ",
             &matListLen, NULL, mossHestTransform);
  hestOptAdd(&hopt, "k", "kernel", airTypeOther, 1, 1, &ksp,
             "cubic:0,0.5", "reconstruction kernel",
             NULL, NULL, nrrdHestKernelSpec);
  hestOptAdd(&hopt, "min", "xMin yMin", airTypeDouble, 2, 2, min, "nan nan",
             "lower bounding corner of output image. Default (by not "
             "using this option) is the lower corner of input image. ");
  hestOptAdd(&hopt, "max", "xMax yMax", airTypeDouble, 2, 2, max, "nan nan",
             "upper bounding corner of output image. Default (by not "
             "using this option) is the upper corner of input image. ");
  hestOptAdd(&hopt, "b", "boundary", airTypeEnum, 1, 1, &bound, "bleed",
             "what to do when sampling outside original image.\n "
             "\b\bo \"bleed\": copy values at image border outward\n "
             "\b\bo \"wrap\": do wrap-around on image locations\n "
             "\b\bo \"pad\": use a given background value (via \"-bg\")",
             NULL, nrrdBoundary);
  hestOptAdd(&hopt, "bg", "bg0 bg1", airTypeFloat, 1, -1, &_bkg, "nan",
             "background color to use with boundary behavior \"pad\". "
             "Defaults to all zeroes.",
             &_bkgLen);
  hestOptAdd(&hopt, "s", "xSize ySize", airTypeOther, 2, 2, scale, "x1 x1",
             "For each axis, information about how many samples in output:\n "
             "\b\bo \"x<float>\": number of output samples is some scaling of "
             " the number input of samples; multiplied by <float>\n "
             "\b\bo \"<int>\": specify exact number of samples",
             NULL, NULL, &unrrduHestScaleCB);
  hestOptAdd(&hopt, "a", "avg #", airTypeUInt, 1, 1, &avgNum, "0",
             "number of averages (if there there is only one "
             "rotation)");
  hestOptAdd(&hopt, "o", "filename", airTypeString, 1, 1, &outS, "-",
             "file to write output nrrd to");
  hestParseOrDie(hopt, argc-1, argv+1, hparm,
                 me, ilkInfo, AIR_TRUE, AIR_TRUE, AIR_TRUE);
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
  msp = mossSamplerNew();
  airMopAdd(mop, msp, (airMopper)mossSamplerNix, airMopAlways);
  msp->boundary = bound;
  if (mossSamplerKernelSet(msp, ksp->kernel, ksp->parm)) {
    fprintf(stderr, "%s: trouble with sampler:\n%s\n",
            me, errS = biffGetDone(MOSS)); free(errS);
    airMopError(mop); return 1;
  }
  if (nrrdBoundaryPad == bound) {
    if (_bkgLen != MOSS_NCOL(nin)) {
      fprintf(stderr, "%s: got %d background colors, image has "
              _AIR_SIZE_T_CNV " colors\n", 
              me, _bkgLen, MOSS_NCOL(nin));
      airMopError(mop); return 1;
    } else {
      bkg = _bkg;
    }
  } else {
    /* maybe warn user if they gave a background that won't be used? */
    /* No- because hest is stupid, and right now we always parse the
       single (default) "nan" for this argument! */
    bkg = NULL;
  }

  ax0 = MOSS_AXIS0(nin);
  if (!( AIR_EXISTS(nin->axis[ax0+0].min)
         && AIR_EXISTS(nin->axis[ax0+0].max))) {
    nrrdAxisInfoMinMaxSet(nin, ax0+0, mossDefCenter);
  }
  if (!( AIR_EXISTS(nin->axis[ax0+1].min)
         && AIR_EXISTS(nin->axis[ax0+1].max))) {
    nrrdAxisInfoMinMaxSet(nin, ax0+1, mossDefCenter);
  }
  min[0] = AIR_EXISTS(min[0]) ? min[0] : nin->axis[ax0+0].min;
  max[0] = AIR_EXISTS(max[0]) ? max[0] : nin->axis[ax0+0].max;
  min[1] = AIR_EXISTS(min[1]) ? min[1] : nin->axis[ax0+1].min;
  max[1] = AIR_EXISTS(max[1]) ? max[1] : nin->axis[ax0+1].max;
  for (d=0; d<2; d++) {
    switch((int)scale[0 + 2*d]) {
    case 0:
      /* same number of samples as input */
      size[d] = nin->axis[ax0+d].size;
      break;
    case 1:
      /* scaling of input # samples */
      size[d] = (int)(scale[1 + 2*d]*nin->axis[ax0+d].size);
      break;
    case 2:
      /* explicit # of samples */
      size[d] = (int)(scale[1 + 2*d]);
      break;
    }
  }

  /* find origin-based pre- and post- translate */
  if (0 == origInfo[0]) {
    /* absolute pixel position */
    mossMatTranslateSet(origMat, -origInfo[1], -origInfo[2]);
  } else {
    /* in unit box [0,1]x[0,1] */
    ox = AIR_AFFINE(0.0, origInfo[1], 1.0,
                    nin->axis[ax0+0].min, nin->axis[ax0+0].max);
    oy = AIR_AFFINE(0.0, origInfo[2], 1.0, 
                    nin->axis[ax0+1].min, nin->axis[ax0+1].max);
    mossMatTranslateSet(origMat, -ox, -oy);
  }
  mossMatInvert(origInvMat, origMat);

  /* form complete transform */
  mossMatIdentitySet(mat);
  mossMatLeftMultiply(mat, origMat);
  for (i=0; i<matListLen; i++) {
    mossMatLeftMultiply(mat, matList[i]);
  }
  mossMatLeftMultiply(mat, origInvMat);

  if (!AIR_EXISTS(nin->axis[ax0+0].min) || !AIR_EXISTS(nin->axis[ax0+0].max)) {
    nrrdAxisInfoMinMaxSet(nin, ax0+0, mossDefCenter);
  }
  if (!AIR_EXISTS(nin->axis[ax0+1].min) || !AIR_EXISTS(nin->axis[ax0+1].max)) {
    nrrdAxisInfoMinMaxSet(nin, ax0+1, mossDefCenter);
  }
  if (avgNum > 1) {
    unsigned int ai;
    double angleMax, angle, mrot[6];
    Nrrd *ntmp, *nacc;
    NrrdIter *itA, *itB;
    int E;

    ntmp = nrrdNew();
    airMopAdd(mop, ntmp, (airMopper)nrrdNuke, airMopAlways);
    nacc = nrrdNew();
    airMopAdd(mop, nacc, (airMopper)nrrdNuke, airMopAlways);
    itA = nrrdIterNew();
    airMopAdd(mop, itA, (airMopper)nrrdIterNix, airMopAlways);
    itB = nrrdIterNew();
    airMopAdd(mop, itB, (airMopper)nrrdIterNix, airMopAlways);
    E = 0;
    angleMax = atan2(mat[3], mat[0]);
    fprintf(stderr, "%s: %u angles ", me, avgNum);
    for (ai=0; ai<avgNum; ai++) {
      fprintf(stderr, "."); fflush(stderr);
      angle = (180/AIR_PI)*AIR_AFFINE(0, ai, avgNum-1, angleMax, -angleMax);
      mossMatIdentitySet(mat);
      mossMatLeftMultiply(mat, origMat);
      mossMatRotateSet(mrot, angle);
      mossMatLeftMultiply(mat, mrot);
      mossMatLeftMultiply(mat, origInvMat);
      if (mossLinearTransform(ntmp, nin, bkg,
                              mat, msp,
                              min[0], max[0], min[1], max[1],
                              size[0], size[1])) {
        fprintf(stderr, "%s: problem doing transform:\n%s\n",
                me, errS = biffGetDone(MOSS)); free(errS);
        airMopError(mop); return 1;
      }
      if (!ai) {
        if (!E) E |= nrrdCopy(nacc, ntmp);
      } else {
        if (!E) E |= nrrdArithBinaryOp(nacc, nrrdBinaryOpAdd, nacc, ntmp);
      }
      if (E) {
        break;
      }
    }
    fprintf(stderr, "\n");
    nrrdIterSetNrrd(itA, nacc);
    nrrdIterSetValue(itB, avgNum);
    if (!E) E |= nrrdArithIterBinaryOp(nout, nrrdBinaryOpDivide,
                                       itA, itB);
    if (E) {
      fprintf(stderr, "%s: problem making output:\n%s\n",
              me, errS = biffGetDone(NRRD)); free(errS);
      airMopError(mop); return 1;
    }
  } else {
    if (mossLinearTransform(nout, nin, bkg,
                            mat, msp,
                            min[0], max[0], min[1], max[1],
                            size[0], size[1])) {
      fprintf(stderr, "%s: problem doing transform:\n%s\n",
              me, errS = biffGetDone(MOSS)); free(errS);
      airMopError(mop); return 1;
    }
  }

  if (nrrdSave(outS, nout, NULL)) {
    fprintf(stderr, "%s: problem saving output:\n%s\n",
            me, errS = biffGetDone(NRRD)); free(errS);
    airMopError(mop); return 1;
  }

  airMopOkay(mop);
  exit(0);
}
Esempio n. 13
0
/* this strongly assumes that nrrdFitsInFormat() was true */
int
_nrrdFormatVTK_write(FILE *file, const Nrrd *_nrrd, NrrdIoState *nio) {
  static const char me[]="_nrrdFormatVTK_write";
  int i, sx, sy, sz, sax;
  double xs, ys, zs, xm, ym, zm;
  char type[AIR_STRLEN_MED], name[AIR_STRLEN_SMALL];
  Nrrd *nrrd;
  airArray *mop;

  /* HEY: should this copy be done more conservatively */
  mop = airMopNew();
  airMopAdd(mop, nrrd=nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  if (nrrdCopy(nrrd, _nrrd)) {
    biffAddf(NRRD, "%s: couldn't make private copy", me);
    airMopError(mop); return 1;
  }
  if (!( 3 == nrrd->dim ||
         (4 == nrrd->dim && (3 == nrrd->axis[0].size ||
                             9 == nrrd->axis[0].size)) )) {
    biffAddf(NRRD, "%s: doesn't seem to be scalar, vector, or matrix", me);
    airMopError(mop); return 1;
  }
  sax = nrrd->dim - 3;
  xs = nrrd->axis[sax+0].spacing;
  ys = nrrd->axis[sax+1].spacing;
  zs = nrrd->axis[sax+2].spacing;
  if (!( AIR_EXISTS(xs) && AIR_EXISTS(ys) && AIR_EXISTS(zs) )) {
    xs = ys = zs = 1.0;
  }
  xm = nrrd->axis[sax+0].min;
  ym = nrrd->axis[sax+1].min;
  zm = nrrd->axis[sax+2].min;
  if (!( AIR_EXISTS(xm) && AIR_EXISTS(ym) && AIR_EXISTS(zm) )) {
    xm = ym = zm = 0.0;
  }
  sx = AIR_CAST(int, nrrd->axis[sax+0].size);
  sy = AIR_CAST(int, nrrd->axis[sax+1].size);
  sz = AIR_CAST(int, nrrd->axis[sax+2].size);

  switch(nrrd->type) {
  case nrrdTypeUChar:
    strcpy(type, "unsigned_char");
    break;
  case nrrdTypeChar:
    strcpy(type, "char");
    break;
  case nrrdTypeUShort:
    strcpy(type, "unsigned_short");
    break;
  case nrrdTypeShort:
    strcpy(type, "short");
    break;
  case nrrdTypeUInt:
    strcpy(type, "unsigned_int");
    break;
  case nrrdTypeInt:
    strcpy(type, "int");
    break;
  case nrrdTypeFloat:
    strcpy(type, "float");
    break;
  case nrrdTypeDouble:
    strcpy(type, "double");
    break;
  default:
    biffAddf(NRRD, "%s: can't put %s-type nrrd into VTK", me,
             airEnumStr(nrrdType, nrrd->type));
    airMopError(mop); return 1;
  }
  fprintf(file, "%s\n", MAGIC3);
  /* there is a file-format-imposed limit on the length of the "content" */
  if (nrrd->content) {
    /* when the "250" below was previously "255", vtk didn't deal */
    for (i=0; i<=250 && nrrd->content[i]; i++) {
      fputc(nrrd->content[i], file);
    }
    fputc('\n', file);
  } else {
    fprintf(file, NRRD_UNKNOWN "\n");
  }
  if (nrrdEncodingRaw == nio->encoding) {
    fprintf(file, "BINARY\n");
  } else {
    fprintf(file, "ASCII\n");
  }
  fprintf(file, "DATASET STRUCTURED_POINTS\n");
  fprintf(file, "DIMENSIONS %d %d %d\n", sx, sy, sz);
  fprintf(file, "ORIGIN %g %g %g\n", xm, ym, zm);
  fprintf(file, "SPACING %g %g %g\n", xs, ys, zs);
  fprintf(file, "POINT_DATA %d\n", sx*sy*sz);
  airSrandMT(AIR_CAST(unsigned int, airTime()));
  sprintf(name, "nrrd%05d", airRandInt(100000));
  if (3 == nrrd->dim) {
    fprintf(file, "SCALARS %s %s\n", name, type);
    fprintf(file, "LOOKUP_TABLE default\n");
  } else {
    /* 4 == nrrd->dim */
    if (3 == nrrd->axis[0].size) {
      fprintf(file, "VECTORS %s %s\n", name, type);
    } else {
      fprintf(file, "TENSORS %s %s\n", name, type);
    }
  }
  if (1 < nrrdElementSize(nrrd)
      && nio->encoding->endianMatters
      && airMyEndian() != airEndianBig) {
    /* encoding exposes endianness, and we're not big, as req.d by VTK */
    nrrdSwapEndian(nrrd);
  }
  if (nio->encoding->write(file, nrrd->data, nrrdElementNumber(nrrd),
                           nrrd, nio)) {
    biffAddf(NRRD, "%s:", me);
    airMopError(mop); return 1;
  }

  airMopOkay(mop);
  return 0;
}
Esempio n. 14
0
int
unrrdu_axinfoMain(int argc, const char **argv, const char *me,
                  hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err, *label, *units, *centerStr, *kindStr;
  Nrrd *nin, *nout;
  int pret, center, kind;
  unsigned int *axes, axesLen, axi;
  double mm[2], spc;
  airArray *mop;

  hestOptAdd(&opt, "a,axes", "ax0", airTypeUInt, 1, -1, &axes, NULL,
             "the one or more axes that should be modified", &axesLen);
  hestOptAdd(&opt, "l,label", "label", airTypeString, 1, 1, &label, "",
             "label to associate with axis");
  hestOptAdd(&opt, "u,units", "units", airTypeString, 1, 1, &units, "",
             "units of measurement");
  hestOptAdd(&opt, "mm,minmax", "min max", airTypeDouble, 2, 2, mm, "nan nan",
             "min and max values along axis");
  hestOptAdd(&opt, "sp,spacing", "spacing", airTypeDouble, 1, 1, &spc, "nan",
             "spacing between samples along axis");
  /* HEY: this is currently a fundamental (but only rarely annoying)
     problem in hest.  Because there is functionally no difference
     between whether an option's information comes from the default
     string or from the command-line, there is no real way to tell
     hest, "hey, its just fine for this option to not be used, and
     if its not used, DON'T DO ANYTHING".  The games of setting strings
     to "" and floats/doubles to NaN are ways of compensating for
     this.  However, there is no analogous trick for airEnums.
  hestOptAdd(&opt, "c,center", "center", airTypeEnum, 1, 1, &cent, "unknown",
             "centering of axis: \"cell\" or \"node\"",
             NULL, nrrdCenter);
  */
  /* but this hack will do for now */
  hestOptAdd(&opt, "c,center", "center", airTypeString, 1, 1, &centerStr, "",
             "axis centering: \"cell\" or \"node\".  Not using this option "
             "leaves the centering as it is on input");
  hestOptAdd(&opt, "k,kind", "kind", airTypeString, 1, 1, &kindStr, "",
             "axis kind. Not using this option "
             "leaves the kind as it is on input");

  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

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

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

  for (axi=0; axi<axesLen; axi++) {
    if (!( axes[axi] < nin->dim )) {
      fprintf(stderr, "%s: axis %u not in valid range [0,%u]\n",
              me, axes[axi], nin->dim-1);
      airMopError(mop);
      return 1;
    }
  }
  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
  if (nrrdCopy(nout, nin)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: error copying input:\n%s", me, err);
    airMopError(mop);
    return 1;
  }

  for (axi=0; axi<axesLen; axi++) {
    unsigned int axis;
    axis = axes[axi];
    if (strlen(label)) {
      nout->axis[axis].label = (char *)airFree(nout->axis[axis].label);
      nout->axis[axis].label = airStrdup(label);
    }
    if (strlen(units)) {
      nout->axis[axis].units = (char *)airFree(nout->axis[axis].units);
      nout->axis[axis].units = airStrdup(units);
    }
    if (AIR_EXISTS(mm[0])) {
      nout->axis[axis].min = mm[0];
    }
    if (AIR_EXISTS(mm[1])) {
      nout->axis[axis].max = mm[1];
    }
    if (AIR_EXISTS(spc)) {
      nout->axis[axis].spacing = spc;
    }
    /* see above
    if (nrrdCenterUnknown != cent) {
      nout->axis[axis].center = cent;
    }
    */
    if (airStrlen(centerStr)) {
      if (!strcmp("none", centerStr)
          || !strcmp("???", centerStr)) {
        center = nrrdCenterUnknown;
      } else {
        if (!(center = airEnumVal(nrrdCenter, centerStr))) {
          fprintf(stderr, "%s: couldn't parse \"%s\" as %s\n", me,
                  centerStr, nrrdCenter->name);
          airMopError(mop);
          return 1;
        }
      }
      nout->axis[axis].center = center;
    }
    if (airStrlen(kindStr)) {
      if (!strcmp("none", kindStr)
          || !strcmp("???", kindStr)) {
        kind = nrrdKindUnknown;
      } else {
        if (!(kind = airEnumVal(nrrdKind, kindStr))) {
          fprintf(stderr, "%s: couldn't parse \"%s\" as %s\n", me,
                  kindStr, nrrdKind->name);
          airMopError(mop);
          return 1;
        }
      }
      nout->axis[axis].kind = kind;
    }
  }

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
Esempio n. 15
0
/*
** parties until the gradients settle down
*/
int
tenGradientBalance(Nrrd *nout, const Nrrd *nin,
                   tenGradientParm *tgparm) {
  static const char me[]="tenGradientBalance";
  double len, lastLen, improv;
  airRandMTState *rstate;
  Nrrd *ncopy;
  unsigned int iter, maxIter;
  int done;
  airArray *mop;

  if (!nout || tenGradientCheck(nin, nrrdTypeUnknown, 2) || !tgparm) {
    biffAddf(TEN, "%s: got NULL pointer (%p,%p) or invalid nin", me,
             AIR_VOIDP(nout), AIR_VOIDP(tgparm));
    return 1;
  }
  if (nrrdConvert(nout, nin, nrrdTypeDouble)) {
    biffMovef(TEN, NRRD, "%s: can't initialize output with input", me);
    return 1;
  }

  mop = airMopNew();
  ncopy = nrrdNew();
  airMopAdd(mop, ncopy, (airMopper)nrrdNuke, airMopAlways);
  rstate = airRandMTStateNew(tgparm->seed);
  airMopAdd(mop, rstate, (airMopper)airRandMTStateNix, airMopAlways);
  /* HEY: factor of 100 is an approximate hack */
  maxIter = 100*tgparm->maxIteration;

  lastLen = 1.0;
  done = AIR_FALSE;
  do {
    iter = 0;
    do {
      iter++;
      len = party(nout, rstate);
    } while (len > lastLen && iter < maxIter);
    if (iter >= maxIter) {
      if (tgparm->verbose) {
        fprintf(stderr, "%s: stopping at max iter %u\n", me, maxIter);
      }
      if (nrrdCopy(nout, ncopy)) {
        biffMovef(TEN, NRRD, "%s: trouble copying", me);
        airMopError(mop); return 1;
      }
      done = AIR_TRUE;
    } else {
      if (nrrdCopy(ncopy, nout)) {
        biffMovef(TEN, NRRD, "%s: trouble copying", me);
        airMopError(mop); return 1;
      }
      improv = lastLen - len;
      lastLen = len;
      if (tgparm->verbose) {
        fprintf(stderr, "%s: (iter %u) improvement: %g  (mean length = %g)\n",
                me, iter, improv, len);
      }
      done = (improv <= tgparm->minMeanImprovement
              || len < tgparm->minMean);
    }
  } while (!done);

  airMopOkay(mop);
  return 0;
}
Esempio n. 16
0
/*
******** nrrdSplice()
**
** (opposite of nrrdSlice): replaces one slice of a nrrd with
** another nrrd.  Will allocate memory for output only if nout != nin.
*/
int
nrrdSplice(Nrrd *nout, const Nrrd *nin, const Nrrd *nslice,
           unsigned int axis, size_t pos) {
  char me[]="nrrdSplice", func[]="splice", err[BIFF_STRLEN];
  size_t 
    I, 
    rowLen,                  /* length of segment */
    colStep,                 /* distance between start of each segment */
    colLen;                  /* number of periods */
  unsigned int ai;
  char *src, *dest, *sliceCont;

  if (!(nin && nout && nslice)) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err); return 1;
  }
  if (nout == nslice) {
    sprintf(err, "%s: nout==nslice disallowed", me);
    biffAdd(NRRD, err); return 1;
  }

  /* check that desired slice location is legit */
  if (!( axis < nin->dim )) {
    sprintf(err, "%s: slice axis %d out of bounds (0 to %d)", 
            me, axis, nin->dim-1);
    biffAdd(NRRD, err); return 1;
  }
  if (!( pos < nin->axis[axis].size )) {
    sprintf(err, "%s: position " _AIR_SIZE_T_CNV 
            " out of bounds (0 to " _AIR_SIZE_T_CNV ")", 
            me, pos, nin->axis[axis].size-1);
    biffAdd(NRRD, err); return 1;
  }

  /* check that slice will fit in nin */
  if (nrrdCheck(nslice) || nrrdCheck(nin)) {
    sprintf(err, "%s: input or slice not valid nrrd", me);
    biffAdd(NRRD, err); return 1;
  }
  if (!( nin->dim-1 == nslice->dim )) {
    sprintf(err, "%s: dim of slice (%d) not one less than dim of input (%d)",
            me, nslice->dim, nin->dim);
    biffAdd(NRRD, err); return 1;
  }
  if (!( nin->type == nslice->type )) {
    sprintf(err, "%s: type of slice (%s) != type of input (%s)",
            me, airEnumStr(nrrdType, nslice->type),
            airEnumStr(nrrdType, nin->type));
    biffAdd(NRRD, err); return 1;
  }
  if (nrrdTypeBlock == nin->type) {
    if (!( nin->blockSize == nslice->blockSize )) {
      sprintf(err, "%s: input's blockSize (" _AIR_SIZE_T_CNV 
              ") != subvolume's blockSize (" _AIR_SIZE_T_CNV ")",
              me, nin->blockSize, nslice->blockSize);
      biffAdd(NRRD, err); return 1;
    }
  }
  for (ai=0; ai<nslice->dim; ai++) {
    if (!( nin->axis[ai + (ai >= axis)].size == nslice->axis[ai].size )) {
      sprintf(err, "%s: input's axis %d size (" _AIR_SIZE_T_CNV
              ") != slices axis %d size (" _AIR_SIZE_T_CNV ")",
              me, ai + (ai >= axis),
              nin->axis[ai + (ai >= axis)].size, ai, 
              nslice->axis[ai].size);
      biffAdd(NRRD, err); return 1;
    }
  }

  if (nout != nin) {
    if (nrrdCopy(nout, nin)) {
      sprintf(err, "%s:", me);
      biffAdd(NRRD, err); return 1;
    }
  } 
  /* else we're going to splice in place */

  /* the following was copied from nrrdSlice() */
  /* set up control variables */
  rowLen = colLen = 1;
  for (ai=0; ai<nin->dim; ai++) {
    if (ai < axis) {
      rowLen *= nin->axis[ai].size;
    } else if (ai > axis) {
      colLen *= nin->axis[ai].size;
    }
  }
  rowLen *= nrrdElementSize(nin);
  colStep = rowLen*nin->axis[axis].size;

  /* the skinny */
  src = (char *)nout->data;    /* switched src,dest from nrrdSlice() */
  dest = (char *)nslice->data;
  src += rowLen*pos;
  for (I=0; I<colLen; I++) {
    /* HEY: replace with AIR_MEMCPY() or similar, when applicable */
    memcpy(src, dest, rowLen);  /* switched src,dest from nrrdSlice() */
    src += colStep;
    dest += rowLen;
  }
  
  sliceCont = _nrrdContentGet(nslice);
  if (nrrdContentSet_va(nout, func, nin, "%s,%d," _AIR_SIZE_T_CNV, 
                        sliceCont, axis, pos)) {
    sprintf(err, "%s:", me);
    biffAdd(NRRD, err); free(sliceCont); return 1;
  }
  free(sliceCont);
  /* basic info copied by nrrdCopy above */

  return 0;
}
Esempio n. 17
0
/*
******** nrrdInset()
**
** (opposite of nrrdCrop()) replace some sub-volume inside a nrrd with
** another given nrrd.
**
*/
int
nrrdInset(Nrrd *nout, const Nrrd *nin, const Nrrd *nsub, const size_t *min) {
  char me[]="nrrdInset", func[] = "inset", err[BIFF_STRLEN],
    buff1[NRRD_DIM_MAX*30], buff2[AIR_STRLEN_SMALL];
  unsigned int ai;
  size_t I,
    lineSize,                /* #bytes in one scanline to be copied */
    typeSize,                /* size of data type */
    cIn[NRRD_DIM_MAX],       /* coords for line start, in input */
    cOut[NRRD_DIM_MAX],      /* coords for line start, in output */
    szIn[NRRD_DIM_MAX],
    szOut[NRRD_DIM_MAX],
    idxIn, idxOut,           /* linear indices for input and output */
    numLines;                /* number of scanlines in output nrrd */
  char *dataIn, *dataOut, *subCont;

  /* errors */
  if (!(nout && nin && nsub && min)) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err); return 1;
  }
  if (nout == nsub) {
    sprintf(err, "%s: nout==nsub disallowed", me);
    biffAdd(NRRD, err); return 1;
  }
  if (nrrdCheck(nin)) {
    sprintf(err, "%s: input not valid nrrd", me);
    biffAdd(NRRD, err); return 1;
  }
  if (nrrdCheck(nsub)) {
    sprintf(err, "%s: subvolume not valid nrrd", me);
    biffAdd(NRRD, err); return 1;
  }
  if (!( nin->dim == nsub->dim )) {
    sprintf(err, "%s: input's dim (%d) != subvolume's dim (%d)",
            me, nin->dim, nsub->dim);
    biffAdd(NRRD, err); return 1;
  }
  if (!( nin->type == nsub->type )) {
    sprintf(err, "%s: input's type (%s) != subvolume's type (%s)", me,
            airEnumStr(nrrdType, nin->type),
            airEnumStr(nrrdType, nsub->type));
    biffAdd(NRRD, err); return 1;
  }
  if (nrrdTypeBlock == nin->type) {
    if (!( nin->blockSize == nsub->blockSize )) {
      sprintf(err, "%s: input's blockSize (" _AIR_SIZE_T_CNV
              ") != subvolume's blockSize (" _AIR_SIZE_T_CNV ")",
              me, nin->blockSize, nsub->blockSize);
      biffAdd(NRRD, err); return 1;
    }
  }
  for (ai=0; ai<nin->dim; ai++) {
    if (!( min[ai] + nsub->axis[ai].size - 1 <= nin->axis[ai].size - 1)) {
      sprintf(err, "%s: axis %d range of inset indices [" _AIR_SIZE_T_CNV 
              "," _AIR_SIZE_T_CNV  "] not within "
              "input indices [0," _AIR_SIZE_T_CNV "]", me, ai,
              min[ai], min[ai] + nsub->axis[ai].size - 1,
              nin->axis[ai].size - 1);
      biffAdd(NRRD, err); return 1;
    }
  }
  
  if (nout != nin) {
    if (nrrdCopy(nout, nin)) {
      sprintf(err, "%s:", me);
      biffAdd(NRRD, err); return 1;
    }
  } 
  /* else we're going to inset in place */

  /* WARNING: following code copied/modified from nrrdCrop(),
     so the meanings of "in"/"out", "src"/"dest" are all messed up */

  nrrdAxisInfoGet_nva(nin, nrrdAxisInfoSize, szIn);
  nrrdAxisInfoGet_nva(nsub, nrrdAxisInfoSize, szOut);
  numLines = 1;
  for (ai=1; ai<nin->dim; ai++) {
    numLines *= szOut[ai];
  }
  lineSize = szOut[0]*nrrdElementSize(nin);
  
  /* the skinny */
  typeSize = nrrdElementSize(nin);
  dataIn = (char *)nout->data;
  dataOut = (char *)nsub->data;
  for (ai=0; ai<NRRD_DIM_MAX; ai++) {
    cOut[ai] = 0;
  }
  for (I=0; I<numLines; I++) {
    for (ai=0; ai<nin->dim; ai++) {
      cIn[ai] = cOut[ai] + min[ai];
    }
    NRRD_INDEX_GEN(idxOut, cOut, szOut, nin->dim);
    NRRD_INDEX_GEN(idxIn, cIn, szIn, nin->dim);
    memcpy(dataIn + idxIn*typeSize, dataOut + idxOut*typeSize, lineSize);
    /* the lowest coordinate in cOut[] will stay zero, since we are 
       copying one (1-D) scanline at a time */
    NRRD_COORD_INCR(cOut, szOut, nin->dim, 1);
  }

  /* HEY: before Teem version 2.0 figure out nrrdKind stuff here */
  
  strcpy(buff1, "[");
  for (ai=0; ai<nin->dim; ai++) {
    sprintf(buff2, "%s" _AIR_SIZE_T_CNV, (ai ? "," : ""), min[ai]);
    strcat(buff1, buff2);
  }
  strcat(buff1, "]");
  subCont = _nrrdContentGet(nsub);
  if (nrrdContentSet_va(nout, func, nin, "%s,%s", subCont, buff1)) {
    sprintf(err, "%s:", me);
    biffAdd(NRRD, err); free(subCont); return 1;
  }
  free(subCont); 
  /* basic info copied by nrrdCopy above */

  return 0;
}
Esempio n. 18
0
int
main(int argc, char *argv[]) {
  char *me, *outS;
  hestOpt *hopt;
  hestParm *hparm;
  airArray *mop;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  airMopOkay(mop);
  exit(0);
}
Esempio n. 19
0
int
unrrdu_basinfoMain(int argc, const char **argv, const char *me,
                   hestParm *hparm) {
  /* these are stock for unrrdu */
  hestOpt *opt = NULL;
  airArray *mop;
  int pret;
  char *err;
  /* these are stock for things using the usual -i and -o */
  char *out;
  Nrrd *nin, *nout;
  /* these are specific to this command */
  NrrdIoState *nio;
  char *spcStr, *_origStr, *origStr;
  int space;
  unsigned int spaceDim;

  hestOptAdd(&opt, "spc,space", "space", airTypeString, 1, 1, &spcStr, "",
             "identify the space (e.g. \"RAS\", \"LPS\") in which the array "
             "conceptually lives, from the nrrdSpace airEnum, which in turn "
             "determines the dimension of the space.  Or, use an integer>0 to"
             "give the dimension of a space that nrrdSpace doesn't know about. "
             "By default (not using this option), the enclosing space is "
             "set as unknown.");
  hestOptAdd(&opt, "orig,origin", "origin", airTypeString, 1, 1, &_origStr, "",
             "(NOTE: must quote vector) the origin in space of the array: "
             "the location of the center "
             "of the first sample, of the form \"(x,y,z)\" (or however "
             "many coefficients are needed for the chosen space). Quoting the "
             "vector is needed to stop interpretation from the shell");
  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

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

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

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

  /* HEY: copy and paste from unrrdu/make.c */
  if (airStrlen(spcStr)) {
    space = airEnumVal(nrrdSpace, spcStr);
    if (!space) {
      /* couldn't parse it as space, perhaps its a uint */
      if (1 != sscanf(spcStr, "%u", &spaceDim)) {
        fprintf(stderr, "%s: couldn't parse \"%s\" as a nrrdSpace "
                "or as a uint", me, spcStr);
        airMopError(mop); return 1;
      }
      /* else we did parse it as a uint */
      nout->space = nrrdSpaceUnknown;
      nout->spaceDim = spaceDim;
    } else {
      /* we did parse a known space */
      nrrdSpaceSet(nout, space);
    }
  }

  /* HEY: copy and paste from unrrdu/make.c */
  if (airStrlen(_origStr)) {
    /* why this is necessary is a bit confusing to me, both the check for
       enclosing quotes, and the need to use to a separate variable (isn't
       hest doing memory management of addresses, not variables?) */
    if ('\"' == _origStr[0] && '\"' == _origStr[strlen(_origStr)-1]) {
      _origStr[strlen(_origStr)-1] = 0;
      origStr = _origStr + 1;
    } else {
      origStr = _origStr;
    }
    /* same hack about using NrrdIoState->line as basis for parsing */
    nio->line = origStr;
    nio->pos = 0;
    if (nrrdFieldInfoParse[nrrdField_space_origin](NULL, nout,
                                                   nio, AIR_TRUE)) {
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble with origin \"%s\":\n%s",
              me, origStr, err);
      nio->line = NULL; airMopError(mop); return 1;
    }
    nio->line = NULL;
  }

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
Esempio n. 20
0
int
unrrdu_dnormMain(int argc, const char **argv, const char *me,
                 hestParm *hparm) {
    char *outS;
    int pret;

    Nrrd *nin, *nout;
    NrrdIoState *nio;
    int kindIn, kindOut, headerOnly, haveMM, trivialOrient, recenter, gotmf;
    unsigned int kindAxis, axi, si, sj;
    double sscl;

    hestOpt *opt = NULL;
    char *err;
    airArray *mop;

    hestOptAdd(&opt, "h,header", NULL, airTypeInt, 0, 0, &headerOnly, NULL,
               "output header of nrrd file only, not the data itself");
    hestOptAdd(&opt, "to", NULL, airTypeInt, 0, 0, &trivialOrient, NULL,
               "(*t*rivial *o*rientation) "
               "even if the input nrrd comes with full orientation or "
               "per-axis min-max info, ignore it and instead assert the "
               "identity mapping between index and world space");
    hestOptAdd(&opt, "c,center", NULL, airTypeInt, 0, 0, &recenter, NULL,
               "re-locate output spaceOrigin so that field is centered "
               "around origin of space coordinates");
    hestOptAdd(&opt, "s,scaling", "scl", airTypeDouble, 1, 1, &sscl, "1.0",
               "when having to contrive orientation information and there's "
               "no per-axis min/max to inform what the sample spacing is, "
               "this is the sample spacing to assert");
    OPT_ADD_NIN(nin, "input image");
    OPT_ADD_NOUT(outS, "output filename");

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

    /* can't deal with block type */
    if (nrrdTypeBlock == nin->type) {
        fprintf(stderr, "%s: can only have scalar kinds (not %s)\n", me,
                airEnumStr(nrrdType, nrrdTypeBlock));
        airMopError(mop);
        exit(1);
    }

    /* make sure all kinds are set to something */
    /* see if there's a range kind, verify that there's only one */
    /* set haveMM */
    haveMM = AIR_TRUE;
    kindIn = nrrdKindUnknown;
    kindAxis = 0;
    for (axi=0; axi<nin->dim; axi++) {
        if (nrrdKindUnknown == nin->axis[axi].kind
                || nrrdKindIsDomain(nin->axis[axi].kind)) {
            haveMM &= AIR_EXISTS(nin->axis[axi].min);
            haveMM &= AIR_EXISTS(nin->axis[axi].max);
        } else {
            if (nrrdKindUnknown != kindIn) {
                fprintf(stderr, "%s: got non-domain kind %s on axis %u, but already "
                        "have %s from axis %u\n", me,
                        airEnumStr(nrrdKind, nin->axis[axi].kind), axi,
                        airEnumStr(nrrdKind, kindIn), kindAxis);
                airMopError(mop);
                exit(1);
            }
            kindIn = nin->axis[axi].kind;
            kindAxis = axi;
        }
    }
    /* see if the non-domain kind is something we can interpret as a tensor */
    if (nrrdKindUnknown != kindIn) {
        switch (kindIn) {
        /* ======= THESE are the kinds that we can possibly output ======= */
        case nrrdKind2Vector:
        case nrrdKind3Vector:
        case nrrdKind4Vector:
        case nrrdKind2DSymMatrix:
        case nrrdKind2DMatrix:
        case nrrdKind3DSymMatrix:
        case nrrdKind3DMatrix:
            /* =============================================================== */
            kindOut = kindIn;
            break;
        /* Some other kinds are mapped to those above */
        case nrrdKind3Color:
        case nrrdKindRGBColor:
            kindOut = nrrdKind3Vector;
            break;
        case nrrdKind4Color:
        case nrrdKindRGBAColor:
            kindOut = nrrdKind4Vector;
            break;
        default:
            fprintf(stderr, "%s: got non-conforming kind %s on axis %u\n", me,
                    airEnumStr(nrrdKind, kindIn), kindAxis);
            airMopError(mop);
            exit(1);
            break;
        }
    } else {
        /* kindIn is nrrdKindUnknown, so its a simple scalar image,
           and that's what the output will be too; kindOut == nrrdKindUnknown
           is used in the code below to say "its a scalar image" */
        kindOut = nrrdKindUnknown;
    }

    /* initialize output by copying */
    nout = nrrdNew();
    airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
    if (nrrdCopy(nout, nin)) {
        airMopAdd(mop, err = biffGet(NRRD), airFree, airMopAlways);
        fprintf(stderr, "%s: trouble copying:\n%s", me, err);
        airMopError(mop);
        exit(1);
    }

    /* no comments, either advertising the format URL or anything else */
    nio = nrrdIoStateNew();
    airMopAdd(mop, nio, (airMopper)nrrdIoStateNix, airMopAlways);
    nio->skipFormatURL = AIR_TRUE;
    if (headerOnly) {
        nio->skipData = AIR_TRUE;
    }
    nrrdCommentClear(nout);

    /* no measurement frame */
    gotmf = AIR_FALSE;
    for (si=0; si<NRRD_SPACE_DIM_MAX; si++) {
        for (sj=0; sj<NRRD_SPACE_DIM_MAX; sj++) {
            gotmf |= AIR_EXISTS(nout->measurementFrame[si][sj]);
        }
    }
    if (gotmf) {
        fprintf(stderr, "%s: WARNING: incoming array measurement frame; "
                "it will be erased on output.\n", me);
        /* airMopError(mop); exit(1); */
    }
    for (si=0; si<NRRD_SPACE_DIM_MAX; si++) {
        for (sj=0; sj<NRRD_SPACE_DIM_MAX; sj++) {
            nout->measurementFrame[si][sj] = AIR_NAN;
        }
    }

    /* no key/value pairs */
    nrrdKeyValueClear(nout);

    /* no content field */
    nout->content = airFree(nout->content);

    /* normalize domain kinds to "space" */
    /* turn off centers (Diderot assumes cell-centered, but that could
       probably stand to be tested and enforced more) */
    /* turn off thickness */
    /* turn off labels and units */
    for (axi=0; axi<nout->dim; axi++) {
        if (nrrdKindUnknown == kindOut) {
            nout->axis[axi].kind = nrrdKindSpace;
        } else {
            nout->axis[axi].kind = (kindAxis == axi
                                    ? kindOut
                                    : nrrdKindSpace);
        }
        nout->axis[axi].center = nrrdCenterUnknown;
        nout->axis[axi].thickness = AIR_NAN;
        nout->axis[axi].label = airFree(nout->axis[axi].label);
        nout->axis[axi].units = airFree(nout->axis[axi].units);
        nout->axis[axi].min = AIR_NAN;
        nout->axis[axi].max = AIR_NAN;
        nout->axis[axi].spacing = AIR_NAN;
    }

    /* logic of orientation definition:
       If space dimension is known:
          set origin to zero if not already set
          set space direction to unit vector if not already set
       Else if have per-axis min and max:
          set spae origin and directions to communicate same intent
          as original per-axis min and max and original centering
       Else
          set origin to zero and all space directions to units.
       It might be nice to use gage's logic for mapping from world to index,
       but we have to accept a greater variety of kinds and dimensions
       than gage ever has to process.
    */
    if (nout->spaceDim && !trivialOrient) {
        int saxi = 0;
        /* we use only the space dimension, not any named space */
        nout->space = nrrdSpaceUnknown;
        if (!nrrdSpaceVecExists(nout->spaceDim, nout->spaceOrigin)) {
            nrrdSpaceVecSetZero(nout->spaceOrigin);
        }
        for (axi=0; axi<nout->dim; axi++) {
            if (nrrdKindUnknown == kindOut || kindAxis != axi) {
                /* its a domain axis of output */
                if (!nrrdSpaceVecExists(nout->spaceDim,
                                        nout->axis[axi].spaceDirection)) {
                    nrrdSpaceVecSetZero(nout->axis[axi].spaceDirection);
                    nout->axis[axi].spaceDirection[saxi] = sscl;
                }
                /* else we leave existing space vector as is */
                saxi++;
            } else {
                /* else its a range axis */
                nrrdSpaceVecSetNaN(nout->axis[axi].spaceDirection);
            }
        }
    } else if (haveMM && !trivialOrient) {
        int saxi = 0;
        size_t N;
        double rng;
        for (axi=0; axi<nout->dim; axi++) {
            if (nrrdKindUnknown == kindOut || kindAxis != axi) {
                /* its a domain axis of output */
                nrrdSpaceVecSetZero(nout->axis[axi].spaceDirection);
                rng = nin->axis[axi].max - nin->axis[axi].min;
                if (nrrdCenterNode == nin->axis[axi].center) {
                    nout->spaceOrigin[saxi] = nin->axis[axi].min;
                    N = nin->axis[axi].size;
                    nout->axis[axi].spaceDirection[saxi] = rng/(N-1);
                } else {
                    /* unknown centering treated as cell */
                    N = nin->axis[axi].size;
                    nout->spaceOrigin[saxi] = nin->axis[axi].min + (rng/N)/2;
                    nout->axis[axi].spaceDirection[saxi] = rng/N;
                }
                saxi++;
            } else {
                /* else its a range axis */
                nrrdSpaceVecSetNaN(nout->axis[axi].spaceDirection);
            }
        }
        nout->spaceDim = saxi;
    } else {
        /* either trivialOrient, or, not spaceDim and not haveMM */
        int saxi = 0;
        nout->space = nrrdSpaceUnknown;
        nrrdSpaceVecSetZero(nout->spaceOrigin);
        for (axi=0; axi<nout->dim; axi++) {
            if (nrrdKindUnknown == kindOut || kindAxis != axi) {
                /* its a domain axis of output */
                nrrdSpaceVecSetZero(nout->axis[axi].spaceDirection);
                nout->axis[axi].spaceDirection[saxi]
                    = (AIR_EXISTS(nin->axis[axi].spacing)
                       ? nin->axis[axi].spacing
                       : sscl);
                saxi++;
            } else {
                /* else its a range axis */
                nrrdSpaceVecSetNaN(nout->axis[axi].spaceDirection);
            }
        }
        nout->spaceDim = saxi;
    }

    /* space dimension has to match the number of domain axes */
    if (nout->dim != nout->spaceDim + !!kindOut) {
        fprintf(stderr, "%s: output dim %d != spaceDim %d + %d %s%s%s\n",
                me, nout->dim, nout->spaceDim, !!kindOut,
                kindOut ? "for non-scalar (" : "(scalar data)",
                kindOut ? airEnumStr(nrrdKind, kindOut) : "",
                kindOut ? ") data" : "");
        airMopError(mop);
        exit(1);
    }

    if (recenter) {
        /* sets field's origin so field is centered on the origin. capiche? */
        /* this code was tacked on later than the stuff above, so its
           logic could probably be moved up there, but it seems cleaner to
           have it as a separate post-process */
        double mean[NRRD_SPACE_DIM_MAX];
        nrrdSpaceVecSetZero(mean);
        for (axi=0; axi<nout->dim; axi++) {
            if (nrrdKindUnknown == kindOut || kindAxis != axi) {
                nrrdSpaceVecScaleAdd2(mean, 1.0, mean,
                                      0.5*(nout->axis[axi].size - 1),
                                      nout->axis[axi].spaceDirection);
            }
        }
        nrrdSpaceVecScaleAdd2(mean, 1.0, mean,
                              1.0, nout->spaceOrigin);
        /* now mean is the center of the field */
        nrrdSpaceVecScaleAdd2(nout->spaceOrigin,
                              1.0, nout->spaceOrigin,
                              -1.0, mean);
    }

    if (nrrdSave(outS, nout, nio)) {
        airMopAdd(mop, err = biffGet(NRRD), airFree, airMopAlways);
        fprintf(stderr, "%s: trouble saving \"%s\":\n%s",
                me, outS, err);
        airMopError(mop);
        exit(1);
    }

    airMopOkay(mop);
    return 0;
}
Esempio n. 21
0
int
baneRawScatterplots(Nrrd *nvg, Nrrd *nvh, Nrrd *hvol, int histEq) {
  Nrrd *gA, *hA, *gB, *hB;
  char me[]="baneRawScatterplots", err[BIFF_STRLEN];
  int E;
  
  if (!( nvg && nvh && hvol )) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(BANE, err); return 1;
  }
  if (baneHVolCheck(hvol)) {
    sprintf(err, "%s: didn't get a valid histogram volume", me);
    biffAdd(BANE, err); return 1;
  }

  gA = nrrdNew(); gB = nrrdNew();
  hA = nrrdNew(); hB = nrrdNew();
  /* create initial projections */
  E = 0;
  if (!E) E |= nrrdProject(gA, hvol, 1, nrrdMeasureSum, nrrdTypeDefault);
  if (!E) E |= nrrdProject(hA, hvol, 0, nrrdMeasureSum, nrrdTypeDefault);
  if (E) {
    sprintf(err, "%s: trouble creating raw scatterplots", me);
    biffMove(BANE, err, NRRD); return 1;
  }

  /* do histogram equalization on them */
  if (histEq) {
    if (!E) E |= nrrdHistoEq(gB, gA, NULL, baneStateHistEqBins,
                             baneStateHistEqSmart, 1.0);
    if (!E) E |= nrrdHistoEq(hB, hA, NULL, baneStateHistEqBins,
                             baneStateHistEqSmart, 1.0);
  } else {
    if (!E) E |= nrrdCopy(gB, gA);
    if (!E) E |= nrrdCopy(hB, hA);
  }
  if (E) {
    sprintf(err, "%s: couldn't histogram equalize or copy", me);
    biffMove(BANE, err, NRRD); return 1;
  }

  /* re-orient them so they look correct on the screen */
  if (!E) E |= nrrdAxesSwap(gA, gB, 0, 1);
  if (!E) E |= nrrdAxesSwap(hA, hB, 0, 1);
  if (!E) E |= nrrdFlip(gB, gA, 1);
  if (!E) E |= nrrdFlip(hB, hA, 1);
  if (E) {
    sprintf(err, "%s: couldn't re-orient scatterplots", me);
    biffMove(BANE, err, NRRD); return 1;
  }
  
  if (!E) E |= nrrdCopy(nvg, gB);
  if (!E) E |= nrrdCopy(nvh, hB);
  if (E) {
    sprintf(err, "%s: trouble saving results to given nrrds", me);
    biffMove(BANE, err, NRRD); return 1;
  }

  nrrdNuke(gA); nrrdNuke(gB);
  nrrdNuke(hA); nrrdNuke(hB);
  return 0;
}
Esempio n. 22
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;
}
Esempio n. 23
0
/*
******** nrrdArithGamma()
**
** map the values in a nrrd through a power function; essentially:
** val = pow(val, 1/gamma), but this is after the val has been normalized
** to be in the range of 0.0 to 1.0 (assuming that the given min and
** max really are the full range of the values in the nrrd).  Thus,
** the given min and max values are fixed points of this
** transformation.  Using a negative gamma means that after the pow()
** function has been applied, the value is inverted with respect to
** min and max (like in xv).
*/
int
nrrdArithGamma(Nrrd *nout, const Nrrd *nin,
               const NrrdRange *_range, double Gamma) {
  static const char me[]="nrrdArithGamma", func[]="gamma";
  double val, min, max;
  size_t I, num;
  NrrdRange *range;
  airArray *mop;
  double (*lup)(const void *, size_t);
  double (*ins)(void *, size_t, double);

  if (!(nout && nin)) {
    /* _range can be NULL */
    biffAddf(NRRD, "%s: got NULL pointer", me);
    return 1;
  }
  if (!( AIR_EXISTS(Gamma) )) {
    biffAddf(NRRD, "%s: gamma doesn't exist", me);
    return 1;
  }
  if (!( nrrdTypeBlock != nin->type && nrrdTypeBlock != nout->type )) {
    biffAddf(NRRD, "%s: can't deal with %s type", me,
             airEnumStr(nrrdType, nrrdTypeBlock));
    return 1;
  }
  if (nout != nin) {
    if (nrrdCopy(nout, nin)) {
      biffAddf(NRRD, "%s: couldn't initialize by copy to output", me);
      return 1;
    }
  }
  mop = airMopNew();
  if (_range) {
    range = nrrdRangeCopy(_range);
    nrrdRangeSafeSet(range, nin, nrrdBlind8BitRangeState);
  } else {
    range = nrrdRangeNewSet(nin, nrrdBlind8BitRangeTrue);
  }
  airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
  min = range->min;
  max = range->max;
  if (min == max) {
    /* this is stupid.  We want min < max to avoid making NaNs */
    max += 1;
  }
  lup = nrrdDLookup[nin->type];
  ins = nrrdDInsert[nout->type];
  Gamma = 1/Gamma;
  num = nrrdElementNumber(nin);
  if (Gamma < 0.0) {
    Gamma = -Gamma;
    for (I=0; I<num; I++) {
      val = lup(nin->data, I);
      val = AIR_AFFINE(min, val, max, 0.0, 1.0);
      val = pow(val, Gamma);
      val = AIR_AFFINE(1.0, val, 0.0, min, max);
      ins(nout->data, I, val);
    }
  } else {
    for (I=0; I<num; I++) {
      val = lup(nin->data, I);
      val = AIR_AFFINE(min, val, max, 0.0, 1.0);
      val = pow(val, Gamma);
      val = AIR_AFFINE(0.0, val, 1.0, min, max);
      ins(nout->data, I, val);
    }
  }
  if (nrrdContentSet_va(nout, func, nin, "%g,%g,%g", min, max, Gamma)) {
    biffAddf(NRRD, "%s:", me);
    airMopError(mop); return 1;
  }
  if (nout != nin) {
    nrrdAxisInfoCopy(nout, nin, NULL, NRRD_AXIS_INFO_NONE);
  }
  /* basic info handled by nrrdCopy above */

  airMopOkay(mop);
  return 0;
}
Esempio n. 24
0
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);
}
/*
******** nrrdApply1DSubstitution
**
** A "subst" is a substitution table, i.e. a list of pairs that
** describes what values should be substituted with what (substitution
** rules).  So, nsubst must be a scalar 2xN array.  The output is a
** copy of the input with values substituted using this table.
**
** Unlike with lookup tables and maps (irregular and regular), we
** aren't at liberty to change the dimensionality of the data (can't
** substitute a grayscale with a color).  The ability to apply
** substitutions to non-scalar data will be in a different function.
** Also unlike lookup tables and maps, the output type is the SAME as
** the input type; the output does NOT inherit the type of the
** substitution
*/
int
nrrdApply1DSubstitution(Nrrd *nout, const Nrrd *nin, const Nrrd *_nsubst) {
  char me[]="nrrdApply1DSubstitution", err[BIFF_STRLEN];
  double (*lup)(const void *, size_t);
  double (*ins)(void *, size_t, double);
  Nrrd *nsubst;
  double val, *subst;
  size_t ii, num;
  int jj, asize0, asize1, changed;
  airArray *mop;

  if (!(nout && _nsubst && nin)) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err); return 1;
  }
  if (nrrdTypeBlock == nin->type || nrrdTypeBlock == _nsubst->type) {
    sprintf(err, "%s: input or substitution type is %s, need scalar",
            me, airEnumStr(nrrdType, nrrdTypeBlock));
    biffAdd(NRRD, err); return 1;
  }
  if (2 != _nsubst->dim) {
    sprintf(err, "%s: substitution table has to be 2-D, not %d-D",
            me, _nsubst->dim);
    biffAdd(NRRD, err); return 1;
  }
  nrrdAxisInfoGet_va(_nsubst, nrrdAxisInfoSize, &asize0, &asize1);
  if (2 != asize0) {
    sprintf(err, "%s: substitution table has to be 2xN, not %dxN",
            me, asize0);
    biffAdd(NRRD, err); return 1;
  }
  if (nout != nin) {
    if (nrrdCopy(nout, nin)) {
      sprintf(err, "%s: couldn't initialize by copy to output", me);
      biffAdd(NRRD, err); return 1;
    }
  }

  mop = airMopNew();
  nsubst = nrrdNew();
  airMopAdd(mop, nsubst, (airMopper)nrrdNuke, airMopAlways);
  if (nrrdConvert(nsubst, _nsubst, nrrdTypeDouble)) {
    sprintf(err, "%s: couldn't create double copy of substitution table", me);
    biffAdd(NRRD, err); airMopError(mop); return 1;
  }
  lup = nrrdDLookup[nout->type];
  ins = nrrdDInsert[nout->type];
  subst = (double *)nsubst->data;
  num = nrrdElementNumber(nout);
  for (ii=0; ii<num; ii++) {
    val = lup(nout->data, ii);
    changed = AIR_FALSE;
    for (jj=0; jj<asize1; jj++) {
      if (val == subst[jj*2+0]) {
        val = subst[jj*2+1];
        changed = AIR_TRUE;
      }
    }
    if (changed) {
      ins(nout->data, ii, val);
    }
  }

  airMopOkay(mop);
  return 0;
}
Esempio n. 26
0
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;
}
Esempio n. 27
0
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;
}
Esempio n. 28
0
/*
******** nrrdAxesPermute
**
** changes the scanline ordering of the data in a nrrd
**
** The basic means by which data is moved around is with memcpy().
** The goal is to call memcpy() as few times as possible, on memory
** segments as large as possible.  Currently, this is done by
** detecting how many of the low-index axes are left untouched by
** the permutation- this constitutes a "scanline" which can be
** copied around as a unit.  For permuting the y and z axes of a
** matrix-x-y-z order matrix volume, this optimization produced a
** factor of 5 speed up (exhaustive multi-platform tests, of course).
**
** The axes[] array determines the permutation of the axes.
** axis[i] = j means: axis i in the output will be the input's axis j
** (axis[i] answers: "what do I put here", from the standpoint of the output,
** not "where do I put this", from the standpoint of the input)
*/
int
nrrdAxesPermute(Nrrd *nout, const Nrrd *nin, const unsigned int *axes) {
  static const char me[]="nrrdAxesPermute", func[]="permute";
  char buff1[NRRD_DIM_MAX*30], buff2[AIR_STRLEN_SMALL];
  size_t idxOut, idxInA=0,   /* indices for input and output scanlines */
    lineSize,                /* size of block of memory which can be
                                moved contiguously from input to output,
                                thought of as a "scanline" */
    numLines,                /* how many "scanlines" there are to permute */
    szIn[NRRD_DIM_MAX], *lszIn,
    szOut[NRRD_DIM_MAX], *lszOut,
    cIn[NRRD_DIM_MAX],
    cOut[NRRD_DIM_MAX];
  char *dataIn, *dataOut;
  int axmap[NRRD_DIM_MAX];
  unsigned int
    ai,                      /* running index along dimensions */
    lowPax,                  /* lowest axis which is "p"ermutated */
    ldim,                    /* nin->dim - lowPax */
    ip[NRRD_DIM_MAX+1],      /* inverse of permutation in "axes" */
    laxes[NRRD_DIM_MAX+1];   /* copy of axes[], but shifted down by lowPax
                                elements, to remove i such that i == axes[i] */
  airArray *mop;

  mop = airMopNew();
  if (!(nin && nout && axes)) {
    biffAddf(NRRD, "%s: got NULL pointer", me);
    airMopError(mop); return 1;
  }
  /* we don't actually need ip[], computing it is for error checking */
  if (nrrdInvertPerm(ip, axes, nin->dim)) {
    biffAddf(NRRD, "%s: couldn't compute axis permutation inverse", me);
    airMopError(mop); return 1;
  }
  /* this shouldn't actually be necessary .. */
  if (!nrrdElementSize(nin)) {
    biffAddf(NRRD, "%s: nrrd reports zero element size!", me);
    airMopError(mop); return 1;
  }

  for (ai=0; ai<nin->dim && axes[ai] == ai; ai++)
    ;
  lowPax = ai;

  /* allocate output by initial copy */
  if (nout != nin) {
    if (nrrdCopy(nout, nin)) {
      biffAddf(NRRD, "%s: trouble copying input", me);
      airMopError(mop); return 1;
    }
    dataIn = (char*)nin->data;
  } else {
    dataIn = (char*)calloc(nrrdElementNumber(nin), nrrdElementSize(nin));
    if (!dataIn) {
      biffAddf(NRRD, "%s: couldn't create local copy of data", me);
      airMopError(mop); return 1;
    }
    airMopAdd(mop, dataIn, airFree, airMopAlways);
    memcpy(dataIn, nin->data, nrrdElementNumber(nin)*nrrdElementSize(nin));
  }
  if (lowPax < nin->dim) {
    /* if lowPax == nin->dim, then we were given the identity permutation, so
       there's nothing to do other than the copy already done.  Otherwise,
       here we are (actually, lowPax < nin->dim-1) */
    for (ai=0; ai<nin->dim; ai++) {
      axmap[ai] = AIR_INT(axes[ai]);
    }
    nrrdAxisInfoGet_nva(nin, nrrdAxisInfoSize, szIn);
    if (nrrdAxisInfoCopy(nout, nin, axmap, NRRD_AXIS_INFO_NONE)) {
      biffAddf(NRRD, "%s:", me);
      airMopError(mop); return 1;
    }
    nrrdAxisInfoGet_nva(nout, nrrdAxisInfoSize, szOut);
    /* the skinny */
    lineSize = 1;
    for (ai=0; ai<lowPax; ai++) {
      lineSize *= szIn[ai];
    }
    numLines = nrrdElementNumber(nin)/lineSize;
    lineSize *= nrrdElementSize(nin);
    lszIn = szIn + lowPax;
    lszOut = szOut + lowPax;
    ldim = nin->dim - lowPax;
    memset(laxes, 0, sizeof(laxes));
    for (ai=0; ai<ldim; ai++) {
      laxes[ai] = axes[ai+lowPax]-lowPax;
    }
    dataOut = AIR_CAST(char *, nout->data);
    memset(cIn, 0, sizeof(cIn));
    memset(cOut, 0, sizeof(cOut));
    for (idxOut=0; idxOut<numLines; idxOut++) {
      /* in our representation of the coordinates of the start of the
         scanlines that we're copying, we are not even storing all the
         zeros in the coordinates prior to lowPax, and when we go to
         a linear index for the memcpy(), we multiply by lineSize */
      for (ai=0; ai<ldim; ai++) {
        cIn[laxes[ai]] = cOut[ai];
      }
      NRRD_INDEX_GEN(idxInA, cIn, lszIn, ldim);
      memcpy(dataOut + idxOut*lineSize, dataIn + idxInA*lineSize, lineSize);
      NRRD_COORD_INCR(cOut, lszOut, ldim, 0);
    }
    /* set content */
    strcpy(buff1, "");
    for (ai=0; ai<nin->dim; ai++) {
      sprintf(buff2, "%s%d", (ai ? "," : ""), axes[ai]);
      strcat(buff1, buff2);
    }
    if (nrrdContentSet_va(nout, func, nin, "%s", buff1)) {
      biffAddf(NRRD, "%s:", me);
      airMopError(mop); return 1;
    }
    if (nout != nin) {
      if (nrrdBasicInfoCopy(nout, nin,
                            NRRD_BASIC_INFO_DATA_BIT
                            | NRRD_BASIC_INFO_TYPE_BIT
                            | NRRD_BASIC_INFO_BLOCKSIZE_BIT
                            | NRRD_BASIC_INFO_DIMENSION_BIT
                            | NRRD_BASIC_INFO_CONTENT_BIT
                            | NRRD_BASIC_INFO_COMMENTS_BIT
                            | (nrrdStateKeyValuePairsPropagate
                               ? 0
                               : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) {
        biffAddf(NRRD, "%s:", me);
        airMopError(mop); return 1;
      }
    }
  }
  airMopOkay(mop);
  return 0;
}
Esempio n. 29
0
File: mod.c Progetto: 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;
    }