/** Make basic arrays for servo analysis. */ static void servo_calc_init(SERVO_CALC_T *st, const dmat *psdin, double dt, long dtrat){ if(psdin->ny!=2){ error("psdin should have two columns\n"); } double Ts=dt*dtrat; st->fny=0.5/Ts; dmat *nu=st->nu=dlogspace(-3,log10(0.5/dt),1000); st->psd=dinterp1(psdin, 0, nu, 1e-40); st->var_sig=psd_inte2(psdin); dcomplex pi2i=COMPLEX(0, TWOPI); if(st->Hsys || st->Hwfs || st->Hint || st->s){ error("Already initialized\n"); } st->Hsys=cnew(nu->nx, 1); st->Hwfs=cnew(nu->nx, 1); st->Hint=cnew(nu->nx, 1); st->s=cnew(nu->nx,1); for(long i=0; i<nu->nx; i++){ dcomplex s=st->s->p[i]=pi2i*nu->p[i]; dcomplex zInv=cexp(-s*Ts); dcomplex Hint=st->Hint->p[i]=1./(1-zInv); dcomplex Hwfs, Hdac; if(dtrat==1){//we have a pure delay Hwfs=st->Hwfs->p[i]=zInv; Hdac=1; }else{ Hwfs=st->Hwfs->p[i]=(1-zInv)/(Ts*s); Hdac=Hwfs; } dcomplex Hlag=cexp(-s*dt);/*lag due to readout/computation*/ dcomplex Hmir=1;/*DM */ st->Hsys->p[i]=Hwfs*Hlag*Hdac*Hmir*Hint; } }
/** Add two PSDs that doesn't have the same frequency. the first column of each dmat is the frequency nu, and the second column is PSD. Bug discovered on 2013-03-24:only psd2 was added to to psd.*/ static dmat *add_psd_nomatch(const dmat *psd1,const dmat *psd2){ dmat *nu1=dsub(psd1,0,psd1->nx,0,1); dmat *p2ynew=dinterp1(psd2, 0, nu1, 1e-40); dmat *psd=dnew(nu1->nx,2); double *py=psd->p+psd->nx; const double *p1y=psd1->p+psd1->nx; for(long i=0; i<psd->nx; i++){ psd->p[i]=nu1->p[i]; py[i]=p1y[i]+p2ynew->p[i]; } dfree(nu1); dfree(p2ynew); return psd; }
/** Convert PSD into time series.*/ dmat* psd2time(const dmat *psdin, rand_t *rstat, double dt, int nstepin){ if(!psdin){ error("psdin cannot be null\n"); } long nstep=nextpow2(nstepin); double df=1./(dt*nstep); dmat *fs=dlinspace(0, df, nstep); dmat *psd=NULL; if(psdin->ny==1){//[alpha, beta, fmin, fmax] discribes power law with cut on/off freq. psd=dnew(nstep, 1); double alpha=psdin->p[0]; double beta=psdin->p[1]; long i0=1, imax=nstep; if(psdin->nx>2){ i0=(long)round(psdin->p[2]/df); if(i0<1) i0=1; } if(psdin->nx>3){ imax=(long)round(psdin->p[3]/df); } info("fmin=%g, fmax=%g, df=%g, i0=%ld, imax=%ld\n", psdin->p[2], psdin->p[3], df, i0, imax); for(long i=i0; i<imax; i++){ psd->p[i]=beta*pow(i*df, alpha); } }else if(psdin->ny==2){ if(psdin->nx<2){ error("Invalid PSD\n"); } psd=dinterp1(psdin, 0, fs, 1e-40); psd->p[0]=0;/*disable pistion. */ }else{ error("psdin is invalid format.\n"); } cmat *wshat=cnew(nstep, 1); //cfft2plan(wshat, -1); for(long i=0; i<nstep; i++){ wshat->p[i]=sqrt(psd->p[i]*df)*COMPLEX(randn(rstat), randn(rstat)); } cfft2(wshat, -1); dmat *out=NULL; creal2d(&out, 0, wshat, 1); cfree(wshat); dfree(psd); dfree(fs); dresize(out, nstepin, 1); return out; }
/*Interpolate psd onto new f. We interpolate in log space which is more linear.*/ dmat *psdinterp1(const dmat *psdin, const dmat *fnew, int uselog){ dmat *f1=drefcols(psdin, 0, 1); dmat *psd1=dsub(psdin, 0, 0, 1, 1);//copy dmat *f2=dref(fnew); double t1=dtrapz(f1, psd1); double ydefault=1e-40; if(uselog){ dcwlog(psd1); ydefault=log(ydefault); } dmat *psd2=dinterp1(f1, psd1, f2, ydefault); if(uselog){ dcwexp(psd2,1); } double t2=dtrapz(f2, psd2); if(fabs(t1-t2)>fabs(0.5*(t1+t2)*2)){ warning("psd interpolation failed. int_orig=%g, int_interp=%g\n", t1, t2); } //Don't scale psd2 as it may have overlapping frequency regions dfree(f1); dfree(f2); dfree(psd1); return psd2; }
/* Add a PSD scaled by scale to another. The first column of each dmat is the frequency nu, and the second column is PSD. */ void add_psd2(dmat **pout, const dmat *in, double scale){ if(!*pout){ *pout=ddup(in); }else{ dmat *out=*pout; double *p1=PCOL(out,1); dmat *p2new=0; const long nx=out->nx; const double *p2=0; if(check_psd_match(out, in)){ p2=PCOL(in, 1); }else{ dmat *nu1=dsub(out,0, nx,0,1); p2new=dinterp1(in, 0, nu1, 1e-40); p2=PCOL(p2new,0); dfree(nu1); } for(long i=0; i<nx; i++){ p1[i]+=p2[i]*scale; } dfree(p2new); } }
/** Setup the detector transfer functions. See maos/setup_powfs.c */ static void setup_powfs_dtf(POWFS_S *powfs, const PARMS_S* parms){ const int npowfs=parms->maos.npowfs; for(int ipowfs=0; ipowfs<npowfs; ipowfs++){ const int ncomp=parms->maos.ncomp[ipowfs]; const int ncomp2=ncomp>>1; const int embfac=parms->maos.embfac[ipowfs]; const int pixpsa=parms->skyc.pixpsa[ipowfs]; const double pixtheta=parms->skyc.pixtheta[ipowfs]; const double blur=parms->skyc.pixblur[ipowfs]*pixtheta; const double e0=exp(-2*M_PI*M_PI*blur*blur); const double dxsa=parms->maos.dxsa[ipowfs]; const double pixoffx=parms->skyc.pixoffx[ipowfs]; const double pixoffy=parms->skyc.pixoffy[ipowfs]; const double pxo=-(pixpsa/2-0.5+pixoffx)*pixtheta; const double pyo=-(pixpsa/2-0.5+pixoffy)*pixtheta; loc_t *loc_ccd=mksqloc(pixpsa, pixpsa, pixtheta, pixtheta, pxo, pyo); powfs[ipowfs].dtf=mycalloc(parms->maos.nwvl,DTF_S); for(int iwvl=0; iwvl<parms->maos.nwvl; iwvl++){ const double wvl=parms->maos.wvl[iwvl]; const double dtheta=wvl/(dxsa*embfac); const double pdtheta=pixtheta*pixtheta/(dtheta*dtheta); const double du=1./(dtheta*ncomp); const double du2=du*du; const double dupth=du*pixtheta; cmat *nominal=cnew(ncomp,ncomp); //cfft2plan(nominal,-1); //cfft2plan(nominal,1); cmat* pn=nominal; const double theta=0; const double ct=cos(theta); const double st=sin(theta); for(int iy=0; iy<ncomp; iy++){ int jy=iy-ncomp2; for(int ix=0; ix<ncomp; ix++){ int jx=ix-ncomp2; double ir=ct*jx+st*jy; double ia=-st*jx+ct*jy; IND(pn,ix,iy)=sinc(ir*dupth)*sinc(ia*dupth) *pow(e0,ir*ir*du2)*pow(e0,ia*ia*du2) *pdtheta; } } if(parms->skyc.fnpsf1[ipowfs]){ warning("powfs %d has additional otf to be multiplied\n", ipowfs); dcell *psf1c=dcellread("%s", parms->skyc.fnpsf1[ipowfs]); dmat *psf1=NULL; if(psf1c->nx == 1){ psf1=dref(psf1c->p[0]); }else if(psf1c->nx==parms->maos.nwvl){ psf1=dref(psf1c->p[iwvl]); }else{ error("skyc.fnpsf1 has wrong dimension\n"); } dcellfree(psf1c); if(psf1->ny!=2){ error("skyc.fnpsf1 has wrong dimension\n"); } dmat *psf1x=dnew_ref(psf1->nx, 1, psf1->p); dmat *psf1y=dnew_ref(psf1->nx, 1, psf1->p+psf1->nx); dmat *psf2x=dnew(ncomp*ncomp, 1); for(int iy=0; iy<ncomp; iy++){ int jy=iy-ncomp2; for(int ix=0; ix<ncomp; ix++){ int jx=ix-ncomp2; psf2x->p[ix+iy*ncomp]=sqrt(jx*jx+jy*jy)*dtheta; } } info("powfs %d, iwvl=%d, dtheta=%g\n", ipowfs, iwvl, dtheta*206265000); writebin(psf2x, "powfs%d_psf2x_%d", ipowfs,iwvl); dmat *psf2=dinterp1(psf1x, psf1y, psf2x, 0); normalize_sum(psf2->p, psf2->nx*psf2->ny, 1); psf2->nx=ncomp; psf2->ny=ncomp; writebin(psf2, "powfs%d_psf2_%d", ipowfs,iwvl); cmat *otf2=cnew(ncomp, ncomp); //cfft2plan(otf2, -1); ccpd(&otf2, psf2);//peak in center cfftshift(otf2);//peak in corner cfft2(otf2, -1); cfftshift(otf2);//peak in center writebin(otf2, "powfs%d_otf2_%d", ipowfs, iwvl); writebin(nominal, "powfs%d_dtf%d_nominal_0",ipowfs,iwvl); for(int i=0; i<ncomp*ncomp; i++){ nominal->p[i]*=otf2->p[i]; } writebin(nominal, "powfs%d_dtf%d_nominal_1",ipowfs,iwvl); dfree(psf1x); dfree(psf1y); dfree(psf2x); dfree(psf1); cfree(otf2); dfree(psf2); } cfftshift(nominal);//peak in corner cfft2(nominal,-1); cfftshift(nominal);//peak in center cfft2i(nominal,1); warning_once("double check nominal for off centered skyc.fnpsf1\n"); /*This nominal will multiply to OTF with peak in corner. But after inverse fft, peak will be in center*/ ccp(&powfs[ipowfs].dtf[iwvl].nominal, nominal); cfree(nominal); loc_t *loc_psf=mksqloc(ncomp, ncomp, dtheta, dtheta, -ncomp2*dtheta, -ncomp2*dtheta); powfs[ipowfs].dtf[iwvl].si=mkh(loc_psf,loc_ccd,0,0,1); locfree(loc_psf); if(parms->skyc.dbg){ writebin(powfs[ipowfs].dtf[iwvl].nominal, "%s/powfs%d_dtf%d_nominal",dirsetup,ipowfs,iwvl); writebin(powfs[ipowfs].dtf[iwvl].si, "%s/powfs%d_dtf%d_si",dirsetup,ipowfs,iwvl); } powfs[ipowfs].dtf[iwvl].U=cnew(ncomp,1); dcomplex *U=powfs[ipowfs].dtf[iwvl].U->p; for(int ix=0; ix<ncomp; ix++){ int jx=ix<ncomp2?ix:(ix-ncomp); U[ix]=COMPLEX(0, -2.*M_PI*jx*du); } }/*iwvl */ locfree(loc_ccd); }/*ipowfs */ }
static inline void clipdm(SIM_T *simu, dcell *dmcmd){ const PARMS_T *parms=simu->parms; if(!dmcmd) return; /* clip integrator. This both limits the output and feeds back the clip since we are acting on the integrator directly. */ if(parms->sim.dmclip){ for(int idm=0; idm<parms->ndm; idm++){ const int nact=dmcmd->p[idm]->nx; if(parms->dm[idm].stroke->nx==1){ if(parms->dm[idm].stroke->ny!=1){ error("dm.stroke is in wrong format\n"); } int nclip=dclip(dmcmd->p[idm], -parms->dm[idm].stroke->p[0], parms->dm[idm].stroke->p[0]); if(nclip>0){ info2("step %d DM %d: %d actuators clipped\n", simu->isim, idm, nclip); } }else if(parms->dm[idm].stroke->nx==nact){ if(parms->dm[idm].stroke->ny!=2){ error("dm.stroke is in wrong format\n"); } double *pcmd=dmcmd->p[idm]->p; double *plow=parms->dm[idm].stroke->p; double *phigh=parms->dm[idm].stroke->p+nact; for(int iact=0; iact<nact; iact++){ if(pcmd[iact]<plow[iact]){ pcmd[iact]=plow[iact]; }else if(pcmd[iact]>phigh[iact]){ pcmd[iact]=phigh[iact]; } } }else{ error("Invalid format\n"); } } } if(parms->sim.dmclipia){ /*Clip interactuator stroke*/ for(int idm=0; idm<parms->ndm; idm++){ /* Embed DM commands to a square array (borrow dmrealsq) */ double iastroke; int nx=simu->recon->anx->p[idm]; double (*dmr)[nx]; dmat *dm; if(parms->dm[idm].iastrokescale){ //convert dm to voltage dm=dinterp1(parms->dm[idm].iastrokescale->p[0], 0, dmcmd->p[idm], NAN); iastroke=parms->dm[idm].iastroke;//voltage. }else{ dm=dmcmd->p[idm]; iastroke=parms->dm[idm].iastroke*2;//surface to opd } if(!parms->fit.square){ loc_embed(simu->dmrealsq->p[idm], simu->recon->aloc->p[idm], dm->p); dmr=(double(*)[nx])simu->dmrealsq->p[idm]->p; }else{ dmr=(double(*)[nx])dm->p; } lcell *actstuck=simu->recon->actstuck; long *stuck=actstuck?(actstuck->p[idm]?actstuck->p[idm]->p:0):0; int count=0,trials=0; do{ count=0; PDMAT(simu->recon->amap->p[idm],map); for(int iy=0; iy<simu->recon->any->p[idm]-1; iy++){ for(int ix=0; ix<nx; ix++){ int iact1=map[iy][ix]; int iact2=map[iy+1][ix]; if(iact1>0 && iact2>0){ count+=limit_diff(&dmr[iy][ix], &dmr[iy+1][ix], iastroke, stuck?stuck[iact1-1]:0, stuck?stuck[iact2-1]:0); } } } for(int iy=0; iy<simu->recon->any->p[idm]; iy++){ for(int ix=0; ix<nx-1; ix++){ int iact1=map[iy][ix]; int iact2=map[iy][ix+1]; if(iact1>0 && iact2>0){ count+=limit_diff(&dmr[iy][ix], &dmr[iy][ix+1], iastroke, stuck?stuck[iact1-1]:0, stuck?stuck[iact2-1]:0); } } } trials++; if(trials==1 && count>0) { info2("Step %d, DM %d: %d actuators over ia limit. ", simu->isim, idm, count); } }while(count>0 && trials<100); if(trials>1){ info2("trials=%d: %s\n", trials, count?"failed.":"success."); } if(!parms->fit.square){//copy data back loc_extract(simu->dmreal->p[idm], simu->recon->aloc->p[idm], simu->dmrealsq->p[idm]); } if(parms->dm[idm].iastrokescale){//convert back to opd dmat *dm2=dinterp1(parms->dm[idm].iastrokescale->p[1], 0, dm, NAN); dcp(&dmcmd->p[idm], dm2); dfree(dm); dfree(dm2); } } } }
/** Setup matched filter for stars. */ static void setup_star_mtch(const PARMS_S *parms, POWFS_S *powfs, STAR_S *star, int nstar, dcell**nonlin){ const long nwvl=parms->maos.nwvl; const long npowfs=parms->maos.npowfs; dmat* rnefs=parms->skyc.rnefs; for(int istar=0; istar<nstar; istar++){ if(!star[istar].idtrat){ star[istar].idtrat=dnew(npowfs, 1); } double radius=sqrt(pow(star[istar].thetax,2)+pow(star[istar].thetay,2)); int igg=round(radius*206265/parms->maos.ngsgrid); //info("radius=%g as, igg=%d\n", radius*206265, igg); for(int ipowfs=0; ipowfs<npowfs; ipowfs++){ const long nsa=parms->maos.nsa[ipowfs]; const long pixpsa=parms->skyc.pixpsa[ipowfs]; //size of PSF const double sigma_theta=parms->skyc.wvlmean/parms->maos.dxsa[ipowfs]; PISTAT_S *pistat=&star[istar].pistat[ipowfs]; pistat->i0=dcellnew(nsa,nwvl); pistat->gx=dcellnew(nsa,nwvl); pistat->gy=dcellnew(nsa,nwvl); pistat->i0s=dcellnew(nsa,1); pistat->gxs=dcellnew(nsa,1); pistat->gys=dcellnew(nsa,1); dcell* psf=pistat->psf; dcell* i0=pistat->i0; dcell* gx=pistat->gx; dcell* gy=pistat->gy; for(long iwvl=0; iwvl<nwvl; iwvl++){ for(long isa=0; isa<nsa; isa++){ double siglev=star[istar].siglev->p[ipowfs]->p[iwvl]; IND(i0,isa,iwvl)=dnew(pixpsa,pixpsa); IND(gx,isa,iwvl)=dnew(pixpsa,pixpsa); IND(gy,isa,iwvl)=dnew(pixpsa,pixpsa); psf2i0gxgy(IND(i0,isa,iwvl),IND(gx,isa,iwvl),IND(gy,isa,iwvl), IND(psf,isa,iwvl),powfs[ipowfs].dtf+iwvl); dadd(&pistat->i0s->p[isa], 1, IND(i0,isa,iwvl), siglev); dadd(&pistat->gxs->p[isa], 1, IND(gx,isa,iwvl), siglev); dadd(&pistat->gys->p[isa], 1, IND(gy,isa,iwvl), siglev); } } if(parms->skyc.dbg){ writebin(pistat->i0s, "%s/star%d_ipowfs%d_i0s", dirsetup,istar,ipowfs); } const double pixtheta=parms->skyc.pixtheta[ipowfs]; int ndtrat=parms->skyc.ndtrat; pistat->mtche=mycalloc(ndtrat,dcell*); pistat->sanea=dcellnew(ndtrat,1); pistat->sanea0=dcellnew(ndtrat,1); pistat->snr=dnew(ndtrat,1); dcell *i0s=NULL; dcell *gxs=NULL; dcell *gys=NULL; for(int idtrat=0; idtrat<ndtrat; idtrat++){ int dtrat=parms->skyc.dtrats->p[idtrat]; dcelladd(&i0s, 0, pistat->i0s, dtrat); dcelladd(&gxs, 0, pistat->gxs, dtrat); dcelladd(&gys, 0, pistat->gys, dtrat); genmtch(&pistat->mtche[idtrat], &pistat->sanea->p[idtrat], i0s, gxs, gys, pixtheta, IND(rnefs,idtrat,ipowfs), star[istar].bkgrnd->p[ipowfs]*dtrat, parms->skyc.mtchcr); /*Add nolinearity*/ if(nonlin){ //add linearly not quadratically since the errors are related. dmat *nea_nonlin=dinterp1(nonlin[ipowfs]->p[igg], NULL, pistat->sanea->p[idtrat], 0); for(int i=0; i<nsa*2; i++){ //info2("%g mas", pistat->sanea->p[idtrat]->p[i]*206265000); pistat->sanea->p[idtrat]->p[i]=sqrt(pow(pistat->sanea->p[idtrat]->p[i],2) +pow(nea_nonlin->p[i],2)); //info2("-->%g mas\n", pistat->sanea->p[idtrat]->p[i]*206265000); } dfree(nea_nonlin); } dcp(&pistat->sanea0->p[idtrat], pistat->sanea->p[idtrat]); if(parms->skyc.neaaniso){ for(int i=0; i<nsa*2; i++){ pistat->sanea->p[idtrat]->p[i]=sqrt(pow(pistat->sanea->p[idtrat]->p[i],2) +pow(star[istar].pistat[ipowfs].neaspec->p[i]->p[idtrat], 2)); } } if(parms->skyc.dbg){ writebin(pistat->mtche[idtrat], "%s/star%d_ipowfs%d_mtche_dtrat%d", dirsetup,istar,ipowfs,dtrat); } #if 1 double nea=sqrt(dsumsq(pistat->sanea->p[idtrat])/(nsa*2)); #else double nea=dmax(pistat->sanea->p[idtrat]); #endif double snr=sigma_theta/nea; pistat->snr->p[idtrat]=snr; if(parms->skyc.verbose) info2("dtrat=%3d, nea=%4.1f, snr=%4.1f\n", (int)parms->skyc.dtrats->p[idtrat], nea*206265000, snr); if(snr>parms->skyc.snrmin->p[parms->skyc.snrmin->nx==1?0:idtrat]){ star[istar].idtrat->p[ipowfs]=idtrat; } }//for idtrat if(parms->skyc.dbg){ info2("star %2d optim: powfs %1d: dtrat=%3d\n", istar, ipowfs, (int)parms->skyc.dtrats->p[(int)star[istar].idtrat->p[ipowfs]]); writebin(pistat->sanea, "%s/star%d_ipowfs%d_sanea", dirsetup,istar,ipowfs); }/*idtrat */ dcellfree(i0s); dcellfree(gxs); dcellfree(gys); }/*for istar */ }/*for ipowfs */ }
/** Read in pistat information, used to compute matched filter, and SANEA. */ static void setup_star_read_pistat(SIM_S *simu, STAR_S *star, int nstar, int seed){ const PARMS_S *parms=simu->parms; const int npowfs=parms->maos.npowfs; const int nwvl=parms->maos.nwvl; const double ngsgrid=parms->maos.ngsgrid; for(int istar=0; istar<nstar; istar++){ STAR_S *stari=&star[istar]; stari->pistat=mycalloc(npowfs,PISTAT_S); const double thetax=stari->thetax*206265;/*in as */ const double thetay=stari->thetay*206265; double thxnorm=thetax/ngsgrid; double thynorm=thetay/ngsgrid; long thxl=(long)floor(thxnorm); long thyl=(long)floor(thynorm); double wtx=thxnorm-thxl; double wty=thynorm-thyl; for(int ipowfs=0; ipowfs<npowfs; ipowfs++){ const int msa=parms->maos.msa[ipowfs]; const int nsa=parms->maos.nsa[ipowfs]; dcell *avgpsf=NULL; dcell *neaspec=NULL; double wtsum=0; for(int ix=0; ix<2; ix++){ double thx=(thxl+ix)*ngsgrid; for(int iy=0; iy<2; iy++){ double thy=(thyl+iy)*ngsgrid; double wtxi=fabs(((1-ix)-wtx)*((1-iy)-wty)); if(wtxi<0.01){ /*info("skipping ix=%d,iy=%d because wt=%g\n",ix,iy,wtxi); */ continue; } char fn[PATH_MAX]; snprintf(fn,PATH_MAX,"%s/pistat/pistat_seed%d_sa%d_x%g_y%g", dirstart, seed,msa,thx,thy); if(!zfexist(fn)){ /*warning("%s doesn't exist\n",fn); */ }else{ dcell *avgpsfi=dcellread("%s",fn); dcelladd(&avgpsf, 1, avgpsfi, wtxi); dcellfree(avgpsfi); wtsum+=wtxi; snprintf(fn,PATH_MAX,"%s/neaspec/neaspec_seed%d_sa%d_x%g_y%g", dirstart, seed, msa, thx, thy); dcell *neaspeci=dcellread("%s",fn); dcelladd(&neaspec, 1, neaspeci, wtxi); dcellfree(neaspeci); } } } if(wtsum<0.01){ warning("PISTAT is not available for (%g,%g) msa=%d\n",thetax,thetay,msa); } dcellscale(neaspec, 1./wtsum); dcellscale(avgpsf, 1./wtsum); dmat *scale=NULL; if(parms->skyc.bspstrehl){ scale=dnew(nsa,nwvl); dmat *gx=dnew(1,1); gx->p[0]=thxnorm; dmat *gy=dnew(1,1); gy->p[0]=thynorm; if(nsa!=avgpsf->nx || nwvl!=avgpsf->ny){ error("Mismatch: nsa=%d, nwvl=%d, avgpsf->nx=%ld, avgpsf->ny=%ld\n", nsa, nwvl, avgpsf->nx, avgpsf->ny); } for(int ic=0; ic<nsa*nwvl; ic++){ dmat *val=dbspline_eval(simu->bspstrehl[ipowfs][ic], simu->bspstrehlxy,simu->bspstrehlxy, gx, gy); double ratio=val->p[0]/avgpsf->p[ic]->p[0]; /*info("strehl: bilinear: %g, cubic: %g\n", avgpsf->p[ic]->p[0],val->p[0]); */ if(ratio<0){ warning("Ratio=%g is less than zero.\n", ratio); scale->p[ic]=1; }else{ dscale(avgpsf->p[ic], ratio); scale->p[ic]=ratio; } dfree(val); } dfree(gx); dfree(gy); } stari->pistat[ipowfs].psf=avgpsf;/*PSF is in corner. */ stari->pistat[ipowfs].neaspec=dcellnew(nsa*2, 1); for(int ig=0; ig<nsa*2; ig++){ dmat *tmp=0; for(int iwvl=0; iwvl<nwvl; iwvl++){ dadd(&tmp, 0, neaspec->p[ig+nsa*2*iwvl], parms->skyc.wvlwt->p[iwvl]); } stari->pistat[ipowfs].neaspec->p[ig]=dinterp1(simu->neaspec_dtrats, tmp, parms->skyc.dtrats, 0); dfree(tmp); } dcellfree(neaspec); stari->pistat[ipowfs].scale=scale; {/* skip stars with large PSF.*/ int size=INT_MAX; for(int ic=0; ic<avgpsf->nx*avgpsf->ny; ic++){ int size0=dfwhm(avgpsf->p[ic]); if(size0<size) size=size0; } if(size>6){ stari->use[ipowfs]=-1; } } if(parms->skyc.dbg){ writebin(avgpsf, "%s/avgpsf_star%d_ipowfs%d_psf",dirsetup,istar,ipowfs); writebin(stari->pistat[ipowfs].neaspec, "%s/pistat_star%d_ipowfs%d_neaspec",dirsetup,istar,ipowfs); } } } }