示例#1
0
文件: grads.c 项目: BRAINSia/teem
/*
******** tenGradientRandom
**
** generates num random unit vectors of type double
*/
int
tenGradientRandom(Nrrd *ngrad, unsigned int num, unsigned int seed) {
  static const char me[]="tenGradientRandom";
  double *grad, len;
  unsigned int gi;

  if (nrrdMaybeAlloc_va(ngrad, nrrdTypeDouble, 2,
                        AIR_CAST(size_t, 3), AIR_CAST(size_t, num))) {
    biffMovef(TEN, NRRD, "%s: couldn't allocate output", me);
    return 1;
  }
  airSrandMT(seed);
  grad = AIR_CAST(double*, ngrad->data);
  for (gi=0; gi<num; gi++) {
    do {
      grad[0] = AIR_AFFINE(0, airDrandMT(), 1, -1, 1);
      grad[1] = AIR_AFFINE(0, airDrandMT(), 1, -1, 1);
      grad[2] = AIR_AFFINE(0, airDrandMT(), 1, -1, 1);
      len = ELL_3V_LEN(grad);
    } while (len > 1 || !len);
    ELL_3V_SCALE(grad, 1.0/len, grad);
    grad += 3;
  }
  return 0;
}
示例#2
0
文件: bday.c 项目: BRAINSia/teem
int
main(int argc, const char *argv[]) {
  airArray *mop;
  hestOpt *hopt=NULL;
  int i, N, M, P, yes, *year;
  unsigned int E;
  const char *me;
  double crct;

  me = argv[0];
  mop = airMopNew();
  hestOptAdd(&hopt, "N", "days", airTypeInt, 1, 1, &N, "365",
             "# of days in year");
  /* E != P */
  hestOptAdd(&hopt, "E", "exps", airTypeInt, 1, 1, &P, "100000",
             "number of experiments after which to print out newly "
             "computed probability");
  hestOptAdd(&hopt, NULL, "people", airTypeInt, 1, 1, &M, NULL,
             "# of people in room");
  hestParseOrDie(hopt, argc-1, argv+1, NULL,
                 me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  if (!( N > 1 && M > 0 && P > 1)) {
    fprintf(stderr, "%s: need both M, P all > 1, M > 0\n", me);
    airMopError(mop); exit(1);
  }
  if (!(year = (int*)calloc(N, sizeof(int)))) {
    fprintf(stderr, "%s: couldn't calloc(%d,sizeof(int))\n", me, N);
    airMopError(mop); exit(1);
  }
  airMopMem(mop, year, airMopAlways);

  crct = 1;
  for (i=0; i<M; i++) {
    crct *= (double)(N-i)/N;
  }
  crct = 1-crct;
  yes = 0;
  E = 1;
  airSrandMT((int)airTime());
  while (E) {
    yes += runexp(year, N, M);
    if (!(E % P)) {
      printf("P = %10d/%10d = %22.20f =?= %22.20f\n",
             yes, E, (double)yes/E, crct);
    }
    E++;
  }

  airMopOkay(mop);
  exit(0);
}
int
pushStart(pushContext *pctx) {
  char me[]="pushStart", err[BIFF_STRLEN];
  unsigned int tidx;

  if (_pushContextCheck(pctx)) {
    sprintf(err, "%s: trouble", me);
    biffAdd(PUSH, err); return 1;
  }

  airSrandMT(pctx->seed);
  
  /* the ordering of things below is important: gage and fiber contexts
     have to be set up before they're copied by task setup */
  if (_pushTensorFieldSetup(pctx)
      || _pushGageSetup(pctx) 
      || _pushFiberSetup(pctx)
      || _pushTaskSetup(pctx)
      || _pushBinSetup(pctx)
      || _pushThingSetup(pctx)) {
    sprintf(err, "%s: trouble setting up context", me);
    biffAdd(PUSH, err); return 1;
  }

  /* HEY: this should be done by the user */
  pctx->process[0] = _pushForce;
  pctx->process[1] = _pushUpdate;

  pctx->finished = AIR_FALSE;
  if (pctx->numThread > 1) {
    pctx->binMutex = airThreadMutexNew();
    pctx->stageBarrierA = airThreadBarrierNew(pctx->numThread);
    pctx->stageBarrierB = airThreadBarrierNew(pctx->numThread);
  }

  /* start threads 1 and up running; they'll all hit stageBarrierA  */
  for (tidx=1; tidx<pctx->numThread; tidx++) {
    if (pctx->verbose > 1) {
      fprintf(stderr, "%s: spawning thread %d\n", me, tidx);
    }
    airThreadStart(pctx->task[tidx]->thread, _pushWorker,
                   (void *)(pctx->task[tidx]));
  }

  return 0;
}
示例#4
0
int
tend_msimMain(int argc, const char **argv, const char *me,
              hestParm *hparm) {
  int pret;
  hestOpt *hopt = NULL;
  char *perr, *err;
  airArray *mop;

  tenExperSpec *espec;
  const tenModel *model;
  int E, seed, keyValueSet, outType, plusB0, insertB0;
  Nrrd *nin, *nT2, *_ngrad, *ngrad, *nout;
  char *outS, *modS;
  double bval, sigma;

  /* maybe this can go in tend.c, but for some reason its explicitly
     set to AIR_FALSE there */
  hparm->elideSingleOtherDefault = AIR_TRUE;

  hestOptAdd(&hopt, "sigma", "sigma", airTypeDouble, 1, 1, &sigma, "0.0",
             "Gaussian/Rician noise parameter");
  hestOptAdd(&hopt, "seed", "seed", airTypeInt, 1, 1, &seed, "42",
             "seed value for RNG which creates noise");
  hestOptAdd(&hopt, "g", "grad list", airTypeOther, 1, 1, &_ngrad, NULL,
             "gradient list, one row per diffusion-weighted image",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "b0", "b0 image", airTypeOther, 1, 1, &nT2, "",
             "reference non-diffusion-weighted (\"B0\") image, which "
             "may be needed if it isn't part of give model param image",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "i", "model image", airTypeOther, 1, 1, &nin, "-",
             "input model image", NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "m", "model", airTypeString, 1, 1, &modS, NULL,
             "model with which to simulate DWIs, which must be specified if "
             "it is not indicated by the first axis in input model image.");
  hestOptAdd(&hopt, "ib0", "bool", airTypeBool, 1, 1, &insertB0, "false",
             "insert a non-DW B0 image at the beginning of the experiment "
             "specification (useful if the given gradient list doesn't "
             "already have one) and hence also insert a B0 image at the "
             "beginning of the output simulated DWIs");
  hestOptAdd(&hopt, "b", "b", airTypeDouble, 1, 1, &bval, "1000",
             "b value for simulated scan");
  hestOptAdd(&hopt, "kvp", "bool", airTypeBool, 1, 1, &keyValueSet, "true",
             "generate key/value pairs in the NRRD header corresponding "
             "to the input b-value and gradients.");
  hestOptAdd(&hopt, "t", "type", airTypeEnum, 1, 1, &outType, "float",
             "output type of DWIs", NULL, nrrdType);
  hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-",
             "output dwis");

  mop = airMopNew();
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  USAGE(_tend_msimInfoL);
  PARSE();
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

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

  airSrandMT(seed);
  if (nrrdTypeDouble == _ngrad->type) {
    ngrad = _ngrad;
  } else {
    ngrad = nrrdNew();
    airMopAdd(mop, ngrad, (airMopper)nrrdNuke, airMopAlways);
    if (nrrdConvert(ngrad, _ngrad, nrrdTypeDouble)) {
      airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble converting grads to %s:\n%s\n", me,
              airEnumStr(nrrdType, nrrdTypeDouble), err);
      airMopError(mop); return 1;
    }
  }
  plusB0 = AIR_FALSE;
  if (airStrlen(modS)) {
    if (tenModelParse(&model, &plusB0, AIR_FALSE, modS)) {
      airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble parsing model \"%s\":\n%s\n",
              me, modS, err);
      airMopError(mop); return 1;
    }
  } else if (tenModelFromAxisLearnPossible(nin->axis + 0)) {
    if (tenModelFromAxisLearn(&model, &plusB0, nin->axis + 0)) {
      airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble parsing model frmo axis 0 of nin:\n%s\n",
              me, err);
      airMopError(mop); return 1;
    }
  } else {
    fprintf(stderr, "%s: need model specified either via \"-m\" or input "
            "model image axis 0\n", me);
    airMopError(mop); return 1;
  }
  /* we have learned plusB0, but we don't actually need it;
     either: it describes the given model param image
     (which is courteous but not necessary since the logic inside
     tenModeSimulate will see this),
     or: it is trying to say something about including B0 amongst
     model parameters (which isn't actually meaningful in the
     context of simulated DWIs */
  E = 0;
  if (!E) E |= tenGradientCheck(ngrad, nrrdTypeDouble, 1);
  if (!E) E |= tenExperSpecGradSingleBValSet(espec, insertB0, bval,
                                             AIR_CAST(const double *,
                                                      ngrad->data),
                                             ngrad->axis[1].size);
  if (!E) E |= tenModelSimulate(nout, outType, espec,
                                model, nT2, nin, keyValueSet);
  if (E) {
    airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble:\n%s\n", me, err);
    airMopError(mop); return 1;
  }
  if (nrrdSave(outS, nout, NULL)) {
    airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble writing:\n%s\n", me, err);
    airMopError(mop); return 1;
  }

  airMopOkay(mop);
  return 0;
}
示例#5
0
int
main() {
  airArray *mop, *submop;
  char *err;

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

  mop = airMopNew();

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

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


  /* --------------------------------------------------------------- */
  /* Quantizing to 8-bits and checking */
  submop = airMopNew();
  NRRD_NEW(nucharScl, mop);
  NRRD_NEW(nunquant, submop);
  NRRD_NEW(nqdiff, submop);
  if (nrrdQuantize(nucharScl, norigScl, NULL, 8)
      || nrrdUnquantize(nunquant, nucharScl, nrrdTypeDouble)
      || nrrdArithBinaryOp(nqdiff, nrrdBinaryOpSubtract,
                           norigScl, nunquant)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "trouble quantizing and back:\n%s", err);
    airMopError(submop); airMopError(mop); return 1;
  }
  if (!( nucharScl->oldMin == omin
         && nucharScl->oldMax == omax )) {
    fprintf(stderr, "quantization range [%g,%g] != real range [%g,%g]\n",
            nucharScl->oldMin, nucharScl->oldMax, omin, omax);
    airMopError(submop); airMopError(mop); return 1;
  }
  {
    double *qdiff, *unquant;
    /* empirically determined tolerance, which had to be increased in
       order to work under valgrind (!)- perhaps because of a
       difference in the use of 80-bit registers */
    double epsilon=0.50000000000004;
    qdiff = AIR_CAST(double *, nqdiff->data);
    unquant = AIR_CAST(double *, nunquant->data);
    for (ii=0; ii<nn; ii++) {
      double dd;
      /* with infinite precision, the max difference between original and
         quantized values should be exactly half the width (in value)
         of 1/256 of value range  ==> dd = 0.5 */
      dd = qdiff[ii]*256/(omax - omin);
      if (AIR_ABS(dd) > epsilon) {
        unsigned int ui;
        ui = AIR_CAST(unsigned int, ii);
        fprintf(stderr, "|orig[%u]=%.17g - unquant=%.17g|*256/%.17g "
                "= %.17g > %.17g!\n", ui, origScl[ii], unquant[ii],
                omax - omin, AIR_ABS(dd), epsilon);
        airMopError(submop); airMopError(mop); return 1;
      }
    }
  }
