/* * Copyright (c) 1999-2003 Smithsonian Astrophysical Observatory */ #include #include #include #include #include #include #include #define MAXROW 8192 static int maxrow=MAXROW; /* max number of intervals we will process in one pass through table data */ #define MAXINTV 1024 /* type of data we process */ #define SRC 0 #define BKG 1 /* this must match number of types above */ #define NTYPE 2 /* how corrections (time and exposure) are applied to source/bkgd */ #define NONE 0 #define SCORR 1 #define BCORR 2 #define BOTH 3 /* types of background */ #define BKG_VAL 1 #define BKG_ALL 2 #define BKG_EACH 3 /* types of image -> exposure pixel conversion algorithms */ #define EXP_RATIO 1 #define EXP_WCS 2 #define ARCSEC_PER_DEG 3600.0 #define ARCSEC_PER_DEGSQ (ARCSEC_PER_DEG*ARCSEC_PER_DEG) extern char *optarg; extern int optind; #ifdef ANSI_FUNC static void usage (char *fname) #else static void usage(fname) char *fname; #endif { fprintf(stderr, "usage: %s sname [sreg] [bname breg|breg|cnts]\n", fname); fprintf(stderr, "optional switches:\n"); fprintf(stderr, " -e \"source_exposure[;bkgd_exposure]\" # exp matches data\n"); fprintf(stderr, " -w \"source_exposure[;bkgd_exposure]\" # WCS method\n"); fprintf(stderr, "\t\t# source (bkgd) FITS exposure image\n"); fprintf(stderr, " -t \"source_timecorr[;bkgd_timecorr]\"\n"); fprintf(stderr, "\t\t# source (bkgd) time correction value or header parameter name\n"); fprintf(stderr, " -g\t\t# output using nice g format\n"); fprintf(stderr, " -G\t\t# output using %%.14g format (maximum precision)\n"); fprintf(stderr, " -i \"[column;]int1;int2...\" # column-based intervals\n"); fprintf(stderr, " -m\t\t# match individual source and bkgd regions\n"); fprintf(stderr, " -p\t\t# output in pixels, even if wcs is present\n"); fprintf(stderr, " -r\t\t# output inner/outer radii (and angles) for annuli (and pandas)\n"); fprintf(stderr, " -s\t\t# output summed values\n"); fprintf(stderr, " -v \"scol[;bcol]\" # src and bkgd value columns for tables\n"); fprintf(stderr, " -T\t\t# output in starbase/rdb table format\n"); fprintf(stderr, " -z\t\t# include regions with zero area in output\n"); fprintf(stderr, "\n(version: %s)\n", FUN_VERSION); exit(1); } #ifdef ANSI_FUNC static double DConvert (char *buf, int type, int n) #else static double DConvert(buf, type, n) char *buf; int type; int n; #endif { int ival; double dval=0.0; switch(type){ case 'X': if( n == 16 ) dval = (double)*(unsigned short *)buf; else if( n == 32 ) dval = (double)*(unsigned int *)buf; else dval = (double)*(unsigned char *)buf; break; case 'B': dval = (double)*(unsigned char *)buf; break; case 'I': dval = (double)*(short *)buf; break; case 'U': dval = (double)*(unsigned short *)buf; break; case 'J': dval = (double)*(int *)buf; break; case 'K': #if HAVE_LONG_LONG == 0 gerror(stderr, "64-bit data support not built (long long not available)\n"); #endif break; case 'V': dval = (double)*(unsigned int *)buf; break; case 'E': dval = (double)*(float *)buf; break; case 'D': dval = *(double *)buf; break; case 'L': ival = (int)*(unsigned char *)buf; if( !ival || (ival == 'F') || (ival == 'f') ) dval = 0.0; else dval = 1.0; break; default: dval = 0.0; break; } return(dval); } #ifdef ANSI_FUNC int main (int argc, char **argv) #else int main(argc, argv) int argc; char **argv; #endif { int c; int i, j, k, v; int args; int bkarea=0; int bktype=BKG_VAL; int dosum=0; int dog=0; int domatch=0; int doradang=0; int dobkgderr=1; int doexp=0; int dotim=0; int dopixels=0; int dozero=0; int evimage=0; int cold=' '; int nintv=1; int endian[NTYPE], type[NTYPE], rawsize[NTYPE], rowsize[NTYPE]; int x0[NTYPE], x1[NTYPE], y0[NTYPE], y1[NTYPE]; int dim1[4], dim2[4], block[4]; int *area[NTYPE]; int *savearea[NTYPE]; int nmask[NTYPE]={0,0}; int nreg[NTYPE]={0,0}; int valtypes[NTYPE]={0,0}; int valoffsets[NTYPE]={0,0}; int valns[NTYPE]={0,0}; int exptrans[NTYPE]={EXP_RATIO,EXP_RATIO}; double bkexp=0.0; double dpp[NTYPE]={-1.0,-1.0}; double timecorr[NTYPE]={1.0,1.0}; double *cnts[MAXINTV][NTYPE]; double *savecnts[MAXINTV][NTYPE]; double *bncnts[MAXINTV]; double *bnerr[MAXINTV]; double *bscnts[MAXINTV]; double *bserr[MAXINTV]; double *exp[NTYPE]; double *saveexp[NTYPE]; double dppnorm=1.0; double bkval=0.0; char mode[SZ_LINE]; char tbuf[SZ_LINE]; char tbuf2[SZ_LINE]; char *intvs[MAXINTV]; char *s, *t, *u; char *ebuf; char *eptr; char *fmt=NULL; char *expstr=NULL; char *intvstr=NULL; char *valstr=NULL; char *timestr=NULL; char *radang=NULL; char *cradang=NULL; char *tradang=NULL; char *region[NTYPE]={NULL,NULL}; char *filtstr[NTYPE]={NULL,NULL}; char *bincols[NTYPE]={NULL,NULL}; char *valname[2]={NULL,NULL}; char *name[4]={NULL,NULL,NULL, NULL}; Fun fun[4]={NULL,NULL,NULL,NULL}; FITSHead header[NTYPE]={NULL,NULL}; FilterMask masks[NTYPE]={NULL,NULL}; Filter filter[NTYPE]={NULL,NULL}; struct WorldCoor *wcs[4]={NULL,NULL,NULL,NULL}; /* clear array elelemts to mark them as unallocated */ memset(cnts, 0, MAXINTV*NTYPE*sizeof(double *)); memset(savecnts, 0, MAXINTV*NTYPE*sizeof(double *)); memset(bncnts, 0, NTYPE*sizeof(double *)); memset(bnerr, 0, NTYPE*sizeof(double *)); memset(bscnts, 0, NTYPE*sizeof(double *)); memset(bserr, 0, NTYPE*sizeof(double *)); memset(exp, 0, NTYPE*sizeof(double *)); memset(saveexp, 0, NTYPE*sizeof(double *)); memset(area, 0, NTYPE*sizeof(int *)); memset(savearea, 0, NTYPE*sizeof(int *)); memset(intvs, 0, MAXINTV*sizeof(char *)); /* exit on gio errors */ if( !getenv("GERROR") ) setgerror(2); /* we want the args in the same order in which they arrived, and gnu getopt sometimes changes things without this */ putenv("POSIXLY_CORRECT=true"); /* process switch arguments */ while ((c = getopt(argc, argv, "e:gGhi:mprst:v:w:zEIT")) != -1){ switch(c){ case 'e': expstr = optarg; break; case 'g': dog = 1; break; case 'G': dog = 2; break; case 'h': usage(argv[0]); break; case 'i': intvstr = optarg; break; case 'm': domatch = 1; break; case 'p': dopixels = 1; break; case 'r': doradang = 1; break; case 's': dosum = 1; break; case 't': timestr = optarg; break; case 'v': valstr = optarg; break; case 'w': putenv("FUNCNTS_EXPTRANS=wcs"); expstr = optarg; break; case 'z': dozero = 1; break; case 'E': evimage = 0; break; case 'I': evimage = 1; break; case 'T': cold = '\t'; break; } } /* get maxrow,if user-specified */ if( (s=getenv("FUN_MAXROW")) != NULL ) maxrow = atoi(s); /* check for required arguments */ args = argc - optind; if( args < 1 ) usage(argv[0]); /* arg 1: source file name */ name[SRC] = xstrdup(argv[optind+0]); /* arg 2: source region */ if( (args == 1) || !*(region[SRC] = argv[optind+1]) ) region[SRC] = "field()"; /* arg 3: background region */ if( args >= 3 ){ if( args == 3 ){ name[BKG] = NULL; region[BKG] = argv[optind+2]; } else{ name[BKG] = xstrdup(argv[optind+2]); region[BKG] = argv[optind+3]; } /* check for constant numeric value -- background counts */ bkval = strtod(region[BKG], &s); /* if we did not get a valid numeric constant, its a region */ if( region[BKG] && *region[BKG] && (s == region[BKG]) ){ bktype = BKG_ALL; bkval = 0.0; } else{ /* can't have background file and background value */ if( args == 4 ) usage(argv[0]); bktype = BKG_VAL; region[BKG] = NULL; } } /* get value column names, if necessary */ if( valstr ){ int ip=0; int i=0; newdtable(";"); for(i=0; i<&|") ){ strcpy(tbuf2, tbuf); strcat(tbuf2, "="); } else{ if( nintv >= MAXINTV ){ gwarning(stderr, "Too many intervals; ignoring: %s\n", tbuf); continue; } intvs[nintv] = (char *)calloc(SZ_LINE, sizeof(char)); if( *tbuf2 ) strcat(intvs[nintv], tbuf2); strcat(intvs[nintv], tbuf); nintv++; } ntok++; } freedtable(); } /* if a value name was specified, make sure its a calid column */ if( valname[SRC] && (*valname[SRC] != '-') ){ if( !FunColumnLookup(fun[SRC], valname[SRC], 0, NULL, &valtypes[SRC], NULL, &valoffsets[SRC], NULL, NULL) ){ gerror(stderr, "value column does not exist: %s\n", valname[SRC]); } } /* allocate space for results */ for(i=0; icoorflip ) dpp[i] = ABS(wcs[i]->cdelt[0]) * block[i]; else dpp[i] = ABS(wcs[i]->cdelt[1]) * block[i]; } } /* note that BOTH must be present or we do not do this normalization */ if( (dpp[SRC] > 0.0) && (dpp[BKG] > 0.0) ) dppnorm = (dpp[SRC]/dpp[BKG]) * (dpp[SRC]/dpp[BKG]); } /* get degrees/pixel for source; not used in norm, but users want to know */ else{ if( wcs[SRC] && iswcs(wcs[SRC]) ){ if( !wcs[SRC]->coorflip ) dpp[SRC] = ABS(wcs[SRC]->cdelt[0]) * block[SRC]; else dpp[SRC] = ABS(wcs[SRC]->cdelt[1]) * block[SRC]; } } /* open exposure file(s), if necessary */ if( expstr ){ int ip=0; int i=0; int got=0; newdtable(";"); for(i=0; i 0 ){ if( valname[k] && (*valname[k] != '-') ) cnts[v][k][rbuf[i]-1] += DConvert(eptr, valtypes[k], valns[k]); else cnts[v][k][rbuf[i]-1] += 1; } } } } /* free for next read */ if( ebuf ) xfree(ebuf); } /* Done with region values */ if( rbuf ) xfree(rbuf); /* close filters */ for(v=0; v 0 ){ if( valname[i] && (*valname[i] != '-') ) cnts[v][i][rbuf[j]-1] += DConvert(eptr, valtypes[i], valns[i]); else cnts[v][i][rbuf[j]-1] += 1; } } } } } /* free for next read */ if( ebuf ) xfree(ebuf); } /* done with region values */ if( rbuf ) xfree(rbuf); /* close filters */ for(v=0; v0) && name[NTYPE+k-1] ) tname = name[NTYPE+k-1]; switch(exptrans[k]){ case EXP_RATIO: lastey = -1; d1 = ((double)dim1[NTYPE+k]/(double)dim1[k]); d2 = ((double)dim2[NTYPE+k]/(double)dim2[k]); for(i=0; i dim1[NTYPE+k] ) ex = dim1[NTYPE+k]; exp[k][masks[k][i].region-1] += exbuf[ex-1]; } } break; case EXP_WCS: lastey = -1; for(i=0; i dim1[NTYPE+k] ) ex = dim1[NTYPE+k]; if( ey < 1 ) ey = 1; if( ey > dim2[NTYPE+k] ) ey = dim2[NTYPE+k]; if( ey != lastey ){ if( !FunImageRowGet(fun[NTYPE+k], exbuf, ey, ey, "bitpix=-64") ) gerror(stderr, "can't FunImageRowGet (exp file): %d %s\n", ey, tname); lastey = ey; } exp[k][masks[k][i].region-1] += exbuf[ex-1]; } } break; default: gerror(stderr, "unknown exposure conversion type"); } if( exbuf ) xfree(exbuf); } /* since we already checked for source exposure, we must be missing bkgd exposure. This is OK, unless we have a bkgd file. In that case, we need to warn the user and make an assumption about errors */ else if( (k==1) && name[BKG] ){ gwarning(stderr, "No exposure file was specified for the background file.\nWe therefore assume that the bkgd already has been corrected for\nexposure and that the error associated with each bkgd pixel is 0.\n"); dobkgderr = 0; } } } /* reset the interval index for next stage of proessing*/ v = 0; /* come back here if we are processing multiple intervals */ intvagain: /* for data-based background, check validity of background area */ if( bktype != BKG_VAL ){ bkval = 0.0; bkarea = 0; bkexp = 0.0; for(i=0; i 0.0 ) fprintf(stdout, "# arcsec/pixel:\t%g\n", dpp[SRC]*ARCSEC_PER_DEG); if( doexp & SCORR ) fprintf(stdout, "# exp_correction:\t%s\n", name[NTYPE+SRC]); if( dotim & SCORR ) fprintf(stdout, "# time_correction:\t%g\n", timecorr[SRC]); /* display bkgd header information */ fprintf(stdout, "# background\n"); if( name[BKG] ){ fprintf(stdout, "# data_file:\t\t%s\n", name[BKG]); if( intvs[v] ) fprintf(stdout, "# interval:\t\t%s\n", intvs[v]); if( valname[BKG] && (*valname[BKG] != '-') ) fprintf(stdout, "# value column:\t%s\n", valname[BKG]); if( dpp[BKG] > 0.0 ) fprintf(stdout, "# arcsec/pixel:\t%g\n", dpp[BKG]*ARCSEC_PER_DEG); if( doexp & BCORR ) fprintf(stdout, "# exp_correction:\t%s\n", name[NTYPE+BKG]); if( dotim & BCORR ) fprintf(stdout, "# time_correction:\t%g\n", timecorr[BKG]); if( dppnorm != 1.0 ) fprintf(stdout, "# wcs area norm factor:\t%g/%g (source/bkgd))\n", dpp[SRC],dpp[BKG]); } else if( bktype != BKG_VAL ){ fprintf(stdout, "# data_file:\t\t%s\n", name[SRC]); if( valname[SRC] && valname[BKG] && strcmp(valname[SRC], valname[BKG]) && (*valname[BKG] != '-') ) fprintf(stdout, "# value_column:\t%s\n", valname[BKG]); } else fprintf(stdout, "# constant_value:\t%.6f\n", bkval); /* dislay table information */ if( (dpp[SRC] > 0.0) && !dopixels ) s = "arcsec"; else s = "pixel"; fprintf(stdout, "# column units\n"); fprintf(stdout, "# area:\t\t%s**2\n", s); fprintf(stdout, "# surf_bri:\t\tcnts/%s**2%s%s\n", s, (dotim & SCORR)? "/sec" : "", (doexp & SCORR)? "/expval" : ""); fprintf(stdout, "# surf_err:\t\tcnts/%s**2%s%s\n", s, (dotim & SCORR)? "/sec" : "", (doexp & SCORR)? "/expval" : ""); if( doradang ){ fprintf(stdout, "# radii:\t\t%ss\n", s); fprintf(stdout, "# angles:\t\tdegrees\n"); } /* come back here if we also are outputting summed results */ sumagain: /* if we need to display sums, so the sum now, but save unsummed values, because we will have to display those as well */ switch(dosum){ case 1: memcpy(savecnts[v][SRC], cnts[v][SRC], (nreg[SRC]+1)*sizeof(double)); memcpy(savearea[SRC], area[SRC], (nreg[SRC]+1)*sizeof(int)); for(i=1; i 0.0) ){ cntsperarea = (cntsperarea / (dpp[SRC]*dpp[SRC])) / ARCSEC_PER_DEGSQ; errperarea = (errperarea / (dpp[SRC]*dpp[SRC])) / ARCSEC_PER_DEGSQ; areasq = (areasq * (dpp[SRC]*dpp[SRC])) * ARCSEC_PER_DEGSQ; } /* get correctly precisioned format statement */ switch(dog){ case 0: fmt = "%4d%c%12.3f%c%9.3f%c%12.3f%c%9.3f%c%9.2f%c%9.3f%c%9.3f"; break; case 1: fmt = "%4d%c%12.3g%c%9.3g%c%12.3g%c%9.3g%c%9.2g%c%9.3g%c%9.3g"; break; case 2: fmt = "%4d%c%.14g%c%.14g%c%.14g%c%.14g%c%.14g%c%.14g%c%.14g"; break; } fprintf(stdout, fmt, i+1, cold, bscnts[v][i], cold, bserr[v][i], cold, bncnts[v][i], cold, bnerr[v][i], cold, areasq, cold, cntsperarea, cold, errperarea); /* display values from this line of radii/angles */ if( doradang && cradang ){ int ip=0; double dval; for(j=0; j<4; j++){ if( word(cradang, tbuf, &ip) && strcmp(tbuf, "NA") ){ dval = strtod(tbuf, NULL); if( (j<2) && !dopixels && (dpp[SRC]>0.0) ) fprintf(stdout, "%c%9.3f", cold, (dval*dpp[SRC]*ARCSEC_PER_DEG)); else fprintf(stdout, "%c%9.3f", cold, dval); } else{ fprintf(stdout, "%c%9.9s", cold, "NA"); } } } /* new-line at end */ fprintf(stdout, "\n"); } /* might have to display zero area pixels */ else if( dozero ){ /* get correctly precisioned format statement */ switch(dog){ case 0: fmt = "%4d%c%12.3f%c%9.3f%c%12.3f%c%9.3f%c%9.2f%c%9.3f%c%9.3f"; break; case 1: fmt = "%4d%c%12.3g%c%9.3g%c%12.3g%c%9.3g%c%9.2g%c%9.3g%c%9.3g"; break; case 2: fmt = "%4d%c%.14g%c%.14g%c%.14g%c%.14g%c%.14g%c%.14g%c%.14g"; break; } fprintf(stdout, fmt, i+1, cold, 0.0, cold, 0.0, cold, 0.0, cold, 0.0, cold, 0.0, cold, 0.0, cold, 0.0); /* add the correct radii and angle info, to make plotting easier */ if( doradang && cradang ){ int ip=0; double dval; for(j=0; j<4; j++){ if( word(cradang, tbuf, &ip) && strcmp(tbuf, "NA") ){ dval = strtod(tbuf, NULL); if( (j<2) && !dopixels && (dpp[SRC]>0.0) ) fprintf(stdout, "%c%9.3f", cold, (dval*dpp[SRC]*ARCSEC_PER_DEG)); else fprintf(stdout, "%c%9.3f", cold, dval); } else{ fprintf(stdout, "%c%9.9s", cold, "NA"); } } } /* new-line at end */ fprintf(stdout, "\n"); } /* bump to next line of radii/angles */ if( tradang ){ cradang = tradang+1; /* put back the cr in case we pass through again */ *tradang = '\n'; } } if( radang ) freedtable(); fprintf(stdout, "\n"); fflush(stdout); /* if we just summed, go back and display unsummed values */ switch(dosum){ case 1: dosum = 2; goto sumagain; /* set flag back to 1 in case we have multiple intervals to process */ case 2: dosum = 1; break; default: break; } /* display raw source counts */ if( dosum ){ int tarea=0; double tcnts=0; if( cold == '\t' ) fprintf(stdout, "\f"); fprintf(stdout, "\n"); /* display source info */ if( filtstr[SRC] ){ fprintf(stdout, "# source_region(s):\n"); fprintf(stdout, "# %s\n\n", filtstr[SRC]); } fprintf(stdout, "# summed_source_data\n"); fprintf(stdout, " reg%c counts%c pixels%c sumcnts%c sumpix\n", cold, cold, cold, cold); fprintf(stdout, "----%c------------%c---------%c------------%c---------\n", cold, cold, cold, cold); for(i=0; i 0 ) fprintf(stdout, fmt, cold, exp[SRC][i]/area[SRC][i]); else fprintf(stdout, fmt, cold, 0.0); } fprintf(stdout, "\n"); } } fprintf(stdout, "\n"); fflush(stdout); /* display raw background info */ switch(bktype){ case BKG_VAL: break; case BKG_ALL: if( cold == '\t' ) fprintf(stdout, "\f"); fprintf(stdout, "\n"); if( filtstr[BKG] ){ fprintf(stdout, "# background_region(s)\n"); fprintf(stdout, "# %s\n\n", filtstr[BKG]); } fprintf(stdout, "# background_data\n"); fprintf(stdout, " reg%c counts%c pixels", cold, cold); if( doexp & BCORR ) fprintf(stdout, "%c avg_exp", cold); fprintf(stdout, "\n"); fprintf(stdout, "----%c------------%c---------", cold, cold); if( doexp & BCORR ) fprintf(stdout, "%c---------", cold); fprintf(stdout, "\n"); /* get correctly precisioned format statement */ switch(dog){ case 0: fmt = "%s%c%12.3f%c%9d"; break; case 1: fmt = "%s%c%12.3g%c%9d"; break; case 2: fmt = "%s%c%.14g%c%9d"; break; } fprintf(stdout, fmt, "all ", cold, bkval, cold, bkarea); if( doexp & BCORR ){ /* get correctly precisioned format statement */ switch(dog){ case 0: fmt = "%c%9.3f"; break; case 1: fmt = "%c%9.3g"; break; case 2: fmt = "%c%.14g"; break; } fprintf(stdout, fmt, cold, bkexp/bkarea); } fprintf(stdout, "\n"); break; case BKG_EACH: if( dosum ){ int tarea=0; double tcnts=0; if( cold == '\t' ) fprintf(stdout, "\f"); fprintf(stdout, "\n"); if( filtstr[BKG] ){ fprintf(stdout, "# background_region(s)\n"); fprintf(stdout, "# %s\n\n", filtstr[BKG]); } fprintf(stdout, "# summed_background_data\n"); fprintf(stdout, " reg%c counts%c pixels%c sumcnts%c sumpix\n", cold, cold, cold, cold); fprintf(stdout, "----%c------------%c---------%c------------%c---------\n", cold, cold, cold, cold); for(i=0; i 0 ) fprintf(stdout, fmt, cold, exp[BKG][i]/area[BKG][i]); else fprintf(stdout, fmt, cold, 0.0); } fprintf(stdout, "\n"); } } break; } fprintf(stdout, "\n"); fflush(stdout); /* process the next interval, if necessary */ if( ++v < nintv ){ fprintf(stdout, "\014\n"); goto intvagain; } /* cleanup */ for(i=0; i