示例#1
0
文件: cell.c 项目: bitursa/maos
/**
   Resize a generic cell array.
*/
void cellresize(void *in, long nx, long ny){
    cell *A=(cell*)in;
    if(A->nx==nx || A->ny==1){
	int nold=A->nx*A->ny;
	int nnew=nx*ny;
	if(nnew<nold && iscell(A)){
	    for(int i=nnew; i<nold; i++){
		cellfree_do(A->p[i]);
	    }
	}
	A->p=realloc(A->p, sizeof(cell*)*nnew);
	if(nnew>nold){
	    memset(A->p+nold, 0, (nnew-nold)*sizeof(cell*));
	}
    }else{
	cell **p=calloc(nx*ny, sizeof(cell*));
	long minx=A->nx<nx?A->nx:nx;
	long miny=A->ny<ny?A->ny:ny;
	for(long iy=0; iy<miny; iy++){
	    for(long ix=0; ix<minx; ix++){
		p[ix+iy*nx]=A->p[ix+iy*A->nx];
		A->p[ix+iy*A->nx]=0;
	    }
	}
	if(iscell(A)){
	    for(long i=0; i<A->nx*A->ny; i++){
		cellfree_do(A->p[i]);
	    }
	}
	free(A->p);
	A->p=p;
    }
    A->nx=nx;
    A->ny=ny;
}
示例#2
0
文件: cell.c 项目: bitursa/maos
/**
   check the size of cell array if exist. Otherwise create it. m is created for dcell
*/
void cellinit2(cell **A, const cell *B){
    if(!iscell(B)){
	error("Invalid usage. B must be cell\n");
    }if(*A){
	cellinit(A, B->nx, B->ny);
    }else{
	uint32_t magic=0;
	for(int ib=0; ib<B->nx*B->ny; ib++){
	    if(IND(B,ib)){
		if(!magic){
		    magic=IND(B,ib)->id;
		}else{
		    if(magic!=IND(B, ib)->id){
			error("Mixed type is not supported: %u vs %u\n",
			      magic, IND(B, ib)->id);
		    }
		}
	    }
	}
	if(magic==M_DBL){
	    *A=(cell*)dcellnew2((const dcell*)B);
	}else if(magic==M_CMP){
	    *A=(cell*)ccellnew2((const ccell*)B);
	}else{
	    *A=(cell*)cellnew(B->nx, B->ny);
	}
    }
}
示例#3
0
文件: cell.c 项目: bitursa/maos
/**
   check the size of cell array if exist. Otherwise create it
*/
void cellinit(cell **A, long nx, long ny){
    if(*A){
	if(!(iscell(*A) && (*A)->nx == nx && (*A)->ny==ny)){
	    error("type or size mismatch: id=%u, require (%ld, %ld), A is (%ld, %ld)\n",
		  (*A)->id, nx, ny, (*A)->nx, (*A)->ny);
	}
    }else{
	*A=cellnew(nx, ny);
    }
}
示例#4
0
文件: cell.c 项目: bitursa/maos
/**
   Allocate a new array of the same type
 */
