/* * GVDR library for reading GVDR data files * Copyright (C) 1994 Michael J. Maurer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Michael Maurer * Durand Bldg - Room 232 * Stanford, CA 94305-4055 * (415) 723-1024 */ static char rcsid[]="$Id: gvdr.c,v 1.11 1994/05/11 07:37:52 maurer Exp $"; /****************************************************************************** gvdr.c Function: Interface to read GVDR files. This file is part of the STARLab Magellan Altimeter Data Processing Software. Michael Maurer, March 1993. ******************************************************************************/ /* $Log: gvdr.c,v $ * Revision 1.11 1994/05/11 07:37:52 maurer * Fixed bug in gvdr_mranf() for real this time. * * Revision 1.10 1994/05/11 00:13:14 maurer * Fixed bug in gvdr_mranf() that wasn't allocating correctly. * * Revision 1.9 1994/04/29 02:00:33 maurer * Modified mgvdr_ranf() for PDS needs. * * Revision 1.8 1994/02/02 02:12:55 maurer * Changed ADF from min/max to mean/var. * * Revision 1.7 1994/01/23 23:01:07 maurer * Moved gvdr_uchdr() here. * * Revision 1.6 1994/01/06 00:12:48 maurer * Added ga_azim. * * Revision 1.5 1993/09/10 19:35:28 maurer * Moved proc_time() to gvdr_proc_time() here. * Changed *_parsehdr() syntax. * * Revision 1.4 1993/08/25 21:09:08 maurer * Added ADF records to GVDR cells. * Added memory-based readers, called by gvdr_mrcell(). * Added pad reader. * * Revision 1.3 1993/08/02 00:58:35 maurer * Split into reader/writer modules. * Moved index code to gv_index.c. * Removed map.h and util.h for public distribution. * * Revision 1.2 1993/07/30 01:59:36 maurer * Removed SFDU from individual GVDR cells. * Added line index and pixel indices to make GVDR nearly direct-accessible. * Removed SFDU line start/end markers (replaced with indices). * * Revision 1.1 1993/07/03 23:42:48 maurer * Updated to use new GVDR data types: * moved NFF into ANF record * changed many sfloats to 1-byte packed * * Revision 1.0 1993/06/12 00:37:22 maurer * Initial revision * */ #include #include #include #include #include "libmisc.h" #include "gvdr.h" #define GVDR_C #include "sfdug.p" #include "gv_sfdu.p" #include "gv_pack.p" #include "gv_cvt.p" #include "gv_index.p" #include "gvdr.p" /****************************************************************************** gvdr_reset Zeroes the Nxxx fields of GVDR cell C. Does not change the NAxxx fields or the pointers. ******************************************************************************/ void gvdr_reset(gvdrcell_t *C) { C->gv_Nxif=0; C->gv_Nedf=0; C->gv_Nadf=0; C->gv_Nanf=0; C->gv_Msig0=0; C->gv_Mfit=0; } /****************************************************************************** gvdr_clear Zeroes the fields of GVDR cell C. ******************************************************************************/ void gvdr_clear(gvdrcell_t *C) { gvdr_reset(C); C->gv_X=0; C->gv_Y=0; C->gv_lon=0; C->gv_lat=0; C->gv_NAxif=0; C->gv_NAedf=0; C->gv_NAadf=0; C->gv_NAanf=0; C->gv_xif=NULL; C->gv_edf=NULL; C->gv_adf=NULL; C->gv_anf=NULL; } /****************************************************************************** gvdr_free Frees all memory associated with GVDR cell C, and zeroes its fields. ******************************************************************************/ void gvdr_free(gvdrcell_t *C) { int i; if (C->gv_NAxif>0 && C->gv_xif) free(C->gv_xif); if (C->gv_NAedf>0 && C->gv_edf) free(C->gv_edf); if (C->gv_NAadf>0 && C->gv_adf) free(C->gv_adf); for (i=0; igv_NAanf; i++) { if (C->gv_anf[i].ga_NAsig0>0 && C->gv_anf[i].ga_sig0) free(C->gv_anf[i].ga_sig0); if (C->gv_anf[i].ga_NAsig0>0 && C->gv_anf[i].ga_Vsig0) free(C->gv_anf[i].ga_Vsig0); if (C->gv_anf[i].ga_NAfit>0 && C->gv_anf[i].ga_fit) free(C->gv_anf[i].ga_fit); } if (C->gv_NAanf>0 && C->gv_anf) free(C->gv_anf); gvdr_clear(C); } /****************************************************************************** gvdr_realloc Allocates additional memory so that GVDR cell C has enough room for NAxif cohorts of type XIF, NAedf cohorts of type EDF, NAadf cohorts of type ADF, NAanf cohorts of type ANF with scattering laws of NAsig0 elements and NAfit scattering law fits. Does not disturb existing cohorts, even if parameter NAxxx is less that C->gv_NAxxx, or if NAsig0 or NAfit is smaller than the current allocation. Thus it can be called like this: gvdr_realloc(C,0,0,0,10,20,4) which would insure there was room for at least 10 ANF cohorts of at least 20 scattering angles and 4 scattering law fits each, but would not cause problems if there were already room for 7 cohorts of 6 fits each. The other fields (xif,edf) would not be disturbed either. ******************************************************************************/ void gvdr_realloc(gvdrcell_t *C, int NAxif, int NAedf, int NAadf, int NAanf, int NAsig0, int NAfit) { int i; if (NAxif>C->gv_NAxif) { realloct_err(C->gv_xif,NAxif,gvdrxif_t); C->gv_NAxif=NAxif; } if (NAedf>C->gv_NAedf) { realloct_err(C->gv_edf,NAedf,gvdredf_t); C->gv_NAedf=NAedf; } if (NAadf>C->gv_NAadf) { realloct_err(C->gv_adf,NAadf,gvdradf_t); C->gv_NAadf=NAadf; } if (NAanf>C->gv_NAanf) { realloct_err(C->gv_anf,NAanf,gvdranf_t); for (i=C->gv_NAanf; igv_anf[i].ga_sig0=NULL; C->gv_anf[i].ga_Vsig0=NULL; C->gv_anf[i].ga_NAsig0=0; C->gv_anf[i].ga_fit=NULL; C->gv_anf[i].ga_NAfit=0; } C->gv_NAanf=NAanf; } if (NAsig0>0) { for (i=0; igv_NAanf; i++) { if (C->gv_anf[i].ga_NAsig0gv_anf[i].ga_sig0,NAsig0,float); realloct_err(C->gv_anf[i].ga_Vsig0,NAsig0,float); } C->gv_anf[i].ga_NAsig0=NAsig0; } } if (NAfit>0) { for (i=0; igv_NAanf; i++) { if (C->gv_anf[i].ga_NAfitgv_anf[i].ga_fit,NAfit,gvdrfit_t); C->gv_anf[i].ga_NAfit=NAfit; } } } /****************************************************************************** gvdr_rhdr Reads the GVDR file header. Returns nonzero on failure. ******************************************************************************/ int gvdr_rhdr(FILE *fp, gvdrhdr_t *hdr) { return gsfdu_rhdr(fp,hdr); } /****************************************************************************** gvdr_rchdr Reads header of GVDR cell in current input format (as set by a call to gcvt_setmode()), converts to local format and decompresses. Returns nonzero on error. ******************************************************************************/ static int gvdr_rchdr(FILE *fp, gvdrcell_t *C) { gvdrcell_rec Cr; if (fread(&Cr,sizeof(gvdrcell_rec),1,fp)!=1) return 1; gcvt_cell(&Cr); gunpack_cell(&Cr,C); return 0; } /****************************************************************************** gvdr_uchdr Updates the gv_Msig0 and gv_Mfit fields of GVDR cell C. ******************************************************************************/ void gvdr_uchdr(gvdrcell_t *C) { int i; C->gv_Msig0=0; C->gv_Mfit=0; for (i=0; igv_Nanf; i++) { if (C->gv_anf[i].ga_Nsig0 > C->gv_Msig0) C->gv_Msig0 = C->gv_anf[i].ga_Nsig0; if (C->gv_anf[i].ga_Nfit > C->gv_Mfit) C->gv_Mfit = C->gv_anf[i].ga_Nfit; } } /****************************************************************************** gvdr_rxif Reads XIF portion of GVDR cell in current input format (as set by a call to gcvt_setmode()) and converts to local format. Space for data must be pre-allocated in cell. Returns nonzero on error. ******************************************************************************/ static int gvdr_rxif(FILE *fp, gvdrxif_t *gxif, int Nxif) { int i; gvdrxif_rec gr; for (i=0; iganf[i].ga_NAsig0 || gr.gar_Nfit>ganf[i].ga_NAfit) return 1; if (gr.gar_Nsig0>NAsig0) { if (sig0) free(sig0); if (Vsig0) free(Vsig0); NAsig0=gr.gar_Nsig0; malloct_err(sig0,NAsig0,unsigned char); malloct_err(Vsig0,NAsig0,unsigned char); } if (gr.gar_Nfit>NAfit) { if (fit) free(fit); NAfit=gr.gar_Nfit; malloct_err(fit,NAfit,gvdrfit_rec); } if (fread(sig0,sizeof(unsigned char),gr.gar_Nsig0,fp)!=gr.gar_Nsig0) return 2; if (fread(Vsig0,sizeof(unsigned char),gr.gar_Nsig0,fp)!=gr.gar_Nsig0) return 3; if (fread(fit,sizeof(gvdrfit_rec),gr.gar_Nfit,fp)!=gr.gar_Nfit) return 4; /* sig0, Vsig0 and fit need no format conversion like gcvt_anf() */ gunpack_anf(&gr,sig0,Vsig0,fit,&ganf[i]); } return 0; } /****************************************************************************** gvdr_rcell Reads a single GVDR cell in current input format (as set by a call to gcvt_setmode()) and converts to local format. Note that gv_X, gv_Y, gv_lon and gv_lat are not stored in the file explicitly, and will not be changed by this function. Returns nonzero on failure. ******************************************************************************/ int gvdr_rcell(FILE *fp, gvdrcell_t *C) { int err; if (err=gvdr_rchdr(fp,C)) { error(0,errno,"[gvdr_rcell] gvdr_rchdr failed %d",err); return 1; } if (err=gvdr_rxif(fp,C->gv_xif,C->gv_Nxif)) { error(0,errno,"[gvdr_rcell] gvdr_rxif failed %d",err); return 2; } if (err=gvdr_redf(fp,C->gv_edf,C->gv_Nedf)) { error(0,errno,"[gvdr_rcell] gvdr_redf failed %d",err); return 3; } if (err=gvdr_radf(fp,C->gv_adf,C->gv_Nadf)) { error(0,errno,"[gvdr_rcell] gvdr_radf failed %d",err); return 3; } if (err=gvdr_ranf(fp,C->gv_anf,C->gv_Nanf)) { error(0,errno,"[gvdr_rcell] gvdr_ranf failed %d",err); return 4; } gvdr_uchdr(C); return 0; } /****************************************************************************** gvdr_mrchdr Memory-based version of gvdr_rchdr(). ******************************************************************************/ static int gvdr_mrchdr(char **src, gvdrcell_t *C) { gvdrcell_rec Cr; memcpy(&Cr,*src,sizeof(gvdrcell_rec)); *src+=sizeof(gvdrcell_rec); gcvt_cell(&Cr); gunpack_cell(&Cr,C); return 0; } /****************************************************************************** gvdr_mrxif Memory-based version of gvdr_rxif(). ******************************************************************************/ int gvdr_mrxif(char **src, gvdrxif_t *gxif, int Nxif) { int i; gvdrxif_rec gr; for (i=0; iganf[i].ga_NAsig0 || gr.gar_Nfit>ganf[i].ga_NAfit) return 1; /* sig0, Vsig0 and fit need no format conversion like gcvt_anf() */ sig0= *src; *src+= Nsig0 ? Nsig0 : gr.gar_Nsig0; Vsig0= *src; *src+= Nsig0 ? Nsig0 : gr.gar_Nsig0; fit=(gvdrfit_rec *)*src; *src+=gr.gar_Nfit*sizeof(gvdrfit_rec); gunpack_anf(&gr,sig0,Vsig0,fit,&ganf[i]); } return 0; } /****************************************************************************** gvdr_mrcell Memory-based version of gvdr_rcell(). ******************************************************************************/ int gvdr_mrcell(char **src, gvdrcell_t *C) { int err; if (err=gvdr_mrchdr(src,C)) { error(0,0,"[gvdr_mrcell] gvdr_mrchdr failed %d",err); return 1; } if (err=gvdr_mrxif(src,C->gv_xif,C->gv_Nxif)) { error(0,0,"[gvdr_mrcell] gvdr_mrxif failed %d",err); return 2; } if (err=gvdr_mredf(src,C->gv_edf,C->gv_Nedf)) { error(0,0,"[gvdr_mrcell] gvdr_mredf failed %d",err); return 3; } if (err=gvdr_mradf(src,C->gv_adf,C->gv_Nadf)) { error(0,0,"[gvdr_mrcell] gvdr_mradf failed %d",err); return 3; } if (err=gvdr_mranf(src,C->gv_anf,C->gv_Nanf,0)) { error(0,0,"[gvdr_mrcell] gvdr_mranf failed %d",err); return 4; } gvdr_uchdr(C); return 0; } /****************************************************************************** gvdr_rihdr Reads an SFDU index header from the file fp. If iposp is non-NULL, fills it with file pointer on entry. Returns nonzero on failure. ******************************************************************************/ int gvdr_rihdr(FILE *fp, int *len, fpos_t *iposp) { if (iposp && fgetpos(fp,iposp)) return 1; return gsfdu_rihdr(fp,len); } /****************************************************************************** gvdr_rlhdr Reads an SFDU line/cell header from the file fp. Returns nonzero on failure. ******************************************************************************/ int gvdr_rlhdr(FILE *fp, int *len) { return gsfdu_rlhdr(fp,len); } /****************************************************************************** gvdr_rtrl Reads an SFDU line trailer from the file fp. Returns nonzero on failure. ******************************************************************************/ int gvdr_rtrl(FILE *fp) { return gsfdu_rtrl(fp); } /****************************************************************************** gvdr_seek1 Seeks file through one dimension of a GVDR index. On input, fp is open GVDR file (with file pointer anywhere) and I already contains an index of any type. The value addr is looked up in the index I, and the file is seeked to the position listed in the index. Returns nonzero on failure. ******************************************************************************/ int gvdr_seek1(FILE *fp, gvdr_index_t *I, int addr, fpos_t *fpos) { if (gindex_get(I,addr,fpos)) return 1; if (fsetpos(fp,fpos)) return 2; return 0; } /****************************************************************************** gvdr_seek2 Seeks file through two dimensions of a GVDR index. On input, fp is open GVDR file (with file pointer anywhere) and I1 already contains an index with entries pointing to other indexes. The value addr1 is looked up in the index I1, and the file is seeked to the position listed in the index. Another index is read from this position into I2. (I2 must have been initialized by gindex_clear() at the beginning of the program, but need not be initialized before every call.) Then addr2 is looked up in I2, and the file is seeked once again. On exit, the file is ready to read whatever is pointed to by the second index entry (normally a single GVDR cell). Returns nonzero on failure. ******************************************************************************/ int gvdr_seek2(FILE *fp, gvdr_index_t *I1, gvdr_index_t *I2, int addr1, int addr2, fpos_t *fpos) { int err; if (gindex_get(I1,addr1,fpos)) return 1; if (fsetpos(fp,fpos)) return 2; if (err=gindex_read(fp,I2,*fpos)) return 3; if (gindex_get(I2,addr2,fpos)) return 4; if (fsetpos(fp,fpos)) return 5; return 0; } /****************************************************************************** gvdr_parsehdr Parse the SFDU file header catalogs into data structure hdr->gc2. ******************************************************************************/ int gvdr_parsehdr(gvdrhdr_t *hdr) { return gsfdu_parsehdr(hdr->kv2,&hdr->gc2); } int gvdr_rpad(FILE *fp, unsigned int mult, char pad, fpos_t *fposp) { fpos_t fpos; unsigned int nb; int c; if (fgetpos(fp,&fpos)) { error(0,errno,"[gvdr_rpad] fgetpos failed"); return 1; } nb=fpos%mult; nb=(mult-nb)%mult; while (nb-- > 0) { if ((c=getc(fp))!=pad) { error(0,0,"[gvdr_rpad] non-pad character '%c'",c); return 2; } } if (fgetpos(fp,fposp)) { error(0,errno,"[gvdr_rpad] fgetpos failed"); return 3; } return 0; } /****************************************************************************** gvdr_pcell Prints out a GVDR cell C in human readable format. ******************************************************************************/ int gvdr_pcell(FILE *fp, gvdrcell_t *C) { int i,j; fprintf(fp,"X=%+4d Y=%+4d lon=%6.2f lat=%+6.2f Nxif=%2d Nedf=%2d Nadf=%2d Nanf=%2d\n", C->gv_X, C->gv_Y, C->gv_lon, C->gv_lat, C->gv_Nxif, C->gv_Nedf, C->gv_Nadf, C->gv_Nanf); if (C->gv_Nxif>0) fprintf(fp,"%3s %5s %6s %5s %5s %3s %3s %3s %3s %6s %6s %6s\n", "XIF","poln","azim","inc","Nlook","hlo","hmd","hhi","hpk","c0","c1","c2"); for (i=0; igv_Nxif; i++) fprintf(fp,"%3d %+5.1f %6.2f %5.2f %5d %3d %3d %3d %3d %+6.2f %+6.2f %+6.2f\n", i, C->gv_xif[i].gx_poln, C->gv_xif[i].gx_azim, C->gv_xif[i].gx_inc, C->gv_xif[i].gx_Nlooks, C->gv_xif[i].gx_hlo, C->gv_xif[i].gx_hmed, C->gv_xif[i].gx_hhi, C->gv_xif[i].gx_hpk, C->gv_xif[i].gx_c0, C->gv_xif[i].gx_c1, C->gv_xif[i].gx_c2); if (C->gv_Nedf>0) fprintf(fp,"%3s %5s %6s %5s %5s %5s %9s\n", "EDF","poln","azim","inc","Nlook","emiss","emissv"); for (i=0; igv_Nedf; i++) fprintf(fp,"%3d %+5.1f %6.2f %5.2f %5d %5.3f %9.7f\n", i, C->gv_edf[i].ge_poln, C->gv_edf[i].ge_azim, C->gv_edf[i].ge_inc, C->gv_edf[i].ge_Nlooks, C->gv_edf[i].ge_emiss, C->gv_edf[i].ge_emissv); if (C->gv_Nadf>0) fprintf(fp,"%3s %5s %7s %7s %5s %5s %5s %9s\n", "ADF","Nlook","rad","radv","slop","slopv","rho","rhov"); for (i=0; igv_Nadf; i++) fprintf(fp,"%3d %5d %7.2f %7.4f %5.2f %5.2f %5.3f %9.7f\n", i, C->gv_adf[i].gd_Nlooks, C->gv_adf[i].gd_radius, C->gv_adf[i].gd_radiusv, C->gv_adf[i].gd_slope, C->gv_adf[i].gd_slopev, C->gv_adf[i].gd_rho, C->gv_adf[i].gd_rhov); for (i=0; igv_Nanf; i++) { fprintf(fp,"ANF %3d azim=%3.0f dcent=%+5.0f Nsig0=%2d Nlook=%4d\n", i, C->gv_anf[i].ga_azim, C->gv_anf[i].ga_dcent, C->gv_anf[i].ga_Nsig0, C->gv_anf[i].ga_Nlooks); for (j=0; jgv_anf[i].ga_Nsig0; j++) fprintf(fp," %6.2f %8.2f\n", C->gv_anf[i].ga_sig0[j], C->gv_anf[i].ga_Vsig0[j]); if (C->gv_anf[i].ga_Nfit>0) { fprintf(fp,"NFF %d %3s %4s %9s %7s %6s %7s %5s %5s %6s\n", i,"law","flag","p1","p1v","p2","p2v","rms","rmsv","resid"); for (j=0; jgv_anf[i].ga_Nfit; j++) fprintf(fp," %3d %4d %9.4f %7.1e %6.3f %7.1e %5.2f %5.2f %6.1f\n", C->gv_anf[i].ga_fit[j].gf_slaw, C->gv_anf[i].ga_fit[j].gf_flags, C->gv_anf[i].ga_fit[j].gf_p1, C->gv_anf[i].ga_fit[j].gf_p1v, C->gv_anf[i].ga_fit[j].gf_p2, C->gv_anf[i].ga_fit[j].gf_p2v, C->gv_anf[i].ga_fit[j].gf_rms, C->gv_anf[i].ga_fit[j].gf_rmsv, C->gv_anf[i].ga_fit[j].gf_resid); } } putc('\n',fp); if (fp==stderr) fflush(fp); return 0; } /****************************************************************************** gvdr_psize Prints out array sizes of GVDR cell C in human readable format. ******************************************************************************/ int gvdr_psize(FILE *fp, gvdrcell_t *C) { fprintf(fp,"%02d\t%02d\t%02d\t%02d\t%02d\t%02d\t%d\n", C->gv_Nxif,C->gv_Nedf,C->gv_Nadf,C->gv_Nanf, (C->gv_Nanf>0) ? C->gv_anf[0].ga_Nsig0 : 0, (C->gv_Nanf>0) ? C->gv_anf[0].ga_Nfit : 0, cell_rlen(C)); return 0; } /****************************************************************************** gvdr_proc_time Sets SCVDR process time in appropriate format. Returns a pointer to a static area in memory which will be overwritten on the next call. ******************************************************************************/ #include char * gvdr_proc_time(void) { time_t clock; /* Time since 0h 1/1/70 */ struct tm *ptm; /* Pointer to tm structure */ static char proc_time[30]; /* Get GMT */ time(&clock); ptm = gmtime(&clock); /* Generate process time string */ sprintf(proc_time,"%04d-%02d-%02dT%02d:%02d:%02d.000", 1900+ptm->tm_year,1+ptm->tm_mon,ptm->tm_mday, ptm->tm_hour,ptm->tm_min,ptm->tm_sec); return proc_time; }