/** 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; }
/** 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); } } }
/** 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); } }
/** 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; } }
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; }
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; }
cell *cell_cast(const void *A){ if(!A) return 0; assert(iscell(A)); return (cell*)A; }
/** 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 */
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; }