shared_ptr< BaseObject > BaseObject::findHitBy(const Vector& origin, const Vector &direction) const { GLdouble prev_dist = 0.0; GLdouble next_dist; GLdouble check_dist; shared_ptr< BaseObject > next; shared_ptr< BaseObject > check; const shared_ptr< BaseObject > cur = findNear(origin); if (!cur) return cur; while (!cur->isHitByRay(origin, direction)) { check = cur->left; if (check) { check_dist = check->position.distance(origin); if (check_dist > prev_dist) { next.swap(check); next_dist = check_dist; } } check = cur->right; if (check) { check_dist = check->position.distance(origin); if (check_dist > prev_dist && check_dist < next_dist) next.reset(); } } return cur; }
SP_spectrum _SP_addSpectra(SP_spectrum* spectra,size_t nbsp,double width,double clip,double prc,int error_type,double rebin_pixfactor,double rebin_pixshift,int spline,int tclip,int keepnbsp,char* file,size_t line) { VC_vector group,factors; double* work,fct; double* tmp; double *dw,*df,*ds; double fact1,fact2; double *wmin,*wmax; VC_vector wlim,wave; SP_spectrum rslt; VC_vector eflux,esigm,emask; VC_vector flx1,flx2,wav1,pds1,pds2; long *npix; double y1,y2; double tmin, tmax,tcen,wpas,old_wpas; double w1min,w1max,w2min,w2max; long k1min,k1max,k2min,k2max; long imin,imax,jmin,jmax; long *idmin,*idmax; long *kmin,*kmax; long nbgroup,igroup,nbcol; long i,j; size_t si,sj,k,ngood; size_t npix_max,npix_tot; int pourc,old_pourc; double fsum,wsum,weight,sigm_srianand,mean_srianand; long nbg_srianand; long nbg_bastien; double a1,b1; SP_spectrum* spline_spectra; if(nbsp<2) return NULL; /****************************/ /* Sort and group by setup */ /****************************/ SP_sortSpectrum(spectra,nbsp); OS_message(0,OS_STD,"[SP_addSpectra] new order for spectra :\n"); for(i=0;i<nbsp;i++) { OS_message(0,OS_STD,"[SP_addSpectra] %4d : %s\n",i+1,spectra[i]->name); } group=SP_groupSpectrum(spectra,nbsp,prc); if(!group) { OS_message(0,OS_ERR,"not enough memory !!\n"); exit(1); } nbgroup=1+group->ldata[nbsp-1]; OS_message(0,OS_STD,"[SP_addSpectra] found %d group%s\n",nbgroup,(nbgroup>1)?"s":" "); npix_max=0; /*will contain the number of pixel of the biggest spectrum*/ for(si=0;si<nbsp;si++) npix_max=(spectra[si]->npix>npix_max)?spectra[si]->npix:npix_max; MMV_malloc(tmp,npix_max,double); /*working buffer*/ MMV_malloc(idmin,nbsp,long); MMV_malloc(idmax,nbsp,long); MMV_malloc( kmin,nbsp,long); MMV_malloc( kmax,nbsp,long); MMV_malloc( wmin,nbsp,double); MMV_malloc( wmax,nbsp,double); for(i=0;i<nbsp;i++) { /**********************************************************/ /*Find first and last pixel that not have null flux values*/ /*sort the corresponding wavelength in wmin and wmax and */ /*the pixel index in idmin and idmax. */ /**********************************************************/ VC_getIdxEdge(spectra[i]->data[spectra[i]->colF],idmin+i,idmax+i); wmin[i]=spectra[i]->wave[idmin[i]]; wmax[i]=spectra[i]->wave[idmax[i]-1]; kmin[i]=kmax[i]=-1; } for(i=0;i<nbgroup;i++) { k=0; for(j=0;j<nbsp;j++) if(group->ldata[j]==i) k++; OS_message(0,OS_STD,"[SP_addSpectra] group #%-2d : %d spectr%s\n",i+1,k,(k>1)?"a":"um"); } /************************************************/ /*Compute scale factors by group and apply them */ /************************************************/ imax=imin=igroup=0; while(imax<nbsp) { imax=imin; while((imax<nbsp)&&(group->ldata[imax]==igroup)) ++imax; // printf("igroup: %2ld imin: %2ld imax: %2ld\n",igroup,imin,imax); factors=addiScaleFactors(spectra+imin,imax-imin,width,NULL); for(i=0,si=imin;si<imax;i++,si++) for(sj=0;sj<spectra[si]->npix;sj++) { spectra[si]->flux[sj]*=factors->ddata[i]; spectra[si]->sigm[sj]*=factors->ddata[i]; } VC_free(factors); imin=imax; igroup++; } /*************/ /* Find edge */ /*************/ /****************************************/ /* Compute merge factors and apply them */ /****************************************/ /* Two steps for the computation. */ /* First find scale factor for the edges */ /* Then rebin each edges and compute their */ /* ratio. Fit the ratio by a line and take */ /* max of 1 and the line value for correction */ if(nbgroup>1) { OS_message(0,OS_STD,"[SP_addSpectra] Compute factor for the merging\n"); MMV_malloc(work,nbsp,double); imin=igroup=0; while(igroup<nbgroup-1) { imax=imin; while((imax<nbsp)&&(group->ldata[imax]==igroup)) imax++; // printf("igroup: %2ld imin: %2ld imax: %2ld\n",igroup,imin,imax); ++igroup; if(imax==nbsp) { OS_message(0,OS_ERR,"[SP_addSpectra] BUG at line %d of file %s\n",__LINE__,__FILE__); exit(1); } jmin=imax; jmax=jmin; while((jmax<nbsp)&&(group->ldata[jmax]==igroup)) jmax++; //printf("igroup: %2ld jmin: %2ld jmax: %2ld\n",igroup,jmin,jmax); w1min=wmin[imin]; w1max=wmax[imin]; for(si=imin+1;si<imax;si++) { w1min=(w1min<wmin[si])?w1min:wmin[si]; w1max=(w1max>wmax[si])?w1max:wmax[si]; } w2min=wmin[jmin]; w2max=wmax[jmin]; for(sj=jmin+1;sj<jmax;sj++) { w2min=(w2min<wmin[sj])?w2min:wmin[sj]; w2max=(w2max>wmax[sj])?w2max:wmax[sj]; } tmin=(w1min>w2min)?w1min:w2min; tmax=(w1max<w2max)?w1max:w2max; if(tmin>=tmax) /* no overlap*/ { w1min=w1max-width/10.; w2max=w2min+width/10.; } else { w1min=w2min=tmin; w1max=w2max=tmax; } for(si=imin;si<imax;si++) { k1min=findNear(spectra[si]->data[spectra[si]->colW],w1min); k1max=findNear(spectra[si]->data[spectra[si]->colW],w1max)+1; for(i=0,j=k1min;j<k1max;j++,i++) tmp[i]=spectra[si]->flux[j]; work[si]=median(tmp,k1max-k1min); } for(sj=jmin;sj<jmax;sj++) { k2min=findNear(spectra[sj]->data[spectra[sj]->colW],w2min); k2max=findNear(spectra[sj]->data[spectra[sj]->colW],w2max)+1; for(i=0,j=k2min;j<k2max;j++,i++) tmp[i]=spectra[sj]->flux[j]; work[sj]=median(tmp,k2max-k2min); } fact1=median(work+imin,imax-imin); fact2=median(work+jmin,jmax-jmin); if(fact1<=0) fact1=1; if(fact2<=0) fact2=1; /* Factor are computed. Now rebin edges*/ /* imin->imax index of spectra in group 1 */ /* jmin->jmax index of spectra in group 2 */ /* Compute flx1 and flx2 */ if(tmin>=tmax) { fact1/=fact2; OS_message(0,OS_STD,"[SP_addSpectra] Factor for merging for group #%d : %f\n",1+igroup,fact1); for(sj=jmin;sj<jmax;sj++) for(j=0;j<spectra[sj]->npix;j++) { spectra[sj]->flux[j]*=fact1; spectra[sj]->sigm[j]*=fact1; } } else { /*First crude addition of the edge 2*/ k1min=findNear(spectra[imin]->data[spectra[imin]->colW],w1min); k1max=findNear(spectra[imin]->data[spectra[imin]->colW],w1max)+1; // printf("%d %d\n",k1min,k1max); VCV_allocate(flx1,k1max-k1min,VCTDOUBLE); VCV_allocate(wav1,k1max-k1min,VCTDOUBLE); VCV_allocate(flx2,k1max-k1min,VCTDOUBLE); VCV_allocate(pds1,k1max-k1min,VCTDOUBLE); VCV_allocate(pds2,k1max-k1min,VCTDOUBLE); // printf("flx1 %x \n",flx1); // printf("flx2 %x \n",flx2); // printf("wav1 %x \n",wav1); for(i=k1min,j=0;i<k1max;i++,j++) { wav1->ddata[j]=spectra[imin]->wave[i]; flx1->ddata[j]=0.; pds1->ddata[j]=0.; flx2->ddata[j]=0.; pds2->ddata[j]=0.; } for(si=imin;si<imax;si++) { k2min=k2max=-1; dw=spectra[si]->wave+idmin[si]; df=spectra[si]->flux+idmin[si]; ds=spectra[si]->sigm+idmin[si]; for(i=k1min,j=0;i<k1max;i++,j++) { if(j==0) tmin=0.5*(3*wav1->ddata[0]-wav1->ddata[1]); else tmin=0.5*(wav1->ddata[j-1]+wav1->ddata[j]); if(j==(wav1->size-1)) tmax=0.5*(3*wav1->ddata[j]-wav1->ddata[j-1]); else tmax=0.5*(wav1->ddata[j+1]+wav1->ddata[j]); rebinLocal(df,ds,dw,idmax[si]-idmin[si], tmin,tmax,&k2min,&k2max, &fsum,&wsum); if(wsum<=0) continue; weight=fsum/wsum; weight*=weight; pds1->ddata[j]+=weight; flx1->ddata[j]+=weight*fsum; } } for(sj=jmin;sj<jmax;sj++) { k2min=k2max=-1; dw=spectra[sj]->wave+idmin[sj]; df=spectra[sj]->flux+idmin[sj]; ds=spectra[sj]->sigm+idmin[sj]; for(i=k1min,j=0;i<k1max;i++,j++) { if(j==0) tmin=0.5*(3*wav1->ddata[0]-wav1->ddata[1]); else tmin=0.5*(wav1->ddata[j-1]+wav1->ddata[j]); if(j==(wav1->size-1)) tmax=0.5*(3*wav1->ddata[j]-wav1->ddata[j-1]); else tmax=0.5*(wav1->ddata[j+1]+wav1->ddata[j]); rebinLocal(df,ds,dw,idmax[sj]-idmin[sj], tmin,tmax,&k2min,&k2max, &fsum,&wsum); if(wsum<=0) continue; weight=fsum/wsum; weight*=weight; pds2->ddata[j]+=weight; flx2->ddata[j]+=weight*fsum; } } ngood=0; for(j=0;j<wav1->size;j++) { if((!pds1->ddata[j])||(!pds2->ddata[j])) continue; y1=flx1->ddata[j]/(fact1*pds1->ddata[j]); y2=flx2->ddata[j]/(fact2*pds2->ddata[j]); if((y1<0.2)||(y2<0.2)) continue; flx1->ddata[ngood]=y1/y2; wav1->ddata[ngood]=wav1->ddata[j]; ngood++; } if(ngood) fitLineIter(flx1->ddata,wav1->ddata,ngood,&a1,&b1); else { a1=0; b1=1; } wpas=0.1/(wav1->ddata[1]-wav1->ddata[0]); fact1/=fact2; /* apply correction */ for(sj=jmin;sj<jmax;sj++) for(j=0;j<spectra[sj]->npix;j++) { wsum=spectra[sj]->wave[j]; weight=(fact1*(a1*wsum+b1)*expFilter(wsum,w1max,-wpas))+ (fact1*(a1*w1max+b1)*expFilter(wsum,w1max,wpas)); spectra[sj]->flux[j]*=weight; spectra[sj]->sigm[j]*=weight; } VC_free(pds2); VC_free(pds1); VC_free(flx1); VC_free(flx2); VC_free(wav1); } imin=jmin; } MM_free(work); } /**************************/ /* Compute the wave range */ /**************************/ OS_message(0,OS_STD,"[SP_addSpectra] Compute wavelength range\n"); /*****************************************/ /* merge all the wave limits and compute */ /* average pixel size for each group */ /*****************************************/ VCV_allocate(wlim,2*nbgroup,VCTDOUBLE); imin=igroup=0; while(imin<nbsp) { imax=imin; tmin=wmin[imin]; tmax=wmax[imin]; while((imax<nbsp)&&(group->ldata[imax]==igroup)) { tmin=(tmin<wmin[imax])?tmin:wmin[imax]; tmax=(tmax>wmax[imax])?tmax:wmax[imax]; imax++; } wlim->ddata[ 2*igroup]=tmin; wlim->ddata[1+2*igroup]=tmax; imin=imax; igroup++; } VC_hpsort(wlim); /* Compute pixel size */ MMV_malloc(npix,(2*nbgroup-1),long); wpas=0; for(i=0;i<2*nbgroup-1;i++) { k=0; npix[i]=0; tcen=0.5*(wlim->ddata[i]+wlim->ddata[i+1]); old_wpas=wpas; wpas=0; for(j=0;j<nbsp;j++) { if((tcen>=wmax[j])||(tcen<=wmin[j])) continue; k++; wpas+=(wmax[j]-wmin[j])/(float)(idmax[j]-idmin[j]); } // printf("chunck %2ld k: %2ld swpas: %f rap:%f\n",i,k,wpas,(k>0)?(wpas/(double)k):0); if(k) wpas/=(double)k; else if(!i) { OS_message(0,OS_ERR,"Bug at %s line %d !!!\n",__FILE__,__LINE__); exit(1); } else wpas=old_wpas; wpas*=rebin_pixfactor; npix[i]=(long)((wlim->ddata[i+1]-wlim->ddata[i])/wpas+0.5); if(!npix[i]) { OS_message(0,OS_ERR,"Bug at %s line %d !!!\n",__FILE__,__LINE__); exit(1); } } npix_tot=0; for(i=0;i<2*nbgroup-1;i++) npix_tot+=npix[i]-1; npix_tot++; /* Fill the final wave array */ VCV_allocate(wave,npix_tot,VCTDOUBLE); k=0; for(i=0;i<2*nbgroup-1;i++) { wpas=(wlim->ddata[i+1]-wlim->ddata[i])/(double)(npix[i]); for(j=0;j<npix[i]-1;j++) wave->ddata[k++]=wlim->ddata[i]+((float)j+rebin_pixshift)*wpas; } wave->ddata[k++]=wlim->ddata[2*nbgroup-1]+rebin_pixshift*wpas; /* display some information */ OS_message(0,OS_STD,"\n[SP_mergeSpectra] New wavelength range (%d chunks) \n",2*nbgroup-1); for(i=0;i<2*nbgroup-1;i++) OS_message(0,OS_STD,"[SP_mergeSpectra] chunks #%-2d : %10.2f %10.2f %9.4f\n", i+1,wlim->ddata[i],wlim->ddata[i+1], (wlim->ddata[i+1]-wlim->ddata[i])/(double)npix[i]); // for(i=0;i<nbsp;i++) printf("i:%2d wmin:%f wmax:%f\n",(int)i,wmin[i],wmax[i]); MM_free( npix); VC_free( wlim); MM_free(wmin); MM_free(wmax); /**********************************/ /* if spline is set rebin spectra */ /* with cubic spline */ /**********************************/ if(spline) { OS_message(0,OS_STD,"[SP_mergeSpectra] Doing spline rebinning : \n"); MMV_malloc(spline_spectra,nbsp,SP_spectrum); if(!spline_spectra) { OS_message(0,OS_ERR,"not enough memory !!\n"); MM_free( kmax); MM_free( kmin); MM_free(idmax); MM_free(idmin); MM_free( tmp); return NULL; } for(i=0;i<nbsp;i++) { tmin=spectra[i]->wave[idmin[i]]; tmax=spectra[i]->wave[idmax[i]-1]; if(wave->ddata[0]>tmin) imin=0; else while((imin<wave->size)&&(wave->ddata[imin]<tmin)) ++imin; imax=imin; while((imax<wave->size)&&(wave->ddata[imax]<tmax)) ++imax; spline_spectra[i]=SP_allocate(imax-imin,3); if(!spline_spectra[i]) { OS_message(0,OS_ERR,"not enough memory !!\n"); MM_free(spline_spectra); MM_free( kmax); MM_free( kmin); MM_free(idmax); MM_free(idmin); MM_free( tmp); return NULL; } /*Copy Wavelength array*/ for(k=0,j=imin;j<imax;j++,k++) spline_spectra[i]->wave[k]=wave->ddata[j]; /*********************************/ /* do the cubic spline estimation*/ /* for the flux */ NRspline(spectra[i]->wave,spectra[i]->flux,spectra[i]->npix,1e30,1e30,tmp); NRasplint(spectra[i]->wave,spectra[i]->flux,tmp,spectra[i]->npix, spline_spectra[i]->wave,spline_spectra[i]->flux,spline_spectra[i]->npix); /* for the error */ /* (strange, maybe to fix latter)*/ NRspline(spectra[i]->wave,spectra[i]->sigm,spectra[i]->npix,1e30,1e30,tmp); NRasplint(spectra[i]->wave,spectra[i]->sigm,tmp,spectra[i]->npix, spline_spectra[i]->wave,spline_spectra[i]->sigm,spline_spectra[i]->npix); /* Rebin Done */ /* Put index instead of wavelenght */ for(k=0,j=imin;j<imax;j++,k++) spline_spectra[i]->wave[k]=j; /*********************************/ /*Old spectra[i] useless, set it to spline_spectra[i] */ SP_free(spectra[i]); spectra[i]=spline_spectra[i]; } } /***************************************/ /* Allocate memory for output spectrum */ /***************************************/ nbcol=3; if(keepnbsp) ++nbcol; if(error_type==_BOTH_ERRORS_) ++nbcol; rslt=_SP_allocate(wave->size,nbcol,file,line); if(!rslt) { OS_message(0,OS_ERR,"not enough memory !!\n"); MM_free( kmax); MM_free( kmin); MM_free(idmax); MM_free(idmin); MM_free( tmp); return NULL; } VC_free(rslt->data[rslt->colW]); rslt->data[rslt->colW]=wave; /*******************/ /* Do the addition */ /*******************/ VCV_allocate(eflux,nbsp,VCTDOUBLE); VCV_allocate(esigm,nbsp,VCTDOUBLE); VCV_allocate(emask,nbsp,VCTDOUBLE); OS_message(0,OS_STD,"\n[SP_addSpectra] Do the addition : 0%%"); old_pourc=pourc=0; for(j=0;j<rslt->npix;j++) { pourc=(int)(j*100/(rslt->npix-1)); if(pourc>old_pourc) { old_pourc=pourc; OS_message(0,OS_STD,"\b\b\b\b%3ld%%",pourc); OS_flush(); } if(spline) { ngood=0; for(i=0;i<nbsp;i++) { eflux->ddata[ngood]=esigm->ddata[ngood]=0.; dw=spectra[i]->wave; df=spectra[i]->flux; ds=spectra[i]->sigm; if(getSplineInter(df,ds,dw,spectra[i]->npix,j,kmin+i, eflux->ddata+ngood,esigm->ddata+ngood)) continue; emask->ddata[ngood]=1.; ++ngood; } } else { if(j==0) tmin=0.5*(3*wave->ddata[0]-wave->ddata[1]); else tmin=0.5*(wave->ddata[j-1]+wave->ddata[j]); if(j==(rslt->npix-1)) tmax=0.5*(3*wave->ddata[rslt->npix-1]-wave->ddata[rslt->npix-2]); else tmax=0.5*( wave->ddata[j+1]+ wave->ddata[j]); ngood=0; for(i=0;i<nbsp;i++) { eflux->ddata[ngood]=esigm->ddata[ngood]=0.; dw=spectra[i]->wave+idmin[i]; df=spectra[i]->flux+idmin[i]; ds=spectra[i]->sigm+idmin[i]; if(rebinLocal(df,ds,dw,idmax[i]-idmin[i], tmin,tmax,kmin+i,kmax+i, eflux->ddata+ngood,esigm->ddata+ngood)) continue; emask->ddata[ngood]=1.; ++ngood; } } /* if((tmin>5156)&&(tmax<5158)) */ /* printf("tmin:%f tmax:%f ngood: %d\n",tmin,tmax,ngood); */ mean_srianand=sigm_srianand=fsum=wsum=0.0; nbg_srianand=nbg_bastien=0; if(ngood) { eflux->size=ngood; esigm->size=ngood; emask->size=ngood; if(tclip==_DATACLIPPING_) dataClipping(eflux,esigm,&emask,clip); else if (tclip!=_NOCLIPPING_) sigmaClipping(eflux,&emask,clip,0); for(i=0;i<ngood;i++) { if(emask->ddata[i]) { weight=esigm->ddata[i]; mean_srianand+=eflux->ddata[i]; sigm_srianand+=eflux->ddata[i]*eflux->ddata[i]; ++nbg_srianand; if(weight<=0) continue; ++nbg_bastien; weight=1./(weight*weight); wsum+=weight; fsum+=eflux->ddata[i]*weight; } } } if(nbg_srianand>0) { /* mean_srianand*=mean_srianand; */ /* mean_srianand/=(double)(nbg_srianand); /\* n.<X>^2 *\/ */ /* sigm_srianand-=mean_srianand; // n<X^2>-n<X>^2 */ /* sigm_srianand/=(double)(nbg_srianand); //(n/n-1)(<X^2>-<X>^2) */ mean_srianand/=(double)(nbg_srianand); mean_srianand*=mean_srianand; sigm_srianand/=(double)(nbg_srianand); sigm_srianand=(sigm_srianand-mean_srianand)/(double)(nbg_srianand); } else sigm_srianand=0.; if(wsum>0) { wsum=1./wsum; fsum*=wsum; switch (error_type) { case _BOTH_ERRORS_ : case _BASTIEN_ : { wsum=sqrt(wsum); sigm_srianand=sqrt(sigm_srianand); } break; case _SRIANAND_ : wsum=sqrt(sigm_srianand); break; case _BASTIEN_AND_SRIANAND_ : wsum=sqrt(wsum+sigm_srianand); break; case _MAX_BASTIEN_AND_SRIANAND_ : wsum=sqrt((sigm_srianand>wsum)?sigm_srianand:wsum); break; case _MAX_BASTIEN_AND_MAX_SRIANAND_ : if(nbg_srianand>1) fct=(1+sqrt(2./(nbg_srianand-1))); else fct=1.; wsum=sqrt((sigm_srianand>wsum)?sigm_srianand*fct:wsum); break; default : wsum=sqrt((sigm_srianand>wsum)?sigm_srianand:wsum); } } else fsum=wsum=0; if((!IS_NAN(fsum))&&(!IS_NAN(wsum))) { rslt->flux[j]=fsum; rslt->sigm[j]=wsum; } if((error_type==_BOTH_ERRORS_)&&(!IS_NAN(sigm_srianand))) rslt->cont[j]=sigm_srianand; if(keepnbsp) rslt->data[rslt->ndata-1]->ddata[j]=nbg_bastien; eflux->size=nbsp; esigm->size=nbsp; emask->size=nbsp; } OS_message(0,OS_STD,"\b\b\b\b%3ld%%\n",100); VC_free(emask); VC_free(esigm); VC_free(eflux); MM_free( kmin); MM_free( kmax); MM_free(idmin); MM_free(idmax); MM_free(tmp); return rslt; }
VC_vector _mergeScaleFactors(SP_spectrum* spectra,size_t nbsp,long width,VC_vector* vout,char* file,size_t line) { size_t i,j,k,sz,msz,swork,i1,i2; double *df1,*dw1,*df2,*dw2,*work; VC_vector rslt,idmin,idmax,sidx; size_t spref,r1min,r1max,r2min,r2max; double med1,med2; double wmin1,wmax1,wmin2,wmax2,wmin,wmax; rslt =_VC_allocate(nbsp,VCTDOUBLE,file,line); for(i=0;i<rslt->size;i++) rslt->ddata[i]=1; if(nbsp>1) { idmin =VC_allocate(nbsp,VCTLONG); idmax =VC_allocate(nbsp,VCTLONG); sidx =VC_allocate(nbsp,VCTLONG); if(rslt) { /************************/ /* Create working space */ /************************/ msz=0; for(i=0;i<nbsp;i++) { sz=spectra[i]->npix; if(sz>msz) msz=sz; } work=(double*)MM_malloc(msz*sizeof(double)); swork=0; /****************************************/ /*First find the limits of each spectrum*/ /****************************************/ for(i=0;i<nbsp;i++) { VC_getIdxEdge(spectra[i]->data[spectra[i]->colF],idmin->ldata+i,idmax->ldata+i); if(idmin->ldata[i]>=idmax->ldata[i]) { OS_message(0,OS_ERR,"[mergeScaleFactors] No data in spectrum #%ld\n",i); exit(1); } sidx->ldata[i]=i; //initialise sort array } /****************************************/ /*Sort spectra in increasing wavelength */ /****************************************/ OS_message(0,OS_STD,"[mergeScaleFactors] Sort spectra in increasing wavelength\n"); for(i=0;i<nbsp-1;i++) for(j=i+1;j<nbsp;j++) { i1=sidx->ldata[i]; i2=sidx->ldata[j]; if((spectra[i1]->data[spectra[i1]->colW]->ddata[idmin->ldata[i1]]) <= (spectra[i2]->data[spectra[i2]->colW]->ddata[idmin->ldata[i2]])) continue; sidx->ldata[i]=i2; sidx->ldata[j]=i1; } spref=sidx->ldata[0]; OS_message(0,OS_STD,"[mergeScaleFactors] ------------------------------------------\n"); OS_message(0,OS_STD,"[mergeScaleFactors] Use spectrum #%d as reference\n",spref+1); rslt->ddata[spref]=1.; OS_message(0,OS_STD,"[mergeScaleFactors]\n"); OS_message(0,OS_STD,"[mergeScaleFactors] Compute scale factors for each spectrum \n"); for(i=1;i<nbsp;i++) { i1=sidx->ldata[i-1]; i2=sidx->ldata[ i]; dw1=spectra[i1]->data[spectra[i1]->colW]->ddata; df1=spectra[i1]->data[spectra[i1]->colF]->ddata; dw2=spectra[i2]->data[spectra[i2]->colW]->ddata; df2=spectra[i2]->data[spectra[i2]->colF]->ddata; /************************/ /* Find overlap regions */ /************************/ wmin1=dw1[idmin->ldata[i1]]; wmax1=dw1[idmax->ldata[i1]-1]; wmin2=dw2[idmin->ldata[i2]]; wmax2=dw2[idmax->ldata[i2]-1]; wmin=(wmin1>wmin2)?wmin1:wmin2; wmax=(wmax1<wmax2)?wmax1:wmax2; /***************************/ /* Get index of the limits */ /* of the overlap */ /***************************/ if(wmin>=wmax) { r1max=idmax->ldata[i1]; r1min=r1max-10*width; r2min=idmin->ldata[i2]; r2max=r2min+10*width; } else { r1min=findNear(spectra[i1]->data[spectra[i1]->colW],wmin); r1max=findNear(spectra[i1]->data[spectra[i1]->colW],wmax); r2min=findNear(spectra[i2]->data[spectra[i2]->colW],wmin); r2max=findNear(spectra[i2]->data[spectra[i2]->colW],wmax); r1max++; r2max++; } /**********************/ /* Compute median for */ /* the overlap */ /**********************/ for(j=0,k=r1min;k<r1max;j++,k++) work[j]=df1[k]; med1=median(work,r1max-r1min); for(j=0,k=r2min;k<r2max;j++,k++) work[j]=df2[k]; med2=median(work,r2max-r2min); if((med1>0)&&(med2>0)) rslt->ddata[i2]=med1/med2*rslt->ddata[i1]; OS_message(0,OS_STD,"[mergeScaleFactors] Factor for spectrum #%2d : %f\n",i+1,rslt->ddata[i]); } MM_free(work); } VC_free(sidx); VC_free(idmax); VC_free(idmin); } if(vout) *vout=rslt; return rslt; }
VC_vector _addiScaleFactors(SP_spectrum* spectra,size_t nbsp,double width,VC_vector* vout,char* file,size_t line) { int done; size_t i,j,k,l,sz,msz,swork; double *df; double *dw; double *work; VC_vector rslt,idmin,idmax,lwave,fctrs; size_t spref,nbchunk,cmin,cmax,rmin,rmax; double medref,aux; double wmin,wmax; double chkmin,chkmax; rslt =_VC_allocate(nbsp,VCTDOUBLE,file,line); VCV_allocate(idmin,nbsp,VCTLONG); VCV_allocate(idmax,nbsp,VCTLONG); /* printf("%d\n",(long)idmin); */ if(rslt) { /*************************/ /* Create working space */ /*************************/ msz=0; for(i=0;i<nbsp;i++) { sz=spectra[i]->npix; if(sz>msz) msz=sz; } MMV_malloc(work,msz,double); swork=0; /****************************************/ /*First find the limits of each spectrum*/ /****************************************/ for(i=0;i<nbsp;i++) { VC_getIdxEdge(spectra[i]->data[spectra[i]->colF],idmin->ldata+i,idmax->ldata+i); if(idmin->ldata[i]>=idmax->ldata[i]) { OS_message(0,OS_ERR,"[addiScaleFactors] No data in spectrum #%ld\n",i); exit(1); } } /*********************************************/ /*Find the spectrum with the greatest median */ /*********************************************/ OS_message(0,OS_STD,"[addiScaleFactors] Search for spectra with the greatest median\n"); spref=0; medref=1; for(i=0;i<nbsp;i++) { sz=spectra[i]->npix; df=spectra[i]->data[spectra[i]->colF]->ddata; for(j=idmin->ldata[i],k=0;j<idmax->ldata[i];j++,k++) work[k]=df[j]; swork=idmax->ldata[i]-idmin->ldata[i]; aux=median(work,swork); OS_message(0,OS_STD,"[addiScaleFactors] #%2d : %f\n",i+1,aux); if((0==i)||(aux>medref)) { medref=aux; spref=i; } } OS_message(0,OS_STD,"[addiScaleFactors] ------------------------------------------\n"); OS_message(0,OS_STD,"[addiScaleFactors] Use spectrum #%d as reference\n",spref+1); wmin=spectra[spref]->data[spectra[spref]->colW]->ddata[idmin->ldata[spref]]; wmax=spectra[spref]->data[spectra[spref]->colW]->ddata[idmax->ldata[spref]-1]; nbchunk=(size_t)((wmax-wmin)/width); nbchunk=(nbchunk<1)?1:nbchunk; VCV_allocate(fctrs,nbchunk,VCTDOUBLE); lwave=VC_span(wmin,wmax,nbchunk+1); OS_message(0,OS_STD,"[addiScaleFactors]\n"); OS_message(0,OS_STD,"[addiScaleFactors] Compute scale factors for each spectrum \n"); for(i=0;i<nbsp;i++) { dw=spectra[i]->data[spectra[i]->colW]->ddata; df=spectra[i]->data[spectra[i]->colF]->ddata; wmin=dw[idmin->ldata[i]]; wmax=dw[idmax->ldata[i]-1]; if(i!=spref) { done=0; for(j=0;j<nbchunk;j++) { chkmin=(wmin>lwave->ddata[ j])?wmin:lwave->ddata[ j]; chkmax=(wmax<lwave->ddata[1+j])?wmax:lwave->ddata[1+j]; if(chkmin>=chkmax) continue; rmin=findNear(spectra[spref]->data[spectra[spref]->colW],chkmin); rmax=findNear(spectra[spref]->data[spectra[spref]->colW],chkmax)+1; cmin=findNear(spectra[ i]->data[spectra[ i]->colW],chkmin); cmax=findNear(spectra[ i]->data[spectra[ i]->colW],chkmax)+1; for(k=rmin,l=0;k<rmax;k++,l++) work[l]=spectra[spref]->data[spectra[spref]->colF]->ddata[k]; medref=median(work,rmax-rmin); for(k=cmin,l=0;k<cmax;k++,l++) work[l]=df[k]; aux=median(work,cmax-cmin); if((aux>0)&&(medref>0)) fctrs->ddata[done++]=medref/aux; if((medref<=0)&&(aux<=0)) fctrs->ddata[done++]=1.; } if(done<=0) { OS_message(0,OS_STD,"[addiScaleFactors] no common region. Set factor to 1\n"); rslt->ddata[i]=1.; } else rslt->ddata[i]=median(fctrs->ddata,done); } else rslt->ddata[i]=1.; OS_message(0,OS_STD,"[addiScaleFactors] Factor for spectrum #%2d : %f\n",i+1,rslt->ddata[i]); } VC_free(lwave); VC_free(fctrs); MM_free(work); } VC_free(idmax); VC_free(idmin); if(vout) *vout=rslt; return rslt; }
/** * Insert un seul objet * @warning drop les relations voisins */ void BaseObject::insertOne (BaseObject* obj) { GLdouble dist_a; shared_ptr<BaseObject> cur; /* suppression de l'ancien voisinage */ obj->left.reset(); obj->right.reset(); obj->up.reset(); obj->down.reset(); obj->front.reset(); obj->back.reset(); /* re-initialisation du compteur d'operation */ obj->cur_op = cur_op; static const auto lambda = [] (const shared_ptr<BaseObject> &lhs, const shared_ptr<BaseObject> &rhs) -> bool { return lhs.get() < rhs.get(); }; set < shared_ptr<BaseObject>, decltype (lambda) > to_recalc (lambda); /* premiere étape : trouver l'objet le plus près */ while (! (cur = findNear (obj->position))) ; /* on ajoute le voisinage a la liste de recalcule */ to_recalc.insert (cur); vector<shared_ptr<BaseObject>> to_add; for (unsigned short i = 0; i < max_add_recursion; i++) { for (auto it = to_recalc.begin(); it != to_recalc.end(); it ++) { if (cur = (*it)->front) to_add.push_back (cur); if (cur = (*it)->back) to_add.push_back (cur); if (cur = (*it)->left) to_add.push_back (cur); if (cur = (*it)->right) to_add.push_back (cur); if (cur = (*it)->up) to_add.push_back (cur); if (cur = (*it)->down) to_add.push_back (cur); } to_recalc.insert (to_add.begin(), to_add.end()); to_add.clear(); } /* deuxieme étape, insertion à la bonne place */ for (auto it = to_recalc.begin(); it != to_recalc.end(); it ++) { cur = *it; dist_a = obj->position.distance( cur->position); if (obj->position.x == cur->position.x && obj->position.y == cur->position.y && obj->position.z == cur->position.z) { /* même position ajout à la liste * reset du voisinage avant => pas besoin */ auto old_here = cur->here; decltype (here) new_here (new vector<shared_ptr<BaseObject>>()); new_here->insert (new_here->end(), old_here->begin(), old_here->end()); obj->left.reset(); obj->right.reset(); obj->up.reset(); obj->down.reset(); obj->front.reset(); obj->back.reset(); new_here->insert (new_here->end(), obj->here->begin(), obj->here->end()); obj->here->clear(); new_here->insert (new_here->end(), obj->my_lock); cur->here = new_here; return; } if (abs (obj->position.x - cur->position.x) >= abs (obj->position.y - cur->position.y) && abs (obj->position.x - cur->position.x) >= abs (obj->position.z - cur->position.z)) { /* gauche ou droite */ if (cur->position.x > obj->position.x) { shared_ptr<BaseObject> RIGHT = obj->right; /* gauche !, insert a droite */ if (!RIGHT || obj->position.distance(RIGHT->position) > dist_a) { obj->right = cur; } else if (abs (obj->position.x - cur->position.x) == abs (obj->position.z - cur->position.z)) goto try_z; else if (abs (obj->position.x - cur->position.x) == abs (obj->position.y - cur->position.y)) goto try_y; } else { shared_ptr<BaseObject> LEFT = obj->left; /* droite !, insert à gauche */ if (!LEFT || obj->position.distance( LEFT->position) > dist_a) { obj->left = cur; } else if (abs (obj->position.x - cur->position.x) == abs (obj->position.z - cur->position.z)) goto try_z; else if (abs (obj->position.x - cur->position.x) == abs (obj->position.y - cur->position.y)) goto try_y; } } else if (abs (obj->position.z - cur->position.z) >= abs (obj->position.y - cur->position.y)) { try_z: /* devant ou deriere */ if (cur->position.z > obj->position.z) { shared_ptr<BaseObject> FRONT = obj->front; /* derière !, insert devant */ if (!FRONT || obj->position.distance(FRONT->position) > dist_a) { obj->front = cur; } else if (abs (obj->position.z - cur->position.z) == abs (obj->position.y - cur->position.y)) goto try_y; } else { shared_ptr<BaseObject> BACK = obj->back; /* devant !, insert derriere */ if (!BACK || obj->position.distance( BACK->position) > dist_a) { obj->back = cur; } else if (abs (obj->position.z - cur->position.z) == abs (obj->position.y - cur->position.y)) goto try_y; } } else { try_y: /* dessus ou dessous */ if (cur->position.y > obj->position.y) { shared_ptr<BaseObject> UP = obj->up; /* dessous !, insert au dessus */ if (!UP || obj->position.distance( UP->position) > dist_a) { obj->up = cur; } } else { shared_ptr<BaseObject> DOWN = obj->down; /* dessus !, insert en dessous */ if (!DOWN || obj->position.distance( DOWN->position) > dist_a) { obj->down = cur; } } } } /* on a le voisinage complet. On casse les ancients lien et on fait les nouveau */ if (shared_ptr<BaseObject> UP = obj->up) { if (shared_ptr<BaseObject> DOWN = UP->down) { /* avant de casser verif si l'objet est bien plus proche */ if ( DOWN->position.distance(UP->position) > UP->position.distance(obj->position)) { DOWN->up.reset(); UP->down = obj->my_lock; } else obj->up.reset(); } else UP->down = obj->my_lock; } else obj->up.reset(); if (shared_ptr<BaseObject> DOWN = obj->down) { if (shared_ptr<BaseObject> UP = DOWN->up) { /* avant de casser verif si l'objet est bien plus proche */ if ( UP->position.distance(DOWN->position) > DOWN->position.distance(obj->position)) { UP->down.reset(); DOWN->up = obj->my_lock; } else obj->down.reset(); } else DOWN->up = obj->my_lock; } else obj->down.reset(); if (shared_ptr<BaseObject> LEFT = obj->left) { if (shared_ptr<BaseObject> RIGHT = LEFT->right) { /* avant de casser verif si l'objet est bien plus proche */ if ( RIGHT->position.distance(LEFT->position) > LEFT->position.distance(obj->position)) { RIGHT->left.reset(); LEFT->right = obj->my_lock; } else obj->left.reset(); } else LEFT->right = obj->my_lock; } else obj->left.reset(); if (shared_ptr<BaseObject> RIGHT = obj->right) { if (shared_ptr<BaseObject> LEFT = RIGHT->left) { /* avant de casser verif si l'objet est bien plus proche */ if ( LEFT->position.distance(RIGHT->position) > RIGHT->position.distance(obj->position)) { LEFT->right.reset(); RIGHT->left = obj->my_lock; } else obj->right.reset(); } else RIGHT->left = obj->my_lock; } else obj->right.reset(); if (shared_ptr<BaseObject> FRONT = obj->front) { if (shared_ptr<BaseObject> BACK = FRONT->back) { /* avant de casser verif si l'objet est bien plus proche */ if ( BACK->position.distance(FRONT->position) > FRONT->position.distance(obj->position)) { BACK->front.reset(); FRONT->back = obj->my_lock; } else obj->front.reset(); } else FRONT->back = obj->my_lock; } else obj->front.reset(); if (shared_ptr<BaseObject> BACK = obj->back) { if (shared_ptr<BaseObject> FRONT = BACK->front) { /* avant de casser verif si l'objet est bien plus proche */ if ( FRONT->position.distance(BACK->position) > BACK->position.distance(obj->position)) { FRONT->back.reset(); BACK->front = obj->my_lock; } else obj->back.reset(); } else BACK->front = obj->my_lock; } else obj->back.reset(); }