void *cellnew2(const void *A_){
    cell *A=(cell*)A_;
    if(!A_){
	return 0;
    }else if(iscell(A)){
	return cellnew(A->nx, A->ny);
    }else if(A->id==M_DBL){
	return dnew(A->nx, A->ny);
    }else{
	error("Invalid type: id=%u\n", A->id);
	return 0;
    }
}
示例#5
0
文件: read.c 项目: bitursa/maos
static mxArray *readdata(file_t *fp, mxArray **header, int start, int howmany){
    /*
      if start!=0 || howmany!=0 and data is cell, will only read cell from start to start+howmany
      if data is not cell and start==-1, will skip the data.
      Only the first call to readdata will possibly have howmany!=0
     */
    if(fp->eof) return NULL;
    header_t header2;
    if(read_header2(&header2, fp)){
	return NULL;
    }
    uint32_t magic=header2.magic & 0xFFFF;
    if(magic==0){//end of file or empty file
	fp->eof=1;
	return NULL;
    }
    if(header){
	if(header2.str)
	    *header=mxCreateString(header2.str);
	else
	    *header=mxCreateString("");
    }
    free(header2.str); header2.str=NULL;
    long nx=header2.nx;
    long ny=header2.ny;
    int start_save=start;
    if(iscell(magic)){
	if(start!=-1 && howmany==0){
	    if(start!=0){
		error("Invalid use\n");
	    }
	    howmany=nx*ny-start;
	}
    }else if(fp->isfits){
	if(howmany!=0){
	    /*first read of fits file. determine if we need it*/
	    if(start>0){
		start=-1;//skip this block.
	    }
	}
    }else{
	if((start!=0 && start!=-1) || howmany!=0){
	    error("invalid use");
	}
    }
    int iscell=0;
    if(fp->eof) return NULL;
    mxArray *out=NULL;
    switch(magic){
    case MCC_ANY:
    case MCC_DBL:
    case MCC_CMP:
    case MC_CSP:
    case MC_SP:
    case MC_DBL:
    case MC_CMP:
    case MC_INT32:
    case MC_INT64:
	{
	    iscell=1;
	    mwIndex ix;
	    if(fp->eof) return NULL;
	    if(nx*ny>1 && skip_unicell){
		out=mxCreateCellMatrix(nx,ny);
	    }
	    mxArray *header0=mxCreateCellMatrix(nx*ny+1,1);
	    for(ix=0; ix<nx*ny; ix++){
		int start2=0;
		if(start==-1 || ix<start || ix>=start+howmany){
		    start2=-1;
		}
		mxArray *header3=NULL;
		mxArray *tmp=readdata(fp, &header3, start2, 0);
		if(fp->eof){
		    break;
		}
		if(tmp && tmp!=SKIPPED){
		    if(nx*ny==1 && skip_unicell){//only one entry
			out=tmp;
		    }else{
			mxSetCell(out, ix, tmp);
		    }
		    if(header3){
			mxSetCell(header0, ix, header3);
		    }
		}
	    }
	    if(header){
		mxSetCell(header0, nx*ny, *header);
		*header=header0;
	    }
	}
	break;
    case M_SP64:
    case M_SP32:
	{
	    if(start==-1) error("Invalid use\n");
	    size_t size;
	    if(magic==M_SP32){
		size=4;
	    }else if(magic==M_SP64){
		size=8;
	    }else{
		size=0;
		error("Invalid magic\n");
	    }
	    uint64_t nzmax;
	    if(nx!=0 && ny!=0){
		zfread(&nzmax,sizeof(uint64_t),1,fp);
	    }else{
		nzmax=0;
	    }
	    if(fp->eof) return NULL;
	    out=mxCreateSparse(nx,ny,nzmax,mxREAL);
	    if(nx!=0 && ny!=0 && nzmax!=0){
		if(sizeof(mwIndex)==size){/*Match*/
		    zfread(mxGetJc(out), size,ny+1,fp);
		    zfread(mxGetIr(out), size,nzmax, fp);
		}else{
		    long i;
		    mwIndex *Jc0=mxGetJc(out);
		    mwIndex *Ir0=mxGetIr(out);
		    void *Jc=malloc(size*(ny+1));
		    void *Ir=malloc(size*nzmax);
		    zfread(Jc, size, ny+1, fp);
		    zfread(Ir, size, nzmax, fp);
		    if(size==4){
			uint32_t* Jc2=Jc;
			uint32_t* Ir2=Ir;
			for(i=0; i<ny+1; i++){
			    Jc0[i]=Jc2[i];
			}
			for(i=0; i<nzmax; i++){
			    Ir0[i]=Ir2[i];
			}
			free(Jc);
			free(Ir);
		    }else if(size==8){
			uint64_t* Jc2=Jc;
			uint64_t* Ir2=Ir;
			for(i=0; i<ny+1; i++){
			    Jc0[i]=Jc2[i];
			}
			for(i=0; i<nzmax; i++){
			    Ir0[i]=Ir2[i];
			}
			free(Jc);
			free(Ir);
		    }else{
			mexErrMsgTxt("Invalid sparse format\n");
		    }
		}
		zfread(mxGetPr(out), sizeof(double), nzmax, fp);
	    }
	}
	break;
    case M_CSP64:
    case M_CSP32:/*complex sparse*/
	{
	    if(start==-1) error("Invalid use\n");
	    size_t size;
	    switch(magic){
	    case M_CSP32:
		size=4;break;
	    case M_CSP64:
		size=8;break;
	    default:
		size=0;
	    }
	    uint64_t nzmax;
	    if(nx!=0 && ny!=0){
		zfread(&nzmax,sizeof(uint64_t),1,fp);
	    }else{
		nzmax=0;
	    }
	    if(fp->eof) return NULL;
	    out=mxCreateSparse(nx,ny,nzmax,mxCOMPLEX);
	    if(nx!=0 && ny!=0){
		long i;
		if(sizeof(mwIndex)==size){
		    zfread(mxGetJc(out), size,ny+1,fp);
		    zfread(mxGetIr(out), size,nzmax, fp);
		}else{
		    mwIndex *Jc0=mxGetJc(out);
		    mwIndex *Ir0=mxGetIr(out);
		    void *Jc=malloc(size*(ny+1));
		    void *Ir=malloc(size*nzmax);
		    zfread(Jc, size, ny+1, fp);
		    zfread(Ir, size, nzmax, fp);
		    if(size==4){
			uint32_t* Jc2=Jc;
			uint32_t* Ir2=Ir;
			for(i=0; i<ny+1; i++){
			    Jc0[i]=Jc2[i];
			}
			for(i=0; i<nzmax; i++){
			    Ir0[i]=Ir2[i];
			}
			free(Jc);
			free(Ir);
		    }else if(size==8){
			uint64_t* Jc2=Jc;
			uint64_t* Ir2=Ir;
			for(i=0; i<ny+1; i++){
			    Jc0[i]=Jc2[i];
			}
			for(i=0; i<nzmax; i++){
			    Ir0[i]=Ir2[i];
			}
			free(Jc);
			free(Ir);
		    }else{
			info("size=%lu\n", size);
			error("Invalid sparse format\n");
		    }
		}
		dcomplex *tmp=malloc(sizeof(dcomplex)*nzmax);
		zfread(tmp, sizeof(dcomplex), nzmax, fp);
		double *Pr=mxGetPr(out);
		double *Pi=mxGetPi(out);
		for(i=0; i<nzmax; i++){
		    Pr[i]=tmp[i].x;
		    Pi[i]=tmp[i].y;
		}
		free(tmp);
	    }
	}
	break;
    case M_DBL:/*double array*/
	if(start==-1){
	    if(zfseek(fp, sizeof(double)*nx*ny, SEEK_CUR)){
		error("Seek failed\n");
	    }
	    out=SKIPPED;
	}else{
	    out=mxCreateDoubleMatrix(nx,ny,mxREAL);
	    if(nx!=0 && ny!=0){
		zfread(mxGetPr(out), sizeof(double),nx*ny,fp);
	    }
	}
	break;
    case M_FLT:/*float array*/
	if(start==-1){
	    if(zfseek(fp, sizeof(float)*nx*ny, SEEK_CUR)){
		error("Seek failed\n");
	    }
	    out=SKIPPED;
	}else{
	    mwSize nxy[2]={nx,ny};
	    out=mxCreateNumericArray(2, nxy,mxSINGLE_CLASS, mxREAL);
	    if(nx!=0 && ny!=0){
		zfread((float*)mxGetPr(out), sizeof(float),nx*ny, fp);
	    }
	}break;
    case M_INT64:/*long array*/
    case M_INT32:
    case M_INT16:
    case M_INT8:
	{
	    int byte=0;
	    mxClassID id;
	    switch(magic){
	    case M_INT64: byte=8; id=mxINT64_CLASS; break;
	    case M_INT32: byte=4; id=mxINT32_CLASS; break;
	    case M_INT16: byte=2; id=mxINT16_CLASS; break;
	    case M_INT8:  byte=1; id=mxINT8_CLASS; break;
	    default: id=0;
	    }
	    if(start==-1){
		if(zfseek(fp, byte*nx*ny, SEEK_CUR)){
		    error("Seek failed\n");
		}
		out=SKIPPED;
	    }else{
		out=mxCreateNumericMatrix(nx,ny,id,mxREAL);
		if(nx!=0 && ny!=0){
		    /*Don't use sizeof(mxINT64_CLASS), it is just an integer, 
		      not a valid C type.*/
		    zfread(mxGetPr(out), byte,nx*ny,fp);
		}
	    }
	}
	break;
    case M_CMP:/*double complex array*/
	if(start==-1){
	    if(zfseek(fp, 16*nx*ny, SEEK_CUR)){
		error("Seek failed\n");
	    }
	    out=SKIPPED;
	}else{
	    out=mxCreateDoubleMatrix(nx,ny,mxCOMPLEX);
	    if(nx!=0 && ny!=0){
		dcomplex*tmp=malloc(sizeof(dcomplex)*nx*ny);
		zfread(tmp,sizeof(dcomplex),nx*ny,fp);
		double *Pr=mxGetPr(out);
		double *Pi=mxGetPi(out);
		long i;
		for(i=0; i<nx*ny; i++){
		    Pr[i]=tmp[i].x;
		    Pi[i]=tmp[i].y;
		}
		free(tmp);
	    }
	}
	break;
    case M_ZMP:/*float complex array. convert to double*/
	if(start==-1){
	    if(zfseek(fp, 8*nx*ny, SEEK_CUR)){
		error("Seek failed\n");
	    }
	    out=SKIPPED;
	}else{
	    mwSize nxy[2]={nx, ny};
	    out=mxCreateNumericArray(2, nxy,mxSINGLE_CLASS, mxCOMPLEX);
	    if(nx!=0 && ny!=0){
		fcomplex*tmp=malloc(sizeof(fcomplex)*nx*ny);
		zfread(tmp,sizeof(fcomplex),nx*ny,fp);
		float *Pr=(float*)mxGetPr(out);
		float *Pi=(float*)mxGetPi(out);
		long i;
		for(i=0; i<nx*ny; i++){
		    Pr[i]=tmp[i].x;
		    Pi[i]=tmp[i].y;
		}
		free(tmp);
	    }
	}
	break;
    case M_HEADER:
	break;
    default:
	fprintf(stderr,"magic=%x\n",magic);
	warning("Unrecognized file. Please recompile the mex routines in the newest code\n");
	out=NULL;
    }
    start=start_save;
    if(!iscell && fp->isfits==1){/*fits file may contain extra extensions.*/
	fp->isfits++;
	int icell=0;
	mxArray **outarr=NULL;
	mxArray **headerarr=NULL;
	while(out){
	    icell++;
	    outarr=realloc(outarr, sizeof(mxArray*)*icell);
	    headerarr=realloc(headerarr, sizeof(mxArray*)*icell);
	    if(out==SKIPPED) out=NULL;
	    outarr[icell-1]=out;
	    if(header) headerarr[icell-1]=*header;
	    int start2=0;
	    if(howmany!=0){//selective reading.
		if(icell<start || icell+1>start+howmany){
		    start2=-1;//don't read next data.
		}
	    }
	    out=readdata(fp, header, start2, 0);
	}
	if(icell>1){/*set output.*/
	    out=mxCreateCellMatrix(icell, 1);
	    if(header) *header=mxCreateCellMatrix(icell, 1);
	    int i;
	    for(i=0; i<icell; i++){
		mxSetCell(out, i, outarr[i]);
		if(header) mxSetCell(*header, i, headerarr[i]);
	    }
	    free(outarr);
	    free(headerarr);
	}else{
	    out=outarr[0];
	    if(header) *header=headerarr[0];
	}
    }
    if(!out){
	out=mxCreateDoubleMatrix(0,0,mxREAL);
    }
    return out;
}
示例#6
0
文件: cell.c 项目: bitursa/maos
cell *readdata_by_id(file_t *fp, uint32_t id, int level, header_t *header){
    header_t header2={0};
    if(!header){
	header=&header2;
	read_header(header, fp);
    }
    void *out=0;
    if(level<0 && !iscell(&header->magic)){
	level=0;
    }
    if(zfisfits(fp) || level==0){
	switch(level){
	case 0:/*read a mat*/
	    if(!id) id=header->magic;
	    switch(id){
	    case M_DBL: 
	    case M_FLT:
		out=dreaddata(fp, header);break;
	    case M_CMP: 
	    case M_ZMP:
		out=creaddata(fp, header);break;
	    case M_LONG: out=lreaddata(fp, header);break;
	    case M_LOC64: out=locreaddata(fp, header); break;
	    case M_MAP64: out=mapreaddata(fp, header); break;
	    case M_DSP32: case M_DSP64: /**Possible to read mismatched integer*/
		out=dspreaddata(fp, header);break;
	    case M_SSP32: case M_SSP64:
		out=sspreaddata(fp, header);break;
	    case M_CSP32: case M_CSP64:
		out=cspreaddata(fp, header);break;
	    case M_ZSP64: case M_ZSP32:
		out=zspreaddata(fp, header);break;	
	    default:error("data type id=%u not supported\n", id);
	    }
	    break;
	case 1:{/*read a cell from fits*/
	    int maxlen=10;
	    void **tmp=malloc(maxlen*sizeof(void*));
	    int nx=0;
	    do{
		if(nx>=maxlen){
		    maxlen*=2;
		    tmp=realloc(tmp, sizeof(void*)*maxlen);
		}
		tmp[nx++]=readdata_by_id(fp, id, 0, header);
		free(header->str);header->str=0;
	    }while(!read_header2(header, fp));
	    cell *dcout=cellnew(nx, 1);
	    memcpy(dcout->p, tmp, sizeof(void*)*nx);
	    free(tmp);
	    out=dcout;
	}
	    break;
	default:
	    error("Only support zero or one level of cell when reading fits file\n");
	}
    }else{
	if(!iscell(&header->magic)){
	    //wrap array into cell
	    info2("Read cell from non cell data\n");
	    cell *dcout=cellnew(1,1);
	    dcout->p[0]=readdata_by_id(fp, id, level-1, header);
	    out=dcout;
	}else{
	    long nx=header->nx;
	    long ny=header->ny;
	    cell *dcout=cellnew(nx, ny);
	    dcout->header=header->str; header->str=0;
	    for(long i=0; i<nx*ny; i++){
		dcout->p[i]=readdata_by_id(fp, id, level-1, 0);
	    }
	    out=dcout;
	}
    }
    free(header->str);header->str=0;
    return out;
}
示例#7
0
文件: cell.c 项目: bitursa/maos
cell *cell_cast(const void *A){
    if(!A) return 0;
    assert(iscell(A));
    return (cell*)A;
}
示例#8
0
/**
   Read in asterism WFS wvf.*/
