Пример #1
0
int main(){
    int N=4;
    dmat *A=dnew(N,N);
    dcell *B=cellnew(2,2);
    B->p[0]=dnew(N,N);
    B->p[2]=dnew(N,N);
    rand_t rstat;
    seed_rand(&rstat, 1);
    drandn(A, 1, &rstat);
    drandn(B->p[0], 1, &rstat);
    drandn(B->p[2], 1, &rstat);
    A->header=strdup("dx=1/64\ndy=1/64\nLong=kaflasdjfl ksflksjlfjasdflkj asldfj als fals fl asfjalsdf jalsf djasldf jal fsalfkjasdflkj asldfkj asldf \nadf\nwvf=1.e-4");
    writebin(A, "A.bin");
    writebin(A, "A.fits");
    writebin(A, "A.fits.gz");
    writebin(B, "B.bin");
    writebin(B, "B.fits");
    dmat *C=dread("A.fits");
    writebin(C, "C.fits");
    dcell *D=dcellread("B.fits");
    writebin(D, "D.fits");
    dcell *E=dcellread("A.fits");
    writebin(E, "E.fits");
    writebin(E, "E.fits.gz");
}
Пример #2
0
static void test_ints(){
    rand_t init;
    seed_rand(&init,1);
    const int nwfs=6;
    lrand(&init);/*atm */
    rand_t wfs_rand[nwfs];
    for(int iwfs=0; iwfs<nwfs; iwfs++){
	seed_rand(wfs_rand+iwfs,lrand(&init));
    }
    dcell *mtche=dcellread("powfs0_mtche.bin");
    int nsim=500;
    int nsa=2582;
    dmat *nea=dnew(nsim,nsa*2);
    double(*pnea)[nsim]=(void*)nea->p;
    double rne=3;
    double bkgrnd=0;
    double siglev=1000;
    for(int iwfs=0; iwfs<nwfs; iwfs++){
	for(int isim=0; isim<nsim; isim++){
	    dbg("iwfs %d isim=%d\n",iwfs,isim);
	    /*dcell *ints=dcellread("ints_%d_wfs%d.bin",isim,iwfs); */
	    dcell *ints=dcellread("ints_%d_wfs%d.bin",isim,iwfs);
	    /*dcell *i0=dcellread("powfs0_i0.bin"); */
	    dmat *im=NULL, *imy=NULL;
	    double gnf[2], gny[2];

	    for(int isa=0; isa<nsa; isa++){
		dcp(&im,ints->p[isa]);
		dscale(im,siglev);
		gnf[0]=0; gnf[1]=0;
		dmulvec(gnf, mtche->p[isa], im->p,1.);
		gny[0]=0; gny[1]=0;
		dcp(&imy, im);
		addnoise(imy, &wfs_rand[iwfs], bkgrnd, bkgrnd, 0,0,rne);
		dmulvec(gny, mtche->p[isa], imy->p,1.);
		P(pnea,isim,isa)=gny[0]-gnf[0];
		P(pnea,isim,isa+nsa)=gny[1]-gnf[1];
	    }
	}
	writebin(nea,"test_sanea_wfs%d.bin",iwfs);
    }
}
Пример #3
0
static int test_tomo(){
    info("Tomo\n");
    dcell *grad=dcellread("grad.bin");
    MUV_T RR;
    RR.M=dspcellread("RRM.bin"); 
    RR.U=dcellread("RRU.bin");
    RR.V=dcellread("RRV.bin");
    tic;
    dcell *rhs=NULL;
    MUV(&rhs, &RR, grad, 1);
    toc("");
    writebin(rhs,"rhs.bin");
    MUV_T RL;
    RL.M=dspcellread("RLM.bin");
    RL.U=dcellread("RLU.bin");
    RL.V=dcellread("RLV.bin");
    dcell *junk=NULL;
    tic; 
    for(int i=0; i<1; i++){
	MUV(&junk, &RL, rhs, 1);
    } 
    toc("");
    writebin(junk,"MUV1.bin");
    RECON_T *recon=mycalloc(1,RECON_T);
    recon->G0=dspcellread("G0.bin");
    recon->TT=dcellread("TT.bin");
    recon->PTT=dcellread("PTT.bin");
    recon->L2=dspcellread("L2.bin");
    recon->ZZT=dspcellread("ZZT.bin");
    recon->saneai=dspcellread("saneai.bin");
    tic;
    dcell *rhs2=NULL;
    TomoR(&rhs2, recon, grad, 1);
    toc("");
    writebin(rhs2,"rhs2.bin");
    dcell *junk2=NULL;
    tic;
    TomoL(&junk2, recon, rhs, 1);
    toc("");
    writebin(junk2,"TomoL1.bin");
    info("Diff between rhs is %g\n", dcelldiff(rhs, rhs2));
    info("Diff between lhs is %g\n", dcelldiff(junk,junk2));

    return 0;
}
Пример #4
0
static int test_fit(){
    info("Fit\n");
    dcell *opdr=dcellread("opdr.bin");
    MUV_T FR;
    FR.M=dspcellread("FRM.bin");
    FR.U=dcellread("FRU.bin");
    FR.V=dcellread("FRV.bin");
    MUV_T FL;
    FL.M=dspcellread("FLM.bin");
    FL.U=dcellread("FLU.bin");
    FL.V=dcellread("FLV.bin");
    dcell *rhs=NULL;
    tic;
    for(int i=0; i<10; i++)
	MUV(&rhs, &FR, opdr, 1);
    toc("");
    dcell *MUV_f=NULL;
    tic;
    for(int i=0; i<10; i++)
	MUV(&MUV_f, &FL, rhs, 1);
    toc("");
    writebin(rhs,"fit_rhs1.bin");
    writebin(MUV_f,"MUV_f.bin");
    RECON_T *recon=mycalloc(1,RECON_T);
    recon->HX=dspcellread("HX.bin");
    recon->HA=dspcellread("HA.bin");
    recon->W1=dread("W1.bin");
    recon->W0=dspread("W0.bin");
    recon->NW=dcellread("NW.bin");
    recon->fitwt=dread("fitwt.bin");
    dcell *rhs2=NULL;
    tic;
    for(int i=0; i<10; i++)
	FitR(&rhs2, recon, opdr, 1);
    toc("");
    writebin(rhs2,"fit_rhs2.bin");
    tic;
    dcell *FitL_f=NULL;
    for(int i=0; i<10; i++)
	FitL(&FitL_f, recon, rhs2, 1);
    toc("");
    writebin(FitL_f,"FitL_f.bin");
    info("Diff between rhs is %g\n", dcelldiff(rhs, rhs2));
    info("Diff between lhs is %g\n", dcelldiff(MUV_f, FitL_f));
    dcellfree(rhs);
    dcellfree(MUV_f);
    dcellfree(rhs2);
    dcellfree(FitL_f);
    return 0;
}
Пример #5
0
/**
   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 */
}
Пример #6
0
/**
   Assemble the DM fitting matrix

   The fitting is done by minimizing \f$||H_X x - H_A a||^2_W\f$ where \f$H_X,
   H_A\f$ are ray tracing operator from tomography grid xloc, and deformable
   mirror grid aloc to pupil grid ploc. The norm is weighted using bilinear
   influence functions within the telescope aperture. We have
   
   \f$a=\left[H_A^T(W_0-W_1 W_1^T)H_A\right]^{-1} H_A^T (W_0-W_1) H_X x\f$

   For details see www.opticsinfobase.org/abstract.cfm?URI=josaa-19-9-1803 
*/
static void
setup_recon_fit_matrix(RECON_T *recon, const PARMS_T *parms){
    const int nfit=parms->fit.nfit;
    const int ndm=parms->ndm;
    if(ndm==0) return;
    dspcell *HATc=dspcelltrans(recon->HA);
    PDSPCELL(HATc, HAT);
    PDSPCELL(recon->HA,HA);

    info2("Before assembling fit matrix:\t%.2f MiB\n",get_job_mem()/1024.);
    /*Assemble Fit matrix. */
    int npsr=recon->npsr;
    if(parms->load.fit){
	if(!(zfexist("FRM") && zfexist("FRU") && zfexist("FRV"))){
	    error("FRM, FRU, FRV (.bin) not all exist\n");
	}
	warning("Loading saved recon->FR\n");
	recon->FR.M=readbin("FRM");
	recon->FR.U=dcellread("FRU");
	recon->FR.V=dcellread("FRV");
    }else{
	if(recon->HXF){
	    info2("Building recon->FR\n");
	    recon->FR.M=cellnew(ndm, npsr);
	    PDSPCELL(recon->FR.M, FRM);
	    PDSPCELL(recon->HXF, HXF);

	    for(int ips=0; ips<npsr; ips++){
		for(int ifit=0; ifit<nfit; ifit++){
		    if(fabs(recon->fitwt->p[ifit])<1.e-12) continue;
		    dsp *tmp=dspmulsp(recon->W0, HXF[ips][ifit],"nn");
		    for(int idm=0; idm<ndm; idm++){
			dspmulsp2(&FRM[ips][idm],HAT[ifit][idm], tmp, "nn",
				  recon->fitwt->p[ifit]);
		    }
		    dspfree(tmp);
		}
	    }
	    recon->FR.V=cellnew(npsr, 1);
	    dmat **FRV=recon->FR.V->p;  
	
	    for(int ips=0; ips<npsr; ips++){
		int nloc=recon->xloc->p[ips]->nloc;
		FRV[ips]=dnew(nloc,nfit);
		for(int ifit=0; ifit<nfit; ifit++){
		    /*notice the sqrt. */
		    if(fabs(recon->fitwt->p[ifit])<1.e-12) continue;
		    dspmulvec(FRV[ips]->p+ifit*nloc, 
			      HXF[ips][ifit], recon->W1->p, 't',
			      sqrt(recon->fitwt->p[ifit]));
		}
	    }
	    if(parms->save.recon){
		writebin(recon->FR.M,"FRM");
		writebin(recon->FR.V,"FRV");
	    }
	}else{
	    info("Avoid building recon->FR.M\n");
	    recon->FR.M=NULL;
	    recon->FR.V=NULL;
	}
	/*Always need FR.U as it is used to do FL.U, FL.V */
	recon->FR.U=cellnew(ndm, 1);
	dmat **FRU=recon->FR.U->p;
	
	for(int idm=0; idm<ndm; idm++){    
	    int nloc=recon->aloc->p[idm]->nloc;
	    FRU[idm]=dnew(nloc, nfit);
	    for(int ifit=0; ifit<nfit; ifit++){
		/*notice the sart. */
		if(fabs(recon->fitwt->p[ifit])<1.e-12) continue;
		dspmulvec(FRU[idm]->p+ifit*nloc, 
			  HA[idm][ifit], recon->W1->p,'t',
			  sqrt(recon->fitwt->p[ifit]));
	    }
	}
	if(parms->save.recon){
	    writebin(recon->FR.U,"FRU");
	}
    }

    if(parms->load.fit){
	if(!(zfexist("FLM") && zfexist("FLU") && zfexist("FLV"))){
	    error("FLM, FLU, FLV (.bin) not all exist\n");
	}
	warning("Loading saved recon->FL\n");
	recon->FL.M=readbin("FLM");
	recon->FL.U=dcellread("FLU");
	recon->FL.V=dcellread("FLV");
    }else{
	info2("Building recon->FL\n");
	recon->FL.M=cellnew(ndm, ndm);
	dsp *(*FLM)[ndm]=(dsp*(*)[ndm])recon->FL.M->p;
	for(int idm=0; idm<ndm; idm++){
	    for(int ifit=0; ifit<nfit; ifit++){
		if(fabs(recon->fitwt->p[ifit])<1.e-12) continue;
		dsp *tmp=dspmulsp(recon->W0, HA[idm][ifit],"nn");
		for(int jdm=0; jdm<ndm; jdm++){
		    dspmulsp2(&FLM[idm][jdm],HAT[ifit][jdm], tmp,"nn",
			      recon->fitwt->p[ifit]);
		}
		dspfree(tmp);
	    }
	}
	dspcellfree(HATc);
	if(fabs(parms->fit.tikcr)>1.e-15){
	    double tikcr=parms->fit.tikcr;
	    /*Estimated from the formula.  1/nloc is due to W0, the other
	      scaling is due to ray tracing between different sampling freq.*/
	    int nact=0;
	    for(int idm=0; idm<parms->ndm; idm++){
		nact+=recon->aloc->p[idm]->nloc;
	    }
	    double maxeig=4./nact;
	    info2("Adding tikhonov constraint of %g to FLM\n", tikcr);
	    info2("The maximum eigen value is estimated to be around %e\n", maxeig);
	    dcelladdI(recon->FL.M,tikcr*maxeig);
	}

	{/*Low rank terms. */
	    recon->FL.U=dcellcat_each(recon->FR.U, recon->fitNW, 2);
	    dcell *tmp=NULL;/*negative NW. */
	    dcelladd(&tmp, 1, recon->fitNW, -1);
	    recon->FL.V=dcellcat_each(recon->FR.U, tmp, 2);
	    dcellfree(tmp);
	}
	if(recon->actslave){
	    dcelladd(&recon->FL.M, 1, recon->actslave, 1);
	}
	/*dspcellsym(recon->FL.M); */
	info2("DM Fit number of Low rank terms: %ld in RHS, %ld in LHS\n",
	      recon->FR.U->p[0]->ny, recon->FL.U->p[0]->ny);
	if(parms->save.recon){
	    writebin(recon->FL.M,"FLM.bin");
	    writebin(recon->FL.U,"FLU");
	    writebin(recon->FL.V,"FLV");
	}
    }
    if((parms->fit.alg==0 || parms->fit.alg==2) && parms->fit.bgs){
	muv_direct_diag_prep(&(recon->FL),(parms->fit.alg==2)*parms->fit.svdthres);
    }
    if((parms->fit.alg==0 || parms->fit.alg==2) && !parms->fit.bgs){
	if(fabs(parms->fit.tikcr)<1.e-14){
	    warning("tickcr=%g is too small, chol may fail.\n", parms->fit.tikcr);
	}
	muv_direct_prep(&(recon->FL),(parms->fit.alg==2)*parms->fit.svdthres);
	info2("After cholesky/svd on matrix:\t%.2f MiB\n",get_job_mem()/1024.);
    }
 
    if(parms->save.recon){
       	if(recon->FL.C){
	    chol_convert(recon->FL.C, 1);
	    chol_save(recon->FL.C,"FLC.bin");
	}
	if(recon->FL.MI)
	    writebin(recon->FL.MI,"FLMI");
	if(recon->FL.Up)
	    writebin(recon->FL.Up, "FLUp");
	if(recon->FL.Vp)
	    writebin(recon->FL.Vp, "FLVp");
	if(recon->FL.CB){
	    for(int ib=0; ib<recon->FL.nb; ib++){
		chol_save(recon->FL.CB[ib],"FLCB_%d.bin", ib);
	    }
	}
	if(recon->FL.MIB){
	    writebin(recon->FL.MIB,"FLMIB");
	}
    }
    info2("After assemble fit matrix:\t%.2f MiB\n",get_job_mem()/1024.);
}
Пример #7
0
/**
   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);
	    }
	}
    }
}