void multiplyBySpectrum(MultidimArray<double>& Min, MultidimArray<double>& spectrum, bool leave_origin_intact) { MultidimArray<Complex > Faux; Matrix1D<double> f(3); MultidimArray<double> lspectrum; FourierTransformer transformer; double dim3 = XSIZE(Min) * YSIZE(Min) * ZSIZE(Min); transformer.FourierTransform(Min, Faux, false); lspectrum = spectrum; if (leave_origin_intact) { lspectrum(0) = 1.; } FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM(Faux) { long int idx = ROUND(sqrt(kp * kp + ip * ip + jp * jp)); dAkij(Faux, k, i, j) *= lspectrum(idx) * dim3; } transformer.inverseFourierTransform(); }
/* FUNCTION: InitNewFont(LOGFONT, COLORREF) PURPOSE: Prepares a new font for use in the terminal screen PARAMETERS: LogFont - New logical font for the screen rgbColour - New colour for screen painting */ void InitNewFont(LOGFONT LogFont, COLORREF rgbColour) { TEXTMETRIC tm; HDC hDC; // If an old font exits, delete it if (HSCREENFONT(TermInfo)) { DeleteObject(HSCREENFONT(TermInfo)); } LFSCREENFONT(TermInfo) = LogFont; HSCREENFONT(TermInfo) = CreateFontIndirect(&(LFSCREENFONT(TermInfo))); FGCOLOUR(TermInfo) = rgbColour; hDC = GetDC(ghWndMain); SelectObject(hDC, HSCREENFONT(TermInfo)); GetTextMetrics(hDC, &tm); ReleaseDC(ghWndMain, hDC); // Character width and height XCHAR(TermInfo) = tm.tmAveCharWidth; YCHAR(TermInfo) = tm.tmHeight + tm.tmExternalLeading; // Set the terminal height and width based on the current font XSIZE(TermInfo) = tm.tmAveCharWidth * MAXCOLS; YSIZE(TermInfo) = (tm.tmHeight + tm.tmExternalLeading) * MAXROWS; }
void getSpectrum(MultidimArray<double>& Min, MultidimArray<double>& spectrum, int spectrum_type) { MultidimArray<Complex > Faux; int xsize = XSIZE(Min); Matrix1D<double> f(3); MultidimArray<double> count(xsize); FourierTransformer transformer; spectrum.initZeros(xsize); count.initZeros(); transformer.FourierTransform(Min, Faux, false); FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM(Faux) { long int idx = ROUND(sqrt(kp * kp + ip * ip + jp * jp)); if (spectrum_type == AMPLITUDE_SPECTRUM) { spectrum(idx) += abs(dAkij(Faux, k, i, j)); } else { spectrum(idx) += norm(dAkij(Faux, k, i, j)); } count(idx) += 1.; } for (long int i = 0; i < xsize; i++) if (count(i) > 0.) { spectrum(i) /= count(i); } }
// Really import ========================================================== void ProgXrayImport::readAndCrop(const FileName &fn, Image<double> &I, int xCropSize, int yCropSize) const { I.read(fn); I().selfWindow(yCropSize,xCropSize, (int)(YSIZE(I())-yCropSize-1),(int)(XSIZE(I())-xCropSize-1)); I().resetOrigin(); }
// Value access double TabFtBlob::operator()(double val) const { int idx = (int)( ABS(val) / sampling); if (idx >= XSIZE(tabulatedValues)) return 0.; else return DIRECT_A1D_ELEM(tabulatedValues, idx); }
static void game_compute_size(const game_params *params, int tilesize, int *x, int *y) { struct bbox bb = find_bbox(params); *x = XSIZE(tilesize, bb, solids[params->solid]); *y = YSIZE(tilesize, bb, solids[params->solid]); }
/* Filter generation ------------------------------------------------------- */ void Steerable::generate1DFilters(double sigma, const MultidimArray<double> &Vtomograph, std::vector< MultidimArray<double> > &hx1, std::vector< MultidimArray<double> > &hy1, std::vector< MultidimArray<double> > &hz1){ // Initialization MultidimArray<double> aux; aux.initZeros(XSIZE(Vtomograph)); aux.setXmippOrigin(); for (int i=0; i<6; i++) hx1.push_back(aux); aux.initZeros(YSIZE(Vtomograph)); aux.setXmippOrigin(); for (int i=0; i<6; i++) hy1.push_back(aux); aux.initZeros(ZSIZE(Vtomograph)); aux.setXmippOrigin(); for (int i=0; i<6; i++) hz1.push_back(aux); double sigma2=sigma*sigma; double k1 = 1.0/pow((2.0*PI*sigma),(3.0/2.0)); double k2 = -1.0/(sigma2); FOR_ALL_ELEMENTS_IN_ARRAY1D(hx1[0]) { double i2=i*i; double g = -exp(-i2/(2.0*sigma2)); hx1[0](i) = k1*k2*g*(1.0-(i2/sigma2)); hx1[1](i) = k1*k2*g; hx1[2](i) = k1*k2*g; hx1[3](i) = k1*k2*k2*g*i; hx1[4](i) = k1*k2*k2*g*i; hx1[5](i) = k1*k2*k2*g; } FOR_ALL_ELEMENTS_IN_ARRAY1D(hy1[0]) { double i2=i*i; double g = -exp(-i2/(2.0*sigma2)); hy1[0](i) = g; hy1[1](i) = g*(1.0-(i2/sigma2)); hy1[2](i) = g; hy1[3](i) = g*i; hy1[4](i) = g; hy1[5](i) = g*i; } FOR_ALL_ELEMENTS_IN_ARRAY1D(hz1[0]) { double i2=i*i; double g = -exp(-i2/(2.0*sigma2)); hz1[0](i) = g; hz1[1](i) = g; hz1[2](i) = g*(1.0-(i2/sigma2)); hz1[3](i) = g; hz1[4](i) = g*i; hz1[5](i) = g*i; } }
void correctMapForMTF(MultidimArray<double >& img, FileName& fn_mtf) { FourierTransformer transformer; MultidimArray<Complex > FT; transformer.FourierTransform(img, FT, false); correctMapForMTF(FT, XSIZE(img), fn_mtf); transformer.inverseFourierTransform(); }
/* analyze given string and return protocol id */ static XTYPE(PROTOCOLS) GetChannelProtocol(char *proto) { XTYPE(PROTOCOLS) p; proto = g_strstrip(proto); for(p = 0; p < XSIZE(PROTOCOLS); ++p) if(g_ascii_strcasecmp(XSTR(PROTOCOLS, p), proto) == 0) return p; return -1; }
/* * return keyword and update given "value" with extracted value * spaces will be trimmed from "value" */ static XTYPE(KEYWORDS) GetKey(char *key) { XTYPE(KEYWORDS) k; key = g_strstrip(key); for(k = 0; k < XSIZE(KEYWORDS); ++k) if(g_strcmp0(XSTR(KEYWORDS, k), key) == 0) return k; return -1; }
FourierProjector::FourierProjector(MultidimArray<double> &V, double paddFactor, double maxFreq, int degree) { volume = &V; volumeSize=XSIZE(*volume); paddingFactor = paddFactor; maxFrequency = maxFreq; BSplineDeg = degree; produceSideInfo(); }
/* ------------------------------------------------------------------------- */ NaiveBayes::NaiveBayes( const std::vector< MultidimArray<double> > &features, const Matrix1D<double> &priorProbs, int discreteLevels) { K = features.size(); Nfeatures=XSIZE(features[0]); __priorProbsLog10.initZeros(K); FOR_ALL_ELEMENTS_IN_MATRIX1D(__priorProbsLog10) VEC_ELEM(__priorProbsLog10,i)=log10(VEC_ELEM(priorProbs,i)); // Create a dummy leaf for features that cannot classify std::vector < MultidimArray<double> > aux(K); dummyLeaf=new LeafNode(aux,0); // Build a leafnode for each feature and assign a weight __weights.initZeros(Nfeatures); for (int f=0; f<Nfeatures; f++) { for (int k=0; k<K; k++) features[k].getCol(f, aux[k]); LeafNode *leaf=new LeafNode(aux,discreteLevels); if (leaf->__discreteLevels>0) { __leafs.push_back(leaf); DIRECT_A1D_ELEM(__weights,f)=__leafs[f]->computeWeight(); } else { __leafs.push_back(dummyLeaf); DIRECT_A1D_ELEM(__weights,f)=0; delete leaf; } #ifdef DEBUG_WEIGHTS if(debugging == true) { std::cout << "Node " << f << std::endl; std::cout << *(__leafs[f]) << std::endl; //char c; //std::cin >> c; } #endif } double norm=__weights.computeMax(); if (norm>0) __weights *= 1.0/norm; // Set default cost matrix __cost.resizeNoCopy(K,K); __cost.initConstant(1); for (int i=0; i<K; i++) MAT_ELEM(__cost,i,i)=0; }
void FourierProjector::produceSideInfo() { // Zero padding MultidimArray<double> Vpadded; int paddedDim=(int)(paddingFactor*volumeSize); volume->window(Vpadded,FIRST_XMIPP_INDEX(paddedDim),FIRST_XMIPP_INDEX(paddedDim),FIRST_XMIPP_INDEX(paddedDim), LAST_XMIPP_INDEX(paddedDim),LAST_XMIPP_INDEX(paddedDim),LAST_XMIPP_INDEX(paddedDim)); volume->clear(); // Make Fourier transform, shift the volume origin to the volume center and center it MultidimArray< std::complex<double> > Vfourier; transformer3D.completeFourierTransform(Vpadded,Vfourier); ShiftFFT(Vfourier, FIRST_XMIPP_INDEX(XSIZE(Vpadded)), FIRST_XMIPP_INDEX(YSIZE(Vpadded)), FIRST_XMIPP_INDEX(ZSIZE(Vpadded))); CenterFFT(Vfourier,true); Vfourier.setXmippOrigin(); // Compensate for the Fourier normalization factor double K=(double)(XSIZE(Vpadded)*XSIZE(Vpadded)*XSIZE(Vpadded))/(double)(volumeSize*volumeSize); FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(Vfourier) DIRECT_MULTIDIM_ELEM(Vfourier,n)*=K; Vpadded.clear(); // Compute Bspline coefficients if (BSplineDeg==3) { MultidimArray< double > VfourierRealAux, VfourierImagAux; Complex2RealImag(Vfourier, VfourierRealAux, VfourierImagAux); Vfourier.clear(); produceSplineCoefficients(BSPLINE3,VfourierRealCoefs,VfourierRealAux); produceSplineCoefficients(BSPLINE3,VfourierImagCoefs,VfourierImagAux); //VfourierRealAux.clear(); //VfourierImagAux.clear(); } else Complex2RealImag(Vfourier, VfourierRealCoefs, VfourierImagCoefs); // Allocate memory for the 2D Fourier transform projection().initZeros(volumeSize,volumeSize); projection().setXmippOrigin(); transformer2D.FourierTransform(projection(),projectionFourier,false); }
// Fourier ring correlation ----------------------------------------------- // from precalculated Fourier Transforms, and without sampling rate etc. void getFSC(MultidimArray< Complex >& FT1, MultidimArray< Complex >& FT2, MultidimArray< double >& fsc) { if (!FT1.sameShape(FT2)) { REPORT_ERROR("fourierShellCorrelation ERROR: MultidimArrays have different shapes!"); } MultidimArray< int > radial_count(XSIZE(FT1)); MultidimArray<double> num, den1, den2; Matrix1D<double> f(3); num.initZeros(radial_count); den1.initZeros(radial_count); den2.initZeros(radial_count); fsc.initZeros(radial_count); FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM(FT1) { int idx = ROUND(sqrt(kp * kp + ip * ip + jp * jp)); if (idx >= XSIZE(FT1)) { continue; } Complex z1 = DIRECT_A3D_ELEM(FT1, k, i, j); Complex z2 = DIRECT_A3D_ELEM(FT2, k, i, j); double absz1 = abs(z1); double absz2 = abs(z2); num(idx) += (conj(z1) * z2).real; den1(idx) += absz1 * absz1; den2(idx) += absz2 * absz2; radial_count(idx)++; } FOR_ALL_ELEMENTS_IN_ARRAY1D(fsc) { fsc(i) = num(i) / sqrt(den1(i) * den2(i)); } }
struct Manifest *ManifestTextCtor(char *text) { struct Manifest *manifest = g_malloc0(sizeof *manifest); int counters[XSIZE(KEYWORDS)] = {0}; char **lines; int i; /* initialize channels */ manifest->channels = g_ptr_array_new(); /* extract all lines */ lines = g_strsplit(text, LINE_DELIMITER, MANIFEST_LINES_LIMIT); /* parse each line */ for(i = 0; lines[i] != NULL; ++i) { char **tokens; tokens = g_strsplit(lines[i], KEY_DELIMITER, MANIFEST_TOKENS_LIMIT); if(strlen(lines[i]) > 0 && tokens[Key] != NULL && tokens[Value] != NULL && tokens[KeyValueTokensNumber] == NULL) { /* switch invoking functions by the keyword */ #define XSWITCH(a) switch(GetKey(tokens[Key])) {a}; #define X(a, o, s) case Key##a: ++counters[Key##a]; a(manifest, tokens[Value]); break; XSWITCH(KEYWORDS) #undef X } g_strfreev(tokens); } /* check obligatory and singleton keywords */ g_strfreev(lines); CheckCounters(counters, XSIZE(KEYWORDS)); return manifest; }
void CTF::getCenteredImage(MultidimArray<DOUBLE> &result, DOUBLE Tm, bool do_abs, bool do_only_flip_phases, bool do_intact_until_first_peak, bool do_damping) { result.setXmippOrigin(); DOUBLE xs = (DOUBLE)XSIZE(result) * Tm; DOUBLE ys = (DOUBLE)YSIZE(result) * Tm; FOR_ALL_ELEMENTS_IN_ARRAY2D(result) { DOUBLE x = (DOUBLE)j / xs; DOUBLE y = (DOUBLE)i / ys; A2D_ELEM(result, i, j) = getCTF(x, y, do_abs, do_only_flip_phases, do_intact_until_first_peak, do_damping); } }
/* Bspline03 by a LUT ------------------------------------------------------ */ double Bspline03LUT(double x) { static bool firstCall = true; static MultidimArray<double> table(BSPLINE03_SUBSAMPLING); static const double deltax = 2.0 / BSPLINE03_SUBSAMPLING; static const double ideltax = 1.0 / deltax; if (firstCall) { FOR_ALL_ELEMENTS_IN_ARRAY1D(table) table(i) = Bspline03(i * deltax); firstCall = false; } size_t i = (size_t)round(fabs(x) * ideltax); if (i >= XSIZE(table)) return 0; else return table(i); }
/* Do inference ------------------------------------------------------------ */ int EnsembleNaiveBayes::doInference(const Matrix1D<double> &newFeatures, double &cost, MultidimArray<int> &votes, Matrix1D<double> &classesProbs, Matrix1D<double> &allCosts) { int nmax=ensemble.size(); MultidimArray<double> minCost, maxCost; votes.initZeros(K); minCost.initZeros(K); minCost.initConstant(1); maxCost.initZeros(K); maxCost.initConstant(1); double bestMinCost=0; int bestClass=0; MultidimArray<double> newFeaturesn; for (int n=0; n<nmax; n++) { double costn; newFeaturesn.initZeros(XSIZE(ensembleFeatures[n])); FOR_ALL_ELEMENTS_IN_ARRAY1D(newFeaturesn) newFeaturesn(i)=newFeatures(ensembleFeatures[n](i)); int k=ensemble[n]->doInference(newFeaturesn, costn, classesProbs, allCosts); votes(k)++; if (minCost(k)>0 || minCost(k)>costn) minCost(k)=costn; if (maxCost(k)>0 || maxCost(k)<costn) maxCost(k)=costn; if (minCost(k)<bestMinCost) { bestMinCost=minCost(k); bestClass=k; } } if (judgeCombination[bestClass]=='m') cost=minCost(bestClass); else if (judgeCombination[bestClass]=='M') cost=maxCost(bestClass); else cost=minCost(bestClass); return bestClass; }
void evaluateClass(MetaData &MD, ClassEvaluation &eval) { eval.FRC_05=0; eval.DPR_05=0; if (MD.size()<10) return; MetaData MDrandomized; std::vector<MetaData> vMD; MultidimArray<double> I0, I1, freq, frc, dpr, frc_noise, error_l2; // Compute FRC MDrandomized.randomize(MD); MDrandomized.split(2,vMD,MDL_IMAGE); getAverageApplyGeo(vMD[0],I0); getAverageApplyGeo(vMD[1],I1); I0.setXmippOrigin(); I1.setXmippOrigin(); frc_dpr(I0, I1, 1, freq, frc, frc_noise, dpr, error_l2, true); // Compute the frequency of FRC=0.5 int i_05=-1; FOR_ALL_ELEMENTS_IN_ARRAY1D(frc) if (dAi(frc,i)<0.5) { i_05=i; break; } if (i_05==-1) { i_05=XSIZE(frc)-1; eval.overfitting=true; } // Extract evaluators eval.FRC_05=dAi(freq,i_05); eval.DPR_05=dAi(dpr,i_05); }
// Some image-specific operations void normalise(Image<DOUBLE> &I, int bg_radius, DOUBLE white_dust_stddev, DOUBLE black_dust_stddev, bool do_ramp) { int bg_radius2 = bg_radius * bg_radius; DOUBLE avg, stddev; if (2*bg_radius > XSIZE(I())) REPORT_ERROR("normalise ERROR: 2*bg_radius is larger than image size!"); if (white_dust_stddev > 0. || black_dust_stddev > 0.) { // Calculate initial avg and stddev values calculateBackgroundAvgStddev(I, avg, stddev, bg_radius); // Remove white and black noise if (white_dust_stddev > 0.) removeDust(I, true, white_dust_stddev, avg, stddev); if (black_dust_stddev > 0.) removeDust(I, false, black_dust_stddev, avg, stddev); } if (do_ramp) subtractBackgroundRamp(I, bg_radius); // Calculate avg and stddev (also redo if dust was removed!) calculateBackgroundAvgStddev(I, avg, stddev, bg_radius); if (stddev < 1e-10) { std::cerr << " WARNING! Stddev of image " << I.name() << " is zero! Skipping normalisation..." << std::endl; } else { // Subtract avg and divide by stddev for all pixels FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(I()) DIRECT_MULTIDIM_ELEM(I(), n) = (DIRECT_MULTIDIM_ELEM(I(), n) - avg) / stddev; } }
/* Do inference for class ------------------------------------------------- */ int EnsembleNaiveBayes::doInferenceForClass(int classNumber, const Matrix1D<double> &newFeatures, double &cost, Matrix1D<double> &classesProbs, Matrix1D<double> &allCosts) { int nmax=ensemble.size(); double minCost=1, maxCost=1; int votes=0; MultidimArray<double> newFeaturesn; for (int n=0; n<nmax; n++) { double costn; const MultidimArray<int> &ensembleFeatures_n=ensembleFeatures[n]; newFeaturesn.resizeNoCopy(XSIZE(ensembleFeatures_n)); FOR_ALL_ELEMENTS_IN_ARRAY1D(newFeaturesn) { int idx=A1D_ELEM(ensembleFeatures_n,i); A1D_ELEM(newFeaturesn,i)=VEC_ELEM(newFeatures,idx); } int k=ensemble[n]->doInference(newFeaturesn, costn, classesProbs, allCosts); if (k==classNumber) { votes++; if (minCost>0 || minCost>costn) minCost=costn; if (maxCost>0 || maxCost<costn) maxCost=costn; } } if (judgeCombination[classNumber]=='m') cost=minCost; else if (judgeCombination[classNumber]=='M') cost=maxCost; else cost=minCost; return votes; }
static void game_redraw(drawing *dr, game_drawstate *ds, const game_state *oldstate, const game_state *state, int dir, const game_ui *ui, float animtime, float flashtime) { int i, j; struct bbox bb = find_bbox(&state->params); struct solid *poly; const int *pkey, *gkey; float t[3]; float angle; int square; draw_rect(dr, 0, 0, XSIZE(GRID_SCALE, bb, state->solid), YSIZE(GRID_SCALE, bb, state->solid), COL_BACKGROUND); if (dir < 0) { const game_state *t; /* * This is an Undo. So reverse the order of the states, and * run the roll timer backwards. */ assert(oldstate); t = oldstate; oldstate = state; state = t; animtime = ROLLTIME - animtime; } if (!oldstate) { oldstate = state; angle = 0.0; square = state->current; pkey = state->dpkey; gkey = state->dgkey; } else { angle = state->angle * animtime / ROLLTIME; square = state->previous; pkey = state->spkey; gkey = state->sgkey; } state = oldstate; for (i = 0; i < state->grid->nsquares; i++) { int coords[8]; for (j = 0; j < state->grid->squares[i].npoints; j++) { coords[2*j] = ((int)(state->grid->squares[i].points[2*j] * GRID_SCALE) + ds->ox); coords[2*j+1] = ((int)(state->grid->squares[i].points[2*j+1]*GRID_SCALE) + ds->oy); } draw_polygon(dr, coords, state->grid->squares[i].npoints, GET_SQUARE(state, i) ? COL_BLUE : COL_BACKGROUND, COL_BORDER); } /* * Now compute and draw the polyhedron. */ poly = transform_poly(state->solid, state->grid->squares[square].flip, pkey[0], pkey[1], angle); /* * Compute the translation required to align the two key points * on the polyhedron with the same key points on the current * face. */ for (i = 0; i < 3; i++) { float tc = 0.0; for (j = 0; j < 2; j++) { float grid_coord; if (i < 2) { grid_coord = state->grid->squares[square].points[gkey[j]*2+i]; } else { grid_coord = 0.0; } tc += (grid_coord - poly->vertices[pkey[j]*3+i]); } t[i] = tc / 2; } for (i = 0; i < poly->nvertices; i++) for (j = 0; j < 3; j++) poly->vertices[i*3+j] += t[j]; /* * Now actually draw each face. */ for (i = 0; i < poly->nfaces; i++) { float points[8]; int coords[8]; for (j = 0; j < poly->order; j++) { int f = poly->faces[i*poly->order + j]; points[j*2] = (poly->vertices[f*3+0] - poly->vertices[f*3+2] * poly->shear); points[j*2+1] = (poly->vertices[f*3+1] - poly->vertices[f*3+2] * poly->shear); } for (j = 0; j < poly->order; j++) { coords[j*2] = (int)floor(points[j*2] * GRID_SCALE) + ds->ox; coords[j*2+1] = (int)floor(points[j*2+1] * GRID_SCALE) + ds->oy; } /* * Find out whether these points are in a clockwise or * anticlockwise arrangement. If the latter, discard the * face because it's facing away from the viewer. * * This would involve fiddly winding-number stuff for a * general polygon, but for the simple parallelograms we'll * be seeing here, all we have to do is check whether the * corners turn right or left. So we'll take the vector * from point 0 to point 1, turn it right 90 degrees, * and check the sign of the dot product with that and the * next vector (point 1 to point 2). */ { float v1x = points[2]-points[0]; float v1y = points[3]-points[1]; float v2x = points[4]-points[2]; float v2y = points[5]-points[3]; float dp = v1x * v2y - v1y * v2x; if (dp <= 0) continue; } draw_polygon(dr, coords, poly->order, state->facecolours[i] ? COL_BLUE : COL_BACKGROUND, COL_BORDER); } sfree(poly); draw_update(dr, 0, 0, XSIZE(GRID_SCALE, bb, state->solid), YSIZE(GRID_SCALE, bb, state->solid)); /* * Update the status bar. */ { char statusbuf[256]; if (state->completed) { strcpy(statusbuf, _("COMPLETED!")); strcpy(statusbuf+strlen(statusbuf), " "); } else statusbuf[0] = '\0'; sprintf(statusbuf+strlen(statusbuf), _("Moves: %d"), (state->completed ? state->completed : state->movecount)); status_bar(dr, statusbuf); } }
EnsembleNaiveBayes::EnsembleNaiveBayes( const std::vector < MultidimArray<double> > &features, const Matrix1D<double> &priorProbs, int discreteLevels, int numberOfClassifiers, double samplingFeatures, double samplingIndividuals, const std::string &newJudgeCombination) { int NFeatures=XSIZE(features[0]); int NsubFeatures=CEIL(NFeatures*samplingFeatures); K=features.size(); judgeCombination=newJudgeCombination; #ifdef WEIGHTED_SAMPLING // Measure the classification power of each variable NaiveBayes *nb_weights=new NaiveBayes(features, priorProbs, discreteLevels); MultidimArray<double> weights=nb_weights->__weights; delete nb_weights; double sumWeights=weights.sum(); #endif for (int n=0; n<numberOfClassifiers; n++) { // Produce the set of features for this subclassifier MultidimArray<int> subFeatures(NsubFeatures); FOR_ALL_ELEMENTS_IN_ARRAY1D(subFeatures) { #ifdef WEIGHTED_SAMPLING double random_sum_weight=rnd_unif(0,sumWeights); int j=0; do { double wj=DIRECT_A1D_ELEM(weights,j); if (wj<random_sum_weight) { random_sum_weight-=wj; j++; if (j==NFeatures) { j=NFeatures-1; break; } } else break; } while (true); DIRECT_A1D_ELEM(subFeatures,i)=j; #else DIRECT_A1D_ELEM(subFeatures,i)=round(rnd_unif(0,NFeatures-1)); #endif } // Container for the new training sample std::vector< MultidimArray<double> > newFeatures; // Produce the data set for each class for (int k=0; k<K; k++) { int NIndividuals=YSIZE(features[k]); int NsubIndividuals=CEIL(NIndividuals*samplingIndividuals); MultidimArray<int> subIndividuals(NsubIndividuals); FOR_ALL_ELEMENTS_IN_ARRAY1D(subIndividuals) subIndividuals(i)=ROUND(rnd_unif(0,NsubIndividuals-1)); MultidimArray<double> newFeaturesK; newFeaturesK.initZeros(NsubIndividuals,NsubFeatures); const MultidimArray<double>& features_k=features[k]; FOR_ALL_ELEMENTS_IN_ARRAY2D(newFeaturesK) DIRECT_A2D_ELEM(newFeaturesK,i,j)=DIRECT_A2D_ELEM(features_k, DIRECT_A1D_ELEM(subIndividuals,i), DIRECT_A1D_ELEM(subFeatures,j)); newFeatures.push_back(newFeaturesK); } // Create a Naive Bayes classifier with this data NaiveBayes *nb=new NaiveBayes(newFeatures, priorProbs, discreteLevels); ensemble.push_back(nb); ensembleFeatures.push_back(subFeatures); } }
// Split several histograms within the indexes l0 and lF so that // the entropy after division is maximized int splitHistogramsUsingEntropy(const std::vector<Histogram1D> &hist, size_t l0, size_t lF) { // Number of classes int K = hist.size(); // Set everything outside l0 and lF to zero, and make it a PDF std::vector<Histogram1D> histNorm; for (int k = 0; k < K; k++) { Histogram1D histaux = hist[k]; for (size_t l = 0; l < XSIZE(histaux); l++) if (l < l0 || l > lF) DIRECT_A1D_ELEM(histaux,l) = 0; histaux *= 1.0/histaux.sum(); histNorm.push_back(histaux); } // Compute for each class the probability of being l<=l0 and l>l0 MultidimArray<double> p(K, 2); for (int k = 0; k < K; k++) { const Histogram1D& histogram=histNorm[k]; DIRECT_A2D_ELEM(p,k, 0) = DIRECT_A1D_ELEM(histogram,l0); DIRECT_A2D_ELEM(p,k, 1) = 0; for (size_t l = l0 + 1; l <= lF; l++) DIRECT_A2D_ELEM(p,k, 1) += DIRECT_A1D_ELEM(histogram,l); } // Compute the splitting l giving maximum entropy double maxEntropy = 0; int lmaxEntropy = -1; size_t l = l0; while (l < lF) { // Compute the entropy of the classes if we split by l double entropy = 0; FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(p) { double aux=DIRECT_MULTIDIM_ELEM(p,n); if (aux != 0) entropy -= aux * log10(aux); } #ifdef DEBUG_SPLITTING_USING_ENTROPY std::cout << "Splitting at " << l << " entropy=" << entropy << std::endl; #endif // Check if this is the maximum if (entropy > maxEntropy) { maxEntropy = entropy; lmaxEntropy = l; } // Move to next split point ++l; // Update probabilities of being l<=l0 and l>l0 for (int k = 0; k < K; k++) { const Histogram1D& histogram=histNorm[k]; double aux=DIRECT_A1D_ELEM(histogram,l); DIRECT_A2D_ELEM(p,k, 0) += aux; DIRECT_A2D_ELEM(p,k, 1) -= aux; } } #ifdef DEBUG_SPLITTING_USING_ENTROPY std::cout << "Finally in l=[" << l0 << "," << lF << " Max Entropy:" << maxEntropy << " lmax=" << lmaxEntropy << std::endl; #endif // If the point giving the maximum entropy is too much on the extreme, // substitute it by the middle point if (lmaxEntropy<=2 || lmaxEntropy>=(int)lF-2) lmaxEntropy = (int)ceil((lF + l0)/2.0); return lmaxEntropy; }
void ProgXrayImport::run() { // Delete output stack if it exists fnOut = fnRoot + ".mrc"; fnOut.deleteFile(); /* Turn off error handling */ H5Eset_auto(H5E_DEFAULT, NULL, NULL); if (dSource == MISTRAL) H5File.openFile(fnInput, H5F_ACC_RDONLY); // Reading bad pixels mask if ( !fnBPMask.empty() ) { std::cerr << "Reading bad pixels mask from "+fnBPMask << "." << std::endl; bpMask.read(fnBPMask); if ( (cropSizeX + cropSizeY ) > 0 ) bpMask().selfWindow(cropSizeY,cropSizeX, (int)(YSIZE(bpMask())-cropSizeY-1),(int)(XSIZE(bpMask())-cropSizeX-1)); STARTINGX(bpMask()) = STARTINGY(bpMask()) = 0; } // Setting the image projections list switch (dSource) { case MISTRAL: { inMD.read(fnInput); H5File.getDataset("NXtomo/data/rotation_angle", anglesArray, false); H5File.getDataset("NXtomo/instrument/sample/ExpTimes", expTimeArray, false); H5File.getDataset("NXtomo/instrument/sample/current", cBeamArray); /* In case there is no angles information we set them to to an increasing sequence * just to be able to continue importing data */ if ( anglesArray.size() != inMD.size() ) { reportWarning("Input file does not contains angle information. Default sequence used."); anglesArray.resizeNoCopy(inMD.size()); anglesArray.enumerate(); } // If expTime is empty or only one single value in nexus file then we fill with 1 if (expTimeArray.size() < 2) { reportWarning("Input file does not contains tomogram exposition time information."); expTimeArray.initConstant(anglesArray.size(), 1.); } // If current is empty or only one single value in nexus file then we fill with 1 if (cBeamArray.size() < 2) { reportWarning("Input file does not contains tomogram current beam information."); cBeamArray.initConstant(anglesArray.size(), 1.); } // Since Alba does not provide slit width, we set to ones slitWidthArray.initConstant(anglesArray.size(), 1.); } break; case BESSY: { size_t objId; for (size_t i = tIni; i <= tEnd; ++i) { objId = inMD.addObject(); inMD.setValue(MDL_IMAGE, fnInput + formatString("/img%d.spe", i), objId); } break; } case GENERIC: { // Get Darkfield std::cerr << "Getting darkfield from "+fnInput << " ..." << std::endl; getDarkfield(fnInput, IavgDark); if (XSIZE(IavgDark())!=0) IavgDark.write(fnRoot+"_darkfield.xmp"); std::vector<FileName> listDir; fnInput.getFiles(listDir); size_t objId; for (size_t i = 0; i < listDir.size(); ++i) { if (!listDir[i].hasImageExtension()) continue; objId = inMD.addObject(); inMD.setValue(MDL_IMAGE, fnInput+"/"+listDir[i], objId); } } break; } inMD.findObjects(objIds); size_t nIm = inMD.size(); // Create empty output stack file getImageInfo(inMD, imgInfo); /* Get the flatfield:: We get the FF after the image list because we need the image size to adapt the FF * in case they were already cropped. */ if (!fnFlat.empty()) { std::cout << "Getting flatfield from "+fnFlat << " ..." << std::endl; getFlatfield(fnFlat,IavgFlat); if ( XSIZE(IavgFlat()) != 0 ) { FileName ffName = fnRoot+"_flatfield_avg.xmp"; IavgFlat.write(ffName); fMD.setValue(MDL_IMAGE, ffName, fMD.addObject()); } } createEmptyFile(fnOut, imgInfo.adim.xdim-cropSizeXi-cropSizeXe, imgInfo.adim.ydim-cropSizeYi-cropSizeYe, 1, nIm); // Process images td = new ThreadTaskDistributor(nIm, XMIPP_MAX(1, nIm/30)); tm = new ThreadManager(thrNum, this); std::cerr << "Getting data from " << fnInput << " ...\n"; init_progress_bar(nIm); tm->run(runThread); progress_bar(nIm); // Write Metadata and angles MetaData MDSorted; MDSorted.sort(outMD,MDL_ANGLE_TILT); MDSorted.write("tomo@"+fnRoot + ".xmd"); if ( fMD.size() > 0 ) fMD.write("flatfield@"+fnRoot + ".xmd", MD_APPEND); // We also reference initial and final images at 0 degrees for Mistral tomograms if ( dSource == MISTRAL ) { fMD.clear(); FileName degree0Fn = "NXtomo/instrument/sample/0_degrees_initial_image"; if ( H5File.checkDataset(degree0Fn.c_str())) fMD.setValue(MDL_IMAGE, degree0Fn + "@" + fnInput, fMD.addObject()); degree0Fn = "NXtomo/instrument/sample/0_degrees_final_image"; if ( H5File.checkDataset(degree0Fn.c_str())) fMD.setValue(MDL_IMAGE, degree0Fn + "@" + fnInput, fMD.addObject()); if ( fMD.size() > 0 ) fMD.write("degree0@"+fnRoot + ".xmd", MD_APPEND); } // Write tlt file for IMOD std::ofstream fhTlt; fhTlt.open((fnRoot+".tlt").c_str()); if (!fhTlt) REPORT_ERROR(ERR_IO_NOWRITE,fnRoot+".tlt"); FOR_ALL_OBJECTS_IN_METADATA(MDSorted) { double tilt; MDSorted.getValue(MDL_ANGLE_TILT,tilt,__iter.objId); fhTlt << tilt << std::endl; } fhTlt.close(); delete td; delete tm; }
void runThread(ThreadArgument &thArg) { int thread_id = thArg.thread_id; ProgXrayImport * ptrProg= (ProgXrayImport *)thArg.workClass; MetaData localMD; Image<double> Iaux; FileName fnImgIn, fnImgOut; size_t first = 0, last = 0; MultidimArray<char> mask; while (ptrProg->td->getTasks(first, last)) { for (size_t i=first; i<=last; i++) { ptrProg->inMD.getValue(MDL_IMAGE, fnImgIn, ptrProg->objIds[i]); MDRow rowGeo; ptrProg->readGeoInfo(fnImgIn, rowGeo); // ptrProg->readAndCrop(fnImgIn, Iaux, ptrProg->cropSizeX, ptrProg->cropSizeY); Iaux.read(fnImgIn); Iaux().selfWindow(ptrProg->cropSizeYi,ptrProg->cropSizeXi, (int)(YSIZE(Iaux())-ptrProg->cropSizeYe-1),(int)(XSIZE(Iaux())-ptrProg->cropSizeXe-1)); Iaux().resetOrigin(); if (XSIZE(ptrProg->IavgDark())!=0) { Iaux()-=ptrProg->IavgDark(); forcePositive(Iaux()); } double currentBeam = 1; double expTime = 1; double slitWidth = 1; if ( ptrProg->dSource == ptrProg->MISTRAL ) { size_t idx = fnImgIn.getPrefixNumber(); currentBeam = dMi(ptrProg->cBeamArray, idx-1); expTime = dMi(ptrProg->expTimeArray, idx-1); slitWidth = dMi(ptrProg->slitWidthArray, idx-1); } else ptrProg->readCorrectionInfo(fnImgIn, currentBeam, expTime, slitWidth); Iaux() *= 1.0/(currentBeam*expTime*slitWidth); if (XSIZE(ptrProg->IavgFlat())!=0) Iaux()/=ptrProg->IavgFlat(); // Assign median filter to zero valued pixels to avoid -inf when applying log10 Iaux().equal(0,mask); mask.resizeNoCopy(Iaux()); if (XSIZE(ptrProg->bpMask()) != 0) mask += ptrProg->bpMask(); boundMedianFilter(Iaux(), mask); if (ptrProg->logFix) { Iaux().selfLog(); if (ptrProg->selfAttFix) Iaux() *= -1.; } fnImgOut.compose(i+1, ptrProg->fnOut); size_t objId = localMD.addObject(); localMD.setValue(MDL_IMAGE,fnImgOut,objId); localMD.setRow(rowGeo, objId); // // localMD.setValue(MDL_ANGLE_TILT,Iaux.tilt(),objId); Iaux.write(fnImgOut); if (thread_id==0) progress_bar(i); } } //Lock for update the total counter ptrProg->mutex.lock(); ptrProg->outMD.unionAll(localMD); ptrProg->mutex.unlock(); }
void ProgAngularProjectLibrary::project_angle_vector (int my_init, int my_end, bool verbose) { Projection P; FileName fn_proj; double rot,tilt,psi; int mySize; int numberStepsPsi = 1; mySize=my_end-my_init+1; if (psi_sampling < 360) { numberStepsPsi = (int) (359.99999/psi_sampling); mySize *= numberStepsPsi; } if (verbose) init_progress_bar(mySize); int myCounter=0; for (double mypsi=0;mypsi<360;mypsi += psi_sampling) for (int i=0;i<my_init;i++) myCounter++; // if (shears && XSIZE(inputVol())!=0 && VShears==NULL) // VShears=new RealShearsInfo(inputVol()); if (projType == SHEARS && XSIZE(inputVol())!=0 && Vshears==NULL) Vshears=new RealShearsInfo(inputVol()); if (projType == FOURIER && XSIZE(inputVol())!=0 && Vfourier==NULL) Vfourier=new FourierProjector(inputVol(), paddFactor, maxFrequency, BSplineDeg); for (double mypsi=0;mypsi<360;mypsi += psi_sampling) { for (int i=my_init;i<=my_end;i++) { if (verbose) progress_bar(i-my_init); psi= mypsi+ZZ(mysampling.no_redundant_sampling_points_angles[i]); tilt= YY(mysampling.no_redundant_sampling_points_angles[i]); rot= XX(mysampling.no_redundant_sampling_points_angles[i]); // if (shears) // projectVolume(*VShears, P, Ydim, Xdim, rot,tilt,psi); // else // projectVolume(inputVol(), P, Ydim, Xdim, rot,tilt,psi); if (projType == SHEARS) projectVolume(*Vshears, P, Ydim, Xdim, rot, tilt, psi); else if (projType == FOURIER) projectVolume(*Vfourier, P, Ydim, Xdim, rot, tilt, psi); else if (projType == REALSPACE) projectVolume(inputVol(), P, Ydim, Xdim, rot, tilt, psi); P.setEulerAngles(rot,tilt,psi); P.setDataMode(_DATA_ALL); P.write(output_file,(size_t) (numberStepsPsi * i + mypsi +1),true,WRITE_REPLACE); } } if (verbose) progress_bar(mySize); }
//#define DEBUG void normalize_tomography(MultidimArray<double> &I, double tilt, double &mui, double &sigmai, bool tiltMask, bool tomography0, double mu0, double sigma0) { // Tilt series are always 2D I.checkDimension(2); const int L=2; // Build a mask using the tilt angle I.setXmippOrigin(); MultidimArray<int> mask; mask.initZeros(I); int Xdimtilt=(int)XMIPP_MIN(FLOOR(0.5*(XSIZE(I)*cos(DEG2RAD(tilt)))), 0.5*(XSIZE(I)-(2*L+1))); int N=0; for (int i=STARTINGY(I); i<=FINISHINGY(I); i++) for (int j=-Xdimtilt; j<=Xdimtilt;j++) { A2D_ELEM(mask,i,j)=1; N++; } // Estimate the local variance MultidimArray<double> localVariance; localVariance.initZeros(I); double meanVariance=0; FOR_ALL_ELEMENTS_IN_ARRAY2D(I) { // Center a mask of size 5x5 and estimate the variance within the mask double meanPiece=0, variancePiece=0; double Npiece=0; for (int ii=i-L; ii<=i+L; ii++) { if (INSIDEY(I,ii)) for (int jj=j-L; jj<=j+L; jj++) { if (INSIDEX(I,jj)) { double pixval=A2D_ELEM(I,ii,jj); meanPiece+=pixval; variancePiece+=pixval*pixval; ++Npiece; } } } meanPiece/=Npiece; variancePiece=variancePiece/(Npiece-1)- Npiece/(Npiece-1)*meanPiece*meanPiece; A2D_ELEM(localVariance,i,j)=variancePiece; meanVariance+=variancePiece; } meanVariance*=1.0/N; // Test the hypothesis that the variance in this piece is // the same as the variance in the whole image double iFu=1/icdf_FSnedecor(4*L*L+4*L,N-1,0.975); double iFl=1/icdf_FSnedecor(4*L*L+4*L,N-1,0.025); double iMeanVariance=1.0/meanVariance; FOR_ALL_ELEMENTS_IN_ARRAY2D(localVariance) { if (A2D_ELEM(localVariance,i,j)==0) A2D_ELEM(mask,i,j)=-2; if (A2D_ELEM(mask,i,j)==1) { double ratio=A2D_ELEM(localVariance,i,j)*iMeanVariance; double thl=ratio*iFu; double thu=ratio*iFl; if (thl>1 || thu<1) A2D_ELEM(mask,i,j)=-1; } } #ifdef DEBUG Image<double> save; save()=I; save.write("PPP.xmp"); save()=localVariance; save.write("PPPLocalVariance.xmp"); Image<int> savemask; savemask()=mask; savemask.write("PPPmask.xmp"); #endif // Compute the statistics again in the reduced mask double avg, stddev, min, max; computeStats_within_binary_mask(mask, I, min, max, avg, stddev); double cosTilt=cos(DEG2RAD(tilt)); double iCosTilt=1.0/cosTilt; if (tomography0) { double iadjustedStddev=1.0/(sigma0*cosTilt); FOR_ALL_ELEMENTS_IN_ARRAY2D(I) switch (A2D_ELEM(mask,i,j)) { case -2: A2D_ELEM(I,i,j)=0; break; case 0: if (tiltMask) A2D_ELEM(I,i,j)=0; else A2D_ELEM(I,i,j)=(A2D_ELEM(I,i,j)*iCosTilt-mu0)*iadjustedStddev; break; case -1: case 1: A2D_ELEM(I,i,j)=(A2D_ELEM(I,i,j)*iCosTilt-mu0)*iadjustedStddev; break; } } else {
/* Run --------------------------------------------------------------------- */ void ProgAngularProjectLibrary::run() { ///////////////////////////// // PreRun for all nodes but not for all works ///////////////////////////// //only rank 0 mysampling.verbose=verbose; show(); //all ranks mysampling.setSampling(sampling); srand ( time(NULL) ); //process the symmetry file //only checks symmetry and set pg_order and pg_group, no memory allocation if (!mysampling.SL.isSymmetryGroup(fn_sym, symmetry, sym_order)) REPORT_ERROR(ERR_VALUE_INCORRECT, (std::string)"Invalid symmetry" + fn_sym); if(perturb_projection_vector!=0) { int my_seed; my_seed=rand(); // set noise deviation and seed mysampling.setNoise(perturb_projection_vector,my_seed); } if(angular_distance_bool!=0) mysampling.setNeighborhoodRadius(angular_distance);//irrelevant //true -> half_sphere mysampling.computeSamplingPoints(false,max_tilt_angle,min_tilt_angle); //only rank 0 //mysampling.createSymFile(fn_sym,symmetry, sym_order); //all nodes mysampling.SL.readSymmetryFile(fn_sym); //store symmetry matrices, this is faster than computing them each time mysampling.fillLRRepository(); //mpi_barrier here //all working nodes must read symmetry file //and experimental docfile if apropiate //symmetry_file = symmetry + ".sym"; //SL.readSymmetryFile(symmetry_file) // We first sample The whole sphere // Then we remove point redundant due to sampling symmetry // use old symmetry, this is geometric does not use L_R mysampling.removeRedundantPoints(symmetry, sym_order); //========================= //====================== //recompute symmetry with neigh symmetry // If uncomment neighbour are not OK. BE CAREFULL #define BREAKSIMMETRY #ifdef BREAKSIMMETRY if (!mysampling.SL.isSymmetryGroup(fn_sym_neigh, symmetry, sym_order)) REPORT_ERROR(ERR_VALUE_INCORRECT, (std::string)"Invalid neig symmetry" + fn_sym_neigh); mysampling.SL.readSymmetryFile(fn_sym_neigh); mysampling.fillLRRepository(); #endif #undef BREAKSIMMETRY //precompute product between symmetry matrices and experimental data if (FnexperimentalImages.size() > 0) mysampling.fillExpDataProjectionDirectionByLR(FnexperimentalImages); //remove points not close to experimental points, only for no symmetric cases if (FnexperimentalImages.size() > 0 && remove_points_far_away_from_experimental_data_bool) { // here we remove points no close to experimental data, neight symmetry must be use mysampling.removePointsFarAwayFromExperimentalData(); } if(compute_closer_sampling_point_bool) { //find sampling point closer to experimental point (only 0) and bool //and save docfile with this information // use neight symmetry mysampling.findClosestSamplingPoint(FnexperimentalImages,output_file_root); } //only rank 0 //write docfile with vectors and angles mysampling.createAsymUnitFile(output_file_root); //all nodes //If there is no reference available exit try { inputVol.read(input_volume); } catch (XmippError XE) { std::cout << XE; exit(0); } inputVol().setXmippOrigin(); Xdim = XSIZE(inputVol()); Ydim = YSIZE(inputVol()); if (compute_neighbors_bool) { // new symmetry mysampling.computeNeighbors(only_winner); mysampling.saveSamplingFile(output_file_root,false); } //release some memory mysampling.exp_data_projection_direction_by_L_R.clear(); unlink(output_file.c_str()); //mpi master should divide doc in chuncks //in this serial program there is a unique chunck //angle information is in //mysampling.no_redundant_sampling_points_vector[i] //Run for all works project_angle_vector(0, mysampling.no_redundant_sampling_points_angles.size()-1,verbose); //only rank 0 create sel file MetaData mySFin, mySFout; FileName fn_temp; mySFin.read(output_file_root+"_angles.doc"); size_t myCounter=0; size_t id; int ref; for (double mypsi=0;mypsi<360;mypsi += psi_sampling) { FOR_ALL_OBJECTS_IN_METADATA(mySFin) { double x,y,z, rot, tilt, psi; mySFin.getValue(MDL_ANGLE_ROT,rot,__iter.objId); mySFin.getValue(MDL_ANGLE_TILT,tilt,__iter.objId); mySFin.getValue(MDL_ANGLE_PSI,psi,__iter.objId); mySFin.getValue(MDL_X,x,__iter.objId); mySFin.getValue(MDL_Y,y,__iter.objId); mySFin.getValue(MDL_Z,z,__iter.objId); mySFin.getValue(MDL_REF,ref,__iter.objId); fn_temp.compose( ++myCounter,output_file); id = mySFout.addObject(); mySFout.setValue(MDL_IMAGE,fn_temp,id); mySFout.setValue(MDL_ENABLED,1,id); mySFout.setValue(MDL_ANGLE_ROT,rot,id); mySFout.setValue(MDL_ANGLE_TILT,tilt,id); mySFout.setValue(MDL_ANGLE_PSI,psi+mypsi,id); mySFout.setValue(MDL_X,x,id); mySFout.setValue(MDL_Y,y,id); mySFout.setValue(MDL_Z,z,id); mySFout.setValue(MDL_SCALE,1.0,id); mySFout.setValue(MDL_REF,ref,id); } } mySFout.setComment("x,y,z refer to the coordinates of the unitary vector at direction given by the euler angles"); mySFout.write(output_file_root+".doc"); unlink((output_file_root+"_angles.doc").c_str()); if (fn_groups!="") createGroupSamplingFiles(); }
void FourierProjector::project(double rot, double tilt, double psi) { double freqy, freqx; std::complex< double > f; Euler_angles2matrix(rot,tilt,psi,E); projectionFourier.initZeros(); double shift=-FIRST_XMIPP_INDEX(volumeSize); double xxshift = -2 * PI * shift / volumeSize; double maxFreq2=maxFrequency*maxFrequency; double volumePaddedSize=XSIZE(VfourierRealCoefs); for (size_t i=0; i<YSIZE(projectionFourier); ++i) { FFT_IDX2DIGFREQ(i,volumeSize,freqy); double freqy2=freqy*freqy; double phasey=(double)(i) * xxshift; double freqYvol_X=MAT_ELEM(E,1,0)*freqy; double freqYvol_Y=MAT_ELEM(E,1,1)*freqy; double freqYvol_Z=MAT_ELEM(E,1,2)*freqy; for (size_t j=0; j<XSIZE(projectionFourier); ++j) { // The frequency of pairs (i,j) in 2D FFT_IDX2DIGFREQ(j,volumeSize,freqx); // Do not consider pixels with high frequency if ((freqy2+freqx*freqx)>maxFreq2) continue; // Compute corresponding frequency in the volume double freqvol_X=freqYvol_X+MAT_ELEM(E,0,0)*freqx; double freqvol_Y=freqYvol_Y+MAT_ELEM(E,0,1)*freqx; double freqvol_Z=freqYvol_Z+MAT_ELEM(E,0,2)*freqx; double c,d; if (BSplineDeg==0) { // 0 order interpolation // Compute corresponding index in the volume int kVolume=(int)round(freqvol_Z*volumePaddedSize); int iVolume=(int)round(freqvol_Y*volumePaddedSize); int jVolume=(int)round(freqvol_X*volumePaddedSize); c = A3D_ELEM(VfourierRealCoefs,kVolume,iVolume,jVolume); d = A3D_ELEM(VfourierImagCoefs,kVolume,iVolume,jVolume); } else if (BSplineDeg==1) { // B-spline linear interpolation double kVolume=freqvol_Z*volumePaddedSize; double iVolume=freqvol_Y*volumePaddedSize; double jVolume=freqvol_X*volumePaddedSize; c=VfourierRealCoefs.interpolatedElement3D(jVolume,iVolume,kVolume); d=VfourierImagCoefs.interpolatedElement3D(jVolume,iVolume,kVolume); } else { // B-spline cubic interpolation double kVolume=freqvol_Z*volumePaddedSize; double iVolume=freqvol_Y*volumePaddedSize; double jVolume=freqvol_X*volumePaddedSize; c=VfourierRealCoefs.interpolatedElementBSpline3D(jVolume,iVolume,kVolume); d=VfourierImagCoefs.interpolatedElementBSpline3D(jVolume,iVolume,kVolume); } // Phase shift to move the origin of the image to the corner double dotp = (double)(j) * xxshift + phasey; double a,b; sincos(dotp,&b,&a); // Multiply Fourier coefficient in volume times phase shift double ac = a * c; double bd = b * d; double ab_cd = (a + b) * (c + d); // And store the multiplication double *ptrI_ij=(double *)&DIRECT_A2D_ELEM(projectionFourier,i,j); *ptrI_ij = ac - bd; *(ptrI_ij+1) = ab_cd - ac - bd; } } //VfourierRealCoefs.clear(); //VfourierImagCoefs.clear(); transformer2D.inverseFourierTransform(); }