extern void rayparticipate( /* compute ray medium participation */ RAY *r ) { COLOR ce, ca; double re, ge, be; if (intens(r->cext) <= 1./FHUGE) return; /* no medium */ re = r->rot*colval(r->cext,RED); ge = r->rot*colval(r->cext,GRN); be = r->rot*colval(r->cext,BLU); if (r->crtype & SHADOW) { /* no scattering for sources */ re *= 1. - colval(r->albedo,RED); ge *= 1. - colval(r->albedo,GRN); be *= 1. - colval(r->albedo,BLU); } setcolor(ce, re<=FTINY ? 1. : re>92. ? 0. : exp(-re), ge<=FTINY ? 1. : ge>92. ? 0. : exp(-ge), be<=FTINY ? 1. : be>92. ? 0. : exp(-be)); multcolor(r->rcol, ce); /* path extinction */ if (r->crtype & SHADOW || intens(r->albedo) <= FTINY) return; /* no scattering */ setcolor(ca, colval(r->albedo,RED)*colval(ambval,RED)*(1.-colval(ce,RED)), colval(r->albedo,GRN)*colval(ambval,GRN)*(1.-colval(ce,GRN)), colval(r->albedo,BLU)*colval(ambval,BLU)*(1.-colval(ce,BLU))); addcolor(r->rcol, ca); /* ambient in scattering */ srcscatter(r); /* source in scattering */ }
static AMBHEMI * samp_hemi( /* sample indirect hemisphere */ COLOR rcol, RAY *r, double wt ) { AMBHEMI *hp; double d; int n, i, j; /* insignificance check */ if (bright(rcol) <= FTINY) return(NULL); /* set number of divisions */ if (ambacc <= FTINY && wt > (d = 0.8*intens(rcol)*r->rweight/(ambdiv*minweight))) wt = d; /* avoid ray termination */ n = sqrt(ambdiv * wt) + 0.5; i = 1 + 5*(ambacc > FTINY); /* minimum number of samples */ if (n < i) n = i; /* allocate sampling array */ hp = (AMBHEMI *)malloc(sizeof(AMBHEMI) + sizeof(AMBSAMP)*(n*n - 1)); if (hp == NULL) error(SYSTEM, "out of memory in samp_hemi"); hp->rp = r; hp->ns = n; hp->acol[RED] = hp->acol[GRN] = hp->acol[BLU] = 0.0; memset(hp->sa, 0, sizeof(AMBSAMP)*n*n); hp->sampOK = 0; /* assign coefficient */ copycolor(hp->acoef, rcol); d = 1.0/(n*n); scalecolor(hp->acoef, d); /* make tangent plane axes */ if (!getperpendicular(hp->ux, r->ron, 1)) error(CONSISTENCY, "bad ray direction in samp_hemi"); VCROSS(hp->uy, r->ron, hp->ux); /* sample divisions */ for (i = hp->ns; i--; ) for (j = hp->ns; j--; ) hp->sampOK += ambsample(hp, i, j, 0); copycolor(rcol, hp->acol); if (!hp->sampOK) { /* utter failure? */ free(hp); return(NULL); } if (hp->sampOK < hp->ns*hp->ns) { hp->sampOK *= -1; /* soft failure */ return(hp); } if (hp->sampOK < 64) return(hp); /* insufficient for super-sampling */ n = ambssamp*wt + 0.5; if (n > 8) { /* perform super-sampling? */ ambsupersamp(hp, n); copycolor(rcol, hp->acol); } return(hp); /* all is well */ }
extern void direct( /* add direct component */ RAY *r, /* ray that hit surface */ srcdirf_t *f, /* direct component coefficient function */ void *p /* data for f */ ) { register int sn; register CONTRIB *scp; SRCINDEX si; int nshadcheck, ncnts; int nhits; double prob, ourthresh, hwt; RAY sr; /* NOTE: srccnt and cntord global so no recursion */ if (nsources <= 0) return; /* no sources?! */ /* potential contributions */ initsrcindex(&si); for (sn = 0; srcray(&sr, r, &si); sn++) { if (sn >= maxcntr) { maxcntr = sn + MAXSPART; srccnt = (CONTRIB *)realloc((void *)srccnt, maxcntr*sizeof(CONTRIB)); cntord = (CNTPTR *)realloc((void *)cntord, maxcntr*sizeof(CNTPTR)); if ((srccnt == NULL) | (cntord == NULL)) error(SYSTEM, "out of memory in direct"); } cntord[sn].sndx = sn; scp = srccnt + sn; scp->sno = sr.rsrc; /* compute coefficient */ (*f)(scp->coef, p, sr.rdir, si.dom); cntord[sn].brt = intens(scp->coef); if (cntord[sn].brt <= 0.0) continue; #if SHADCACHE /* check shadow cache */ if (si.np == 1 && srcblocked(&sr)) { cntord[sn].brt = 0.0; continue; } #endif VCOPY(scp->dir, sr.rdir); copycolor(sr.rcoef, scp->coef); /* compute potential */ sr.revf = srcvalue; rayvalue(&sr); multcolor(sr.rcol, sr.rcoef); copycolor(scp->val, sr.rcol); cntord[sn].brt = bright(sr.rcol); } /* sort contributions */ qsort(cntord, sn, sizeof(CNTPTR), cntcmp); { /* find last */ register int l, m; ncnts = l = sn; sn = 0; while ((m = (sn + ncnts) >> 1) != l) { if (cntord[m].brt > 0.0) sn = m; else ncnts = m; l = m; } } if (ncnts == 0) return; /* no contributions! */ /* accumulate tail */ for (sn = ncnts-1; sn > 0; sn--) cntord[sn-1].brt += cntord[sn].brt; /* compute number to check */ nshadcheck = pow((double)ncnts, shadcert) + .5; /* modify threshold */ ourthresh = shadthresh / r->rweight; /* test for shadows */ for (nhits = 0, hwt = 0.0, sn = 0; sn < ncnts; hwt += (double)source[scp->sno].nhits / (double)source[scp->sno].ntests, sn++) { /* check threshold */ if ((sn+nshadcheck>=ncnts ? cntord[sn].brt : cntord[sn].brt-cntord[sn+nshadcheck].brt) < ourthresh*bright(r->rcol)) break; scp = srccnt + cntord[sn].sndx; /* test for hit */ rayorigin(&sr, SHADOW, r, NULL); copycolor(sr.rcoef, scp->coef); VCOPY(sr.rdir, scp->dir); sr.rsrc = scp->sno; /* keep statistics */ if (source[scp->sno].ntests++ > 0xfffffff0) { source[scp->sno].ntests >>= 1; source[scp->sno].nhits >>= 1; } if (localhit(&sr, &thescene) && ( sr.ro != source[scp->sno].so || source[scp->sno].sflags & SFOLLOW )) { /* follow entire path */ raycont(&sr); if (trace != NULL) (*trace)(&sr); /* trace execution */ if (bright(sr.rcol) <= FTINY) { #if SHADCACHE if ((scp <= srccnt || scp[-1].sno != scp->sno) && (scp >= srccnt+ncnts-1 || scp[1].sno != scp->sno)) srcblocker(&sr); #endif continue; /* missed! */ } rayparticipate(&sr); multcolor(sr.rcol, sr.rcoef); copycolor(scp->val, sr.rcol); } else if (trace != NULL && (source[scp->sno].sflags & (SDISTANT|SVIRTUAL|SFOLLOW)) == (SDISTANT|SFOLLOW) && sourcehit(&sr) && rayshade(&sr, sr.ro->omod)) { (*trace)(&sr); /* trace execution */ /* skip call to rayparticipate() & scp->val update */ } /* add contribution if hit */ addcolor(r->rcol, scp->val); nhits++; source[scp->sno].nhits++; }
FoMo::RenderCube CGAL2D(FoMo::GoftCube goftcube, const double l, const int x_pixel, const int y_pixel, const int lambda_pixel, const double lambda_width) { // // results is an array of at least dimension (x2-x1+1)*(y2-y1+1)*lambda_pixel and must be initialized to zero // // determine contributions per pixel typedef K::FT Coord_type; typedef K::Point_2 Point; std::map<Point, Coord_type, K::Less_xy_2> peakmap, fwhmmap, losvelmap; // typedef CGAL::Data_access< std::map<Point, Coord_type, K::Less_xyz_3 > > Value_access; int commrank; #ifdef HAVEMPI MPI_Comm_rank(MPI_COMM_WORLD,&commrank); #else commrank = 0; #endif //FoMo::DataCube goftcube=object.datacube; FoMo::tgrid grid = goftcube.readgrid(); int ng=goftcube.readngrid(); // We will calculate the maximum image coordinates by projecting the grid onto the image plane // Rotate the grid over an angle -l (around z-axis), and -b (around y-axis) // Take the min and max of the resulting coordinates, those are coordinates in the image plane if (commrank==0) std::cout << "Rotating coordinates to POS reference... " << std::flush; std::vector<double> xacc, yacc, zacc; xacc.resize(ng); yacc.resize(ng); zacc.resize(ng); std::vector<double> gridpoint; gridpoint.resize(3); Point temporarygridpoint; // Define the unit vector along the line-of-sight: the LOS is along y std::vector<double> unit = {cos(l), sin(l)}; // Read the physical variables FoMo::tphysvar peakvec=goftcube.readvar(0);//Peak intensity FoMo::tphysvar fwhmvec=goftcube.readvar(1);// line width, =1 for AIA imaging FoMo::tphysvar vx=goftcube.readvar(2); FoMo::tphysvar vy=goftcube.readvar(3); double losvelval; // No openmp possible here // Because of the insertions at the end of the loop, we get segfaults :( /*#ifdef _OPENMP #pragma omp parallel for #endif*/ for (int i=0; i<ng; i++) { for (int j=0; j<2; j++) gridpoint[j]=grid[j][i]; xacc[i]=gridpoint[0]*cos(l)-gridpoint[1]*sin(l);// rotated grid yacc[i]=gridpoint[0]*sin(l)+gridpoint[1]*cos(l); temporarygridpoint=Point(grid[0][i],grid[1][i]); //position vector // also create the map function_values here std::vector<double> velvec = {vx[i], vy[i]};// velocity vector losvelval = inner_product(unit.begin(),unit.end(),velvec.begin(),0.0);//velocity along line of sight for position [i]/[ng] losvelmap[temporarygridpoint]=Coord_type(losvelval); peakmap[temporarygridpoint]=Coord_type(peakvec[i]); fwhmmap[temporarygridpoint]=Coord_type(fwhmvec[i]); /* peakmap.insert(make_pair(temporarygridpoint,Coord_type(peakvec[i]))); fwhmmap.insert(make_pair(temporarygridpoint,Coord_type(fwhmvec[i]))); losvelmap.insert(make_pair(temporarygridpoint,Coord_type(losvelval)));*/ } double minx=*(min_element(xacc.begin(),xacc.end())); double maxx=*(max_element(xacc.begin(),xacc.end())); double miny=*(min_element(yacc.begin(),yacc.end())); double maxy=*(max_element(yacc.begin(),yacc.end())); /* Value_access peak=Value_access(peakmap); Value_access fwhm=Value_access(fwhmmap); Value_access losvel=Value_access(losvelmap);*/ xacc.clear(); // release the memory yacc.clear(); if (commrank==0) std::cout << "Done!" << std::endl; std::string chiantifile=goftcube.readchiantifile(); double lambda0=goftcube.readlambda0();// lambda0=AIA bandpass for AIA imaging double lambda_width_in_A=lambda_width*lambda0/speedoflight; Delaunay_triangulation_2 DT=triangulationfrom2Ddatacube(goftcube); Delaunay_triangulation_2 * DTpointer=&DT; if (commrank==0) std::cout << "Building frame: " << std::flush; double x,y,z,intpolpeak,intpolfwhm,intpollosvel,lambdaval,tempintens; int li,lj,ind; Point p,nearest; Delaunay_triangulation_2::Vertex_handle v; Delaunay_triangulation_2::Locate_type lt; Delaunay_triangulation_2::Face_handle c; boost::progress_display show_progress(x_pixel*y_pixel); //initialize grids FoMo::tgrid newgrid; FoMo::tcoord xvec(x_pixel*lambda_pixel),yvec(x_pixel*lambda_pixel),lambdavec(x_pixel*lambda_pixel); newgrid.push_back(xvec); if (lambda_pixel > 1) newgrid.push_back(lambdavec); FoMo::tphysvar intens(x_pixel*lambda_pixel,0); #ifdef _OPENMP #pragma omp parallel for schedule(dynamic) private (x,y,p,lt,li,v,nearest,intpolpeak,intpolfwhm,intpollosvel,lambdaval,tempintens,ind) #endif for (int j=0; j<x_pixel; j++) { #ifdef _OPENMP #pragma omp task #endif for (int i=0; i<y_pixel; i++) // scanning through ccd { x = double(j)/(x_pixel-1)*(maxx-minx)+minx; y = double(i)/(y_pixel-1)*(maxy-miny)+miny; // calculate the interpolation in the original frame of reference // i.e. derotate the point using angles -l and -b p= {x*cos(l)+y*sin(l),-x*sin(l)+y*cos(l)}; c=DTpointer->locate(p,lt,li); // Only look for the nearest point and interpolate, if the point p is inside the convex hull. if (lt!=Delaunay_triangulation_2::OUTSIDE_CONVEX_HULL) { // is this a critical operation? v=DTpointer->nearest_vertex(p,c); nearest=v->point(); /* This is how it is done in the CGAL examples pair<Coord_type,bool> tmppeak=peak(nearest); pair<Coord_type,bool> tmpfwhm=fwhm(nearest); pair<Coord_type,bool> tmplosvel=losvel(nearest); intpolpeak=tmppeak.first; intpolfwhm=tmpfwhm.first; intpollosvel=tmplosvel.first;*/ intpolpeak=peakmap[nearest]; intpolfwhm=fwhmmap[nearest]; intpollosvel=losvelmap[nearest]; } else { intpolpeak=0; } if (lambda_pixel>1)// spectroscopic study { for (int il=0; il<lambda_pixel; il++) // changed index from global variable l into il [D.Y. 17 Nov 2014] { // lambda is made around lambda0, with a width of lambda_width lambdaval=double(il)/(lambda_pixel-1)*lambda_width_in_A-lambda_width_in_A/2.; tempintens=intpolpeak*exp(-pow(lambdaval-intpollosvel/speedoflight*lambda0,2)/pow(intpolfwhm,2)*4.*log(2.)); ind=j*lambda_pixel+il;// newgrid[0][ind]=x; newgrid[2][ind]=lambdaval+lambda0; // this is critical, but with tasks, the ind is unique for each task, and no collision should occur intens[ind]+=tempintens;// loop over z and lambda [D.Y 17 Nov 2014] } } if (lambda_pixel==1) // AIA imaging study. Algorithm not verified [DY 14 Nov 2014] { tempintens=intpolpeak; ind=j; newgrid[0][ind]=x; intens[ind]+=tempintens; // loop over z [D.Y 17 Nov 2014] } // print progress ++show_progress; } } if (commrank==0) std::cout << " Done! " << std::endl << std::flush; FoMo::RenderCube rendercube(goftcube); FoMo::tvars newdata; double pathlength=(maxy-miny)/(y_pixel-1); intens=FoMo::operator*(pathlength*1e8,intens); // assume that the coordinates are given in Mm, and convert to cm newdata.push_back(intens); rendercube.setdata(newgrid,newdata); rendercube.setrendermethod("CGAL2D"); rendercube.setresolution(x_pixel,y_pixel,1,lambda_pixel,lambda_width); if (lambda_pixel == 1) { rendercube.setobservationtype(FoMo::Imaging); } else { rendercube.setobservationtype(FoMo::Spectroscopic); } return rendercube; }
void PeakList::filterWeakPeaks(const Config* config, mass_t pmWith19, int peakDensity, bool removeGloballyWeak) { if (numPeaks_<10) return; const mass_t maxMassToConsider = 10.0 + (pmWith19 > peaks_[numPeaks_-1].mass ? pmWith19 : peaks_[numPeaks_-1].mass); const mass_t windowSize = 0.5 * config->get_local_window_size(); const int numPeaksInWindow = (peakDensity>0 ? peakDensity : config->get_max_number_peaks_per_local_window()); const mass_t tolerance = config->getTolerance(); vector<bool> keep_peaks(numPeaks_, false); vector<Peak> new_peaks; int maximalPeakIndex = numPeaks_ -1; // keep first peak and last peak keep_peaks[0]=true; if (peaks_[maximalPeakIndex].mass<maxMassToConsider) keep_peaks[maximalPeakIndex]=true; int min_idx=1; int max_idx=1; // check the rest of the peaks int i; for (i=1; i<maximalPeakIndex; i++) { mass_t peak_mass=peaks_[i].mass; mass_t min_mass=peaks_[min_idx].mass; mass_t max_mass=peaks_[max_idx].mass; if (peaks_[i].mass > maxMassToConsider) break; // advance min/max pointers while (peak_mass-min_mass > windowSize) min_mass=peaks_[++min_idx].mass; while (max_idx < maximalPeakIndex && max_mass - peak_mass <= windowSize) max_mass=peaks_[++max_idx].mass; if (max_mass - peak_mass > windowSize) max_idx--; // this peak might already be marked for keeping (isotpoic peak) if (keep_peaks[i]) continue; // if there are less than the maximum number of peaks in the window, keep it. if (max_idx-min_idx < numPeaksInWindow) { keep_peaks[i]=true; continue; } // check if this is one of the top peaks in the window int higher_count=0; for (int j=min_idx; j<=max_idx; j++) if (peaks_[j].intensity > peaks_[i].intensity) higher_count++; if (higher_count < numPeaksInWindow) { keep_peaks[i]=true; } } if (pmWith19>0) { // look for b/y pairs // mass_t pm_with_20 = (originalPmWith19_>0 ? correctedPmWith19_ : originalPmWith19_) + // MASS_PROTON ; mass_t pm_with_20 = pmWith19 + MASS_PROTON; mass_t pm_with_20_upper = pm_with_20 + tolerance; mass_t pm_with_20_lower = pm_with_20 - tolerance; int f_idx =0; int b_idx = numPeaks_-1; while (f_idx<numPeaks_ && b_idx>=0) { if (! keep_peaks[f_idx]) { f_idx++; continue; } while (b_idx>=0 && peaks_[f_idx].mass + peaks_[b_idx].mass > pm_with_20_upper ) b_idx--; if (b_idx<0) break; mass_t mass_sum = peaks_[f_idx].mass + peaks_[b_idx].mass; if (mass_sum > pm_with_20_lower && mass_sum < pm_with_20_upper) { keep_peaks[f_idx]=true; keep_peaks[b_idx]=true; } f_idx++; } } // copy peaks int j=0; for (size_t i=0; i<numPeaks_; i++) if (keep_peaks[i] && peaks_[i].intensity>=0.001) peaks_[j++]=peaks_[i]; numPeaks_ = j; // filter very low intensity peaks (without a window) if (removeGloballyWeak) { vector<intensity_t> intens(numPeaks_); for (size_t i=0; i<numPeaks_; i++) intens[i]=peaks_[i].intensity; sort(intens.begin(), intens.end()); j=1; const intensity_t minIntensity = intens[(2*numPeaks_)/3] * 0.001; for (size_t i=1; i<numPeaks_; i++) if (peaks_[i].intensity > minIntensity) peaks_[j++]=peaks_[i]; numPeaks_ = j; } }
extern int rayorigin( /* start new ray from old one */ RAY *r, int rt, const RAY *ro, const COLOR rc ) { double rw, re; /* assign coefficient/weight */ if (rc == NULL) { rw = 1.0; setcolor(r->rcoef, 1., 1., 1.); } else { rw = intens(rc); if (rc != r->rcoef) copycolor(r->rcoef, rc); } if ((r->parent = ro) == NULL) { /* primary ray */ r->rlvl = 0; r->rweight = rw; r->crtype = r->rtype = rt; r->rsrc = -1; r->clipset = NULL; r->revf = raytrace; copycolor(r->cext, cextinction); copycolor(r->albedo, salbedo); r->gecc = seccg; r->slights = NULL; } else { /* spawned ray */ if (ro->rot >= FHUGE) { memset(r, 0, sizeof(RAY)); return(-1); /* illegal continuation */ } r->rlvl = ro->rlvl; if (rt & RAYREFL) { r->rlvl++; r->rsrc = -1; r->clipset = ro->clipset; r->rmax = 0.0; } else { r->rsrc = ro->rsrc; r->clipset = ro->newcset; r->rmax = ro->rmax <= FTINY ? 0.0 : ro->rmax - ro->rot; } r->revf = ro->revf; copycolor(r->cext, ro->cext); copycolor(r->albedo, ro->albedo); r->gecc = ro->gecc; r->slights = ro->slights; r->crtype = ro->crtype | (r->rtype = rt); VCOPY(r->rorg, ro->rop); r->rweight = ro->rweight * rw; /* estimate extinction */ re = colval(ro->cext,RED) < colval(ro->cext,GRN) ? colval(ro->cext,RED) : colval(ro->cext,GRN); if (colval(ro->cext,BLU) < re) re = colval(ro->cext,BLU); re *= ro->rot; if (re > 0.1) { if (re > 92.) { r->rweight = 0.0; } else { r->rweight *= exp(-re); } } } rayclear(r); if (r->rweight <= 0.0) /* check for expiration */ return(-1); if (r->crtype & SHADOW) /* shadow commitment */ return(0); if (maxdepth <= 0 && rc != NULL) { /* Russian roulette */ if (minweight <= 0.0) error(USER, "zero ray weight in Russian roulette"); if (maxdepth < 0 && r->rlvl > -maxdepth) return(-1); /* upper reflection limit */ if (r->rweight >= minweight) return(0); if (frandom() > r->rweight/minweight) return(-1); rw = minweight/r->rweight; /* promote survivor */ scalecolor(r->rcoef, rw); r->rweight = minweight; return(0); } return(r->rweight >= minweight && r->rlvl <= abs(maxdepth) ? 0 : -1); }