long setup_star_read_wvf(STAR_S *star, int nstar, const PARMS_S *parms, int seed){
    const double ngsgrid=parms->maos.ngsgrid;
    const int nwvl=parms->maos.nwvl;
    long nstep=0;
    TIC;tic;
    for(int istar=0; istar<nstar; istar++){
	STAR_S *stari=&star[istar];
	int npowfs=parms->maos.npowfs;
	stari->wvfout=mycalloc(npowfs,ccell**);
	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);/*Used to be double, but -0 appears. */
	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];
	    if(stari->use[ipowfs]==0){
		continue;
	    }
	    char *fnwvf[2][2]={{NULL,NULL},{NULL,NULL}};
	    PISTAT_S *pistati=&stari->pistat[ipowfs];
	    
	    /*info2("Reading PSF for (%5.1f, %5.1f), ipowfs=%d\n",thetax,thetay,ipowfs); */
	    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;
		    }
		    fnwvf[iy][ix]=myalloca(PATH_MAX, char);
		    snprintf(fnwvf[iy][ix],PATH_MAX,"%s/wvfout/wvfout_seed%d_sa%d_x%g_y%g",
			     dirstart,seed,msa,thx,thy);
	
		    if(!zfexist(fnwvf[iy][ix])){
			//warning("%s doesnot exist\n",fnwvf[iy][ix]);
			fnwvf[iy][ix]=0;
		    }else{
			wtsum+=wtxi;
		    }
		}
	    }
	    if(wtsum<0.01){
		error("PSF is not available for (%g,%g). wtsum=%g\n",thetax,thetay, wtsum);
	    }
	    /*Now do the actual reading */
	    for(int ix=0; ix<2; ix++){
		for(int iy=0; iy<2; iy++){
		    double wtxi=fabs(((1-ix)-wtx)*((1-iy)-wty))/wtsum;
		    if(fnwvf[iy][ix]){
			/*info("Loading %.4f x %s\n", wtxi, fnwvf[iy][ix]); */
			file_t *fp_wvf=zfopen(fnwvf[iy][ix],"rb");
			header_t header={0,0,0,0};
			read_header(&header, fp_wvf);
			if(!iscell(&header.magic)){
			    error("expected data type: %u, got %u\n",(uint32_t)MCC_ANY, header.magic);
			}
			nstep=header.nx;
			free(header.str);
			if(parms->skyc.limitnstep >0 && nstep>parms->skyc.limitnstep){
			    nstep=parms->skyc.limitnstep;
			    warning("Only read %ld steps\n",nstep);
			}
			if(stari->nstep==0){
			    stari->nstep=nstep;
			}else{
			    if(stari->nstep!=nstep){
				error("Different type has different steps\n");
			    }
			}
		    
			if(!stari->wvfout[ipowfs]){
			    stari->wvfout[ipowfs]=mycalloc(nstep,ccell*);
			}
			ccell **pwvfout=stari->wvfout[ipowfs];
			for(long istep=0; istep<nstep; istep++){
			    ccell *wvfi=ccellreaddata(fp_wvf, 0);
			    ccelladd(&(pwvfout[istep]), 1, wvfi, wtxi);
			    ccellfree(wvfi);
			}
			/*zfeof(fp_wvf); */
			zfclose(fp_wvf);
		    }
		}/*iy */
	    }/*ix */
	    /*Don't bother to scale ztiltout since it does not participate in physical optics simulations. */
	    if(parms->skyc.bspstrehl){
		dmat*  scale=pistati->scale;
		ccell **pwvfout=stari->wvfout[ipowfs];
		for(int iwvl=0; iwvl<nwvl; iwvl++){
		    for(int isa=0; isa<nsa; isa++){
			/*info("Scaling WVF isa %d iwvl %d with %g\n", isa, iwvl, IND(scale,isa,iwvl)); */
			for(long istep=0; istep<stari->nstep; istep++){
			    cscale(pwvfout[istep]->p[isa+nsa*iwvl], IND(scale,isa,iwvl));
			}/*istep */
		    }/*isa */
		}/*iwvl */
	    }/* */
	}/*ipowfs */
    }/*istar */