示例#6
0
文件: ax.c 项目: BRAINSia/teem
int
main(int argc, char *argv[]) {
  int i;
  Nrrd *nrrd;
  double diff, idx, idx2, idx3, idx4, lo, hi, pos, pos2, pos3, pos4;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

  exit(0);
}
示例#7
0
int
unrrdu_2opMain(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err, *seedS;
  NrrdIter *in1, *in2;
  Nrrd *nout, *ntmp=NULL;
  int op, type, E, pret;
  airArray *mop;
  unsigned int seed;

  hestOptAdd(&opt, NULL, "operator", airTypeEnum, 1, 1, &op, NULL,
             "Binary operator. Possibilities include:\n "
             "\b\bo \"+\", \"-\", \"x\", \"/\": "
             "add, subtract, multiply, divide\n "
             "\b\bo \"^\": exponentiation (pow)\n "
             "\b\bo \"spow\": signed exponentiation: sgn(x)pow(abs(x),p)\n "
             "\b\bo \"%\": integer modulo\n "
             "\b\bo \"fmod\": same as fmod() in C\n "
             "\b\bo \"atan2\": same as atan2() in C\n "
             "\b\bo \"min\", \"max\": minimum, maximum\n "
             "\b\bo \"lt\", \"lte\", \"gt\", \"gte\": same as C's <, <=, >, <=\n "
             "\b\bo \"eq\", \"neq\": same as C's == and !=\n "
             "\b\bo \"comp\": -1, 0, or 1 if 1st value is less than, "
             "equal to, or greater than 2nd value\n "
             "\b\bo \"if\": if 1st value is non-zero, use it, "
             "else use 2nd value\n "
             "\b\bo \"exists\": if 1st value exists, use it, "
             "else use 2nd value\n "
             "\b\bo \"nrand\": scale unit-stdv Gaussian noise by 2nd value "
             "and add to first value",
             NULL, nrrdBinaryOp);
  hestOptAdd(&opt, NULL, "in1", airTypeOther, 1, 1, &in1, NULL,
             "First input.  Can be a single value or a nrrd.",
             NULL, NULL, nrrdHestIter);
  hestOptAdd(&opt, NULL, "in2", airTypeOther, 1, 1, &in2, NULL,
             "Second input.  Can be a single value or a nrrd.",
             NULL, NULL, nrrdHestIter);
  hestOptAdd(&opt, "s,seed", "seed", airTypeString, 1, 1, &seedS, "",
             "seed value for RNG for nrand, so that you "
             "can get repeatable results between runs, or, "
             "by not using this option, the RNG seeding will be "
             "based on the current time");
  hestOptAdd(&opt, "t,type", "type", airTypeOther, 1, 1, &type, "default",
             "type to convert all INPUT nrrds to, prior to "
             "doing operation, useful for doing, for instance, the difference "
             "between two unsigned char nrrds.  This will also determine "
             "output type. By default (not using this option), the types of "
             "the input nrrds are left unchanged.",
             NULL, NULL, &unrrduHestMaybeTypeCB);
  OPT_ADD_NOUT(out, "output nrrd");

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

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

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

  /*
  fprintf(stderr, "%s: op = %d\n", me, op);
  fprintf(stderr, "%s: in1->left = %d, in2->left = %d\n", me, 
          (int)(in1->left), (int)(in2->left));
  */
  if (nrrdTypeDefault != type) {
    /* they wanted to convert nrrds to some other type first */
    E = 0;
    if (in1->ownNrrd) {
      if (!E) E |= nrrdConvert(ntmp=nrrdNew(), in1->ownNrrd, type);
      if (!E) nrrdIterSetOwnNrrd(in1, ntmp);
    }
    if (in2->ownNrrd) {
      if (!E) E |= nrrdConvert(ntmp=nrrdNew(), in2->ownNrrd, type);
      if (!E) nrrdIterSetOwnNrrd(in2, ntmp);
    }
    if (E) {
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: error converting input nrrd(s):\n%s", me, err);
      airMopError(mop);
      return 1;
    }
    /* this will still leave a nrrd in the NrrdIter for nrrdIterNix()
       (called by hestParseFree() called be airMopOkay()) to clear up */
  }
  if (nrrdBinaryOpNormalRandScaleAdd == op) {
    if (airStrlen(seedS)) {
      if (1 != sscanf(seedS, "%u", &seed)) {
        fprintf(stderr, "%s: couldn't parse seed \"%s\" as uint\n", me, seedS);
        airMopError(mop);
        return 1;
      } else {
        airSrandMT(seed);
      }
    } else {
      /* got no request for specific seed */
      airSrandMT(AIR_CAST(unsigned int, airTime()));
    }
  }
  if (nrrdArithIterBinaryOp(nout, op, in1, in2)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: error doing binary operation:\n%s", me, err);
    airMopError(mop);
    return 1;
  }
  
  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
示例#8
0
int
main(int argc, const char *argv[]) {
  const char *me;
  size_t vi, ii, qvalLen;
  Nrrd *nval, *nhist, *nimg, *nread, *ncorr;
  double aa, bb, *val;
  airArray *mop;
  char *corrname, explain[AIR_STRLEN_LARGE];
  int differ;

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

  qvalLen = 10*BINS;
  nrrdAlloc_va(nval=nrrdNew(), nrrdTypeDouble, 1, 4*qvalLen);
  airMopAdd(mop, nval, (airMopper)nrrdNuke, airMopAlways);
  val = AIR_CAST(double*, nval->data);

  airSrandMT(999);
  vi = 0;
  for (ii=0; ii<qvalLen; ii++) {
    airNormalRand(&aa, NULL);
    val[vi++] = aa;
  }
  for (ii=0; ii<qvalLen; ii++) {
    airNormalRand(NULL, &bb);
    val[vi++] = bb;
  }
  for (ii=0; ii<qvalLen; ii++) {
    airNormalRand(&aa, &bb);
    val[vi++] = aa;
    val[vi++] = bb;
  }

  nhist=nrrdNew();
  airMopAdd(mop, nhist, (airMopper)nrrdNuke, airMopAlways);
  nimg=nrrdNew();
  airMopAdd(mop, nimg, (airMopper)nrrdNuke, airMopAlways);
  if (nrrdHisto(nhist, nval, NULL, NULL, BINS, nrrdTypeInt)
      || nrrdHistoDraw(nimg, nhist, HGHT, AIR_TRUE, 0.0)
      || nrrdSave(THISNAME, nimg, NULL)) {
    char *err;
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble producing histo:\n%s", me, err);
    airMopError(mop); return 1;
  }

  nread = nrrdNew();
  airMopAdd(mop, nread, (airMopper)nrrdNuke, airMopAlways);
  ncorr = nrrdNew();
  airMopAdd(mop, ncorr, (airMopper)nrrdNuke, airMopAlways);

  corrname = testDataPathPrefix(CORRNAME);
  airMopAdd(mop, corrname, airFree, airMopAlways);
  if (nrrdLoad(ncorr, corrname, NULL)
      || nrrdLoad(nread, THISNAME, NULL)) {
    char *err;
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble reading:\n%s", me, err);
    airMopError(mop); return 1;
  }

  if (nrrdCompare(ncorr, nread, AIR_FALSE /* onlyData */,
                  0.0 /* epsilon */, &differ, explain)) {
    char *err;
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble comparing:\n%s", me, err);
    airMopError(mop); return 1;
  }
  if (differ) {
    fprintf(stderr, "%s: new and correct (%s) images differ: %s\n",
            me, corrname, explain);
    airMopError(mop); return 1;
  } else {
    printf("%s: all good\n", me);
  }

  airMopOkay(mop);
  return 0;
}
示例#9
0
文件: spots.c 项目: BRAINSia/teem
int
main(int argc, const char *argv[]) {
  const char *me;
  char *err;
  hestOpt *hopt = NULL;
  airArray *mop;

  char *outS;
  alanContext *actx;
  int *size, sizeLen, fi, si, wrap, nt, cfn, ha, maxi;
  unsigned int srnd;
  double deltaT, mch, xch, alphabeta[2], time0, time1, deltaX, react, rrange;
  Nrrd *ninit=NULL, *nten=NULL, *nparm=NULL;

  me = argv[0];
  hestOptAdd(&hopt, "s", "sx sy", airTypeInt, 2, 3, &size, "128 128",
             "size of texture, and also determines its dimension",
             &sizeLen);
  hestOptAdd(&hopt, "srand", "N", airTypeUInt, 1, 1, &srnd, "42",
             "number to seed random number generator with.  This uses "
             "airDrandMT(), so it should be portable.");
  hestOptAdd(&hopt, "i", "tensors", airTypeOther, 1, 1, &nten, "",
             "diffusion tensors to use for guiding the texture generation. "
             "If used, over-rides the \"-s\" option, both for setting "
             "texture dimension and size.  If you want upsampling, you "
             "do it yourself before sending it here.",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "ha", NULL, airTypeInt, 0, 0, &ha, NULL,
             "use the homogenous anisotropy assumption- that the spatial "
             "derivative of the diffusion tensor is negligible when "
             "computing the diffusive term ");
  hestOptAdd(&hopt, "wrap", NULL, airTypeInt, 0, 0, &wrap, NULL,
             "wrap edges of texture around a topological torus (which "
             "makes a texture suitable for tiling)");
  hestOptAdd(&hopt, "ab", "alpha beta", airTypeDouble, 2, 2, alphabeta,
             "16.0 12.0",
             "the growth and decay parameters appearing in the reaction "
             "terms of the reaction-diffusion equations.  The default "
             "values were the ones published by Turing.");
  hestOptAdd(&hopt, "sr", "react", airTypeDouble, 1, 1, &react, "1.0",
             "scaling of reaction term");
  hestOptAdd(&hopt, "rr", "range range", airTypeDouble, 1, 1, &rrange, "4.0",
             "amount of random noise to add to inital textures");
  hestOptAdd(&hopt, "dt", "time", airTypeDouble, 1, 1, &deltaT, "1.0",
             "time-step size in Euler integration.  Can be larger, at "
             "risk of hitting divergent instability.");
  hestOptAdd(&hopt, "dx", "size", airTypeDouble, 1, 1, &deltaX, "1.3",
             "nominal size of simulation grid element.");
  hestOptAdd(&hopt, "mch", "change", airTypeDouble, 1, 1, &mch, "0.00001",
             "the minimum significant change (averaged over the whole "
             "texture) in the first morphogen: to signify convergence");
  hestOptAdd(&hopt, "xch", "change", airTypeDouble, 1, 1, &xch, "6",
             "the maximum allowable change (averaged over the whole "
             "texture) in the first morphogen: to signify divergence");
  hestOptAdd(&hopt, "maxi", "# iter", airTypeInt, 1, 1, &maxi, "0",
             "maximum number of iterations to run for, or \"0\" to have "
             "no limit based on iteration count");
  hestOptAdd(&hopt, "fi", "frame inter", airTypeInt, 1, 1, &fi, "0",
             "the number of iterations between which to save out an 8-bit "
             "image of the texture, or \"0\" to disable such action");
  hestOptAdd(&hopt, "si", "snap inter", airTypeInt, 1, 1, &si, "0",
             "the number of iterations between which to save out a complete "
             "floating-point snapshot of the morphogen state, suitable for "
             "later re-initialization, or \"0\" to disable such action");
  hestOptAdd(&hopt, "cfn", NULL, airTypeInt, 0, 0, &cfn, NULL,
             "when saving out frames or snapshots, use a constant filename, "
             "instead of incrementing it each save");
  hestOptAdd(&hopt, "nt", "# threads", airTypeInt, 1, 1, &nt, "1",
             (airThreadCapable
              ? "number of threads to use in computation"
              : "number of \"threads\" to use in computation, which is "
              "moot here because this Teem build doesn't support "
              "multi-threading. "));
  hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, NULL,
             "filename for output of final converged (two-channel) texture");
  hestParseOrDie(hopt, argc-1, argv+1, NULL,
                 me, spotsInfo, AIR_TRUE, AIR_TRUE, AIR_TRUE);
  mop = airMopNew();
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  actx = alanContextNew();
  airMopAdd(mop, actx, (airMopper)alanContextNix, airMopAlways);
  if (nten) {
    if (alanDimensionSet(actx, nten->dim - 1)
        || alanTensorSet(actx, nten, 1)) {
      airMopAdd(mop, err = biffGetDone(ALAN), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble setting parameters:\n%s\n", me, err);
      airMopError(mop);
      return 1;
    }
  } else {
    alanDimensionSet(actx, sizeLen);
    if (2 == sizeLen) {
      alan2DSizeSet(actx, size[0], size[1]);
    } else {
      alan3DSizeSet(actx, size[0], size[1], size[2]);
    }
  }

  airSrandMT(srnd);
  if (alanParmSet(actx, alanParmVerbose, 1)
      || alanParmSet(actx, alanParmTextureType, alanTextureTypeTuring)
      || alanParmSet(actx, alanParmK, 0.0125)
      || alanParmSet(actx, alanParmAlpha, alphabeta[0])
      || alanParmSet(actx, alanParmBeta, alphabeta[1])
      || alanParmSet(actx, alanParmDeltaX, deltaX)
      || alanParmSet(actx, alanParmDeltaT, deltaT)
      || alanParmSet(actx, alanParmReact, react)
      || alanParmSet(actx, alanParmMinAverageChange, mch)
      || alanParmSet(actx, alanParmMaxPixelChange, xch)
      || alanParmSet(actx, alanParmMaxIteration, maxi)
      || alanParmSet(actx, alanParmRandRange, rrange)
      || alanParmSet(actx, alanParmSaveInterval, si)
      || alanParmSet(actx, alanParmFrameInterval, fi)
      || alanParmSet(actx, alanParmConstantFilename, cfn)
      || alanParmSet(actx, alanParmWrapAround, wrap)
      || alanParmSet(actx, alanParmHomogAniso, ha)
      || alanParmSet(actx, alanParmNumThreads, nt)) {
    airMopAdd(mop, err = biffGetDone(ALAN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble setting parameters:\n%s\n", me, err);
    airMopError(mop);
    return 1;
  }

  if (alanUpdate(actx) || alanInit(actx, ninit, nparm)) {
    airMopAdd(mop, err = biffGetDone(ALAN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble initializing texture: %s\n", me, err);
    airMopError(mop);
    return 1;
  }
  fprintf(stderr, "%s: going to run (%d threads) ...\n", me, actx->numThreads);
  time0 = airTime();
  if (alanRun(actx)) {
    airMopAdd(mop, err = biffGetDone(ALAN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble generating texture: %s\n", me, err);
    airMopError(mop);
    return 1;
  }
  time1 = airTime();
  fprintf(stderr, "%s: stopped after %d iterations (%g seconds): %s\n",
          me, actx->iter, time1 - time0,
          airEnumDesc(alanStop, actx->stop));

  if (nrrdSave(outS, actx->nlev, NULL)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble saving output:\n%s\n", me, err);
    airMopError(mop);
    return 1;
  }


  airMopOkay(mop);
  return 0;
}
int
tend_simMain(int argc, char **argv, char *me, hestParm *hparm) {
  int pret;
  hestOpt *hopt = NULL;
  char *perr, *err;
  tenEstimateContext *tec;
  airArray *mop;

  int E, oldstuff, seed;
  Nrrd *nin, *nT2, *nbmat, *nout;
  char *outS;
  float b, sigma;

  hestOptAdd(&hopt, "old", NULL, airTypeInt, 0, 0, &oldstuff, NULL,
             "don't use the new tenEstimateContext functionality");
  hestOptAdd(&hopt, "sigma", "sigma", airTypeFloat, 1, 1, &sigma, "0.0",
             "Rician noise parameter");
  hestOptAdd(&hopt, "seed", "seed", airTypeInt, 1, 1, &seed, "42",
             "seed value for RNG which creates noise");
  hestOptAdd(&hopt, "B", "B matrix", airTypeOther, 1, 1, &nbmat, NULL,
             "B matrix, one row per diffusion-weighted image", 
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "r", "reference field", airTypeOther, 1, 1, &nT2, "-",
             "reference anatomical scan, with no diffusion weighting",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "i", "tensor field", airTypeOther, 1, 1, &nin, "-",
             "input diffusion tensor field", NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "b", "b", airTypeFloat, 1, 1, &b, "1",
             "b value for simulated scan");
  hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-",
             "output image (floating point)");

  mop = airMopNew();
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  USAGE(_tend_simInfoL);
  PARSE();
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
  
  if (!oldstuff) {
    airSrandMT(seed);
    tec = tenEstimateContextNew();
    airMopAdd(mop, tec, (airMopper)tenEstimateContextNix, airMopAlways);
    E = 0;
    if (!E) E |= tenEstimateMethodSet(tec, tenEstimateMethodLLS);
    if (!E) E |= tenEstimateValueMinSet(tec, 0.0001);
    if (!E) E |= tenEstimateBMatricesSet(tec, nbmat, b, AIR_TRUE);
    if (!E) E |= tenEstimateThresholdSet(tec, 0, 0);
    if (!E) E |= tenEstimateUpdate(tec);
    if (!E) E |= tenEstimate1TensorSimulateVolume(tec, 
                                                  nout, sigma, b, 
                                                  nT2, nin,
                                                  nrrdTypeFloat);
    if (E) {
      airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble making DWI volume (new):\n%s\n", me, err);
      airMopError(mop); return 1;
    }
  } else {
    if (tenSimulate(nout, nT2, nin, nbmat, b)) {
      airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble making DWI volume:\n%s\n", me, err);
      airMopError(mop); return 1;
    }
  }
  if (nrrdSave(outS, nout, NULL)) {
    airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble writing:\n%s\n", me, err);
    airMopError(mop); return 1;
  }

  airMopOkay(mop);
  return 0;
}
示例#11
0
int
main(int argc, char *argv[]) {
  char *me, *err;
  hestOpt *hopt=NULL;
  airArray *mop;

  char *outTenS, *outCovarS, *outRmvS;
  int seed, E;
  unsigned int NN;
  Nrrd *_ninTen, *ninTen, *ngrad, *_ninB0, *ninB0, *nmask,
    *noutCovar, *noutTen, *noutRmv, *ntbuff;
  float sigma, bval;
  size_t sizeX, sizeY, sizeZ;
  tenEstimateContext *tec;
  int axmap[NRRD_DIM_MAX], randrot;

  mop = airMopNew();
  me = argv[0];
  hestOptAdd(&hopt, "i", "ten", airTypeOther, 1, 1, &_ninTen, NULL,
             "input tensor volume", NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "n", "#sim", airTypeUInt, 1, 1, &NN, "100",
             "number of simulations to run");
  hestOptAdd(&hopt, "seed", "seed", airTypeInt, 1, 1, &seed, "42",
             "seed value for RNG which creates noise");
  hestOptAdd(&hopt, "r", "reference field", airTypeOther, 1, 1, &_ninB0, NULL,
             "reference anatomical scan, with no diffusion weighting",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "rr", NULL, airTypeOther, 0, 0, &randrot, NULL,
             "randomize gradient set orientation");
  hestOptAdd(&hopt, "g", "grad list", airTypeOther, 1, 1, &ngrad, "",
             "gradient list, one row per diffusion-weighted image", 
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "b", "b", airTypeFloat, 1, 1, &bval, "1000",
             "b value for simulated scan");
  hestOptAdd(&hopt, "sigma", "sigma", airTypeFloat, 1, 1, &sigma, "0.0",
             "Rician noise parameter");
  hestOptAdd(&hopt, "ot", "filename", airTypeString, 1, 1, &outTenS, 
             "tout.nrrd", "file to write output tensor nrrd to");
  hestOptAdd(&hopt, "oc", "filename", airTypeString, 1, 1, &outCovarS, 
             "cout.nrrd", "file to write output covariance nrrd to");
  hestOptAdd(&hopt, "or", "filename", airTypeString, 1, 1, &outRmvS, 
             "rout.nrrd", "file to write output R_i means, variances to");
  hestParseOrDie(hopt, argc-1, argv+1, NULL,
                 me, info, AIR_TRUE, AIR_TRUE, AIR_TRUE);
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  if (tenGradientCheck(ngrad, nrrdTypeDefault, 7)) {
    airMopAdd(mop, err = biffGetDone(TEN), airFree, airMopAlways);
    fprintf(stderr, "%s: problem with gradient list:\n%s\n", me, err);
    airMopError(mop); 
    return 1;
  }
  if (tenTensorCheck(_ninTen, nrrdTypeDefault, AIR_TRUE, AIR_TRUE)) {
    airMopAdd(mop, err = biffGetDone(TEN), airFree, airMopAlways);
    fprintf(stderr, "%s: didn't like input:\n%s\n", me, err);
    airMopError(mop); 
    return 1;
  }
  sizeX = _ninTen->axis[1].size;
  sizeY = _ninTen->axis[2].size;
  sizeZ = _ninTen->axis[3].size;
  if (!(3 == _ninB0->dim &&
        sizeX == _ninB0->axis[0].size &&
        sizeY == _ninB0->axis[1].size &&
        sizeZ == _ninB0->axis[2].size)) {
    fprintf(stderr, "%s: given B0 (%u-D) volume not 3-D " _AIR_SIZE_T_CNV
            "x" _AIR_SIZE_T_CNV "x" _AIR_SIZE_T_CNV, me, _ninB0->dim,
            sizeX, sizeY, sizeZ);
    airMopError(mop); 
    return 1;
  }

  ninTen = nrrdNew();
  airMopAdd(mop, ninTen, (airMopper)nrrdNuke, airMopOnError);
  nmask = nrrdNew();
  airMopAdd(mop, nmask, (airMopper)nrrdNuke, airMopOnError);
  ninB0 = nrrdNew();
  airMopAdd(mop, ninB0, (airMopper)nrrdNuke, airMopOnError);
  noutCovar = nrrdNew();
  airMopAdd(mop, noutCovar, (airMopper)nrrdNuke, airMopOnError);
  noutTen = nrrdNew();
  airMopAdd(mop, noutTen, (airMopper)nrrdNuke, airMopOnError);
  noutRmv = nrrdNew();
  airMopAdd(mop, noutRmv, (airMopper)nrrdNuke, airMopOnError);
  ntbuff = nrrdNew();
  airMopAdd(mop, ntbuff, (airMopper)nrrdNuke, airMopOnError);

  if (nrrdConvert(ninTen, _ninTen, nrrdTypeDouble)
      || nrrdSlice(nmask, ninTen, 0, 0)
      || nrrdConvert(ninB0, _ninB0, nrrdTypeDouble)
      || nrrdMaybeAlloc_va(noutTen, nrrdTypeDouble, 4, 
                           AIR_CAST(size_t, 7), sizeX, sizeY, sizeZ)
      || nrrdMaybeAlloc_va(noutCovar, nrrdTypeDouble, 4, 
                           AIR_CAST(size_t, 21), sizeX, sizeY, sizeZ)
      || nrrdMaybeAlloc_va(noutRmv, nrrdTypeDouble, 4, 
                           AIR_CAST(size_t, 6), sizeX, sizeY, sizeZ)
      || nrrdMaybeAlloc_va(ntbuff, nrrdTypeDouble, 2,
                           AIR_CAST(size_t, 7), NN)) {
    airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble setting up tec:\n%s\n", me, err);
    airMopError(mop);
    return 1;
  }

  tec = tenEstimateContextNew();
  airMopAdd(mop, tec, (airMopper)tenEstimateContextNix, airMopAlways);

  E = 0;
  if (!E) E |= tenEstimateMethodSet(tec, tenEstimate1MethodLLS);
  if (!E) E |= tenEstimateValueMinSet(tec, 0.000000001);
  if (!E) E |= tenEstimateGradientsSet(tec, ngrad, bval, AIR_TRUE);
  if (!E) E |= tenEstimateThresholdSet(tec, 0, 0);
  if (!E) E |= tenEstimateUpdate(tec);
  if (E) {
    airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble setting up tec:\n%s\n", me, err);
    airMopError(mop);
    return 1;
  }

  airSrandMT(seed);

  fprintf(stderr, "!%s: randrot = %d\n", me, randrot);
  if (1) {
    unsigned int II;
    unsigned int nsamp;
    double *inTen, *outTen, *outCovar, *outRmv, 
      *dwibuff, (*lup)(const void *, size_t);
    char doneStr[AIR_STRLEN_SMALL];

    dwibuff = AIR_CAST(double *, calloc(ngrad->axis[1].size, sizeof(double)));
    airMopAdd(mop, dwibuff, airFree, airMopAlways);
    nsamp = sizeX*sizeY*sizeZ;
    inTen = AIR_CAST(double *, ninTen->data);
    lup  = nrrdDLookup[nrrdTypeDouble];
    outTen = AIR_CAST(double *, noutTen->data);
    outCovar = AIR_CAST(double *, noutCovar->data);
    outRmv = AIR_CAST(double *, noutRmv->data);
    fprintf(stderr, "!%s: simulating ...       ", me);
    fflush(stderr);
    for (II=0; II<nsamp; II++) {
      if (!(II % sizeX)) {
        fprintf(stderr, "%s", airDoneStr(0, II, nsamp, doneStr));
        fflush(stderr);
      }
      if (csimDo(outTen, outCovar, outRmv + 0, outRmv + 3, ntbuff,
                 tec, dwibuff, sigma,
                 bval, lup(ninB0->data, II), NN, randrot, inTen)) {
        airMopAdd(mop, err=biffGetDone(TEN), airFree, airMopAlways);
        fprintf(stderr, "%s: trouble:\n%s\n", me, err);
        airMopError(mop);
        return 1;
      }
      inTen += 7;
      outTen += 7;
      outCovar += 21;
      outRmv += 6;
    }
    fprintf(stderr, "%s\n", airDoneStr(0, II, nsamp, doneStr));
  }