static double _nrrdBinaryOpRicianRand(double a, double b) { double vr, vi, rr, ri; airNormalRand(&rr, &ri); vr = a + b*rr; vi = b*ri; return sqrt(vr*vr + vi*vi); }
/* ** hist[0]: hue vs sat ** hist[1]: hue vs val */ void imageProc(Nrrd *nhproj[3], Nrrd *nhist[2], unsigned int sH, float *rgb, unsigned int size0, unsigned int sXY, unsigned int overSampleNum, float overSampleScale) { unsigned int xyi, hi, si, vi, oi; float rr, gg, bb, hh, ss, vv, *hist[2]; double rndA, rndB; nrrdZeroSet(nhist[0]); nrrdZeroSet(nhist[1]); hist[0] = AIR_CAST(float *, nhist[0]->data); hist[1] = AIR_CAST(float *, nhist[1]->data); for (xyi=0; xyi<sXY; xyi++) { rr = AIR_CLAMP(0, rgb[0], 255); gg = AIR_CLAMP(0, rgb[1], 255); bb = AIR_CLAMP(0, rgb[2], 255); rr = AIR_AFFINE(-1, rr, 256, 0, 1); gg = AIR_AFFINE(-1, gg, 256, 0, 1); bb = AIR_AFFINE(-1, bb, 256, 0, 1); dyeRGBtoHSV(&hh, &ss, &vv, rr, gg, bb); si = airIndexClamp(0, ss, 1, sH); vi = airIndexClamp(0, vv, 1, sH); #define UPDATE_HIST(rnd) \ hi = airIndexClamp(0, hh + overSampleScale*(1-ss)*(rnd), 1, sH); \ hist[0][hi + sH*si] += 1.0/overSampleNum; \ hist[1][hi + sH*vi] += 1.0/overSampleNum if (overSampleNum % 2 == 1) { airNormalRand(&rndA, NULL); UPDATE_HIST(rndA); overSampleNum -= 1; } for (oi=0; oi<overSampleNum; oi+=2) { airNormalRand(&rndA, &rndB); UPDATE_HIST(rndA); UPDATE_HIST(rndB); } rgb += size0; } nrrdProject(nhproj[0], nhist[0], 1, nrrdMeasureHistoMean, nrrdTypeFloat); nrrdProject(nhproj[1], nhist[1], 1, nrrdMeasureHistoMean, nrrdTypeFloat); nrrdProject(nhproj[2], nhist[1], 1, nrrdMeasureSum, nrrdTypeFloat); }
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; } } }
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; }
static double _nrrdBinaryOpNormalRandScaleAdd(double a, double b) { double v; airNormalRand(&v, NULL); return a + b*v; }
static double _nrrdUnaryOpNormalRand(double a) { double v; AIR_UNUSED(a); airNormalRand(&v, NULL); return v; }
static int csimDo(double tm[7], double tcov[21], double rm[3], double rv[3], Nrrd *ntbuff, tenEstimateContext *tec, double *dwibuff, double sigma, double bvalue, double B0, unsigned int NN, int randrot, double _tenOrig[7]) { char me[]="csimDo", err[BIFF_STRLEN]; double *tbuff; unsigned int II, taa, tbb, cc; if (!(ntbuff && ntbuff->data && 2 == ntbuff->dim && 7 == ntbuff->axis[0].size && NN == ntbuff->axis[1].size)) { sprintf(err, "%s: ntbuff not allocated for 2-by-%u array of %s", me, NN, airEnumStr(nrrdType, nrrdTypeDouble)); biffAdd(TEN, err); return 1; } /* find all tensors from simulated DWIs */ tbuff = AIR_CAST(double *, ntbuff->data); for (II=0; II<NN; II++) { double tenOrig[7], rotf[9], rotb[9], matA[9], matB[9], qq[4], tmp; ELL_3M_IDENTITY_SET(rotf); /* sssh warnings */ ELL_3M_IDENTITY_SET(rotb); /* sssh warnings */ if (randrot) { if (1) { double eval[3], evec[9], eps, ma[9], mb[9], rf[9], rb[9]; tenEigensolve_d(eval, evec, _tenOrig); airNormalRand(&eps, NULL); ell_aa_to_3m_d(rf, 0*eps/20, evec + 0); TEN_T_SCALE_INCR(_tenOrig, 0*eps/30, _tenOrig); TEN_T2M(ma, _tenOrig); ELL_3M_TRANSPOSE(rb, rf); ELL_3M_MUL(mb, ma, rf); ELL_3M_MUL(ma, rb, mb); TEN_M2T(_tenOrig, ma); } TEN_T2M(matA, _tenOrig); airNormalRand(qq+0, qq+1); airNormalRand(qq+2, qq+3); ELL_4V_NORM(qq, qq, tmp); ell_q_to_3m_d(rotf, qq); ELL_3M_TRANSPOSE(rotb, rotf); ELL_3M_MUL(matB, matA, rotf); ELL_3M_MUL(matA, rotb, matB); TEN_M2T(tenOrig, matA); } else { TEN_T_COPY(tenOrig, _tenOrig); } if (tenEstimate1TensorSimulateSingle_d(tec, dwibuff, sigma, bvalue, B0, tenOrig) || tenEstimate1TensorSingle_d(tec, tbuff, dwibuff)) { sprintf(err, "%s: trouble on exp %u/%u", me, II, NN); biffAdd(TEN, err); return 1; } if (randrot) { TEN_T2M(matA, tbuff); ELL_3M_MUL(matB, matA, rotb); ELL_3M_MUL(matA, rotf, matB); TEN_M2T(tbuff, matA); } /* else we leave tbuff as it is */ /* if (_tenOrig[0] > 0.5) { double tdiff[7]; TEN_T_SUB(tdiff, _tenOrig, tbuff); fprintf(stderr, "!%s: %g\n" " (%g) %g,%g,%g %g,%g %g\n" " (%g) %g,%g,%g %g,%g %g\n", me, TEN_T_NORM(tdiff), _tenOrig[0], _tenOrig[1], _tenOrig[2], _tenOrig[3], _tenOrig[4], _tenOrig[5], _tenOrig[6], tbuff[0], tbuff[1], tbuff[2], tbuff[3], tbuff[4], tbuff[5], tbuff[6]); } */ tbuff += 7; } /* find mean tensor, and mean R_i */ tbuff = AIR_CAST(double *, ntbuff->data); TEN_T_SET(tm, 0, 0, 0, 0, 0, 0, 0); ELL_3V_SET(rm, 0, 0, 0); for (II=0; II<NN; II++) { TEN_T_INCR(tm, tbuff); rm[0] += sqrt(_tenAnisoTen_d[tenAniso_S](tbuff)); rm[1] += _tenAnisoTen_d[tenAniso_FA](tbuff); rm[2] += _tenAnisoTen_d[tenAniso_Mode](tbuff); tbuff += 7; } rm[0] /= NN; rm[1] /= NN; rm[2] /= NN; TEN_T_SCALE(tm, 1.0/NN, tm); /* accumulate covariance tensor, and R_i variances */ for (cc=0; cc<21; cc++) { tcov[cc] = 0; } ELL_3V_SET(rv, 0, 0, 0); tbuff = AIR_CAST(double *, ntbuff->data); for (II=0; II<NN; II++) { double r[3]; r[0] = sqrt(_tenAnisoTen_d[tenAniso_S](tbuff)); r[1] = _tenAnisoTen_d[tenAniso_FA](tbuff); r[2] = _tenAnisoTen_d[tenAniso_Mode](tbuff); cc = 0; rv[0] += (r[0] - rm[0])*(r[0] - rm[0])/(NN-1); rv[1] += (r[1] - rm[1])*(r[1] - rm[1])/(NN-1); rv[2] += (r[2] - rm[2])*(r[2] - rm[2])/(NN-1); for (taa=0; taa<6; taa++) { for (tbb=taa; tbb<6; tbb++) { tcov[cc] += (10000*(tbuff[taa+1]-tm[taa+1]) *10000*(tbuff[tbb+1]-tm[tbb+1])/(NN-1)); cc++; } } tbuff += 7; } return 0; }