示例#9
0
long setup_star_read_ztilt(STAR_S *star, int nstar, const PARMS_S *parms, int seed){
    const double ngsgrid=parms->maos.ngsgrid;
    long nstep=0;
    TIC;tic;
    for(int istar=0; istar<nstar; istar++){
	STAR_S *stari=&star[istar];
	int npowfs=parms->maos.npowfs;
	stari->ztiltout=dcellnew(npowfs, 1);
	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);/*Used to be double, but -0 appears. */
	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];
	    const int ng=nsa*2;
	    char *fnztilt[2][2]={{NULL,NULL},{NULL,NULL}};
	    char *fngoff[2][2]={{NULL, NULL}, {NULL, 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;
		    }
		    fnztilt[iy][ix]=myalloca(PATH_MAX, char);
		    if(parms->skyc.usephygrad){
			warning_once("Using phygrad\n");
			snprintf(fnztilt[iy][ix],PATH_MAX,"%s/phygrad/phygrad_seed%d_sa%d_x%g_y%g",
				 dirstart,seed,msa,thx,thy);
		    }else{
			snprintf(fnztilt[iy][ix],PATH_MAX,"%s/ztiltout/ztiltout_seed%d_sa%d_x%g_y%g",
				 dirstart,seed,msa,thx,thy);
		    }
		    fngoff[iy][ix]=myalloca(PATH_MAX, char);
		    snprintf(fngoff[iy][ix],PATH_MAX,"%s/gradoff/gradoff_sa%d_x%g_y%g",
			     dirstart,msa,thx,thy);
		    if(!zfexist(fnztilt[iy][ix])){
			//warning("%s doesnot exist\n",fnwvf[iy][ix]);
			fnztilt[iy][ix]=fngoff[iy][ix]=NULL;
		    }else{
			wtsum+=wtxi;
		    }
		}
	    }
	    if(wtsum<0.01){
		error("PSF is not available for (%g,%g). wtsum=%g\n",thetax,thetay, wtsum);
	    }
	    /*Now do the actual reading */
	    for(int ix=0; ix<2; ix++){
		for(int iy=0; iy<2; iy++){
		    double wtxi=fabs(((1-ix)-wtx)*((1-iy)-wty))/wtsum;
		    if(fnztilt[iy][ix]){
			file_t *fp_ztilt=zfopen(fnztilt[iy][ix],"rb");
			header_t header={0,0,0,0};
			read_header(&header, fp_ztilt);
			
			if(iscell(&header.magic)){
			    // error("expected data type: %u, got %u\n",(uint32_t)MCC_ANY, header.magic);
			    nstep=header.nx;
			    free(header.str);
			    if(stari->nstep==0){
				stari->nstep=nstep;
			    }else{
				if(stari->nstep!=nstep){
				    error("Different type has different steps\n");
				}
			    }
			    if(!stari->ztiltout->p[ipowfs]){
				stari->ztiltout->p[ipowfs]=dnew(ng, nstep);
			    }
			    dmat  *ztiltout=stari->ztiltout->p[ipowfs];
			    for(long istep=0; istep<nstep; istep++){
				dmat *ztilti=dreaddata(fp_ztilt, 0);
				for(int ig=0; ig<ng; ig++){
				    ztiltout->p[ig+istep*ng]+=ztilti->p[ig]*wtxi;
				}
				dfree(ztilti);
			    }
			}else{
			    dmat *tmp=dreaddata(fp_ztilt, &header);
			    dadd(&stari->ztiltout->p[ipowfs], 1, tmp, wtxi );
			    dfree(tmp);
			}
			zfclose(fp_ztilt);
		    }/* if(fnwvf) */
		    if(fngoff[iy][ix] && zfexist(fngoff[iy][ix])){
			if(!stari->goff){
			    stari->goff=dcellnew(npowfs, 1);
			}
			dmat *tmp=dread("%s", fngoff[iy][ix]);
			dadd(&stari->goff->p[ipowfs], 1, tmp, wtxi);
			dfree(tmp);
		    }
		}/*iy */
	    }/*ix */
	}/*ipowfs */
    }/*istar */
    if(parms->skyc.verbose){
	toc2("Reading PSF");
    }
    //close(fd);
    return nstep;
}