wcstools-3.9.5/0000755000016200013320000000000013073717750011701 5ustar minktdcwcstools-3.9.5/libwcs/0000755000016200013320000000000013073720303013150 5ustar minktdcwcstools-3.9.5/libwcs/Makefile0000644000016200001660000000463011634446141015403 0ustar minkoirsysCFLAGS= -g -D_FILE_OFFSET_BITS=64 CC= cc OBJS = imsetwcs.o imgetwcs.o matchstar.o findstar.o daoread.o wcscon.o \ fitswcs.o wcsinit.o wcs.o ty2read.o webread.o tmcread.o \ gscread.o gsc2read.o ujcread.o uacread.o ubcread.o ucacread.o \ sdssread.o tabread.o binread.o ctgread.o actread.o catutil.o \ skybotread.o imrotate.o fitsfile.o imhfile.o \ hget.o hput.o imio.o dateutil.o imutil.o \ worldpos.o tnxpos.o zpxpos.o dsspos.o platepos.o \ sortstar.o platefit.o iget.o fileutil.o \ wcslib.o lin.o cel.o proj.o sph.o wcstrig.o distort.o poly.o libwcs.a: $(OBJS) ar rv $@ $? ranlib $@ actread.o: fitsfile.h wcscat.h wcs.h fitshead.h wcslib.h binread.o: wcscat.h wcs.h fitshead.h wcslib.h ctgread.o: wcscat.h wcs.h fitshead.h wcslib.h catutil.o: wcscat.h wcs.h fitshead.h wcslib.h cel.o: wcslib.h daoread.o: wcscat.h dateutil.o: fitsfile.h fitshead.h distort.o: wcs.h fitshead.h wcslib.h dsspos.o: wcs.h fitshead.h wcslib.h fileutil.o: fitsfile.h fitshead.h imutil.o: fitsfile.h fitshead.h findstar.o: fitshead.h lwcs.h wcscat.h fitsfile.o: fitsfile.h fitshead.h fitswcs.o: fitsfile.h wcs.h fitshead.h wcslib.h gscread.o: fitsfile.h wcs.h wcscat.h fitshead.h wcslib.h gsc2read.o: fitsfile.h wcs.h wcscat.h fitshead.h wcslib.h hget.o: fitshead.h hput.o: fitshead.h iget.o: fitshead.h imgetwcs.o: fitshead.h wcs.h lwcs.h wcslib.h imhfile.o: fitsfile.h fitshead.h imio.o: fitsfile.h imsetwcs.o: fitshead.h wcs.h lwcs.h wcscat.h wcslib.h imrotate.o: fitsfile.h lin.o: wcslib.h matchstar.o: fitshead.h wcs.h lwcs.h wcslib.h wcscat.h platefit.o: wcs.h fitshead.h wcslib.h platepos.o: wcs.h fitshead.h wcslib.h poly.o: wcslib.h proj.o: wcslib.h sdssread.o: fitsfile.h wcs.h wcscat.h fitshead.h wcslib.h skybotread.o: fitsfile.h wcs.h wcscat.h fitshead.h wcslib.h sortstar.o: wcscat.h sph.o: wcslib.h tabread.o: fitshead.h wcs.h wcslib.h wcscat.h tmcread.o: fitsfile.h wcs.h wcscat.h fitshead.h wcslib.h tnxpos.o: wcs.h fitshead.h wcslib.h zpxpos.o: wcs.h fitshead.h wcslib.h ty2read.o: fitsfile.h wcs.h wcscat.h fitshead.h wcslib.h uacread.o: fitshead.h wcs.h wcscat.h wcslib.h ubcread.o: fitshead.h wcs.h wcscat.h wcslib.h ucacread.o: fitshead.h wcs.h wcscat.h wcslib.h ujcread.o: fitshead.h wcs.h wcscat.h wcslib.h wcs.o: fitshead.h wcs.h wcslib.h wcsinit.o: fitshead.h wcs.h wcslib.h wcscon.o: wcs.h fitshead.h wcslib.h wcslib.o: wcslib.h wcstrig.o: wcslib.h webread.o: wcscat.h worldpos.o: wcs.h fitshead.h wcslib.h clean: rm -f *.a *.o wcstools-3.9.5/libwcs/Files0000644000016200001660000001772411537520365014743 0ustar minkoirsysWCSTools libwcs Subroutines (3.9.0, March 11, 2011) actread.c Return stars from the USNO ACT Reference Catalog binread.c Return stars from catalog files in the TDC binary catalog format catread.c Return stars from catalog files in the TDC ASCII catalog format catutil.c Subroutines for catalog identification and number range decoding cel.c WCSLIB spherical coordinate transformation drivers daoread.c Read x, y, and magnitude from DAOFIND output file and return x, y, and flux for use by IMSTAR or IMWCS. dateutil.c Subroutines for conversions between various date and time formats distort.c Subroutines for conversions between image pixel and focal plane coordinates dsspos.c dsspos() uses the WCS structure to compute sky coordinates given image pixel X and Y for images with Digitized Sky Survey plate solutions in their headers. dsspix() uses the WCS structure to compute image pixel X and Y given sky coordinates for DSS images. Algorithms from StSCI CASB. fileutil.c Subroutines for finding size and contents of ASCII files findstar.c findStars() gets the location and brightest pixel of stars in the given image. Included are subroutines to find and reject bright pixels and compute a star centroid. fitsfile.c FITS header and image reading and writing subroutines, including FITS table support. fitswcs.c GetWCSFITS() returns a WCS structure used by wcs.c subroutines from a FITS or IRAF .imh image, reading only the header. GetFITShead() returns a FITS header from a FITS or IRAF .imh image. DelWCS() delete the WCS keywords in a FITS header. fortcat.c Fortran wrapper subroutines for catalog reading subroutines ctgread() and ctgrnum() fortwcs.c Fortran wrapper subroutines for all useful subroutines in wcs.c and wcsinit.c gscread.c Return HST Guide Stars from standard CDROM format FITS table files for a given RA, Dec, and magnitude range or list of star numbers. gsc2read.c Return GSC II Stars using an HTTP query over the web for a given RA, Dec, and magnitude range or list of star numbers. hget.c Subroutines to extract values from FITS headers by keyword. Subroutines for parsing RA and Dec strings are included. hput.c Subroutines to implant values into FITS headers by keyword (and to delete headers). iget.c Subroutines to extract values from IRAF multi-keyword header parameters imhfile.c IRAF header and image reading and writing subroutines. IRAF headers are converted to FITS headers for use by other programs and can be derived from FITS headers for writing. imio.c Subroutines to get, put, and move pixels of various data types between images im memory and a program. imrotate.c RotFITS() rotates an image by 90, 180, or 270 degrees, with an optional left-right reflection before the rotation. imgetwcs.c GetWCSFITS() reads world coordinate system header information and returns the image center coordinates and size as well as the wcs data structure. imsetwcs.c SetWCSFITS() uses findStars to find the stars in an image, gscread to find the Guide Stars in the nominal image region, and findRegisration or findCoords to fit plate-tangent WCS to the image. lin.c WCSLIB linear transformation subroutines matchstar.c StarMatch() takes a list of reference star positions and a list of object coordinates from an image and finds the image pixels which correspond to each of the reference stars. It then uses these matches to get an image center, plate scale, and rotation. The actual fit is based on the amoeba subroutine in Numerical Recipes, and all necessary subroutines are included. platepos.c platepos() uses the WCS structure to compute sky coordinates given image pixel X and Y for images with polynomial plate solutions in their headers. platepix() uses the WCS structure to compute image pixel X and Y given sky coordinates for such images. Algorithms are based on those in dsspos.c, but go straight from pixels to angles without an intermediate plate coordinate. poly.c Polynomial evaluation for SCAMP distortion correction proj.c WCSLIB spherical map projection subroutines sdssread.c Return Sloan Digital Sky Survey Photometry Catalog sources using an HTTP query over the web for a given RA, Dec, and magnitude range. sortstars.c Subroutines to sort lists of stars by right ascension, magnitude, or flux sph.c WCSLIB spherical coordinate transformation subroutines tabread.c Return stars from a tab table format catalog file for a given RA, Dec, and magnitude range or list of star numbers. Based on John Roll's Starbase format. tmcread.c Return 2MASS Point Source Catalog stars from the catalog as ungzipped from the DVD into (or linked from) a common root directory for a given RA, Dec, and magnitude range or list of star numbers. Both IDR2 and All-Sky release formats are supported. tnxpos.c tnxpos() uses the WCS keywords set up for IRAF's TNX projection to compute sky coordinates given image pixel X and Y. tnxpix() uses the WCS structure to compute image pixel X and Y given sky coordinates for such images. The projection is a tangent plane with corrections between the rotation and scaling and the actual projection. uacread.c Return USNO A and SA Catalog stars from their standard CDROM format files for a given RA, Dec, and magnitude range or list of star numbers. ubcread.c Return USNO B Catalog stars from their standard format files for a given RA, Dec, and magnitude range or list of star numbers. ucacread.c Return USNO UCAC1, UCAC2, or UCAC3 Catalog stars from their standard format files for a given RA, Dec, and magnitude range or list of star numbers. ujcread.c Return USNO UJ Catalog stars from its standard CDROM format files for a given RA, Dec, and magnitude range or list of star numbers. wcs.c Subroutines for using FITS or IRAF header spatial world coordinate system information. wcsinit.c Subroutines to initialize WCS structure from a FITS header wcscon.c Subroutines for converting between B1950, J2000, and galactic coordinates, mostly based on Starlink SLA_LIB subroutines. webread.c Open Starbase files across the Internet using HTTP queries worldpos.c worldpos() uses the WCS structure to compute sky coordinates given image pixel X and Y for images with header information for any of 8 standard world coordinate systems. worldpix() uses the WCS structure to compute image pixel X and Y given sky coordinates for the same images. Mostly from NRAO. zpxpos.c zpxpos() uses the WCS keywords set up for IRAF's ZPX projection to compute sky coordinates given image pixel X and Y. zpxpix() uses the WCS structure to compute image pixel X and Y given sky coordinates for such images. The projection is a tangent plane with corrections between the rotation and scaling and the actual projection. fitshead.h Declarations of FITS header access subroutines fitsfile.h Declarations of image access subroutines and FITS table data structure. imio.h Declarations of subroutines to convert binary formats of numbers lwcs.h Constants used by star-finding and WCS-setting subroutines wcscat.h Declarations for star catalog data structures wcs.h Declaration of WCS data structure and useful conversions. wcslib.h Declarations for WCSLIB high level driver subroutines, trig and inverse trig functions, spherical map projection subroutines, spherical coordinate transformation drivers, and linear transformation subroutines * Notes: WCSLIB subroutines were written by Mark Calabretta of CSIRO and have been modified in several ways: 1) His distributed wcs.h has been changed to wcslib.h, and 2) wcstrig.c subroutine names have been changed from d() to deg() to avoid name conflicts on some operating systems. 3) ifndef's at start of headers files have been named to reflect the names of the header files, i.e. wcslib_h_ in wcslib.h. 4) All header files have been combined into wcslib.h 5) Emmanuel Bertin's SCAMP distortion has been added to proj.c:1 wcstools-3.9.5/libwcs/NEWS0000644000016200001660000005105113073720303014433 0ustar minkoirsysWCSTools WCS subroutine library release history Version 3.9.5 (March 30, 2017) Version 3.9.4 (August 2, 2016) (after Ole Streicher) wcs.c: Clean up use of ptype so it is always 3 characters long Version 3.9.3 (June 23, 2016) wcs.h, wcs.c: Increase ctype string length to 15 (+null=16) for distortion wcslib.h, wcslib.c: Increase ctype string length to 15 (+null=16) for distortion hget.c, fitsfile.c: Fix isnum() tests for added coloned times and dashed date Version 3.9.2 (December 10, 2015) hget.c: Add return of 4 for yyyy-mm-dd dates to isnum() (2015-11-06) Version 3.9.0 (December 19, 2014) fileutil.c: Add next_line() to return one line of file fitfile.c: fix buffer reallocation bug in fitsrhead() Version 3.8.7 (October 31, 2012) dateutil.c: Unused l0 dropped from jd2lst(); ts2ss from jd2mst() imio.c: Fix errors with short and character images in minvec(), maxvec() wcs.c: Drop d1 and d2 from wcsdist(); diffi from wcsdist1() wcs.c: Drop depwcs; it's in main wcs structure wcsinit.c: Drop unused variable iszpx; fix bug in latmin assignment zpxpos.c: Fix code for quadratic near pole catutil.c: Skip trailing right bracket in aget*() Version 3.8.6 (August 10, 2012) All: Update author name imio.c: Fix 8-bit variables to be unsigned char Version 3.8.5 (April 12, 2012) imio.c: Change 8-bit pixel values from char to unsigned char fitsfile.c: Always check first 8 characters of FITS files for "SIMPLE" Version 3.8.4 (September 1, 2011) imgetwcs.c, wcsinit.c, wcs.c, wcs.h, worldpos.c: Add TPV WCS for TAN with PV terms Version 3.8.3 (May 20, 2011) hget.c: Free allocated memory in strnsrch() to eliminate memory leak (2011-05-19) imhfile.c: Free *newpixname* not pixname. (2011-05-20) wcsinit.c: Change error() calls to setwcserr() wcslib.h: Declare undeclared SCAMP subroutine raw-to-pv() wcs.c: Fix wcsfree() so it frees depended-on WCS structures (2011-05-09) March 18, 2011 - Release 3.8.2 zpxpos.c, wcs.c, wcsinit.c: Add support for NOAO ZPX protection (Frank Valdes) imsetwcs.c: Allocate NMAXMAG instead of number of magnitudes, nmag wcsinit.c,wcs.c,proj.c: Support SCAMP TAN distortion correction (Ed Los) wcsinit.c: ARSEC and DEG constants used by SCAMP replaced by S2D and D2S proj.c: If no PV coefficients in ZPN projection, make it ARC wcs.c: Fix bug involving dependent WCS's (Ed Los) April 30, 2010 - Release 3.8.1 scat,imcat: Set GSC2 magnitudes > 90 to 99.99 gethead: Fix buffer reallocation bug which crashed reading very large headers gethead: Fix trailing spaces on ASCII file quoted string values gethead: Fix problems with string value extraction changing ASCII files skycoor: Use number of decimal places from -n for -r difference if set wcscon.c: Fix bug in fk524() e-term computation; fix J<->B conversions fitsfile.c: In fitswhead(), always pad blocks to 2880 bytes with spaces and fix bug dealing with large primary headers wcscon.c: Fix bug in computing the magnitude of the e-terms in fk524() and drop ep1 assignment after line 178 in wcsconp() November 13, 2009 - Release 3.8.0 dateutil.c: Fix possible bug in nutation subroutine fitsfile.c: Add subroutine moveb() and fix binary table calls to it Fix lengths for ASCII numeric table entries in fitsrthead() fitsfile.h: Add moveb() which is used by binary FITS table code in fitsfile.c hget.c: In strfix(), if parentheses enclose a number, drop them November 21, 2008 - Release 3.7.6 fitsfile.c: In fitswhead() do not print write error if nw = nbytes dateutil.c: Use IAU 2006 nutation for sidereal time computations dateutil.c: Add ang2hr(), ang2deg(), deg2ang(), and ang2hr() to convert betweem decimal floating point degrees and vigesimal hours or degrees tnxpos.c: Fix image to world coordinate system transformation and WCS to image transformation July 1, 2008 - Release 3.7.5 wcsinit.c: Initialize TNX projection when projection types first set and check for IMAGEW and IMAGEH if NAXIS1 and NAXIS2 not present, fitsfile.c: Drop comma from name when reading file in isfits() and do not append primary data header if it is the only header May 9, 2008 - Release 3.7.4 fitsfile.c: In isfits(), allow extensions in FITS files without .fit or .fts wcsinit.c: Call tnxinit() before any projection calls are made March 20, 2008 - Release 3.7.3 wcs.c: Compute angular separation in wcsdist() using arcos December 31, 2007 - Release 3.7.2 wcscon.c: In wcsconp, make it clear that proper motion is in spherical coordinates fitsfile.c: Add support to BINTABLE in ftget*() and fitsrthead() fitsfile.c: Add data heap numerated by PCOUNT when skipping HDU in fitsrhead() fitsfile.c: Return NULL pointer if fitsrhead() cannot find requested HDU fitswcs.c: Print error message set by fitsrhead() November 9, 2007 - Release 3.7.1 wcsinit.c: Fix bug which tested &mchar instead of mchar in if statement August 24, 2007 - Release 3.7.0 hget.c: If a closing quote isn't found in a string value, make one up hput.c: Fix bug in comment insertion and deal correctly with missing quotes June 11, 2007 - Release 3.6.9 imio.c: Add minvec() and speed up maxvec() April 3, 2007 - Release 3.6.8 hget.c: Initial header length to zero in hlength() if lhead argument <= 0 wcs.c: In wcstype(), set to WCS_PIX if CTYPEi starts with "DET" wcs.c: In wcspset(), use correct cdelts when converting PC matrix to CD matrix wcsinit.c: Fix bug so RA, DEC, SECPIX can be used to set a WCS tnxpos.c: Fix bug so it doesn't crash January 16, 2007 - Release 3.6.7 wcs.h: Fix and add ANSI C prototypes imio.h: Drop as it has been included in fitsfile.h for several releases now fitsfile.h, fitshead.h: Add ANSI C prototypes wcsinitc(),wcsninitc(),hgeti4c(),hgetr8c(),hgetsc(): Change WCS letter argument from char to char* hget.c: Declare header and keyword const char in most subroutines hput.c: Declare keyword and value const in most subroutines hput.c: Fix bug in ra2str() and dec2str() so ndec=0 works imio.c: Include fitsfile.h instead of imio.h wcslib.h: Drop semicolon at end of c++ ifdef wcslib.h: Drop second declaration of SZP subroutines November 2, 2006 - Release 3.6.6 fitsfile.c: Use calloc() when reallocating header as it is read wcsinit.c: Limit naxes to 2 everywhere; RA and DEC should always be 1st wcsinit.c: If either CUNITi is "pixel" set projection to WCS_XY wcscon.c: In wcscsys, set system to WCS_XY if PIXEL projection wcscon.c: In wcscsys, set system to WCS_LINEAR if LINEAR coordinate system dateutil.c, fitshead.h: Add sidereal time to UT and vice versa June 30, 2006 - Release 3.6.5 wcsinit.c: Deal with up to 9x9 PC matrix wcs.c: Limit WCSLIB dimensions to two (this will change in 4.0) hput.c: Fix comment placement and replacement hget.c: Add strfix(), a utility to clean up strings May 3, 2006 - Release 3.6.4 fileutil.c: Add istiff(), isjpeg(), isgif() to check TIFF, JPEG, GIF files fitsfile.c: Add fitsrtail() to read appended FITS headers fitsfile.c: Add file name to header-reading error messages fitswcs.c: Add code to read FITS header appended to TIFF file imio.c: Fix bug of occasional double application of bscale in getvec() Clean up arithmetic and increment in addpix() and multpix() imsetwcs.c: Allow number of decimal places in image coordinates to be set wcsinit.c: Get Epoch of observation from MJD-OBS or DATE-OBS/UT unless DSS wcsinit.c: Set wcs->naxes to actual number of image WCS axes, usually 2 wcscon.c,dateutil.c,fitsfile.c: Drop declarations of unused variables wcs.c: Fix calls to avoid type conflicts in Linux January 5, 2006 - Release 3.6.3 wcs.h: Add WCS_ICRS to list of coordinate systems wcsinit.c: Initialize sys to WCS_ICRS if appropriate wcscon.c: Avoid precesssing ICRS coordinates wcscon.c: Fix precession which broke in 3.6.1 July 21, 2005 - Release 3.6.2 wcs.c: Fix wcsrange() to return correct range around RA=0 Clean up accumulated unused and misdeclared variables using lint April 13, 2005 - Release 3.6.1 Remove all sla_lib subroutines and calls thereto from wcscon.c, replacing them with local code. March 17, 2005 - Release 3.6.0 In wcs.c, fix bug in wcsrotset() so angles > 360 are set to angle - 360, not 360 Use unbuffered read() in isfits() in fitsfile.c ------------------------ November 01, 2004 - Release 3.5.8 In wcs.c, keep wcs->rot between 0 and 360 degrees (360.0 -> 0.0) September 21, 2004 - Release 3.5.7 In pix2wcs(), if spherical coordinate output, keep 0 < long/RA < 360 Fix bug in wcsfull() when wrapping around RA=0:00 In hput.c, add fixnegzero() to avoid putting -0.000 in header September 3, 2004 - Release 3.5.6 Modify FITS file reading software to get image size from file size if SIMPLE is F, so FITS headers with WCS can be used on arbitrary files. In hget.c, fix bug so comment is not pushed onto the next line if character value string lengthens (off by one bug). July 13, 2004 - Release 3.5.5 Add headshrink to hput.c to optionally keep blank lines after keywords are deleted. Read D, d, E, and e as exponent delimiters in floating point values in hget.c May 6, 2004 - Release 3.5.4 Add fitswexhead() to fitsfile.c to overwrite FITS extension headers April 16, 2004 - Release 3.5.3 Use strncsrch() in hget.c to get differently-cased keywords. February 3, 2004 - Release 3.5.2 In worldpix() in worldpos.c, allow ra/long. to exceed 180 if reference pixel is more than 180 degrees from image (1,1). December 12, 2003 - Release 3.5.1 Change p[0,1,2] initializations to p[1,2,3] in wcsinit.c to match proj.c (This affects constants for AZP,SIN,COP,COE,COD,COO,SZP,CEA,CYP,AIR,BON) Add wcs->naxes back into wcs structure for backward compatibility; it should always be equal to wcs->naxis. Fix bug in numdec() to return 0 if no digits after decimal point Fix call to setwcserr() with format in it November 17, 2003 - Release 3.5.0 Rename mgets() to mgetstr() in iget.c, wcsinit.c and fitshead.h Add numdec() to hget.c to return number of decimal places in numeric string Change wcs->naxes to wcs->naxis to prepare for WCSLIB 3.* In iraf2fits() and irafrimage(), use image, not physical, dimensions. In iraf2fits(), set NAXISi to image dimensions, NPAXISi to physical dimensions. Fix bugs in wcsfull() in wcs.c Move all distortion-related code to distort.c; include unistd.h Include stdlib.h instead of malloc.h in lin.c and drop malloc.h from matchstar.c ------------------------ August 22, 2003 - Release 3.4.2 Add fitsrfull() subroutine to read FITS files with more than 2 dimensions Modify fitswimage() to write FITS files with more than 2 dimensions July 11, 2003 - Release 3.4.1 Use strncmp to check for both stdin and stdout in fitsfile.c May 30, 2003 - Release 3.4.0 Add partial support for ZPX projection Fix bug reading COE and other projections when PROJPn coefficients were accidently reinitialized ------------------------ May 8, 2003 - Release 3.3.4 Add two missing semicolons in C++ declarations in wcs.h Read prj.p[0] from PROJP0 for ZPN projections, instead of ignoring it April 3, 2003 - Release 3.3.2 Add distortion conversion for SIRTF images March 27, 2003 - Release 3.3.1 Add conversions to and from Heliocentric Julian Dates to dateutil.c Open FITS and IMH files "rb" instead of "r" for Linux compatibility Add isimlistd() to fileutil.c to check for list of images in a specified directory Fix default center pixel computation in GetFITSWCS(); it was off by half a pixel January 30, 2003 - Release 3.3.0 Fix bug in dateutil.c ts2gst() sidereal time conversion. ------------------------ January 3, 2003 - Release 3.2.1 Fix bug in wcsinit() which failed to read PVi_0, and now initialize PVi_j in only once place. December 6, 2002 - Release 3.2.0 Add ET/TDT/TT and sidereal time conversion to dateutil.c Fix subroutine calls for radvel and latpole and correctly compute pixel at center of image for default CRPIX in wcsinit.c Add fitsrsect() to fitsfile.c to read a section of an image ------------------------ August 30, 2002 - Release 3.1.3 Fix bug in imio.c getvec() dealing with scaled images Add case-insensitive string search subroutines strcsrch() and strncsrch() Accept stdin as file in isfile() Add Ephemeris time conversions to dateutil() July 8, 2002 - Release 3.1.2 Fix bug in date utilities which always rounded to integer seconds of UT Fix bugs in date utilities to handle BC (negative) dates to JD 0. June 26, 2002 - Release 3.1.1 Fix bugs which caused TNX projection to fail Fix two bugs in wcsinit() which caused setting RADECSYS when an EQUINOX keyword is present. Write FITS error messages to string accessible by fitserr() Put SAO-written software under Gnu Lesser Public License April 12, 2002 - Release 3.1.0 Implement WCSLIB 2.9 Support PV entry of constants and PCi_j rotation matrices in wcsinit.c Support inversion (WCS->pix) of multiple dependent WCSs Add hgetri4c(), hgetr8c(), and hgetsc() for multiple WCS handling Fix bug in TNX projection software which caused an infinite loop during coefficient parsing. ------------------------ February 13, 2002 - Release 3.0.7 Fix bug in ecliptic coordinate conversion in wcscon.c Allow "stdin" to include extension and/or WCS selection in fitsfile.c Add a global switch to turn off scaling in imio.c Add ifdef to lin.c so it will compile under Mac OS/X December 4, 2001 - Release 3.0.6 In movepix(), add char to char move Always include stdlib.h in lin.c September 25, 2001 - Release 3.0.5 Implement WCSLIB version 2.7 Fix Makefile to include header files appropriately Accept FITS dates as yyyy/mm/dd Fix bug in str2dec() which misinterpreting strings with leading spaces Fix bug in isnum() which caused bad answer if trailing spaces Add fileutil.c, which includes various file info utilities September 7, 2001 - Release 3.0.3 Disallow files with = in their name in isfits() and isiraf() Set coordinate system from CTYPE if not equatorial July 12, 2001 - Release 3.0 Read PROJPn projection constants in wcsinit() ------------------------ March 30, 2001 - Release 2.9.4 Fix possible header length problem in hget.c March 22, 2001 - Release 2.9.3 Fix minor bugs in wcs.h, wcs.c, and wcsinit.c, wcslib.c, fitsfile.c, and cel.c found by gcc on Linux and possible memory leak in wcs.c March 9, 2001 - Release 2.9.2 In fitsfile.c, change multiple WCS separator in FITS file names from : to % and fix bug which failed to read multi-extension files if END was not preceded by a blank line in the extension's header. February 28, 2001 - Release 2.9.1 Fix major bug in wcsinit() which always set CRPIX2 the same as CRPIX1 February 23, 2001 - Release 2.9.0 FITS reading subroutines are fixed to ignore WCS name or character specified as :name or :character at end of filename. wcsinit() has new APIs which specify either a WCSNAME, wcsinitn(), or a WCS character, wcsinitc(), to allow use of multiple WCS's in a single FITS header. The WCSDEPx keyword has been added to indicate dependence on another WCS, though this feature has not been thoroughly debugged. fitscimage() is fixed so it doesn't overwrite data when overwriting a file An off-by-one bug was fixed for some polynomial types in tnxpos(). The WCSLIB subroutines were brought up to release 2.6 with very minor changes ------------------------ December 29, 2000 - Release 2.8.6 Fix handling of embedded + or - in isnum() in hget.c Default to 2000 for EQUINOX and EPOCH and FK5 for RADECSYS, if keywords not present. In wcscon.c, fk425() and fk524() algorithms were updated to include parallax and rv, proper motion is added by wcscon*() after fk425() or fk524() from system epoch, and proper motion units in fk524p() and fk425p() were fixed. In wcsinit.c, a bug initializing CD matrix was fixed. In cel.c, include string.h for strcmp(). September 29, 2000 - Release 2.8.5 wcsinit will now use a CD matrix if ANY CD keywords are present in header In getvec() in imio.c, move scaling outside of loop and make it conditional. Read .pix files in same directory as .imh file, if not otherwise found. August 1, 2000 - Release 2.8.3 Improve handling of 1-D WCS data. Fix numerous warning-generating bugs. Fix bug in ep2jd()/jd2ep() so both start year at 1/1 0:00 June 13, 2000 - Release 2.8.2 If imh pixel file has no directory, *always* use same as header file June 9, 2000 - Release 2.8.1 Read keyword values in hget.c even if no equal sign is present. June 2, 2000 - Release 2.8.0 Only a few minor changes due to running lint on everything ------------------------ May 10, 2000 - Release 2.7.4 In wcstype(), default to WCS_LIN, not error (after Bill Joye) May 1, 2000 - Release 2.7.3 Bug in hadd() fixed so new line is not overwritten. Pixel files whcih are in subdirectories of files where IRAF .imh header files reside are now dealt with correctly. All dates in the old FITS format (dd/mm/yy) where the year ranges from 0 to 999 have 1900 added to them: 01/05/100 becomes 2000-05-01. March 27, 2000 - Release 2.7.2 In hputs(), do not add quotes if writing COMMENT or HISTORY In fits2iraf(), in imhfile.c, minimize length of path in pixel file name Fix code to deal with .imh file paths longer than 67 characters. In platepix(), use inverse CD matrix to get better initial x,y value Change the maximum header string length in the hget header reading subroutines from 57600 to 256000 Replace oldsys with wcsproj in the WCS data structure so that more options are available, such as forcing use of AIPS or WCSLIB projection subroutines Add setdatedec() to set the number of decimal places in FITS date strings returned by dateutil subroutines Fix precession code to deal correctly with equinoxes other than J2000 and B1950. Move all date operations to dateutil.c, including current time used in imhfile.c February 23, 2000 - Release 2.7.0 Upgrade WCSLIB subroutines to WCSLIB 2.5 from 2.4 Add MJD and Besselian and Julian epoch conversion to dateutil.c Use WCSLIB CAR, COE, NCP projections if oldsys is 1, else use worldpos() Set CD matrix when using DSS projection Change oldwcs in wcs.h from switch to multi-value flag wcsproj, default is same Fix minor bug in fitsfile.c fitscimage error returns. ------------------------ January 11, 2000 - Release 2.6.12 Fix bug in dateutil() to get fractional year to date conversion right December 20, 1999 - Release 2.6.11 Fix bug in hgetdate() to get ISO minutes and seconds right Upgrade dateutil() to do many date conversions December 10, 1999 - Release 2.6.10 Fix bug which caused strings starting with d and e followed by numbers to be declared numeric even though they're not really numbers Fix bug in dateutil.c ts2jd() which does not affect SAOimage Fix bugs dealing with NOAO TNX projection November 17, 1999 - Release 2.6.9 Fix bug which caused loss of NCP projection November 5, 1999 - Release 2.6.8 Change release number to match WCSTools Clean up code in all subroutines using lint Add DATE-MOD to FITS header in iraf2fits() Added dateutil.c file for conversions between date formats (used by iraf2fits()) Return error code from hput*() subroutines if header buffer length exceeded. ------------------------ May 5, 1999 - Release 1.26 hget.c, iget.c Use POSIX-compliant limits.h instead of values.h April 7, 1999 - Release 1.26 wcs.c Fix bug in dealing with EPOCHless non-equatorial coordinates wcsinit.c Add optional filename to printed error messages April 5, 1999 - Release 1.26 hget.c Check all string lengths before copying; ignore ^M at 80th character February 22, 1999 - Release 1.26 wcs.c Fix bug dealing with SPA and NPA coordinates Use faaces 0-5, not 1-6 for quad cube projections wcsinit.c Fix computed rotation angle for DSS projection February 9, 1999 - Release 1.26 fitsfile.c: Allow BITPIX=0 dataless images wcsinit.c: Fix bug initializing DSS image rotation wcs.c: Free lin.imgpix and lin.piximg in wcsfree() hput.c: Fix bug to avoid writing HISTORY or COMMENT lines past 80 chars ------------------------ December 8, 1998 - Release 1.25 fitsfile.c: Fix bug in fitsrhead() reading FITS table files caused by fix below November 30, 1998 - Release 1.25 fitsfile.c: Fix bug dealing with very large headers in fitsrhead() November 12, 1998 - Release 1.25 dsspos.c: Fix possible divide by zero problems fitsfile.c: Add isfits() which checks filename or first line of header imhfile.c: Add isiraf() which checks filename for .imh hget.c: Assume 2-digit year in hyphen-separated date means FITS, not ISO tnxpos.c: Fix multiple bugs wcscon.c: Add wcscstr() to get coordinate system as a character string wcscon.c: Add subroutine wcsconp() to convert coordinates + proper motions wcs.c: Add North and South Polar Angle coordinate systems wcs.c: Build WCS command initialization by getenv() into wcs*init() wcs.c: Fix bug in wcssize(); fix bug with rotated mirrored images wcslib.h: Add cel.h, lin.h, proj.h, and wcstrig.h to wcslib.h worldpos.c: Fix bug in inverse (sky to pixel) COE projection cel.c, lin.c, proj.c, sph.c, wcstrig.c: Include only wcslib.h wcstools-3.9.5/libwcs/Readme0000644000016200001660000000134407021765007015062 0ustar minkoirsysWCSTools libwcs.a These subroutines support the programs in the WCSTools package and include catalog search engines, image manipulation software, and fitting software. There use is documented on the World Wide Web at http://tdc-www.harvard.edu/software/wcstools/ Information about the individual files is in the Subroutines file. A self-contained subset of these programs which deal with image world coordinate systems is separately available and is used by the SAOimage, SAOtng, Skycat, and DS9 image display programs: cel.c dsspos.c fitshead.h fitsfile.c fitsfile.h hget.c hput.c iget.c imhfile.c imio.c lin.c platepos.c proj.c slasubs.c sph.c tnxpos.c wcs.c wcs.h wcscon.c wcslib.c wcslib.h wcstrig.c worldpos.c dateutil.c wcstools-3.9.5/libwcs/actread.c0000664000016200001660000010056211750060473015514 0ustar minkoirsys/*** File libwcs/actread.c *** January 10, 2007 *** By Jessica Mink, jmink@cfa.harvard.edu *** Copyright (C) 1999-2007 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include #include #include #include "fitsfile.h" #include "wcs.h" #include "wcscat.h" /* pathname of ACT CDROM or catalog search engine URL */ char actcd[64]="/data/act"; #define MAXREG 100 static double *gdist; /* Array of distances to stars */ static int ndist = 0; static int actreg(); struct StarCat *actopen(); void actclose(); static int actstar(); static int actsize(); static int actsra(); /* ACTREAD -- Read USNO ACT Star Catalog stars from CDROM */ int actread (cra,cdec,dra,ddec,drad,dradi,distsort,sysout,eqout,epout,mag1,mag2, sortmag,nstarmax,gnum,gra,gdec,gpra,gpdec,gmag,gtype,nlog) double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ double dradi; /* Inner edge of annulus in degrees (ignore if 0) */ int distsort; /* 1 to sort stars by distance from center */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 to nmag) */ int nstarmax; /* Maximum number of stars to be returned */ double *gnum; /* Array of Guide Star numbers (returned) */ double *gra; /* Array of right ascensions (returned) */ double *gdec; /* Array of declinations (returned) */ double *gpra; /* Array of right ascension proper motions (returned) */ double *gpdec; /* Array of declination proper motions (returned) */ double **gmag; /* Array of visual magnitudes (returned) */ int *gtype; /* Array of object types (returned) */ int nlog; /* 1 for diagnostics */ { double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ double dist = 0.0; /* Distance from search center in degrees */ double faintmag=0.0; /* Faintest magnitude */ double maxdist=0.0; /* Largest distance */ int faintstar=0; /* Faintest star */ int farstar=0; /* Most distant star */ int nreg = 0; /* Number of ACT regions in search */ int rlist[MAXREG]; /* List of input region files */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ double secmarg = 60.0; /* Arcsec/century margin for proper motion */ struct StarCat *starcat; struct Star *star; int verbose; int wrap; int pass; int magsort; int rnum, ireg; int jstar, iw; int nrmax,nstar,i, ntot; int istar, istar1, istar2; double num, ra, dec, rapm, decpm, mag, magb, magv; double rra1, rra2, rra2a, rdec1, rdec2; double rdist, ddist; char *str; char cstr[32], decstr[32], rastr[32]; int nbytes; ntot = 0; if (nlog == 1) verbose = 1; else verbose = 0; /* Set path to ACT Catalog */ if ((str = getenv("ACT_PATH")) == NULL ) str = actcd; /* If pathname is a URL, search and return */ if (!strncmp (str, "http:",5)) { return (webread (str,"act",distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nstarmax, gnum,gra,gdec,gpra,gpdec,gmag,gtype,nlog)); } if (sortmag > 0 && sortmag < 3) magsort = sortmag - 1; else magsort = 1; wcscstr (cstr, sysout, eqout, epout); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* make mag1 always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } /* Allocate table for distances of stars from search center */ if (nstarmax > 10) nbytes = nstarmax * sizeof (double); else nbytes = 10 * sizeof (double); if (nstarmax > ndist) { if (ndist > 0) free ((void *) gdist); gdist = (double *) malloc (nbytes); if (gdist == NULL) { fprintf (stderr,"ACTREAD: cannot allocate separation array\n"); return (0); } ndist = nstarmax; } /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; nstar = 0; jstar = 0; rra1 = ra1; rra2 = ra2; rdec1 = dec1; rdec2 = dec2; RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref,secmarg, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); if (wrap) { rra2a = rra2; rra2 = 360.0; } else rra2a = 0.0; nrmax = MAXREG; /* Write header if printing star entries as found */ if (nstarmax < 1) { char *revmessage; revmessage = getrevmsg(); printf ("catalog ACT\n"); ra2str (rastr, 31, cra, 3); printf ("ra %s\n", rastr); dec2str (decstr, 31, cdec, 2); printf ("dec %s\n", decstr); printf ("rpmunit mas/year\n"); printf ("dpmunit mas/year\n"); if (drad != 0.0) { printf ("radmin %.1f\n", drad*60.0); if (dradi > 0) printf ("radimin %.1f\n", dradi*60.0); } else { printf ("dramin %.1f\n", dra*60.0 * cosdeg (cdec)); printf ("ddecmin %.1f\n", ddec*60.0); } printf ("radecsys %s\n", cstr); printf ("equinox %.3f\n", eqout); printf ("epoch %.3f\n", epout); printf ("program scat %s\n", revmessage); printf ("act_id ra dec "); printf ("magb magv ura udec arcmin\n"); printf ("---------- ------------ ------------ "); printf ("----- ----- ------ ------ ------\n"); } /* If searching through RA = 0:00, split search in two */ for (iw = 0; iw <= wrap; iw++) { /* Find ACT Star Catalog regions in which to search */ nreg = actreg (rra1,rra2,rdec1,rdec2,nrmax,rlist,verbose); if (nreg <= 0) { fprintf (stderr,"ACTREAD: no ACT regions found\n"); free ((void *)star); return (0); } /* Loop through region list */ for (ireg = 0; ireg < nreg; ireg++) { /* Open catalog file for this region */ starcat = actopen (rlist[ireg]); rnum = rlist[ireg]; /* Set first and last stars to check */ istar1 = actsra (starcat, star, rra1); istar2 = actsra (starcat, star, rra2); if (verbose) fprintf (stderr,"ACTREAD: Searching stars %d.%d through %d.%d\n", rnum,istar1,rnum,istar2); /* Loop through catalog for this region */ for (istar = istar1; istar <= istar2; istar++) { if (actstar (starcat, star, istar)) { fprintf (stderr,"ACTREAD: Cannot read star %d\n", istar); break; } /* Magnitude */ magv = star->xmag[0]; magb = star->xmag[1]; mag = star->xmag[magsort]; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; /* Get position in output coordinate system */ if (pass) { rapm = star->rapm; decpm = star->decpm; ra = star->ra; dec = star->dec; wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); /* Compute distance from search center */ if (drad > 0 || distsort) dist = wcsdist (cra,cdec,ra,dec); else dist = 0.0; /* Check radial distance to search center */ if (drad > 0) { if (dist > drad) pass = 0; if (dradi > 0.0 && dist < dradi) pass = 0; } /* Check distance along RA and Dec axes */ else { ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } } if (pass) { /* ID number */ num = (double) rlist[ireg] + (star->num / 100000.0); /* Write star position and magnitudes to stdout */ if (nstarmax < 1) { ra2str (rastr, 31, ra, 3); dec2str (decstr, 31, dec, 2); dist = wcsdist (cra,cdec,ra,dec) * 60.0; printf ("%010.5f %s %s", num,rastr,decstr); printf (" %.2f %.2f %6.1f %6.1f %.2f\n", magb, magv, gpra[nstar] * 3600000.0 * cosdeg(dec), gpdec[nstar] * 3600000.0, dist / 60.0); } /* Save star position and magnitude in table */ if (nstar < nstarmax) { gnum[nstar] = num; gra[nstar] = ra; gdec[nstar] = dec; gpra[nstar] = rapm; gpdec[nstar] = decpm; gmag[0][nstar] = magb; gmag[1][nstar] = magv; gdist[nstar] = dist; if (dist > maxdist) { maxdist = dist; farstar = nstar; } if (mag > faintmag) { faintmag = mag; faintstar = nstar; } } /* If too many stars and distance sorting, replace farthest star */ else if (distsort) { if (dist < maxdist) { gnum[farstar] = num; gra[farstar] = ra; gdec[farstar] = dec; gpra[farstar] = rapm; gpdec[farstar] = decpm; gmag[0][farstar] = magb; gmag[1][farstar] = magv; gdist[farstar] = dist; /* Find new farthest star */ maxdist = 0.0; for (i = 0; i < nstarmax; i++) { if (gdist[i] > maxdist) { maxdist = gdist[i]; farstar = i; } } } } /* Else if too many stars, replace faintest star */ else if (mag < faintmag) { gnum[faintstar] = num; gra[faintstar] = ra; gdec[faintstar] = dec; gpra[farstar] = rapm; gpdec[farstar] = decpm; gmag[0][faintstar] = magb; gmag[1][faintstar] = magv; gdist[faintstar] = dist; faintmag = 0.0; /* Find new faintest star */ for (i = 0; i < nstarmax; i++) { if (gmag[magsort][i] > faintmag) { faintmag = gmag[magsort][i]; faintstar = i; } } } nstar++; if (nlog == 1) fprintf (stderr,"ACTREAD: %11.6f: %9.5f %9.5f %5.2f %5.2f\n", num,ra,dec,magb,mag); /* End of accepted star processing */ } /* Log operation */ jstar++; if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"ACTREAD: %5d / %5d / %5d sources\r", nstar,jstar,starcat->nstars); /* End of star loop */ } ntot = ntot + starcat->nstars; if (nlog > 0) fprintf (stderr,"ACTREAD: %4d / %4d: %5d / %5d / %5d sources from region %4d \n", ireg+1,nreg,nstar,jstar,starcat->nstars,rlist[ireg]); /* Close region input file */ actclose (starcat); } rra1 = 0.0; rra2 = rra2a; } /* close output file and summarize transfer */ if (nlog > 0) { if (nreg > 1) fprintf (stderr,"ACTREAD: %d regions: %d / %d found\n",nreg,nstar,ntot); else fprintf (stderr,"ACTREAD: 1 region: %d / %d found\n",nstar,ntot); if (nstar > nstarmax) fprintf (stderr,"ACTREAD: %d stars found; only %d returned\n", nstar,nstarmax); } free ((void *)star); return (nstar); } /* ACTRNUM -- Read HST Guide Star Catalog stars from CDROM */ int actrnum (nstars,sysout,eqout,epout, gnum,gra,gdec,gpra,gpdec,gmag,gtype,nlog) int nstars; /* Number of stars to find */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double *gnum; /* Array of Guide Star numbers (returned) */ double *gra; /* Array of right ascensions (returned) */ double *gdec; /* Array of declinations (returned) */ double *gpra; /* Array of right ascension proper motions (returned) */ double *gpdec; /* Array of declination proper motions (returned) */ double **gmag; /* Array of V, B magnitudes (returned) */ int *gtype; /* Array of object types (returned) */ int nlog; /* 1 for diagnostics */ { int sysref; /* Catalog coordinate system */ double eqref; /* Catalog equinox */ double epref; /* Catalog epoch */ struct StarCat *starcat = NULL; struct Star *star; int rnum; int jstar; int istar, nstar, snum; double num, ra, dec, rapm, decpm, mag, magb; char *str; /* Set path to ACT Catalog */ if ((str = getenv("ACT_PATH")) == NULL ) str = actcd; /* If pathname is a URL, search and return */ if (!strncmp (str, "http:",5)) { return (webrnum (str,"act",nstars, sysout,eqout,epout, 1, gnum,gra,gdec,gpra,gpdec,gmag,gtype,nlog)); } /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; nstar = 0; /* Loop through star list */ for (jstar = 0; jstar < nstars; jstar++) { rnum = (int) gnum[jstar]; snum = (int) (((gnum[jstar] - (double)rnum) * 100000.0) + 0.01); /* Open file for this region of ACT catalog */ starcat = actopen (rnum); if (starcat == NULL) { free ((void*) star); return (0); } sysref = starcat->coorsys; eqref = starcat->equinox; epref = starcat->epoch; /* Find star in catalog */ istar = snum; if (actstar (starcat, star, istar)) { fprintf (stderr,"ACTRNUM: Cannot read star %d\n", istar); gra[nstar] = 0.0; gdec[nstar] = 0.0; gmag[0][nstar] = 0.0; gmag[1][nstar] = 0.0; gtype[nstar] = 0; continue; } /* If star has been found in catalog */ /* ID number */ num = star->num; /* Position in degrees at designated epoch */ ra = star->ra; dec = star->dec; rapm = star->rapm; decpm = star->decpm; wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); /* Magnitude */ mag = star->xmag[0]; magb = star->xmag[1]; /* Save star position and magnitude in table */ gra[nstar] = ra; gdec[nstar] = dec; gpra[nstar] = rapm; gpdec[nstar] = decpm; gmag[0][nstar] = magb; gmag[1][nstar] = mag; nstar++; if (nlog == 1) fprintf (stderr,"ACTRNUM: %11.6f: %9.5f %9.5f %5.2f %5.2f \n", num, ra, dec, magb, mag); /* End of star loop */ } /* Summarize search */ if (nlog > 0) fprintf (stderr,"ACTRNUM: %d / %d found\n",nstar,nstars); if (starcat != NULL) actclose (starcat); free ((void*) star); return (nstar); } /* ACTBIN -- Fill FITS WCS image with USNO ACT Star Catalog stars */ int actbin (wcs, header, image, mag1, mag2, sortmag, magscale, nlog) struct WorldCoor *wcs; /* World coordinate system for image */ char *header; /* FITS header for output image */ char *image; /* Output FITS image */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 to nmag) */ double magscale; /* Scaling factor for magnitude to pixel flux * (number of catalog objects per bin if 0) */ int nlog; /* 1 for diagnostics */ { double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ int nreg = 0; /* Number of ACT regions in search */ int rlist[MAXREG]; /* List of input region files */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ double secmarg = 60.0; /* Arcsec/century margin for proper motion */ struct StarCat *starcat; struct Star *star; int verbose; int wrap; int pass; int magsort; int rnum, ireg; int ix, iy; int jstar, iw; int nrmax,nstar, ntot; int istar, istar1, istar2; double num, ra, dec, rapm, decpm, mag, magb, magv; double rra1, rra2, rra2a, rdec1, rdec2; double rdist, ddist; char *str; char cstr[32]; double xpix, ypix, flux; int offscl; int bitpix, w, h; /* Image bits/pixel and pixel width and height */ double logt = log(10.0); ntot = 0; if (nlog == 1) verbose = 1; else verbose = 0; /* Set path to ACT Catalog */ str = getenv("ACT_PATH"); if (sortmag > 0 && sortmag < 3) magsort = sortmag - 1; else magsort = 1; /* Set image parameters */ bitpix = 0; (void)hgeti4 (header, "BITPIX", &bitpix); w = 0; (void)hgeti4 (header, "NAXIS1", &w); h = 0; (void)hgeti4 (header, "NAXIS2", &h); /* Set catalog search limits from image WCS information */ sysout = wcs->syswcs; eqout = wcs->equinox; epout = wcs->epoch; wcscstr (cstr, sysout, eqout, epout); wcssize (wcs, &cra, &cdec, &dra, &ddec); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* If RA range includes zero, split it in two */ wrap = 0; if (ra1 > ra2) wrap = 1; else wrap = 0; /* make mag1 always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; nstar = 0; jstar = 0; rra1 = ra1; rra2 = ra2; rdec1 = dec1; rdec2 = dec2; RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref,secmarg, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); if (wrap) { rra2a = rra2; rra2 = 360.0; } else rra2a = 0.0; nrmax = MAXREG; /* If searching through RA = 0:00, split search in two */ for (iw = 0; iw <= wrap; iw++) { /* Find ACT Star Catalog regions in which to search */ nreg = actreg (rra1,rra2,rdec1,rdec2,nrmax,rlist,verbose); if (nreg <= 0) { fprintf (stderr,"ACTBIN: no ACT regions found\n"); free ((void *)star); return (0); } /* Loop through region list */ for (ireg = 0; ireg < nreg; ireg++) { /* Open catalog file for this region */ starcat = actopen (rlist[ireg]); rnum = rlist[ireg]; /* Set first and last stars to check */ istar1 = actsra (starcat, star, rra1); istar2 = actsra (starcat, star, rra2); if (verbose) fprintf (stderr,"ACTBIN: Searching stars %d.%d through %d.%d\n", rnum,istar1,rnum,istar2); /* Loop through catalog for this region */ for (istar = istar1; istar <= istar2; istar++) { if (actstar (starcat, star, istar)) { fprintf (stderr,"ACTBIN: Cannot read star %d\n", istar); break; } /* ID number */ num = star->num; /* Magnitude */ magv = star->xmag[0]; magb = star->xmag[1]; mag = star->xmag[magsort]; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; /* Get position in output coordinate system */ if (pass) { rapm = star->rapm; decpm = star->decpm; ra = star->ra; dec = star->dec; wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); /* Check distance along RA and Dec axes */ ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } /* Save star in FITS image */ if (pass) { wcs2pix (wcs, ra, dec, &xpix, &ypix, &offscl); if (!offscl) { if (magscale > 0.0) flux = magscale * exp (logt * (-mag / 2.5)); else flux = 1.0; ix = (int) (xpix + 0.5); iy = (int) (ypix + 0.5); addpix1 (image, bitpix, w,h, 0.0,1.0, xpix,ypix, flux); nstar++; jstar++; } else { ix = 0; iy = 0; } if (nlog == 1) { fprintf (stderr,"TABBIN: %11.6f: %9.5f %9.5f %s", num,ra,dec,cstr); if (magscale > 0.0) fprintf (stderr, " %5.2f", mag); if (!offscl) flux = getpix1 (image, bitpix, w, h, 0.0, 1.0, ix, iy); else flux = 0.0; fprintf (stderr," (%d,%d): %f\n", ix, iy, flux); } /* End of accepted star processing */ } /* Log operation */ jstar++; if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"ACTBIN: %5d / %5d / %5d sources\r", nstar,jstar,starcat->nstars); /* End of star loop */ } ntot = ntot + starcat->nstars; if (nlog > 0) fprintf (stderr,"ACTBIN: %4d / %4d: %5d / %5d / %5d sources from region %4d \n", ireg+1,nreg,nstar,jstar,starcat->nstars,rlist[ireg]); /* Close region input file */ actclose (starcat); } rra1 = 0.0; rra2 = rra2a; } /* close output file and summarize transfer */ if (nlog > 0) { if (nreg > 1) fprintf (stderr,"ACTBIN: %d regions: %d / %d found\n",nreg,nstar,ntot); else fprintf (stderr,"ACTBIN: 1 region: %d / %d found\n",nstar,ntot); } free ((void *)star); return (nstar); } /* ACTREG -- from RA and Dec ranges, figure out which ACT files to search * Build a list containing the numeric part of the CDROM file names. */ static int regions[48]={ 0, 30, 100, 130, 200, 230, 300, 330, 400, 430, 500, 530, 600, 630, 700, 730, 800, 830, 900, 930, 1000,1030,1100,1130,1200,1230,1300,1330,1400,1430, 1500,1530,1600,1630,1700,1730,1800,1830,1900,1930, 2000,2030,2100,2130,2200,2230,2300,2330}; static double reghour[49]={ 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0,10.5,11.0,11.5,12.0,12.5,13.0,13.5,14.0,14.5, 15.0,15.5,16.0,16.5,17.0,17.5,18.0,18.5,19.0,19.5, 20.0,20.5,21.0,21.5,22.0,22.5,23.0,23.5,24.0}; static int actreg (ra1, ra2, dec1, dec2, nrmax, rgns, verbose) double ra1, ra2; /* Right ascension limits in degrees */ double dec1, dec2; /* Declination limits in degrees */ int nrmax; /* Maximum number of regions to find */ int *rgns; /* Region numbers (returned)*/ int verbose; /* 1 for diagnostics */ { int nsrch; /* Number of regions found (returned) */ int i, ir, irx; int ir1 = 0; int ir2 = 0; /* Zero out regions to be searched */ for (i = 0; i < nrmax; i++) rgns[i] = 0; /* Find region range to search based on declination */ /* Find RA regions to search */ ra1 = ra1 / 15.0; ra2 = ra2 / 15.0; irx = 0; /* Find first region to search */ for (ir = 1; ir < 49; ir++) { if (ra1 >= reghour[ir-1] && ra1 <= reghour[ir]) { ir1 = ir - 1; break; } } /* Find last region to search */ for (ir = 1; ir < 49; ir++) { if (ra2 >= reghour[ir-1] && ra2 <= reghour[ir]) { ir2 = ir - 1; break; } } if (ir2 >= ir1) { for (ir = ir1; ir <= ir2; ir++) { if (irx < nrmax) rgns[irx++] = regions[ir]; } } else if (ir2 < ir1) { for (ir = ir1; ir < 48; ir++) { if (irx < nrmax) rgns[irx++] = regions[ir]; } for (ir = 0; ir <= ir2; ir++) { if (irx < nrmax) rgns[irx++] = regions[ir]; } } nsrch = irx; if (verbose) { fprintf (stderr,"ACTREG: RA: %.5f - %.5f, Dec: %.5f - %.5f\n", ra1,ra2,dec1,dec2); fprintf (stderr,"ACTREG: searching %d regions:",nsrch); for (ir = 0; ir < nsrch; ir++) fprintf (stderr," %04d",rgns[ir]); fprintf (stderr,"\n"); } return (nsrch); } /* ACTOPEN -- Open ACT catalog region file, returning number of entries */ struct StarCat * actopen (regnum) int regnum; /* ACT Catalog region number */ { FILE *fcat; struct StarCat *sc; int lfile, lpath; char *actfile; char *path; /* Full pathname for catalog file */ char *cdpath; /* Set the pathname using the appropriate ACT CDROM directory */ if ((cdpath = getenv("ACT_PATH")) == NULL ) cdpath = actcd; lpath = strlen (cdpath) + 32; path = (char *) calloc (lpath, 1); /* Declination zoned regions */ if (regnum > 0 && regnum < 5) sprintf (path,"%s/data2/act%1d.dat", cdpath, regnum); /* Right ascension zoned regions */ else sprintf (path,"%s/data1/act%04d.dat", cdpath, regnum); /* Find length of ACT catalog region file */ lfile = actsize (path); /* Check for existence of catalog */ if (lfile < 2) { fprintf (stderr,"ACTOPEN: Binary catalog %s has no entries\n", path); free (path); return (0); } /* Open ACT region file */ if (!(fcat = fopen (path, "r"))) { fprintf (stderr,"ACTOPEN: ACT region file %s cannot be read\n",path); free (path); return (0); } /* Set ACT catalog header information */ sc = (struct StarCat *) calloc (1, sizeof (struct StarCat)); sc->byteswapped = 0; sc->nbent = 161; sc->nstars = lfile / sc->nbent; /* Separate filename from pathname and save in structure */ actfile = strrchr (path,'/'); if (actfile) actfile = actfile + 1; else actfile = path; if (strlen (actfile) < 24) strcpy (sc->isfil, actfile); else strncpy (sc->isfil, actfile, 23); /* Set other catalog information in structure */ sc->inform = 'J'; sc->coorsys = WCS_J2000; sc->epoch = 2000.0; sc->equinox = 2000.0; sc->ifcat = fcat; sc->sptype = 2; /* ACT region files are all RA-sorted */ sc->rasorted = 1; return (sc); } void actclose (sc) struct StarCat *sc; /* Star catalog descriptor */ { fclose (sc->ifcat); free ((void *)sc); return; } /* ACTSRA -- Find star closest to given RA in ACT catalog file */ static int actsra (sc, st, dra) struct StarCat *sc; /* Star catalog descriptor */ struct Star *st; /* Current star entry */ double dra; /* Right ascension in degrees */ { char rastr[32], raxstr[32], ramins[32], ramaxs[32]; int istar0, istarx, nrep, ismin, ismax; double rax, ramin, ramax; int verbose = 0; /* Keep RA between 0 and 360 degrees */ if (dra > 360.0) rax = dra - 360.0; else rax = dra; ismin = 1; if (actstar (sc, st, ismin)) { fprintf (stderr,"ACTSRA: Cannot read star %d\n", ismin); return (0); } else ramin = st->ra; ismax = sc->nstars; if (actstar (sc, st, ismax)) { fprintf (stderr,"ACTSRA: Cannot read star %d\n", ismax); return (0); } else ramax = st->ra; istarx = sc->nstars / 2; for (nrep = 0; nrep < 32; nrep++) { if (actstar (sc, st, istarx)) { fprintf (stderr,"ACTSRA: Cannot read star %d\n", istarx); return (0); } /* Find next catalog number to read */ if (st->ra < rax) { ismin = istarx; ramin = st->ra; istar0 = istarx; if (ismax - istarx > 1) istarx = istarx + (ismax - istarx) / 2; else if (ismax - istarx > 0) istarx = istarx + 1; } else if (st->ra > rax) { ismax = istarx; ramax = st->ra; istar0 = istarx; if (istarx - ismin > 1) istarx = istarx - ((istarx - ismin) / 2); else if (istarx - ismin > 0) istarx = istarx - 1; } else break; if (verbose) { ra2str (rastr, 16, st->ra, 3); ra2str (raxstr, 16, rax, 3); ra2str (ramins, 16, ramin, 3); ra2str (ramaxs, 16, ramax, 3); fprintf (stderr,"%9d: %s -> %s %9d: %s %9d: %s\n", istarx, rastr, raxstr, ismin,ramins,ismax,ramaxs); } if (istarx == istar0) break; } /* Make sure final star is real */ if (actstar (sc, st, istarx)) { fprintf (stderr,"ACTSRA: Cannot read star %d\n", istarx); return (0); } else return (istarx); } /* ACTSTAR -- Get ACT catalog entry for one star; return 0 if successful */ static int actstar (sc, st, istar) struct StarCat *sc; /* Star catalog descriptor */ struct Star *st; /* Current star entry */ int istar; /* Star sequence number in ACT catalog region file */ { int nbr; long offset; char dsgn; char line[256]; int irh,irm,idd,idm; double rs, ds; /* double bvmag; */ /* Drop out if catalog pointer is not set */ if (sc == NULL) return (1); /* Drop out if catalog is not open */ if (sc->ifcat == NULL) return (2); /* Drop out if star number is too large */ if (istar > sc->nstars) { fprintf (stderr, "ACTSTAR: %d > %d is not in catalog\n", istar, sc->nstars); return (3); } /* Move file pointer to start of correct star entry */ if (istar > 0) { offset = (istar - 1) * sc->nbent; if (fseek (sc->ifcat, offset, SEEK_SET)) return (4); } /* Read catalog entry */ if ((nbr = fread (line, sc->nbent, 1, sc->ifcat)) > sc->nbent) { fprintf (stderr, "ACTSTAR: %d / %d bytes read from %s\n", nbr, sc->nbent, sc->isfil); return (5); } st->num = (double) istar; /* Read position for this star */ irh = atoi (line); irm = atoi (line+3); rs = atof (line+6); dsgn = line[14]; idd = atoi (line+15); idm = atoi (line+18); ds = atof (line+21); /* Convert position to degrees */ st->ra = hrdeg ((double)irh + ((double)irm)/60.0 + rs / 3600.0); st->dec = (double) idd + ((double)idm) / 60.0 + ds / 3600.0; if (dsgn == '-') st->dec = -st->dec; /* Read proper motion and convert it to to degrees/year */ st->rapm = hrdeg (atof (line+28)) / 3600.0; st->decpm = atof (line+36) / 3600.0; /* Set V, B, B-V magnitudes */ st->xmag[0] = atof (line+75); st->xmag[1] = atof (line+68); st->xmag[2] = atof (line+82); st->isp[0] = (char) 0; st->isp[1] = (char) 0; return (0); } /* ACTSIZE -- return size of one ACT catalog file in bytes */ static int actsize (filename) char *filename; /* Name of file for which to find size */ { FILE *diskfile; long filesize; /* Open file */ if ((diskfile = fopen (filename, "r")) == NULL) return (-1); /* Move to end of the file */ if (fseek (diskfile, 0, 2) == 0) /* Position is the size of the file */ filesize = ftell (diskfile); else filesize = -1; fclose (diskfile); return (filesize); } /* Feb 11 1999 New program * Apr 13 1999 Fix bugs which caused failure on crossing 0:00 h * May 12 1999 Fix bug for all searches * May 21 1999 Fix bug with proper motion so it is in deg/yr, not sec/yr * Jun 16 1999 Use SearchLim() * Aug 16 1999 Add RefLim() to get converted search coordinates right * Aug 25 1999 Return real number of stars from actread() * Sep 16 1999 Fix bug which didn't always return closest stars * Sep 16 1999 Add distsort argument so brightest stars in circle works, too * Oct 21 1999 Delete unused varaiables after lint * * Jan 5 2000 Add 2 to spectral type string so there can be proper termination * Mar 15 2000 Add proper motions to returns from actread() and actrnum() * May 31 2000 Get spectral type from bv2sp() * Jun 2 2000 Free all allocated data structures * Jun 9 2000 Fix bug which caused memory overflow if limiting number * Jun 26 2000 Add coordinate system to SearchLim() arguments * Sep 25 2000 Set sc->sptype to 2 to indicate presence of spectral type * Nov 29 2000 Add option to read catalog using HTTP * Dec 11 2000 Allow catalog search engine URL in actcd[] * * Jan 11 2001 All printing is to stderr * Jun 14 2001 Drop spectral type approximation * Sep 11 2001 Change to single magnitude argeument * Sep 11 2001 Add sort magnitude argument to actread() * * Apr 8 2002 Fix extraneous declaration of actsize() * Oct 2 2002 Print stars as found in actread() if nstarmax < 1 * * Mar 11 2003 Fix position limit testing * Apr 3 2003 Drop unused type variables in actstar() and actread() * Apr 14 2003 Explicitly get revision date if nstarmax < 1 * Jun 2 2003 Print proper motion as mas/year * Aug 22 2003 Add radi argument for inner edge of search annulus * Aug 22 2003 Fix bug in actrnum: mags were not in one array * Sep 25 2003 Add actbin() to fill an image with sources * Oct 6 2003 Update actread() and actbin() for improved RefLim() * Nov 18 2003 Initialize image size and bits/pixel from header in actbin() * Dec 1 2003 Add missing tab to n=-1 header * Dec 12 2003 Fix bug in wcs2pix() call in actbin() * * Aug 30 2004 Include math.h * * Jun 20 2006 Initialize uninitialized variables * Sep 26 2006 Increase length of rastr and destr from 16 to 32 * Nov 16 2006 Fix binning * * Jan 10 2007 Add match=1 argument to webrnum() * Jan 10 2007 Rewrite web access in actread() and actrnum() to reduce code */ wcstools-3.9.5/libwcs/binread.c0000664000016200001660000012264612011324524015513 0ustar minkoirsys/*** File libwcs/binread.c *** September 16, 2011 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1998-2011 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ /* int binread() Read binary catalog sources + names in specified region * int binrnum() Read binary catalog sources + names with specified numbers * int binopen() Open binary catalog, returning number of entries * int binstar() Get binary catalog entry for one source * void binclose() Close binary catalog */ /* default pathname for catalog, used if catalog file not found in current working directory, but overridden by the WCS_BINDIR, SAO_PATH (if bincat is SAO), PPM_PATH (if bincat is PPM, HIP_PATH, if bincat is HIP, or IRAS_PATH is bincat is IRAS) environment variable */ char bindir[64]="/data/astrocat"; static double *tdist; /* Array of distances to sources from search center */ static int ndist = 0; #include #include #include #include #include #include #include #include #include #include "wcs.h" #include "fitsfile.h" #include "wcscat.h" #ifndef O_BINARY #define O_BINARY 0 #endif static int binsra(); static int binsize(); void binclose(); static void binswap8(); static void binswap4(); static void binswap2(); /* BINREAD -- Read binary catalog sources + names in specified region */ int binread (bincat,distsort,cra,cdec,dra,ddec,drad,dradi,sysout,eqout,epout, mag1,mag2,sortmag,nstarmax,starcat, tnum,tra,tdec,tpra,tpdec,tmag,tpeak,tobj,nlog) char *bincat; /* Name of reference star catalog file */ int distsort; /* 1 to sort stars by distance from center */ double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ double dradi; /* Inner edge of annulus in degrees (ignore if 0) */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 to nmag) */ int nstarmax; /* Maximum number of sources to be returned */ struct StarCat **starcat; /* Star catalog data structure */ double *tnum; /* Array of catalog numbers (returned) */ double *tra; /* Array of right ascensions (returned) */ double *tdec; /* Array of declinations (returned) */ double *tpra; /* Array of right ascension proper motions (returned) */ double *tpdec; /* Array of declination proper motions (returned) */ double **tmag; /* 2-D Array of magnitudes (returned) */ int *tpeak; /* Array of encoded spectral types (returned) */ char **tobj; /* Array of object names (returned) */ int nlog; { double rra1,rra2; /* Limiting catalog right ascensions of region */ double rdec1,rdec2; /* Limiting catalog declinations of region */ double ra1,ra2; /* Limiting output right ascensions of region */ double dec1,dec2; /* Limiting output declinations of region */ double dist = 0.0; /* Distance from search center in degrees */ double faintmag=0.0; /* Faintest magnitude */ double maxdist=0.0; /* Largest distance */ int faintstar=0; /* Faintest star */ int farstar=0; /* Most distant star */ int sysref; /* Catalog coordinate system */ double eqref; /* Catalog coordinate equinox */ double epref; /* Catalog position epoch */ double secmarg = 60.0; /* Arcsec/century margin for proper motion */ double ra, dec, rapm, decpm; double rra1a, rra2a; double rdist, ddist; struct StarCat *sc; /* Star catalog data structure */ struct Star *star; int wrap, iwrap, istar1,istar2; int pass; int imag; char *objname; int lname; int nmag; /* Real number of magnitudes per entry (- rv) */ int jstar; int nstar; double mag = 0.0; double num; int i; int magsort; int istar = 0; int isp; int verbose; int mrv; char cstr[16]; char str[128]; sc = *starcat; if (nlog > 0) verbose = 1; else verbose = 0; /* Open catalog */ if (sc == NULL) sc = binopen (bincat); *starcat = sc; if (sc == NULL) return (0); /* If pathname is a URL, search and return */ if (sc->caturl != NULL) { *starcat = NULL; strcpy (str, sc->caturl); free (sc); return (webread (str,bincat,distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nstarmax, tnum,tra,tdec,tpra,tpdec,tmag,tpeak,nlog)); } if (sc->nstars <= 0) { binclose (sc); sc = NULL; return (0); } /* Keep mag1 the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } if (sortmag > 0 && sortmag <= sc->nmag) magsort = sortmag - 1; else magsort = 0; /* Logging interval */ nstar = 0; /* Allocate space for distances from search center, if necessary */ if (nstarmax > ndist) { if (ndist > 0) free ((void *)tdist); if (nstarmax > 10) tdist = (double *) calloc (nstarmax, sizeof(double)); else tdist = (double *) calloc (10, sizeof(double)); if (tdist == NULL) { fprintf (stderr,"BINREAD: cannot allocate separation array\n"); ndist = 0; return (0); } if (nstarmax > 10) ndist = nstarmax; else ndist = 10; } SearchLim (cra, cdec, dra, ddec, sysout, &ra1, &ra2, &dec1, &dec2, verbose); /* Make sure first declination is always the smallest one */ if (dec1 > dec2) { dec = dec1; dec1 = dec2; dec2 = dec; } sysref = sc->coorsys; eqref = sc->equinox; epref = sc->epoch; RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref,secmarg, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); if (verbose) { char rstr1[16],rstr2[16],dstr1[16],dstr2[16]; ra2str (rstr1, 16, rra1, 3); dec2str (dstr1, 16, rdec1, 2); ra2str (rstr2, 16, rra2, 3); dec2str (dstr2, 16, rdec2, 2); wcscstr (cstr, sysref,eqref,epref); fprintf (stderr,"BINREAD: RA: %s - %s Dec: %s - %s %s\n", rstr1, rstr2, dstr1, dstr2, cstr); } /* If catalog RA range includes zero, split search in two */ if (wrap) { rra1a = 0.0; rra2a = rra2; rra2 = 360.0; } else { rra2a = 0; } if (sc->entrv > 0) { nmag = sc->nmag - 1; mrv = nmag; } else { nmag = sc->nmag; mrv = 0; } /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; jstar = 0; /* Loop through wraps (do not cross 360 degrees in search */ for (iwrap = 0; iwrap <= wrap; iwrap++) { /* Set first and last stars to check */ if (sc->rasorted) { istar1 = binsra (sc, star, rra1); istar2 = binsra (sc, star, rra2); } else { istar1 = sc->star1; istar2 = sc->star0 + sc->nstars; } if (verbose) fprintf (stderr,"BINREAD: Searching stars %d through %d\n",istar1,istar2); /* Loop through catalog */ for (istar = istar1; istar <= istar2; istar++) { if (binstar (sc, star, istar)) { fprintf (stderr,"BINREAD: Cannot read star %d\n", istar); break; } /* ID number */ num = star->num; /* Magnitude */ if (sc->entmag[0] > 0) mag = star->xmag[magsort]; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; /* Get position in output coordinate system, equinox, and epoch */ if (pass) { rapm = star->rapm; decpm = star->decpm; ra = star->ra; dec = star->dec; wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); /* Compute distance from search center */ if (drad > 0 || distsort) dist = wcsdist (cra,cdec,ra,dec); else dist = 0.0; /* Check radial distance to search center */ if (drad > 0) { if (dist > drad) pass = 0; if (dradi > 0.0 && dist < dradi) pass = 0; } /* Check distance along RA and Dec axes */ else { ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } } if (pass) { /* Radial velocity */ if (sc->entrv > 0) star->xmag[mrv] = star->radvel; /* Spectral Type */ isp = (1000 * (int) star->isp[0]) + (int)star->isp[1]; /* Save star position and magnitude in table */ if (nstar < nstarmax) { tnum[nstar] = num; tra[nstar] = ra; tdec[nstar] = dec; if (sc->mprop == 1) { tpra[nstar] = rapm; tpdec[nstar] = decpm; } for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][nstar] = star->xmag[imag]; } tpeak[nstar] = isp; tdist[nstar] = dist; if (sc->ncobj > 0 && tobj != NULL) { lname = strlen (star->objname) + 1; objname = (char *)calloc (lname, 1); strcpy (objname, star->objname); tobj[nstar] = objname; } if (dist > maxdist) { maxdist = dist; farstar = nstar; } if (mag > faintmag) { faintmag = mag; faintstar = nstar; } } /* If too many stars and distance sorting, replace furthest star */ else if (distsort) { if (dist < maxdist) { tnum[farstar] = num; tra[farstar] = ra; tdec[farstar] = dec; if (sc->mprop == 1) { tpra[farstar] = rapm; tpdec[farstar] = decpm; } for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][farstar] = star->xmag[imag]; } tpeak[farstar] = isp; tdist[farstar] = dist; if (sc->ncobj > 0 && tobj != NULL) { free ((void *)tobj[farstar]); lname = strlen (star->objname) + 1; objname = (char *)calloc (lname, 1); strcpy (objname, star->objname); tobj[farstar] = objname; } maxdist = 0.0; /* Find new farthest star */ for (i = 0; i < nstarmax; i++) { if (tdist[i] > maxdist) { maxdist = tdist[i]; farstar = i; } } } } /* Else if too many stars, replace faintest star */ else if (mag < faintmag) { tnum[faintstar] = num; tra[faintstar] = ra; tdec[faintstar] = dec; if (sc->mprop == 1) { tpra[faintstar] = rapm; tpdec[faintstar] = decpm; } for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][faintstar] = star->xmag[imag]; } tpeak[faintstar] = isp; tdist[faintstar] = dist; if (sc->ncobj > 0 && tobj != NULL) { free ((void *)tobj[faintstar]); lname = strlen (star->objname) + 1; objname = (char *)calloc (lname, 1); strcpy (objname, star->objname); tobj[faintstar] = objname; } faintmag = 0.0; /* Find new faintest star */ for (i = 0; i < nstarmax; i++) { if (tmag[magsort][i] > faintmag) { faintmag = tmag[magsort][i]; faintstar = i; } } } nstar++; jstar++; if (nlog == 1) fprintf (stderr,"BINREAD: %11.6f: %9.5f %9.5f %5.2f\n", num,ra,dec,mag); /* End of accepted star processing */ } /* Log operation */ if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"BINREAD: %5d / %5d / %5d sources catalog %s\r", jstar,istar,sc->nstars,bincat); /* End of star loop */ } /* Set second set of RA limits if passing through 0h */ rra1 = rra1a; rra2 = rra2a; } /* Summarize search */ if (nlog > 0) { fprintf (stderr,"BINREAD: Catalog %s : %d / %d / %d found\n", bincat,jstar,istar,sc->nstars); if (nstar > nstarmax) fprintf (stderr,"BINREAD: %d stars found; only %d returned\n", nstar,nstarmax); } free ((void *)star); /* free ((void *)tdist); */ return (nstar); } /* BINRNUM -- Read binary catalog stars with specified numbers */ int binrnum (bincat, nnum, sysout, eqout, epout, match, tnum,tra,tdec,tpra,tpdec,tmag,tpeak,tobj,nlog) char *bincat; /* Name of reference star catalog file */ int nnum; /* Number of stars to look for */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ int match; /* If 1, match number exactly, else number is sequence*/ double *tnum; /* Array of star numbers to look for */ double *tra; /* Array of right ascensions (returned) */ double *tdec; /* Array of declinations (returned) */ double *tpra; /* Array of right ascension proper motions (returned) */ double *tpdec; /* Array of declination proper motions (returned) */ double **tmag; /* 2-D Array of magnitudes (returned) */ int *tpeak; /* Array of peak counts (returned) */ char **tobj; /* Array of object names (returned) */ int nlog; { int sysref; /* Catalog coordinate system */ double eqref; /* Catalog coordinate equinox */ double epref; /* Catalog position epoch */ int jnum; int nstar; double ra, dec, rapm, decpm; double num; int istar; int isp; int imag; int lname; char *objname; struct StarCat *starcat; struct Star *star; char str[128]; int nmag; int mrv; nstar = 0; starcat = binopen (bincat); if (starcat == NULL) return (0); /* If pathname is a URL, search and return */ if (starcat->caturl != NULL) { strcpy (str, starcat->caturl); free (starcat); return (webrnum (str,bincat,nnum,sysout,eqout,epout,1, tnum,tra,tdec,tpra,tpdec,tmag,tpeak,nlog)); } /* If no stars in catalog, print error message and return */ if (starcat->nstars <= 0) { free ((void *)starcat); fprintf (stderr,"BINRNUM: Cannot read catalog %s\n", bincat); return (0); } sysref = starcat->coorsys; eqref = starcat->equinox; epref = starcat->epoch; if (!sysout) sysout = sysref; if (!eqout) eqout = eqref; if (!epout) epout = epref; /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; if (starcat->entrv > 0) { nmag = starcat->nmag - 1; mrv = nmag; } else nmag = starcat->nmag; /* Loop through star list */ for (jnum = 0; jnum < nnum; jnum++) { /* Find star in catalog */ istar = (int) tnum[jnum]; if (match) { istar = 1; while (istar <= starcat->nstars) { if (binstar (starcat, star, istar)) { fprintf (stderr,"BINRNUM: Cannot read star %d\n", istar); tra[jnum] = 0.0; tdec[jnum] = 0.0; tpra[jnum] = 0.0; tpdec[jnum] = 0.0; for (imag = 0; imag < starcat->nmag; imag++) tmag[imag][jnum] = 0.0; tpeak[jnum] = 0; continue; } if (star->num == tnum[jnum]) break; istar++; } if (star->num != tnum[jnum]) continue; } else if (binstar (starcat, star, istar)) { fprintf (stderr,"BINRNUM: Cannot read star %d\n", istar); tra[jnum] = 0.0; tdec[jnum] = 0.0; tpra[jnum] = 0.0; tpdec[jnum] = 0.0; for (imag = 0; imag < starcat->nmag; imag++) tmag[imag][jnum] = 0.0; tpeak[jnum] = 0; continue; } /* If star has been found in catalog */ /* ID number */ num = star->num; /* Position in degrees at designated epoch */ ra = star->ra; dec = star->dec; rapm = star->rapm; decpm = star->decpm; wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); /* Spectral Type */ isp = (1000 * (int) star->isp[0]) + (int)star->isp[1]; /* Save star position and magnitude in table */ tnum[jnum] = num; tra[jnum] = ra; tdec[jnum] = dec; if (starcat->mprop == 1) { tpra[jnum] = rapm; tpdec[jnum] = decpm; } /* Radial velocity, if present */ if (starcat->entrv > 0) tmag[mrv][nstar] = star->radvel; /* Magnitudes */ if (nmag > 0) { for (imag = 0; imag < nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][nstar] = star->xmag[imag]; } } tpeak[jnum] = isp; if (starcat->ncobj > 0 && tobj != NULL) { lname = strlen (star->objname) + 1; objname = (char *)calloc (lname, 1); strcpy (objname, star->objname); tobj[nstar] = objname; } nstar++; if (nlog == 1) { fprintf (stderr,"BINRNUM: %11.6f: %9.5f %9.5f", num, ra, dec); for (imag = 0; imag < starcat->nmag; imag++) fprintf (stderr," %5.2f",tmag[imag][nstar]); fprintf (stderr," %s \n", star->isp); } /* End of star loop */ } /* Summarize search */ if (nlog > 0) fprintf (stderr,"BINRNUM: Catalog %s : %d / %d found\n", bincat,nstar,starcat->nstars); binclose (starcat); free ((void *) star); return (nstar); } /* BINBIN -- Fill FITS WCS image with stars from binary catalog */ int binbin (bincat, wcs, header, image, mag1, mag2, sortmag, magscale, nlog) char *bincat; /* Name of reference star catalog file */ struct WorldCoor *wcs; /* World coordinate system for image */ char *header; /* FITS header for output image */ char *image; /* Output FITS image */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 to nmag) */ double magscale; /* Scaling factor for magnitude to pixel flux * (number of catalog objects per bin if 0) */ int nlog; { double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double rra1,rra2; /* Limiting catalog right ascensions of region */ double rdec1,rdec2; /* Limiting catalog declinations of region */ double ra1,ra2; /* Limiting output right ascensions of region */ double dec1,dec2; /* Limiting output declinations of region */ int sysref; /* Catalog coordinate system */ double eqref; /* Catalog coordinate equinox */ double epref; /* Catalog position epoch */ double secmarg = 60.0; /* Arcsec/century margin for proper motion */ double ra, dec, rapm, decpm; double rra1a, rra2a; double rdist, ddist; struct StarCat *sc; /* Star catalog data structure */ struct Star *star; int wrap, iwrap, istar1,istar2; int ix, iy; int pass; int nmag; /* Real number of magnitudes per entry (- rv) */ int jstar; int nstar; double mag; double num; int magsort; int istar = 0; int verbose; int mrv; char cstr[16]; double xpix, ypix, flux; int offscl; int bitpix, w, h; /* Image bits/pixel and pixel width and height */ double logt = log(10.0); if (nlog > 0) verbose = 1; else verbose = 0; /* Set image parameters */ bitpix = 0; (void)hgeti4 (header, "BITPIX", &bitpix); w = 0; (void)hgeti4 (header, "NAXIS1", &w); h = 0; (void)hgeti4 (header, "NAXIS2", &h); /* Open catalog */ sc = binopen (bincat); if (sc == NULL) return (0); if (sc->nstars <= 0) { binclose (sc); sc = NULL; return (0); } /* Keep mag1 the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } if (sortmag > 0 && sortmag <= sc->nmag) magsort = sortmag - 1; else magsort = 0; /* Logging interval */ nstar = 0; /* Set catalog search limits from image WCS information */ sysout = wcs->syswcs; eqout = wcs->equinox; epout = wcs->epoch; wcscstr (cstr, sysout, eqout, epout); wcssize (wcs, &cra, &cdec, &dra, &ddec); SearchLim (cra, cdec, dra, ddec, sysout, &ra1, &ra2, &dec1, &dec2, verbose); /* Make sure first declination is always the smallest one */ if (dec1 > dec2) { dec = dec1; dec1 = dec2; dec2 = dec; } sysref = sc->coorsys; eqref = sc->equinox; epref = sc->epoch; RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref,secmarg, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); if (verbose) { char rstr1[16],rstr2[16],dstr1[16],dstr2[16]; ra2str (rstr1, 16, rra1, 3); dec2str (dstr1, 16, rdec1, 2); ra2str (rstr2, 16, rra2, 3); dec2str (dstr2, 16, rdec2, 2); wcscstr (cstr, sysref,eqref,epref); fprintf (stderr,"BINREAD: RA: %s - %s Dec: %s - %s %s\n", rstr1, rstr2, dstr1, dstr2, cstr); } /* If catalog RA range includes zero, split search in two */ if (wrap) { rra1a = 0.0; rra2a = rra2; rra2 = 360.0; } else { rra2a = 0.0; } if (sc->entrv > 0) { nmag = sc->nmag - 1; mrv = nmag; } else nmag = sc->nmag; /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; jstar = 0; /* Loop through wraps (do not cross 360 degrees in search */ for (iwrap = 0; iwrap <= wrap; iwrap++) { /* Set first and last stars to check */ if (sc->rasorted) { istar1 = binsra (sc, star, rra1); istar2 = binsra (sc, star, rra2); } else { istar1 = sc->star1; istar2 = sc->star0 + sc->nstars; } if (verbose) fprintf (stderr,"BINREAD: Searching stars %d through %d\n",istar1,istar2); /* Loop through catalog */ for (istar = istar1; istar <= istar2; istar++) { if (binstar (sc, star, istar)) { fprintf (stderr,"BINREAD: Cannot read star %d\n", istar); break; } /* ID number */ num = star->num; /* Magnitude */ if (sc->entmag[0] > 0) mag = star->xmag[magsort]; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; /* Get position in output coordinate system, equinox, and epoch */ if (pass) { rapm = star->rapm; decpm = star->decpm; ra = star->ra; dec = star->dec; wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); /* Check distance along RA and Dec axes */ ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } /* Save star in FITS image */ if (pass) { wcs2pix (wcs, ra, dec, &xpix, &ypix, &offscl); if (!offscl) { if (magscale > 0.0) flux = magscale * exp (logt * (-mag / 2.5)); else flux = 1.0; ix = (int) (xpix + 0.5); iy = (int) (ypix + 0.5); addpix1 (image, bitpix, w,h, 0.0,1.0, xpix,ypix, flux); nstar++; jstar++; } else { ix = 0; iy = 0; } if (nlog == 1) { fprintf (stderr,"BINBIN: %11.6f: %9.5f %9.5f %s", num,ra,dec,cstr); if (magscale > 0.0) fprintf (stderr, " %5.2f", mag); if (!offscl) flux = getpix1 (image, bitpix, w, h, 0.0, 1.0, ix, iy); else flux = 0.0; fprintf (stderr," (%d,%d): %f\n", ix, iy, flux); } if (nlog == 1) fprintf (stderr,"BINREAD: %11.6f: %9.5f %9.5f %5.2f\n", num,ra,dec,mag); /* End of accepted star processing */ } /* Log operation */ if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"BINREAD: %5d / %5d / %5d sources catalog %s\r", jstar,istar,sc->nstars,bincat); /* End of star loop */ } /* Set second set of RA limits if passing through 0h */ rra1 = rra1a; rra2 = rra2a; } /* Summarize search */ if (nlog > 0) { fprintf (stderr,"BINREAD: Catalog %s : %d / %d / %d found\n", bincat,jstar,istar,sc->nstars); } free ((void *)star); free ((void *)tdist); return (nstar); } /* BINOPEN -- Open binary catalog, returning number of entries */ struct StarCat * binopen (bincat) char *bincat; /* Binary catalog file name */ { int fcat; struct StarCat *sc; int nr, lfile; char *binfile; char binpath[128]; /* Full pathname for catalog file */ int lf, nb, binset; char *str; sc = (struct StarCat *) calloc (1, sizeof (struct StarCat)); /* Find length of binary catalog, if in working directory */ lfile = binsize (bincat); /* Set catalog directory; if pathname is a URL, return */ binset = 0; if (!strncasecmp (bincat,"PPM",3)) { if ((str = getenv("PPM_PATH")) != NULL ) { if (!strncmp (str, "http:",5)) { sc->caturl = str; } else if (strlen (str) < 64) { strcpy (bindir, str); binset = 1; } } } else if (!strncasecmp (bincat,"SAO",3)) { if ((str = getenv("SAO_PATH")) != NULL ) { if (!strncmp (str, "http:",5)) { sc->caturl = str; } else if (strlen (str) < 64) { strcpy (bindir, str); binset = 1; } } } else if (!strncasecmp (bincat,"SKY2K",3)) { if ((str = getenv("SKY2K_PATH")) != NULL ) { if (!strncmp (str, "http:",5)) { sc->caturl = str; } else if (strlen (str) < 64) { strcpy (bindir, str); binset = 1; } } } else if (!strncasecmp (bincat,"HIP",3)) { if ((str = getenv("HIP_PATH")) != NULL ) { if (!strncmp (str, "http:",5)) { sc->caturl = str; } else if (strlen (str) < 64) { strcpy (bindir, str); binset = 1; } } } else if (!strncasecmp (bincat,"IRAS",4)) { if ((str = getenv("IRAS_PATH")) != NULL ) { if (!strncmp (str, "http:",5)) { sc->caturl = str; } else if (strlen (str) < 64) { strcpy (bindir, str); binset = 1; } } } if (!binset && (str = getenv("WCS_BINDIR")) != NULL ) { if (!strncmp (str, "http:",5)) { sc->caturl = str; } else if (strlen (str) < 64) strcpy (bindir, str); } /* Set up catalog information and return if over web */ if (sc->caturl != NULL) { sc->coorsys = 0; sc->epoch = 0.0; sc->equinox = 0.0; if (!strncasecmp (bincat, "sao", 3) || !strncasecmp (bincat, "ppm", 3) || !strncasecmp (bincat, "sky2k", 3) || !strncasecmp (bincat, "hip", 3)) sc->mprop = 1; else sc->mprop = 0; return (sc); } /* Prepend directory name file not in working directory */ if (lfile < 2) { strcpy (binpath, bindir); strcat (binpath, "/"); strcat (binpath, bincat); lfile = binsize (binpath); if (lfile < 2) { fprintf (stderr,"BINOPEN: Binary catalog %s has no entries\n",bincat); return (NULL); } } else strcpy (binpath, bincat); /* Open binary catalog */ if ((fcat = open (binpath, O_RDONLY+O_BINARY)) < 3) { fprintf (stderr,"BINOPEN: Binary catalog %s cannot be read\n",binpath); free (sc); return (NULL); } /* Read binary catalog header information */ nr = (int) read (fcat, sc, 28); if (nr < 28) { fprintf (stderr,"BINOPEN: read only %d / %d bytes of file %s\n", nr, lfile, binpath); (void) close (fcat); return (NULL); } /* Check for byte reversal */ if (sc->nbent > 80) { sc->byteswapped = 1; binswap4 (&sc->star0); binswap4 (&sc->star1); binswap4 (&sc->nstars); binswap4 (&sc->stnum); binswap4 (&sc->mprop); binswap4 (&sc->nmag); binswap4 (&sc->nbent); } else sc->byteswapped = 0; /* Allocate buffer to read one line of catalog */ sc->catline = (char *) calloc (sc->nbent, sizeof (char)); nb = 0; sc->ncobj = 0; if (sc->stnum < 0) sc->ncobj = -sc->stnum; else if (sc->stnum > 0) nb = 4; sc->entra = nb; sc->entdec = nb + 8; sc->entpeak = nb + 16; /* Set other catalog information in structure */ if (sc->nmag < 0) { sc->inform = 'J'; sc->coorsys = WCS_J2000; sc->epoch = 2000.0; sc->equinox = 2000.0; sc->nmag = -sc->nmag; } else if (sc->nstars < 0) { sc->inform = 'J'; sc->coorsys = WCS_J2000; sc->epoch = 2000.0; sc->equinox = 2000.0; sc->nstars = -sc->nstars; } else { sc->inform = 'B'; sc->coorsys = WCS_B1950; sc->epoch = 1950.0; sc->equinox = 1950.0; } if (sc->nmag > 0) sc->entmag[0] = nb + 18; else sc->entmag[0] = 0; nb = nb + 18 + (sc->nmag * 2); if (sc->mprop == -1) sc->mprop = 1; if (sc->mprop == 1) { sc->entrpm = nb; sc->entdpm = nb + 4; nb = nb + 8; } else if (sc->mprop == 2) { sc->entrv = nb; nb = nb + 8; } if (sc->ncobj) sc->entname = nb; /* Set number of decimal places in star numbers */ if (sc->stnum == 2) sc->nndec = 4; else if (sc->stnum == 3) sc->nndec = 5; else sc->nndec = 0; strcpy (sc->incdir, bindir); strcpy (sc->incfile, bincat); /* Separate filename from pathname and save in structure */ binfile = strrchr (binpath,'/'); if (binfile) binfile = binfile + 1; else binfile = binpath; if (strlen (binfile) < 24) strcpy (sc->isfil, binfile); else strncpy (sc->isfil, binfile, 23); sc->entadd = fcat; sc->sptype = 1; if (sc->mprop == 2) sc->nmag = sc->nmag + 1; /* Check name to see if file is RA-sorted */ lf = strlen (binfile); sc->rasorted = 0; if (binfile[lf-2] == 'r' && binfile[lf-1] == 'a') sc->rasorted = 1; if (!strncmp (binfile, "IRAS", 4)) sc->rasorted = 1; sc->refcat = BINCAT; return (sc); } void binclose (sc) struct StarCat *sc; /* Star catalog descriptor */ { close (sc->entadd); free ((void *)sc->catline); free ((void *)sc); return; } /* BINSRA -- Find star closest to given RA in RA-sorted catalog */ static int binsra (sc, st, dra) struct StarCat *sc; /* Star catalog descriptor */ struct Star *st; /* Current star entry */ double dra; /* Right ascension in degrees */ { char rastr[32], raxstr[32], ramins[32], ramaxs[32]; int istar0, istarx, nrep, ismin, ismax; double rax, ramin, ramax; int verbose = 0; /* Keep RA between 0 and 360 degrees */ if (dra > 360.0) rax = dra - 360.0; else rax = dra; ismin = 1; if (binstar (sc, st, ismin)) { fprintf (stderr,"BINSRA: Cannot read star %d\n", ismin); return (0); } else ramin = st->ra; ismax = sc->nstars; if (binstar (sc, st, ismax)) { fprintf (stderr,"BINSRA: Cannot read star %d\n", ismax); return (0); } else ramax = st->ra; istarx = sc->nstars / 2; for (nrep = 0; nrep < 32; nrep++) { if (binstar (sc, st, istarx)) { fprintf (stderr,"BINSRA: Cannot read star %d\n", istarx); return (0); } /* Find next catalog number to read */ if (st->ra < rax) { ismin = istarx; ramin = st->ra; istar0 = istarx; if (ismax - istarx > 1) istarx = istarx + (ismax - istarx) / 2; else if (ismax - istarx > 0) istarx = istarx + 1; } else if (st->ra > rax) { ismax = istarx; ramax = st->ra; istar0 = istarx; if (istarx - ismin > 1) istarx = istarx - ((istarx - ismin) / 2); else if (istarx - ismin > 0) istarx = istarx - 1; } else break; if (verbose) { ra2str (rastr, 16, st->ra, 3); ra2str (raxstr, 16, rax, 3); ra2str (ramins, 16, ramin, 3); ra2str (ramaxs, 16, ramax, 3); fprintf (stderr,"%9d: %s -> %s %9d: %s %9d: %s\n", istarx, rastr, raxstr, ismin,ramins,ismax,ramaxs); } if (istarx == istar0) break; } /* Make sure final star is real */ if (binstar (sc, st, istarx)) { fprintf (stderr,"BINSRA: Cannot read star %d\n", istarx); return (0); } else return (istarx); } /* BINSTAR -- Get binary catalog entry for one star; return 0 if successful */ int binstar (sc, st, istar) struct StarCat *sc; /* Star catalog descriptor */ struct Star *st; /* Current star entry */ int istar; /* Star sequence number in binary catalog */ { int ino, i, nmag; long offset; double radvel; float pm[2]; /* Drop out if catalog pointer is not set */ if (sc == NULL) return (1); /* Drop out if catalog is not open */ if (sc->entadd < 3) return (2); /* Drop out if star number is too large */ if (istar > sc->nstars) { fprintf (stderr, "BINSTAR: %d > %d is not in catalog\n", istar, sc->nstars); return (3); } /* Move file pointer to start of correct star entry */ if (istar > 0) { offset = 28 + (istar - sc->star1) * sc->nbent; if (lseek (sc->entadd, offset, SEEK_SET) < offset) return (0); } /* Read catalog entry */ if ((int)read (sc->entadd, sc->catline, sc->nbent) < 1) return (4); /* Read catalog number or object name */ sc->ncobj = 0; if (sc->stnum <= 0) { sc->ncobj = -sc->stnum; movebuff (sc->catline, st->objname, sc->ncobj, sc->entname, 0); } else { movebuff (sc->catline, (char *) &st->xno, 4, 0, 0); if (sc->byteswapped) binswap4 (&st->xno); } /* Interpret catalog number */ switch (sc->stnum) { case 1: st->num = (double) st->xno; break; case 2: memcpy ((char *) &ino, (char *)&st->xno, 4); st->num = 0.0001 * (double) ino; break; case 3: memcpy ((char *) &ino, (char *)&st->xno, 4); st->num = 0.00001 * (double) ino; break; case 4: memcpy ((char *) &ino, (char *)&st->xno, 4); st->num = (double) ino; break; default: if (istar > 0) st->num = (double) istar; else st->num = st->num + 1.0; break; } /* Right ascension and declination and convert to degrees */ movebuff (sc->catline, (char *) &st->ra, 8, sc->entra, 0); movebuff (sc->catline, (char *) &st->dec, 8, sc->entdec, 0); if (sc->byteswapped) { binswap8 (&st->ra); binswap8 (&st->dec); } st->ra = raddeg (st->ra); st->dec = raddeg (st->dec); /* Proper motion, if present, and convert to degrees/year */ nmag = sc->nmag; if (sc->mprop == 1) { movebuff (sc->catline, (char *) &pm[0], 4, sc->entrpm, 0); movebuff (sc->catline, (char *) &pm[1], 4, sc->entdpm, 0); if (sc->byteswapped) { binswap4 (&pm[0]); binswap4 (&pm[1]); } st->rapm = raddeg ((double) pm[0]); st->decpm = raddeg ((double) pm[1]); } /* Radial velocity, if it is present */ else if (sc->mprop == 2) { movebuff (sc->catline, (char *) &radvel, 8, sc->entrv, 0); if (sc->byteswapped) binswap8 (&radvel); st->radvel = radvel; nmag = nmag - 1; } /* Spectral type */ movebuff (sc->catline, (char *) st->isp, 2, sc->entpeak, 0); /* Magnitudes */ if (sc->entmag[0] > 0) { for (i = 0; i < nmag; i++) { movebuff (sc->catline, (char *) st->mag, 2, sc->entmag[0]+(i*2), i*2); if (sc->byteswapped) binswap2 (&st->mag[i], 2); st->xmag[i] = 0.01 * (double) st->mag[i]; } } return (0); } /* BINSWAP2 -- Swap bytes in string in place */ static void binswap2 (string,nbytes) char *string; /* Address of starting point of bytes to swap */ int nbytes; /* Number of bytes to swap */ { char *sbyte, temp, *slast; slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp = sbyte[0]; sbyte[0] = sbyte[1]; sbyte[1] = temp; sbyte= sbyte + 2; } return; } /* BINSWAP4 -- Reverse bytes of Integer*4 or Real*4 number in place */ static void binswap4 (string) char *string; /* Address of Integer*4 or Real*4 vector */ { char temp0, temp1, temp2, temp3; temp3 = string[0]; temp2 = string[1]; temp1 = string[2]; temp0 = string[3]; string[0] = temp0; string[1] = temp1; string[2] = temp2; string[3] = temp3; return; } /* BINSWAP8 -- Reverse bytes of Real*8 vector in place */ static void binswap8 (string) char *string; /* Address of Real*8 vector */ { char temp[8]; temp[7] = string[0]; temp[6] = string[1]; temp[5] = string[2]; temp[4] = string[3]; temp[3] = string[4]; temp[2] = string[5]; temp[1] = string[6]; temp[0] = string[7]; string[0] = temp[0]; string[1] = temp[1]; string[2] = temp[2]; string[3] = temp[3]; string[4] = temp[4]; string[5] = temp[5]; string[6] = temp[6]; string[7] = temp[7]; return; } /* BINSIZE -- return size of binary catalog file in bytes */ static int binsize (filename) char *filename; /* Name of file for which to find size */ { FILE *diskfile; long filesize; /* Open file */ if ((diskfile = fopen (filename, "rb")) == NULL) return (-1); /* Move to end of the file */ if (fseek (diskfile, 0, 2) == 0) /* Position is the size of the file */ filesize = ftell (diskfile); else filesize = -1; fclose (diskfile); return (filesize); } /* ISBIN -- Return 1 if TDC binary catalog file, else 0 */ int isbin (filename) char *filename; /* Name of file to check */ { FILE *diskfile; char line[8]; int nbr; if ((diskfile = fopen (filename, "rb")) == NULL) return (0); else { nbr = fread (line, 1, 4, diskfile); fclose (diskfile); if (nbr < 4) return (0); else if (line[0] == 0 || line[1] == 0 || line[2] == 0 || line[3] == 0) return (1); else return (0); } } /* Sep 10 1998 New subroutines * Sep 15 1998 Add byte swapping * Sep 16 1998 Use limiting radius correctly; use arbitrary search system * Sep 21 1998 Return converted coordinates * Sep 23 1998 Set search limits in catalog system, but test in output system * Sep 24 1998 Return second magnitude if more than one in catalog * Oct 15 1998 Add binsize() to compute file length in bytes * Oct 20 1998 Add binrobj() to read object names for specified stars * Oct 21 1998 Fix binsra() to get out of 3-in-a-row identical RAs * Oct 21 1998 Add isbin() to check whether file could be TDC binary catalog * Oct 26 1998 Add object retrieval to binread() and binrnum() * Oct 29 1998 Correctly assign numbers when too many stars are found * Oct 30 1998 Be more careful with coordinate system of catalog * Oct 30 1998 Fix convergence at edges of catalog * Nov 9 1998 Add flag to catalog structure for RA-sorted catalogs * Dec 8 1998 Have binstar() return 0 instead of null * * Feb 1 1999 Add match argument to binrnum() * Feb 2 1999 Set number of decimal places in star number * Feb 11 1999 Change starcat.insys to starcat.coorsys * Jun 16 1999 Use SearchLim() * Aug 16 1999 Add RefLim() to get converted search coordinates right * Aug 24 1999 Fix declination limit bug which broke search * Aug 25 1999 Return real number of stars from binread() * Sep 16 1999 Fix bug which didn't always return closest stars * Sep 16 1999 Add distsort argument so brightest stars in circle works, too * Oct 21 1999 Fix declarations after lint * * Mar 15 2000 Add proper motion return to binread() and binrnum() * Mar 28 2000 Use moveb() to extract information from entries * Mar 30 2000 Use standard i/O instead of stream I/O * Jun 2 2000 Minor changes after lint * Jun 26 2000 Add coordinate system to SearchLim() arguments * Jul 12 2000 Add star catalog structure to binread() argument list * Jul 25 2000 Pass star catalog address of data structure address * Sep 25 2000 Set sc->sptype to 1 to indicate presence of spectral type * Nov 29 2000 Add option to read catalogs using HTTP * Dec 1 2000 Add separate paths for SAO and PPM catalogs * Dec 18 2000 Drop unused variable str in binopen() * * Jan 11 2001 Print all messages to stderr * Feb 14 2001 Correctly full-circle limits at poles * Mar 19 2001 Check WCS_BINDIR if PPM_PATH or SAO_PATH not set in binread() * Mar 22 2001 Move path environment variable reading to binopen() * Mar 23 2001 Set system, equinox, and epoch to 0 in binopen if using Web * Jun 20 2001 Save all four magnitudes if present, dropping spectral type * Jun 22 2001 Do not swap spectral type in binstar() * Jun 25 2001 Add HIP_PATH and IRAS_PATH; allow 5 digits for magnitudes * Jun 27 2001 Allocate separation array only when larger one is needed * Jul 6 2001 Fix bug in dealing with proper motions of excess stars * Jul 17 2001 Fix bug which prevented use of full catalog pathname on CL * Aug 8 2001 Add radial velocity if mprop is 2; return as magnitude * Sep 11 2001 Pass array of magnitude vectors to avoid kludges * Sep 11 2001 Add sort magnitude argument * Sep 18 2001 Fix magnitude number in binrnum() * Sep 19 2001 Drop fitshead.h; it is in wcs.h * * Mar 25 2002 Fix bugs dealing with radial velocity * Mar 26 2002 Don't set object name unless header says it is there * Aug 6 2002 Make sc->entmag into vector, but only use first position * * Feb 4 2003 Open catalog file rb instead of r (Martin Ploner, Bern) * Feb 19 2003 Increase maximum nbent from 50 to 80 * Feb 20 2003 Eliminate unused variables after lint * Mar 11 2003 Upgrade position testing * Mar 11 2003 If proper motion flag is -1, reset it to 1 * Mar 26 2003 Open binpath with binary flag set * Aug 22 2003 Add radi argument for inner edge of search annulus * Sep 25 2003 Add binbin() to fill an image with sources * Oct 6 2003 Update binread() and binbin() for improved RefLim() * Nov 18 2003 Initialize image size and bits/pixel from header in binbin() * Dec 12 2003 Fix bug in wcs2pix() call in binbin() * * Aug 27 2004 Include math.h * * Jan 19 2006 Fix bug when J2000 system set by negative number of magnitudes * Jun 20 2006 Initialize uninitialized variables * Sep 26 2006 Increase length of rastr and destr from 16 to 32 * Nov 15 2006 Fix binning * * Jan 8 2007 Drop unused variables in binbin() * Jan 10 2007 Add match=1 argument to webrnum() * Nov 28 2007 Move moveb() to catutil.c * * Sep 25 2009 Call movebuff() instead of moveb() and move mvebuff() to catutil.c * * Sep 16 2011 Change depricated bcopy() to memcpy() */ wcstools-3.9.5/libwcs/caphot.c0000664000016200001660000002542011750060473015366 0ustar minkoirsys/*** File caphot.c *** January 30, 2002 *** By Jessica Mink from Fortran code by Sam Conner (MIT, 1984) *** Copyright (C) 2002 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include "fitshead.h" #include "imio.h" static double apint(); static double imapfr(); /* CAPHOT -- Perform rigorous circular aperture photometry using the imapfr() * subroutine to determine the fraction of a square pixel enclosed * by a circular aperture. */ void caphot (imbuff,header,cx,cy,rad,sumw,wsum) char *imbuff; /* address of start of image buffer */ char *header; /* image FITS header */ double cx,cy; /* center x,y of aperture */ double rad; /* radius of aperture */ double sumw; /* sum of values of pixel weights (returned) */ double wsum; /* sum of weighted pixel fluxes (returned) */ { double x, y, factor, flux, bs, bz; int ix1, ix2, iy1, iy2, ix, iy, bitpix, nx, ny; sumw = 0.0; wsum = 0.0; hgeti4 (header, "BITPIX", &bitpix); hgeti4 (header, "NAXIS1", &nx); hgeti4 (header, "NAXIS2", &ny); hgetr8 (header, "BSCALE", &bs); hgeti4 (header, "BZERO", &bz); /* Find range of ys to check */ iy1 = (int) (cy - rad); iy2 = (int) (cy + rad + 0.99999); if (iy1 < 1) iy1 = 1; if (iy2 > ny) iy2 = ny; /* Find range of xumns to check */ ix1 = (int) (cx - rad); ix2 = (int) (cx + rad + 0.99999); if (ix1 < 1) ix1 = 1; if (ix2 > nx) ix2 = nx; for (iy = iy1; iy <= iy2; iy++) { y = (double) iy; for (ix = ix1; ix <= ix2; ix++) { x = (double) ix; factor = imapfr (x,y,cx,cy,rad); sumw = sumw + factor; flux = getpix1 (imbuff, bitpix, nx, ny, bz, bs, ix, iy); wsum = wsum + (factor * flux); /* fprintf (stderr, "IMAPSB: (%d,%d)= %f weight= %f\n", ix,iy,flux,factor); */ } } /* fprintf (stderr, "IMAPSB: sum of weights = %f\n", sumw); fprintf (stderr, "IMAPSB: sum of weighted intensity = %f\n", wsum); */ return; } /* IMAPFR -- Determine the fraction of a square pixel that is included * within the boundary of a circle of arbitrary center and radius */ static double imapfr (pcol,prow,ccol,crow,rad) double pcol,prow; /* column, row of pixel */ double ccol,crow; /* column, row of center of circle */ double rad; /* radius of circle in pixels */ { int icorn[4], ncorn, j, i; double dist, xdiff, y0, y1, ydiff, x0, x1, x, y, dc5, dr5; double cterm, ulim, llim, dc, dr, dx, dy; double frac; /* fraction of pixel within circle */ /* Compute distance to center of circle from most distant corner of pixel */ dc = fabs (pcol - ccol); dr = fabs (prow - crow); dc5 = dc + 0.5; dr5 = dr + 0.5; dist = sqrt ((dc5 * dc5) + (dr5 * dr5)); dc5 = dc - 0.5; dr5 = dr - 0.5; /* if the pixel is completely enclosed by the aperture, return 1 */ if (dist <= rad) return (1.0); /* if the pixel is not completely included, compute distance from the center of the circle to the nearest point on the periphery of the pixel*/ if ((pcol-0.5) < ccol && ccol < (pcol+.5)) { dist = dr5; /* the pixel is completely excluded from the aperture */ if (dist >= rad) return (0.0); else if ((prow - 0.5) < crow && crow < (prow + 0.5)) { dist = dc5; /* the pixel is completely excluded from the aperture */ if (dist >= rad) return (0.0); } else dist = sqrt (dc5*dc5 + dr5*dr5); /* the pixel is completely excluded from the aperture */ if (dist >= rad) return (0.0); } /* If the pixel is partially included in the aperture, determine how many corners are enclosed */ ncorn = 1; y = prow - 1.5; for (i = 0; i < 2; i++) { y = y + 1.0; x = pcol - 1.50; for (j = 0; j < 2; j++) { icorn[j+(i*2)] = 0; x = x + 1.0; dx = x - ccol; dy = y - crow; dist = sqrt (dx*dx + dy*dy); if (dist < rad) { ncorn = ncorn + 1; icorn[j+(i*2)] = 1; } } } /* Depending on number of corners enclosed, branch to appropriate computation */ /* If no corners are enclosed, determine whether the slice is vertical or horizontal */ if (ncorn < 1) { /* If the slice is vertical (at the sides of the aperture, at extreme x), determine the limits of integration */ if ((pcol - 0.5) >= ccol || ccol >= (pcol + 0.5)) { xdiff = fabs (pcol - ccol) - 0.5; dx = sqrt (rad*rad - xdiff*xdiff); y0 = crow - dx; y1 = crow + dx; if (ccol >= pcol) x = pcol + 0.5; else x = pcol - 0.5; /* Evaluate integral */ frac = -xdiff * (y1 - y0) + apint ((y1 - crow), rad) - apint ((y0 - crow), rad); return (frac); } /* If the slice is horizontal (at top or bottom of the aperture, at extreme y), determine the limits of integration. */ else { ydiff = fabs (prow - crow) - 0.5; dy = sqrt (rad*rad - ydiff*ydiff); x0 = ccol - dy; x1 = ccol + dy; if (crow >= prow) y = prow + 0.5; else y = prow - 0.5; /* Evaluate integral */ frac = -ydiff*(x1 - x0) + apint ((x1 - ccol),rad) - apint ((x0 - ccol),rad); return (frac); } } /* if one corner is enclosed, find direction (ne,nw,se,sw) from the center*/ else if (ncorn < 2) { if (pcol < ccol) { /* Determine the limits of integration */ ydiff = fabs (prow - crow) - 0.5;; x0 = ccol - sqrt (rad*rad - ydiff*ydiff); if (crow >= prow) y = prow + 0.5; else y = prow - 0.5; /* Evaluate integral */ frac = -ydiff*(pcol + 0.5 - x0) + apint ((pcol + 0.5 - ccol),rad) - apint ((x0 - ccol),rad); return (frac); } else { /* Determine the limits of integration */ ydiff = fabs (crow - prow) - 0.5; x1 = ccol + sqrt (rad*rad - ydiff*ydiff); if (crow >= prow) y = prow + 0.5; else y = prow - 0.5; /* Evaluate integral */ frac = -ydiff*(x1 - pcol + 0.5) + apint ((x1 - ccol),rad) - apint ((pcol - .5 - ccol),rad); return (frac); } } /* If two corners are enclosed, this problem has two cases: one in which the aperture boundary intersects the pixel boundary twice, and another in which it intersects the pixel boundaries 4 times */ /* determine whether this may be a 4-intersection configuration */ else if (ncorn < 3) { if (((pcol - 0.5) < ccol && ccol < (pcol + .5) && (fabs(crow - prow) + 0.5) < rad) || ((prow - 0.5) < crow && crow < (prow + 0.5) && (fabs(ccol - pcol) + 0.5) < rad)) { /* if the pixel boundary intersects the aperture boundary in four places, determine whether the pixel is east-west or north-south. */ /* pixel is east-west */ if ((pcol - 0.5) >= ccol || (pcol + 0.5) <= ccol) { xdiff = dc + 0.5; /* Determine the limits of integration */ dx = sqrt (rad*rad - xdiff*xdiff); y0 = crow - dx; y1 = crow + dx; if (pcol >= ccol) x = pcol + .5; else x = pcol - .5; frac = 1. - xdiff*(y0 - y1 + 1.0) + apint ((y0 - crow), rad) - apint ((prow - 0.5 - crow), rad) + apint ((prow + 0.5 - crow), rad) - apint ((y1 - crow), rad); return (frac); } /* Pixel is north-south */ else { ydiff = dr + 0.5; /* determine the limits of integration */ dy = sqrt (rad*rad - ydiff*ydiff); /* x0 is the x-coordinate of the small x intercept */ x0 = ccol - dy; /* x1 is the x-coordinate of the large x intercept */ x1 = ccol + dy; if (prow >= crow) y = prow + 0.5; else y = prow - 0.5; frac = 1. - ydiff * (x0 - x1 + 1.0) + apint ((x0 - ccol), rad) - apint ((pcol - 0.5 - ccol), rad) + apint ((pcol + 0.5 - ccol), rad) - apint ((x1 - ccol), rad); return (frac); } } /* in the two-intersection case, determine which corners are included */ else { /* the pixel is north or south of the center of the aperture */ if (icorn[0]*icorn[1] == 1 || icorn[2]*icorn[3] == 1) { cterm = 0.5 - dr; ulim = apint ((pcol + 0.5 - ccol) ,rad); llim = apint ((pcol - 0.5 - ccol) ,rad); frac = cterm + ulim - llim; return (frac); } /* the pixel is east or west of the center */ else { cterm = 0.5 - dc; ulim = apint ((prow + 0.5 - crow), rad); llim = apint ((prow - 0.5 - crow), rad); frac = cterm + ulim - llim; return (frac); } } } /* if three corners are enclosed, determine whether the corner in question is east or west of the center of the aperture */ else { if (pcol > ccol) { ydiff = dr + 0.5; if (prow >= crow) y = prow + 0.5; else y = prow - 0.5; x0 = ccol + sqrt (rad*rad - ydiff*ydiff); frac = 1.0 - (ydiff * (pcol + 0.5 - x0)) + apint ((pcol + 0.5 - ccol), rad) - apint ((x0 - ccol), rad); return (frac); } else { ydiff = dr + 0.5; if (prow >= crow) y = prow + 0.5; else y = prow - 0.5; x0 = ccol - sqrt (rad*rad - ydiff*ydiff); frac = 1. - ydiff*(x0 - pcol + 0.5) + apint ((x0 - ccol),rad) - apint ((pcol - 0.5 - ccol),rad); return (frac); } } } /* APINT -- Evaluate the integral of sqrt (rad**2 - x**2) dx at one limit */ static double apint (x, rad) double x; double rad; { double x2,rad2,arg,arg2,arcsin,pi; pi = 3.141592654; arg = x / rad; x2 = x * x; rad2 = rad * rad; arg2 = x2 / rad2; arcsin = atan2 (arg, sqrt (1.0 - arg2)); if ((1. - fabs (arg)) < 0.000001) { if (arg >= 0) arcsin = pi / 2.0; else arcsin = -pi / 2.0; } return (0.5 * (x * sqrt (rad2 - x2) + rad2 * arcsin)); } /* Jul 4 1984 Original Fortran program by Sam Conner at MIT * Mar 2 1987 Original VAX Unix version * Mar 2 1987 declare undecldared variables x, y, and j * * Jan 8 1993 Modify to handle arbitrary byte-per-pixel images * Apr 16 1993 Declare undeclared variables iy, ic0, and ir0 * * Jan 30 2002 Translate from Fortran to C */ wcstools-3.9.5/libwcs/catutil.c0000664000016200001660000030056313065034663015564 0ustar minkoirsys/*** File libwcs/catutil.c *** November 25, 2015 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1998-2015 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ /* int RefCat (refcatname,title,syscat,eqcat,epcat, catprop, nmag) * Return catalog type code, title, coord. system, proper motion, num mags * char *CatName (refcat, refcatname) * Return catalog name given catalog type code * char *CatSource (refcat, refcatname) * Return name for catalog sources given catalog type code * void CatID (catid, refcat) * Return ID column heading for the given catalog * double CatRad (refcat) * Return default search radius for the given catalog * char *ProgCat (progname) * Return catalog name from program name, NULL if none there * char *ProgName (progpath0) * Return program name from pathname by which program is invoked * void CatNum (refcat, nndec, dnum, numstr) * Return formatted source number * void SearchLim (cra, cdec, dra, ddec, sys, ra1, ra2, dec1, dec2, verbose) * Compute limiting RA and Dec from center and half-widths * int CatNumLen (refcat, nndec) * Return length of source number * int CatNdec (refcat) * Return number of decimal places in source number, if known * void CatMagName (imag, refcat, magname) * Returns name of specified magnitude * int CatMagNum (imag, refcat) * Returns number of magnitude specified by letter as int * int StrNdec (string) * Returns number of decimal places in a numeric string (-1=not number) * int NumNdec (number) * Returns number of decimal places in a number * char *DateString (dateform,epoch) * Return string with epoch of position in desired format * void RefLim (cra,cdec,dra,ddec,sysc,sysr,eqc,eqr,epc,ramin,ramax,decmin,decmax,verbose) * Compute limiting RA and Dec in new system from center and half-widths * struct Range *RangeInit (string, ndef) * Return structure containing ranges of numbers * int isrange (string) * Return 1 if string is a range, else 0 * int rstart (range) * Restart at beginning of range * int rgetn (range) * Return number of values from range structure * int rgeti4 (range) * Return next number from range structure as 4-byte integer * int rgetr8 (range) * Return next number from range structure as 8-byte floating point number * int ageti4 (string, keyword, ival) * Read int value from a file where keyword=value, anywhere on a line * int agetr8 (string, keyword, dval) * Read double value from a file where keyword=value, anywhere on a line * int agets (string, keyword, lval, fillblank, value) * Read value from a file where keyword=value, anywhere on a line * void bv2sp (bv, b, v, isp) * approximate spectral type given B - V or B and V magnitudes * void br2sp (br, b, r, isp) * approximate spectral type given B - R or B and R magnitudes * void vothead (refcat, refcatname, mprop, typecol) * Print heading for VOTable format catalog search return * void vottail () * Print end of VOTable format catalog search return * void setrevmsg (revmessage) * Set version/date message for nstarmax=-1 returns from *read subroutines * char *getrevmsg () * Return version/date message for nstarmax=-1 returns from *read subroutines * int *is2massid (string) * Return 1 if string is 2MASS ID, else 0 * void polfit (x, y, x0, npts, nterms, a, stdev) * Polynomial least squares fitting program *double polcomp (xi, x0, norder, a) * Polynomial evaluation Y = A(1) + A(2)*X + A(3)*X^2 + A(3)*X^3 + ... * void moveb (source, dest, nbytes, offs, offd) * Copy nbytes bytes from source+offs to dest+offd (any data type) */ #include #include #include #include #include #include "wcs.h" #include "fitsfile.h" #include "wcscat.h" static char *revmessage = NULL; /* Version and date for calling program */ static char *revmsg0 = ""; void setrevmsg (revmsg) /* Set version and date string*/ char *revmsg; { revmessage = revmsg; return; } char * getrevmsg () /* Return version and date string */ { if (revmessage == NULL) return (revmsg0); else return (revmessage); } static int degout = 0; /* Set to 1 to print coordinates in degrees */ void setlimdeg (degoutx) /* Set degree output flag */ int degoutx; { degout = degoutx; return; } /* Return code for reference catalog or its type */ int RefCat (refcatname, title, syscat, eqcat, epcat, catprop, nmag) char *refcatname; /* Name of reference catalog */ char *title; /* Description of catalog (returned) */ int *syscat; /* Catalog coordinate system (returned) */ double *eqcat; /* Equinox of catalog (returned) */ double *epcat; /* Epoch of catalog (returned) */ int *catprop; /* 1 if proper motion in catalog (returned) */ int *nmag; /* Number of magnitudes in catalog (returned) */ { struct StarCat *starcat; int refcat, nbuff; *catprop = 0; refcat = CatCode (refcatname); if (refcat == GSCACT) { strcpy (title, "HST Guide Stars/ACT"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *nmag = 1; *catprop = 0; } else if (refcat == GSC2) { if (strsrch (refcatname, "22")) { strcpy (title, "GSC 2.2 Sources"); *catprop = 0; } else if (strsrch (refcatname, "23")) { strcpy (title, "GSC 2.3 Sources"); *catprop = 1; } else { strcpy (title, "GSC 2.3 Sources"); *catprop = 0; } *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *nmag = 5; refcat = GSC2; } else if (refcat == GSC) { strcpy (title, "HST Guide Stars"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 0; *nmag = 1; } else if (refcat == SDSS) { strcpy (title, "SDSS Sources"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 0; *nmag = 5; } else if (refcat == SKYBOT) { strcpy (title, "SkyBot Sources"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 1; *nmag = 3; } else if (refcat == UB1) { strcpy (title, "USNO-B1.0 Sources"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 1; *nmag = 5; refcat = UB1; } else if (refcat == YB6) { strcpy (title, "USNO-YB6 Sources"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 1; *nmag = 5; refcat = YB6; } else if (refcat == USA1 || refcat == USA2 || refcat == USAC) { *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *nmag = 2; *catprop = 0; if (strchr (refcatname, '1') != NULL) strcpy (title, "USNO SA-1.0 Catalog Stars"); else if (strchr (refcatname, '2') != NULL) strcpy (title, "USNO SA-2.0 Catalog Stars"); else strcpy (title, "USNO SA Catalog Stars"); } else if (refcat == USNO) { *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 0; *nmag = 1; sprintf (title, "USNO %s Stars", refcatname); } else if (refcat == UA1 || refcat == UA2 || refcat == UAC) { *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 0; *nmag = 2; if (strchr (refcatname, '1') != NULL) strcpy (title, "USNO A-1.0 Sources"); else if (strchr (refcatname, '2') != NULL) strcpy (title, "USNO A-2.0 Sources"); else strcpy (title, "USNO A Sources"); } else if (refcat == UCAC1) { strcpy (title, "USNO UCAC1 Catalog Stars"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 1; *nmag = 1; } else if (refcat == UCAC2) { strcpy (title, "USNO UCAC2 Catalog Stars"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 1; *nmag = 4; } else if (refcat == UCAC3) { strcpy (title, "USNO UCAC3 Catalog Stars"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 1; *nmag = 8; } else if (refcat == UCAC4) { strcpy (title, "USNO UCAC4 Catalog Stars"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 1; *nmag = 8; } else if (refcat == UJC) { strcpy (title, "USNO J Catalog Stars"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 0; *nmag = 1; } else if (refcat == SAO) { strcpy (title, "SAO Catalog Stars"); starcat = binopen ("SAO"); if (starcat == NULL) starcat = binopen ("SAOra"); if (starcat) { *syscat = starcat->coorsys; *eqcat = starcat->equinox; *epcat = starcat->epoch; *catprop = starcat->mprop; *nmag = 1; binclose (starcat); } } else if (refcat == PPM) { strcpy (title, "PPM Catalog Stars"); starcat = binopen ("PPM"); if (starcat == NULL) starcat = binopen ("PPMra"); if (starcat) { *syscat = starcat->coorsys; *eqcat = starcat->equinox; *epcat = starcat->epoch; *catprop = starcat->mprop; *nmag = 1; binclose (starcat); } } else if (refcat == IRAS) { strcpy (title, "IRAS Point Sources"); if ((starcat = binopen ("IRAS"))) { *syscat = starcat->coorsys; *eqcat = starcat->equinox; *epcat = starcat->epoch; *nmag = 1; *catprop = starcat->mprop; binclose (starcat); } } else if (refcat == SKY2K) { strcpy (title, "SKY2000 Master Catalog Stars"); starcat = binopen ("sky2k"); if (starcat == NULL) starcat = binopen ("sky2kra"); if (starcat) { *syscat = starcat->coorsys; *eqcat = starcat->equinox; *epcat = starcat->epoch; *catprop = starcat->mprop; *nmag = 4; binclose (starcat); } } else if (refcat == TYCHO2) { strcpy (title, "Tycho 2 Catalog Stars"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 1; *nmag = 2; } else if (refcat == TYCHO2E) { strcpy (title, "Tycho 2 Catalog Stars"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 1; *nmag = 4; } else if (refcat == TYCHO) { strcpy (title, "Tycho Catalog Stars"); if ((starcat = binopen ("tycho"))) { *syscat = starcat->coorsys; *eqcat = starcat->equinox; *epcat = starcat->epoch; *catprop = 1; *nmag = 2; binclose (starcat); } } else if (refcat == HIP) { strcpy (title, "Hipparcos Catalog Stars"); if ((starcat = binopen ("hipparcos"))) { *syscat = starcat->coorsys; *eqcat = starcat->equinox; *epcat = starcat->epoch; *catprop = starcat->mprop; *nmag = 1; binclose (starcat); } } else if (refcat == ACT) { strcpy (title, "ACT Catalog Stars"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 1; *nmag = 2; } else if (refcat == BSC) { strcpy (title, "Bright Star Catalog Stars"); if ((starcat = binopen ("BSC5"))) { *syscat = starcat->coorsys; *eqcat = starcat->equinox; *epcat = starcat->epoch; *catprop = starcat->mprop; *nmag = 1; binclose (starcat); } } else if (refcat == TMPSC || refcat == TMIDR2) { strcpy (title, "2MASS Point Sources"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 0; *nmag = 3; } else if (refcat == TMPSCE) { strcpy (title, "2MASS Point Sources"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 0; *nmag = 6; } else if (refcat == TMXSC) { strcpy (title, "2MASS Extended Sources"); *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 0; *nmag = 3; } else if (refcat == USNO) { *syscat = WCS_J2000; *eqcat = 2000.0; *epcat = 2000.0; *catprop = 0; *nmag = 1; sprintf (title, "USNO %s Stars", refcatname); } else if (refcat == BINCAT) { strcpy (title, refcatname); strcat (title, " Catalog Sources"); if ((starcat = binopen (refcatname))) { *syscat = starcat->coorsys; *eqcat = starcat->equinox; *epcat = starcat->epoch; *catprop = starcat->mprop; *nmag = starcat->nmag; binclose (starcat); } } else if (refcat == TABCAT) { strcpy (title, refcatname); strcat (title, " Catalog Sources"); if (strchr (refcatname, ',')) nbuff = 0; else nbuff = 1000; if ((starcat = tabcatopen (refcatname, NULL, nbuff))) { *syscat = starcat->coorsys; *eqcat = starcat->equinox; *epcat = starcat->epoch; *catprop = starcat->mprop; *nmag = starcat->nmag; ctgclose (starcat); } } else if (refcat != 0) { strcpy (title, refcatname); strcat (title, " Catalog Sources"); if ((starcat = ctgopen (refcatname, TXTCAT))) { *syscat = starcat->coorsys; *eqcat = starcat->equinox; *epcat = starcat->epoch; *catprop = starcat->mprop; *nmag = starcat->nmag; ctgclose (starcat); } } return refcat; } /* Return code for reference catalog or its type */ int CatCode (refcatname) char *refcatname; /* Name of reference catalog */ { struct StarCat *starcat; int refcat, nbuff; refcat = 0; if (refcatname == NULL) refcat = 0; else if (strlen (refcatname) < 1) refcat = 0; else if (strncasecmp(refcatname,"gsca",4)==0 && strcsrch(refcatname, ".tab") == NULL) refcat = GSCACT; else if (strncasecmp(refcatname,"gsc2",4)==0 && strcsrch(refcatname, ".tab") == NULL) refcat = GSC2; else if (strncasecmp(refcatname,"sdss",4)==0 && strcsrch(refcatname, ".tab") == NULL) refcat = SDSS; else if (strncasecmp(refcatname,"skyb",4)==0 && strcsrch(refcatname, ".tab") == NULL) refcat = SKYBOT; else if (strncasecmp(refcatname,"gs",2)==0 && strcsrch(refcatname, ".tab") == NULL) refcat = GSC; else if (strncasecmp(refcatname,"ub",2)==0 && strcsrch(refcatname, ".tab") == NULL) refcat = UB1; else if (strncasecmp(refcatname,"ucac1",5)==0 && strcsrch(refcatname, ".tab") == NULL) refcat = UCAC1; else if (strncasecmp(refcatname,"ucac2",5)==0 && strcsrch(refcatname, ".tab") == NULL) refcat = UCAC2; else if (strncasecmp(refcatname,"ucac3",5)==0 && strcsrch(refcatname, ".tab") == NULL) refcat = UCAC3; else if (strncasecmp(refcatname,"ucac4",5)==0 && strcsrch(refcatname, ".tab") == NULL) refcat = UCAC4; else if (strncasecmp(refcatname,"usa",3)==0 && strcsrch(refcatname, ".tab") == NULL) { if (strchr (refcatname, '1') != NULL) refcat = USA1; else if (strchr (refcatname, '2') != NULL) refcat = USA2; else refcat = USAC; } else if (strncmp (refcatname, ".usnop", 6) == 0) refcat = USNO; else if (strncasecmp(refcatname,"ua",2)==0 && strcsrch(refcatname, ".tab") == NULL) { if (strchr (refcatname, '1') != NULL) refcat = UA1; else if (strchr (refcatname, '2') != NULL) refcat = UA2; else refcat = UAC; } else if (strncasecmp(refcatname,"uj",2)==0 && strcsrch(refcatname, ".tab") == NULL) refcat = UJC; else if (strncasecmp(refcatname,"yb6",3)==0 && strcsrch(refcatname, ".tab") == NULL) refcat = YB6; else if (strncasecmp(refcatname,"sky2k",5)==0 && strcsrch(refcatname, ".tab") == NULL) refcat = SKY2K; else if (strncasecmp(refcatname,"sao",3)==0 && strcsrch(refcatname, ".tab") == NULL) { starcat = binopen ("SAO"); if (starcat == NULL) starcat = binopen ("SAOra"); if (starcat) { binclose (starcat); refcat = SAO; } } else if (strncasecmp(refcatname,"ppm",3)==0 && strcsrch(refcatname, ".tab") == NULL) { starcat = binopen ("PPM"); if (starcat == NULL) starcat = binopen ("PPMra"); if (starcat) { binclose (starcat); refcat = PPM; } } else if (strncasecmp(refcatname,"iras",4)==0 && strcsrch(refcatname, ".tab") == NULL) { if ((starcat = binopen ("IRAS"))) { binclose (starcat); refcat = IRAS; } } else if (strncasecmp(refcatname,"ty",2)==0 && strcsrch(refcatname, ".tab") == NULL) { if (strcsrch (refcatname, "2e") != NULL) { refcat = TYCHO2E; } else if (strsrch (refcatname, "2") != NULL) { refcat = TYCHO2; } else { if ((starcat = binopen ("tycho"))) { binclose (starcat); refcat = TYCHO; } } } else if (strncasecmp(refcatname,"hip",3)==0 && strcsrch(refcatname, ".tab") == NULL) { if ((starcat = binopen ("hipparcos"))) { binclose (starcat); refcat = HIP; } } else if (strncasecmp(refcatname,"act",3)==0 && strcsrch(refcatname, ".tab") == NULL) refcat = ACT; else if (strncasecmp(refcatname,"bsc",3)==0 && strcsrch(refcatname, ".tab") == NULL) { if ((starcat = binopen ("BSC5"))) { binclose (starcat); refcat = BSC; } } else if (strcsrch (refcatname,"idr2") && strcsrch (refcatname, ".tab") == NULL) { refcat = TMIDR2; } else if ((strncasecmp(refcatname,"2mp",3)==0 || strncasecmp(refcatname,"2mc",3)==0 || strncasecmp(refcatname,"tmp",3)==0 || strncasecmp(refcatname,"tmc",3)==0) && strcsrch(refcatname, ".tab") == NULL) { if (strcsrch (refcatname, "ce")) refcat = TMPSCE; else refcat = TMPSC; } else if ((strncasecmp(refcatname,"2mx",3)==0 || strncasecmp(refcatname,"tmx",3)==0) && strcsrch(refcatname, ".tab") == NULL) { refcat = TMXSC; } else if (strcsrch (refcatname, ".usno")) { refcat = USNO; } else if (isbin (refcatname)) { if ((starcat = binopen (refcatname))) { binclose (starcat); refcat = BINCAT; } else refcat = 0; } else if (istab (refcatname)) { if (strchr (refcatname, ',')) nbuff = 0; else nbuff = 1000; if ((starcat = tabcatopen (refcatname, NULL, nbuff))) { ctgclose (starcat); refcat = TABCAT; } else refcat = 0; } else if (refcatname != NULL) { if ((starcat = ctgopen (refcatname, TXTCAT))) { ctgclose (starcat); refcat = TXTCAT; } else refcat = 0; } else refcat = 0; return refcat; } char * CatName (refcat, refcatname) int refcat; /* Catalog code */ char *refcatname; /* Catalog file name */ { char *catname; if (refcat < 1 || refcat > NUMCAT) return (refcatname); /* Allocate string in which to return a catalog name */ catname = (char *)calloc (16, 1); if (refcat == GSC) /* HST Guide Star Catalog */ strcpy (catname, "GSC"); else if (refcat == GSCACT) /* HST GSC revised with ACT */ strcpy (catname, "GSC-ACT"); else if (refcat == GSC2) { /* GSC II */ if (strsrch (refcatname, "22")) { strcpy (catname, "GSC 2.2"); } else { strcpy (catname, "GSC 2.3"); } } else if (refcat == YB6) /* USNO YB6 Star Catalog */ strcpy (catname, "USNO-YB6"); else if (refcat == UJC) /* USNO UJ Star Catalog */ strcpy (catname, "UJC"); else if (refcat == UAC) /* USNO A Star Catalog */ strcpy (catname, "USNO-A2.0"); else if (refcat == USAC) /* USNO SA Star Catalog */ strcpy (catname, "USNO-SA2.0"); else if (refcat == SAO) /* SAO Star Catalog */ strcpy (catname, "SAO"); else if (refcat == IRAS) /* IRAS Point Source Catalog */ strcpy (catname, "IRAS PSC"); else if (refcat == SDSS) /* Sloan Digital Sky Survey */ strcpy (catname, "SDSS"); else if (refcat == PPM) /* PPM Star Catalog */ strcpy (catname, "PPM"); else if (refcat == TYCHO) /* Tycho Star Catalog */ strcpy (catname, "TYCHO"); else if (refcat == UA1) /* USNO A-1.0 Star Catalog */ strcpy (catname, "USNO-A1.0"); else if (refcat == UB1) /* USNO B-1.0 Star Catalog */ strcpy (catname, "USNO-B1.0"); else if (refcat == UCAC1) /* USNO UCAC1 Star Catalog */ strcpy (catname, "USNO-UCAC1"); else if (refcat == UCAC2) /* USNO UCAC2 Star Catalog */ strcpy (catname, "USNO-UCAC2"); else if (refcat == UCAC3) /* USNO UCAC3 Star Catalog */ strcpy (catname, "USNO-UCAC3"); else if (refcat == UCAC4) /* USNO UCAC4 Star Catalog */ strcpy (catname, "USNO-UCAC4"); else if (refcat == UA2) /* USNO A-2.0 Star Catalog */ strcpy (catname, "USNO-A2.0"); else if (refcat == USA1) /* USNO SA-1.0 Star Catalog */ strcpy (catname, "USNO-SA1.0"); else if (refcat == USA2) /* USNO SA-2.0 Star Catalog */ strcpy (catname, "USNO-SA2.0"); else if (refcat == HIP) /* Hipparcos Star Catalog */ strcpy (catname, "Hipparcos"); else if (refcat == ACT) /* USNO ACT Star Catalog */ strcpy (catname, "ACT"); else if (refcat == BSC) /* Yale Bright Star Catalog */ strcpy (catname, "BSC"); else if (refcat == TYCHO2 || refcat == TYCHO2E) /* Tycho-2 Star Catalog */ strcpy (catname, "TYCHO-2"); else if (refcat == TMPSC || refcat == TMPSCE) /* 2MASS Point Source Catalog */ strcpy (catname, "2MASS PSC"); else if (refcat == TMXSC) /* 2MASS Extended Source Catalog */ strcpy (catname, "2MASS XSC"); else if (refcat == TMIDR2) /* 2MASS Point Source Catalog */ strcpy (catname, "2MASS PSC IDR2"); else if (refcat == SKY2K) /* SKY2000 Master Catalog */ strcpy (catname, "SKY2000"); else if (refcat == SKYBOT) /* SkyBot Solar System Objects */ strcpy (catname, "SkyBot"); return (catname); } char * CatSource (refcat, refcatname) int refcat; /* Catalog code */ char *refcatname; /* Catalog file name */ { char *catname; int lname; if (refcat < 1 || refcat > NUMCAT) { if (refcatname == NULL) lname = 0; else lname = strlen (refcatname); catname = (char *)calloc (lname + 16, 1); if (lname > 0) sprintf (catname, "%s sources", refcatname); else sprintf (catname, "catalog sources"); return (catname); } /* Allocate string in which to return a catalog name */ catname = (char *)calloc (64, 1); if (refcat == GSC) /* HST Guide Star Catalog */ strcpy (catname, "HST Guide Stars"); else if (refcat == GSCACT) /* HST GSC revised with ACT */ strcpy (catname, "GSC-ACT Stars"); else if (refcat == GSC2) { /* GSC II */ if (strsrch (refcatname, "22")) { strcpy (catname, "GSC 2.2 Stars"); } else { strcpy (catname, "GSC 2.3 Stars"); } } else if (refcat == YB6) /* USNO YB6 Star Catalog */ strcpy (catname, "USNO-YB6 Stars"); else if (refcat == UJC) /* USNO UJ Star Catalog */ strcpy (catname, "USNO J Catalog Stars"); else if (refcat == UAC) /* USNO A Star Catalog */ strcpy (catname, "USNO-A2.0 Stars"); else if (refcat == USAC) /* USNO SA Star Catalog */ strcpy (catname, "USNO-SA2.0 Stars"); else if (refcat == SAO) /* SAO Star Catalog */ strcpy (catname, "SAO Catalog Stars"); else if (refcat == IRAS) /* IRAS Point Source Catalog */ strcpy (catname, "IRAS Point Sources"); else if (refcat == SDSS) /* Sloan Digital Sky Survey */ strcpy (catname, "SDSS Photmetric Catalog Sources"); else if (refcat == PPM) /* PPM Star Catalog */ strcpy (catname, "PPM Catalog Stars"); else if (refcat == TYCHO) /* Tycho Star Catalog */ strcpy (catname, "Tycho Catalog Stars"); else if (refcat == TYCHO2) /* Tycho-2 Star Catalog */ strcpy (catname, "Tycho-2 Catalog Stars"); else if (refcat == TYCHO2E) /* Tycho-2 Star Catalog */ strcpy (catname, "Tycho-2 Catalog Stars with mag error"); else if (refcat == UA1) /* USNO A-1.0 Star Catalog */ strcpy (catname, "USNO-A1.0 Stars"); else if (refcat == UB1) /* USNO B-1.0 Star Catalog */ strcpy (catname, "USNO-B1.0 Stars"); else if (refcat == UCAC1) /* USNO UCAC1 Star Catalog */ strcpy (catname, "USNO-UCAC1 Stars"); else if (refcat == UCAC2) /* USNO UCAC2 Star Catalog */ strcpy (catname, "USNO-UCAC2 Stars"); else if (refcat == UCAC3) /* USNO UCAC3 Star Catalog */ strcpy (catname, "USNO-UCAC3 Stars"); else if (refcat == UCAC4) /* USNO UCAC4 Star Catalog */ strcpy (catname, "USNO-UCAC4 Stars"); else if (refcat == UA2) /* USNO A-2.0 Star Catalog */ strcpy (catname, "USNO-A2.0 Stars"); else if (refcat == USA1) /* USNO SA-1.0 Star Catalog */ strcpy (catname, "USNO-SA1.0 Stars"); else if (refcat == USA2) /* USNO SA-2.0 Star Catalog */ strcpy (catname, "USNO-SA2.0 Stars"); else if (refcat == HIP) /* Hipparcos Star Catalog */ strcpy (catname, "Hipparcos Catalog Stars"); else if (refcat == ACT) /* USNO ACT Star Catalog */ strcpy (catname, "ACT Catalog Stars"); else if (refcat == BSC) /* Yale Bright Star Catalog */ strcpy (catname, "Bright Star Catalog Stars"); else if (refcat == TMPSC) /* 2MASS Point Source Catalog */ strcpy (catname, "2MASS Point Sources"); else if (refcat == TMPSCE) /* 2MASS Point Source Catalog */ strcpy (catname, "2MASS Point Sources with mag error"); else if (refcat == TMXSC) /* 2MASS Extended Source Catalog */ strcpy (catname, "2MASS Extended Sources"); else if (refcat == TMIDR2) /* 2MASS Point Source Catalog */ strcpy (catname, "2MASS-IDR2 Point Sources"); else if (refcat == SKY2K) /* SKY2000 Master Catalog */ strcpy (catname, "SKY2000 Catalog Stars"); else if (refcat == SKYBOT) /* SkyBot Solar System Objects */ strcpy (catname, "SkyBot Objects"); return (catname); } void CatID (catid, refcat) char *catid; /* Catalog ID (returned) */ int refcat; /* Catalog code */ { if (refcat == ACT) strcpy (catid, "act_id "); else if (refcat == BSC) strcpy (catid, "bsc_id "); else if (refcat == GSC || refcat == GSCACT) strcpy (catid, "gsc_id "); else if (refcat == GSC2) strcpy (catid, "gsc2_id "); else if (refcat == SDSS) strcpy (catid, "sdss_id "); else if (refcat == USAC) strcpy (catid,"usac_id "); else if (refcat == USA1) strcpy (catid,"usa1_id "); else if (refcat == USA2) strcpy (catid,"usa2_id "); else if (refcat == UAC) strcpy (catid,"usnoa_id "); else if (refcat == UA1) strcpy (catid,"usnoa1_id "); else if (refcat == UB1) strcpy (catid,"usnob1_id "); else if (refcat == YB6) strcpy (catid,"usnoyb6_id "); else if (refcat == UA2) strcpy (catid,"usnoa2_id "); else if (refcat == UCAC1) strcpy (catid,"ucac1_id "); else if (refcat == UCAC2) strcpy (catid,"ucac2_id "); else if (refcat == UCAC3) strcpy (catid,"ucac3_id "); else if (refcat == UCAC4) strcpy (catid,"ucac4_id "); else if (refcat == UJC) strcpy (catid,"usnoj_id "); else if (refcat == TMPSC || refcat == TMPSCE) strcpy (catid,"2mass_id "); else if (refcat == TMXSC) strcpy (catid,"2mx_id "); else if (refcat == SAO) strcpy (catid,"sao_id "); else if (refcat == PPM) strcpy (catid,"ppm_id "); else if (refcat == IRAS) strcpy (catid,"iras_id"); else if (refcat == TYCHO) strcpy (catid,"tycho_id "); else if (refcat == TYCHO2 || refcat == TYCHO2E) strcpy (catid,"tycho2_id "); else if (refcat == HIP) strcpy (catid,"hip_id "); else if (refcat == SKY2K) strcpy (catid,"sky_id "); else if (refcat == SKYBOT) strcpy (catid,"skybot_id "); else strcpy (catid,"id "); return; } double CatRad (refcat) int refcat; /* Catalog code */ { if (refcat==GSC || refcat==GSCACT || refcat==UJC || refcat==USAC || refcat==USA1 || refcat==USA2 || refcat == UCAC1 || refcat == UCAC2 || refcat == UCAC3 || refcat == UCAC4) return (900.0); else if (refcat==UAC || refcat==UA1 || refcat==UA2) return (120.0); else if (refcat == UB1 || refcat==SDSS) return (120.0); else if (refcat==GSC2) return (120.0); else if (refcat==TMPSC || refcat==TMPSCE || refcat==TMIDR2) return (120.0); else if (refcat==TMXSC) return (900.0); else if (refcat==GSC2) return (120.0); else if (refcat==SAO || refcat==PPM || refcat==IRAS || refcat == SKY2K || refcat==SKYBOT) return (5000.0); else if (refcat==BSC) return (7200.0); else return (1800.0); } char * ProgName (progpath0) char *progpath0; /* Pathname by which program is invoked */ { char *progpath, *progname; int i, lpath; lpath = (strlen (progpath0) + 2) / 8; lpath = (lpath + 1) * 8;; progpath = (char *) calloc (lpath, 1); strcpy (progpath, progpath0); progname = progpath; for (i = strlen (progpath); i > -1; i--) { if (progpath[i] > 63 && progpath[i] < 90) progpath[i] = progpath[i] + 32; if (progpath[i] == '/') { progname = progpath + i + 1; break; } } return (progname); } char * ProgCat (progname) char *progname; /* Program name which might contain catalog code */ { char *refcatname; refcatname = NULL; if (strcsrch (progname,"gsca") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "gscact"); } else if (strcsrch (progname,"gsc2") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "gsc2"); } else if (strcsrch (progname,"gsc") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "gsc"); } else if (strcsrch (progname,"sdss") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "sdss"); } else if (strcsrch (progname,"uac") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "uac"); } else if (strcsrch (progname,"ua1") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "ua1"); } else if (strcsrch (progname,"ub") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "ub1"); } else if (strcsrch (progname,"yb6") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "yb6"); } else if (strcsrch (progname,"ua2") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "ua2"); } else if (strcsrch (progname,"usac") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "usac"); } else if (strcsrch (progname,"usa1") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "usa1"); } else if (strcsrch (progname,"usa2") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "usa2"); } else if (strcsrch (progname,"ucac1") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "ucac1"); } else if (strcsrch (progname,"ucac2") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "ucac2"); } else if (strcsrch (progname,"ucac3") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "ucac3"); } else if (strcsrch (progname,"ucac4") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "ucac4"); } else if (strcsrch (progname,"ujc") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "ujc"); } else if (strcsrch (progname,"sao") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "sao"); } else if (strcsrch (progname,"ppm") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "ppm"); } else if (strcsrch (progname,"ira") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "iras"); } else if (strcsrch (progname,"ty") != NULL) { refcatname = (char *) calloc (1,8); if (strcsrch (progname, "2e") != NULL) strcpy (refcatname, "tycho2e"); else if (strcsrch (progname, "2") != NULL) strcpy (refcatname, "tycho2"); else strcpy (refcatname, "tycho"); } else if (strcsrch (progname,"hip") != NULL) { refcatname = (char *) calloc (1,16); strcpy (refcatname, "hipparcos"); } else if (strcsrch (progname,"act") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "act"); } else if (strcsrch (progname,"bsc") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "bsc"); } else if (strcsrch (progname,"sky2k") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "sky2k"); } else if (strcsrch (progname,"skybot") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "skybot"); } else if (strcsrch (progname,"2mp") != NULL || strcsrch (progname,"tmc") != NULL) { refcatname = (char *) calloc (1,8); if (strcsrch (progname,"ce")) strcpy (refcatname, "tmce"); else strcpy (refcatname, "tmc"); } else if (strcsrch (progname,"2mx") != NULL || strcsrch (progname,"tmx") != NULL) { refcatname = (char *) calloc (1,8); strcpy (refcatname, "tmx"); } else refcatname = NULL; return (refcatname); } void CatNum (refcat, nnfld, nndec, dnum, numstr) int refcat; /* Catalog code */ int nnfld; /* Number of characters in number (from CatNumLen) */ /* Print leading zeroes if negative */ int nndec; /* Number of decimal places ( >= 0) */ /* Omit leading spaces if negative */ double dnum; /* Catalog number of source */ char *numstr; /* Formatted number (returned) */ { char nform[16]; /* Format for star number */ int lnum, i; /* USNO A1.0, A2.0, SA1.0, or SA2.0 Catalogs */ if (refcat == USAC || refcat == USA1 || refcat == USA2 || refcat == UAC || refcat == UA1 || refcat == UA2) { if (nnfld < 0) sprintf (numstr, "%013.8f", dnum); else sprintf (numstr, "%13.8f", dnum); } /* USNO-B1.0 and USNO-YB6 */ else if (refcat == UB1 || refcat == YB6) { if (nnfld < 0) sprintf (numstr, "%012.7f", dnum); else sprintf (numstr, "%12.7f", dnum); } /* USNO-UCAC1 */ else if (refcat == UCAC1) { if (nnfld < 0) sprintf (numstr, "%010.6f", dnum); else sprintf (numstr, "%10.6f", dnum); } /* USNO-UCAC2 */ else if (refcat == UCAC2) { if (nnfld < 0) sprintf (numstr, "%010.6f", dnum); else sprintf (numstr, "%10.6f", dnum); } /* USNO-UCAC3 */ else if (refcat == UCAC3) { if (nnfld < 0) sprintf (numstr, "%010.6f", dnum); else sprintf (numstr, "%10.6f", dnum); } /* USNO-UCAC4 */ else if (refcat == UCAC4) { if (nnfld < 0) sprintf (numstr, "%010.6f", dnum); else sprintf (numstr, "%10.6f", dnum); } /* SDSS */ else if (refcat == SDSS) { sprintf (numstr, "582%015.0f", dnum); } /* GSC II */ else if (refcat == GSC2) { if (nnfld < 0) { if (dnum > 0) sprintf (numstr, "N%.0f", (dnum+0.01)); else sprintf (numstr, "S%.0f", (-dnum + 0.01)); lnum = strlen (numstr); if (lnum < -nnfld) { for ( i = lnum; i < -nnfld; i++) strcat (numstr, " "); } } else { if (dnum > 0) sprintf (numstr, "N%.0f", (dnum+0.5)); else sprintf (numstr, "S%.0f", (-dnum + 0.5)); } } /* 2MASS Point Source Catalogs */ else if (refcat == TMPSC || refcat == TMPSCE) { if (nnfld < 0) sprintf (numstr, "%011.6f", dnum); else sprintf (numstr, "%11.6f", dnum); } /* 2MASS Extended Source Catalog */ else if (refcat == TMXSC) { if (nnfld < 0) sprintf (numstr, "%011.6f", dnum); else sprintf (numstr, "%11.6f", dnum); } /* 2MASS Point Source Catalogs */ else if (refcat == TMIDR2) { if (nnfld < 0) sprintf (numstr, "%010.7f", dnum); else sprintf (numstr, "%10.7f", dnum); } /* USNO Plate Catalog */ else if (refcat == USNO) { if (nnfld < 0) sprintf (numstr, "%07d", (int)(dnum+0.5)); else sprintf (numstr, "%7d", (int)(dnum+0.5)); } /* USNO UJ 1.0 Catalog */ else if (refcat == UJC) { if (nnfld < 0) sprintf (numstr, "%012.7f", dnum); else sprintf (numstr, "%12.7f", dnum); } /* HST Guide Star Catalog */ else if (refcat == GSC || refcat == GSCACT) { if (nnfld < 0) sprintf (numstr, "%09.4f", dnum); else sprintf (numstr, "%9.4f", dnum); } /* SAO, PPM, or IRAS Point Source Catalogs (TDC binary format) */ else if (refcat==SAO || refcat==PPM || refcat==IRAS || refcat==HIP) { if (nnfld < 0) sprintf (numstr, "%06d", (int)(dnum+0.5)); else sprintf (numstr, "%6d", (int)(dnum+0.5)); } /* Yale Bright Star Catalog (TDC binary format) */ else if (refcat==BSC) { if (nnfld < 0) sprintf (numstr, "%04d", (int)(dnum+0.5)); else sprintf (numstr, "%4d", (int)(dnum+0.5)); } /* SKY2000 Catalog (TDC binary format) */ else if (refcat==SKY2K) { if (nnfld < 0) sprintf (numstr, "%07d", (int)(dnum+0.5)); else sprintf (numstr, "%7d", (int)(dnum+0.5)); } /* Tycho2 */ else if (refcat==TYCHO2) { if (nnfld < 0) sprintf (numstr, "%010.6f", dnum); else sprintf (numstr, "%10.6f", dnum); } /* Other Tycho or ACT catalogs */ else if (refcat==TYCHO || refcat == TYCHO2E || refcat==ACT) { if (nnfld < 0) sprintf (numstr, "%010.5f", dnum); else sprintf (numstr, "%10.5f", dnum); } /* Starbase tab-separated, TDC binary, or TDC ASCII catalogs */ else if (nndec > 0) { if (nnfld > 0) sprintf (nform,"%%%d.%df", nnfld, nndec); else if (nnfld < 0) sprintf (nform,"%%0%d.%df", -nnfld, nndec); else sprintf (nform,"%%%d.%df", nndec+5, nndec); sprintf (numstr, nform, dnum); } else if (nnfld > 10) { sprintf (nform,"%%%d.0f", nnfld); sprintf (numstr, nform, dnum+0.49); } else if (nnfld > 0) { sprintf (nform,"%%%dd", nnfld); sprintf (numstr, nform, (int)(dnum+0.49)); } else if (nnfld < 0) { sprintf (nform,"%%0%dd", -nnfld); sprintf (numstr, nform, (int)(dnum+0.49)); } else if (nndec < 0) sprintf (numstr, "%d", (int)(dnum+0.49)); else sprintf (numstr, "%6d", (int)(dnum+0.49)); return; } int CatNumLen (refcat, maxnum, nndec) int refcat; /* Catalog code */ double maxnum; /* Maximum ID number */ /* (Ignored for standard catalogs) */ int nndec; /* Number of decimal places ( >= 0) */ { int ndp; /* Number of characters for decimal point */ /* USNO A1.0, A2.0, SA1.0, or SA2.0 Catalogs */ if (refcat == USAC || refcat == USA1 || refcat == USA2 || refcat == UAC || refcat == UA1 || refcat == UA2) return (13); /* USNO-B1.0 and YB6 */ else if (refcat == UB1 || refcat == YB6) return (12); /* GSC II */ else if (refcat == GSC2) return (13); /* 2MASS Point Source Catalog */ else if (refcat == TMPSC || refcat == TMPSCE) return (11); else if (refcat == TMIDR2) return (10); /* 2MASS Extended Source Catalog */ else if (refcat == TMXSC) return (11); /* UCAC1 Catalog */ else if (refcat == UCAC1) return (10); /* UCAC2 Catalog */ else if (refcat == UCAC2) return (10); /* UCAC3 Catalog */ else if (refcat == UCAC3) return (10); /* UCAC4 Catalog */ else if (refcat == UCAC4) return (10); /* USNO Plate Catalogs */ else if (refcat == USNO) return (7); /* USNO UJ 1.0 Catalog */ else if (refcat == UJC) return (12); /* SDSS Catalog */ else if (refcat == SDSS) return (18); /* SkyBot Objects */ else if (refcat == SKYBOT) return (6); /* HST Guide Star Catalog */ else if (refcat == GSC || refcat == GSCACT) return (9); /* SAO, PPM, Hipparcos, or IRAS Point Source Catalogs (TDC binary format) */ else if (refcat==SAO || refcat==PPM || refcat==IRAS || refcat==HIP) return (6); /* Bright Star Catalog (TDC binary format) */ else if (refcat==BSC) return (4); /* SKY2000 Catalog (TDC binary format) */ else if (refcat==SKY2K) return (7); /* Tycho2 catalog */ else if (refcat == TYCHO2) return (11); /* Tycho, Tycho2, or ACT catalogs */ else if (refcat == TYCHO || refcat == TYCHO2E || refcat == ACT) return (10); /* Starbase tab-separated, TDC binary, or TDC ASCII catalogs */ else { if (nndec > 0) ndp = 1; else { if ((nndec = NumNdec (maxnum)) > 0) ndp = 1; else ndp = 0; } if (maxnum < 10.0) return (1 + nndec + ndp); else if (maxnum < 100.0) return (2 + nndec + ndp); else if (maxnum < 1000.0) return (3 + nndec + ndp); else if (maxnum < 10000.0) return (4 + nndec + ndp); else if (maxnum < 100000.0) return (5 + nndec + ndp); else if (maxnum < 1000000.0) return (6 + nndec + ndp); else if (maxnum < 10000000.0) return (7 + nndec + ndp); else if (maxnum < 100000000.0) return (8 + nndec + ndp); else if (maxnum < 1000000000.0) return (9 + nndec + ndp); else if (maxnum < 10000000000.0) return (10 + nndec + ndp); else if (maxnum < 100000000000.0) return (11 + nndec + ndp); else if (maxnum < 1000000000000.0) return (12 + nndec + ndp); else if (maxnum < 10000000000000.0) return (13 + nndec + ndp); else return (14 + nndec + ndp); } } /* Return number of decimal places in catalogued numbers, if known */ int CatNdec (refcat) int refcat; /* Catalog code */ { /* USNO A1.0, A2.0, SA1.0, or SA2.0 Catalogs */ if (refcat == USAC || refcat == USA1 || refcat == USA2 || refcat == UAC || refcat == UA1 || refcat == UA2) return (8); /* USNO B1.0 and USNO YB6 */ else if (refcat == UB1 || refcat == YB6) return (7); /* GSC II */ else if (refcat == GSC2) return (0); /* SDSS */ else if (refcat == SDSS) return (0); /* SkyBot */ else if (refcat == SKYBOT) return (0); /* 2MASS Point Source Catalog */ else if (refcat == TMPSC || refcat == TMPSCE) return (6); /* 2MASS Extended Source Catalog */ else if (refcat == TMXSC) return (6); /* 2MASS Point Source Catalog */ else if (refcat == TMIDR2) return (7); /* USNO Plate Catalogs */ else if (refcat == USNO) return (0); /* UCAC1 Catalog */ else if (refcat == UCAC1) return (6); /* UCAC2 Catalog */ else if (refcat == UCAC2) return (6); /* UCAC3 Catalog */ else if (refcat == UCAC3) return (6); /* UCAC4 Catalog */ else if (refcat == UCAC4) return (6); /* USNO UJ 1.0 Catalog */ else if (refcat == UJC) return (7); /* HST Guide Star Catalog */ else if (refcat == GSC || refcat == GSCACT) return (4); /* SAO, PPM, Hipparcos, or IRAS Point Source Catalogs (TDC binary format) */ else if (refcat==SAO || refcat==PPM || refcat==IRAS || refcat==BSC || refcat==HIP || refcat == SKY2K) return (0); /* Tycho, Tycho2, or ACT catalogs */ else if (refcat == TYCHO || refcat == TYCHO2 || refcat == TYCHO2E || refcat == ACT) return (5); /* Starbase tab-separated, TDC binary, or TDC ASCII catalogs */ else return (-1); } /* Return name of specified magnitude */ void CatMagName (imag, refcat, magname) int imag; /* Sequence number of magnitude */ int refcat; /* Catalog code */ char *magname; /* Name of magnitude, returned */ { if (refcat == UAC || refcat == UA1 || refcat == UA2 || refcat == USAC || refcat == USA1 || refcat == USA2) { if (imag == 2) strcpy (magname, "MagR"); else strcpy (magname, "MagB"); } else if (refcat == UB1) { if (imag == 5) strcpy (magname, "MagN"); else if (imag == 4) strcpy (magname, "MagR2"); else if (imag == 3) strcpy (magname, "MagB2"); else if (imag == 2) strcpy (magname, "MagR1"); else strcpy (magname, "MagB1"); } else if (refcat == YB6) { if (imag == 5) strcpy (magname, "MagK"); else if (imag == 4) strcpy (magname, "MagH"); else if (imag == 3) strcpy (magname, "MagJ"); else if (imag == 2) strcpy (magname, "MagR"); else strcpy (magname, "MagB"); } else if (refcat == SDSS) { if (imag == 5) strcpy (magname, "Magz"); else if (imag == 4) strcpy (magname, "Magi"); else if (imag == 3) strcpy (magname, "Magr"); else if (imag == 2) strcpy (magname, "Magg"); else strcpy (magname, "Magu"); } else if (refcat==TYCHO || refcat==TYCHO2 || refcat==HIP || refcat==ACT) { if (imag == 2) strcpy (magname, "MagV"); else strcpy (magname, "MagB"); } else if (refcat==TYCHO2E) { if (imag == 1) strcpy (magname, "MagB"); else if (imag == 3) strcpy (magname, "MagBe"); else if (imag == 4) strcpy (magname, "MagVe"); else strcpy (magname, "MagV"); } else if (refcat==GSC2) { if (imag == 2) strcpy (magname, "MagJ"); else if (imag == 3) strcpy (magname, "MagN"); else if (imag == 4) strcpy (magname, "MagU"); else if (imag == 5) strcpy (magname, "MagB"); else if (imag == 6) strcpy (magname, "MagV"); else if (imag == 7) strcpy (magname, "MagR"); else if (imag == 8) strcpy (magname, "MagI"); else strcpy (magname, "MagF"); } else if (refcat==SKY2K) { if (imag == 1) strcpy (magname, "MagB"); else if (imag == 2) strcpy (magname, "MagV"); else if (imag == 3) strcpy (magname, "MagP"); else strcpy (magname, "MagPv"); } else if (refcat==TMPSC || refcat == TMXSC) { if (imag == 1) strcpy (magname, "MagJ"); else if (imag == 2) strcpy (magname, "MagH"); else strcpy (magname, "MagK"); } else if (refcat==TMPSCE) { if (imag == 1) strcpy (magname, "MagJ"); else if (imag == 2) strcpy (magname, "MagH"); else if (imag == 3) strcpy (magname, "MagK"); else if (imag == 4) strcpy (magname, "MagJe"); else if (imag == 5) strcpy (magname, "MagHe"); else if (imag == 6) strcpy (magname, "MagKe"); } else if (refcat==UCAC2) { if (imag == 1) strcpy (magname, "MagJ"); else if (imag == 2) strcpy (magname, "MagH"); else if (imag == 3) strcpy (magname, "MagK"); else if (imag == 4) strcpy (magname, "MagC"); } else if (refcat==UCAC3) { if (imag == 1) strcpy (magname, "MagB"); else if (imag == 2) strcpy (magname, "MagR"); else if (imag == 3) strcpy (magname, "MagI"); else if (imag == 4) strcpy (magname, "MagJ"); else if (imag == 5) strcpy (magname, "MagH"); else if (imag == 6) strcpy (magname, "MagK"); else if (imag == 7) strcpy (magname, "MagM"); else if (imag == 8) strcpy (magname, "MagA"); } else if (refcat==UCAC4) { if (imag == 1) strcpy (magname, "MagB"); else if (imag == 2) strcpy (magname, "MagR"); else if (imag == 3) strcpy (magname, "MagI"); else if (imag == 4) strcpy (magname, "MagJ"); else if (imag == 5) strcpy (magname, "MagH"); else if (imag == 6) strcpy (magname, "MagK"); else if (imag == 7) strcpy (magname, "MagM"); else if (imag == 8) strcpy (magname, "MagA"); } else if (refcat==SKYBOT) strcpy (magname, "MagV"); else strcpy (magname, "Mag"); return; } /* Return number of magnitude specified by int of letter */ int CatMagNum (imag, refcat) int imag; /* int of magnitude letter */ int refcat; /* Catalog code */ { char cmag = (char) imag; /* Letter name of magnitude */ /* Make letter upper case */ if (cmag > 96) cmag = cmag - 32; if (refcat == UAC || refcat == UA1 || refcat == UA2 || refcat == USAC || refcat == USA1 || refcat == USA2) { if (cmag == 'R') return (2); else return (1); /* B */ } if (refcat == UB1) { if (cmag == 'N') return (5); else if (cmag == 'R') return (4); else return (3); /* B */ } else if (refcat == YB6) { if (cmag == 'K') return (5); else if (cmag == 'H') return (4); else if (cmag == 'J') return (3); else if (cmag == 'R') return (2); else if (cmag == 'B') return (1); else return (3); /* J */ } else if (refcat == SKYBOT) { return (1); } else if (refcat == SDSS) { if (cmag == 'Z') return (5); else if (cmag == 'I') return (4); else if (cmag == 'R') return (3); else if (cmag == 'G') return (2); else if (cmag == 'B') return (1); else return (2); /* G */ } else if (refcat==TYCHO || refcat==TYCHO2 || refcat==HIP || refcat==ACT) { if (cmag == 'B') return (1); else return (2); /* V */ } else if (refcat==GSC2) { if (cmag == 'J') return (2); else if (cmag == 'N') return (3); else if (cmag == 'U') return (4); else if (cmag == 'B') return (5); else if (cmag == 'V') return (6); else if (cmag == 'R') return (7); else if (cmag == 'I') return (8); else return (1); /* F */ } else if (refcat==TMPSC || refcat == TMXSC) { if (cmag == 'J') return (1); else if (cmag == 'H') return (2); else return (3); /* K */ } else if (refcat==UCAC2) { if (cmag == 'J') return (1); else if (cmag == 'H') return (2); else if (cmag == 'K') return (3); else if (cmag == 'C') return (4); else return (3); /* K */ } else if (refcat==UCAC3) { if (cmag == 'R') return (2); else if (cmag == 'I') return (3); else if (cmag == 'J') return (4); else if (cmag == 'H') return (5); else if (cmag == 'K') return (6); else if (cmag == 'M') return (7); else if (cmag == 'A') return (8); else return (1); /* B */ } else if (refcat==UCAC4) { if (cmag == 'R') return (2); else if (cmag == 'I') return (3); else if (cmag == 'J') return (4); else if (cmag == 'H') return (5); else if (cmag == 'K') return (6); else if (cmag == 'M') return (7); else if (cmag == 'A') return (8); else return (1); /* B */ } else return (1); } /* Return number of decimal places in numeric string (-1 if not number) */ int StrNdec (string) char *string; /* Numeric string */ { char *cdot; int lstr; if (notnum (string)) return (-1); else { lstr = strlen (string); if ((cdot = strchr (string, '.')) == NULL) return (0); else return (lstr - (cdot - string)); } } /* Return number of decimal places in a number */ int NumNdec (number) double number; /* Floating point number */ { char nstring[16]; char format[16]; int fracpart; int ndec, ndmax; double shift; if (number < 10.0) { ndmax = 12; shift = 1000000000000.0; } else if (number < 100.0) { ndmax = 11; shift = 100000000000.0; } else if (number < 1000.0) { ndmax = 10; shift = 10000000000.0; } else if (number < 10000.0) { ndmax = 9; shift = 1000000000.0; } else if (number < 100000.0) { ndmax = 8; shift = 100000000.0; } else if (number < 1000000.0) { ndmax = 7; shift = 10000000.0; } else if (number < 10000000.0) { ndmax = 6; shift = 1000000.0; } else if (number < 100000000.0) { ndmax = 5; shift = 100000.0; } else if (number < 1000000000.0) { ndmax = 4; shift = 10000.0; } else if (number < 10000000000.0) { ndmax = 3; shift = 1000.0; } else if (number < 100000000000.0) { ndmax = 2; shift = 100.0; } else if (number < 1000000000000.0) { ndmax = 1; shift = 10.0; } else return (0); fracpart = (int) (((number - floor (number)) * shift) + 0.5); sprintf (format, "%%0%dd", ndmax); sprintf (nstring, format, fracpart); for (ndec = ndmax; ndec > 0; ndec--) { if (nstring[ndec-1] != '0') break; } return (ndec); } static int dateform = 0 ; void setdateform (dateform0) int dateform0; { dateform = dateform0; return; } /* DateString-- Return string with epoch of position in desired format */ char * DateString (epoch, tabout) double epoch; int tabout; { double year; char *temp, *temp1; temp = calloc (16, 1); if (dateform < 1) dateform = EP_MJD; if (dateform == EP_EP) { if (tabout) sprintf (temp, " %9.4f", epoch); else sprintf (temp, " %9.4f", epoch); } else if (dateform == EP_JD) { if (epoch == 0.0) year = 0.0; else year = ep2jd (epoch); if (tabout) sprintf (temp, " %13.5f", year); else sprintf (temp, " %13.5f", year); } else if (dateform == EP_MJD) { if (epoch == 0.0) year = 0.0; else year = ep2mjd (epoch); if (tabout) sprintf (temp, " %11.5f", year); else sprintf (temp, " %11.5f", year); } else { if (epoch == 0.0) { if (tabout) sprintf (temp," 0000-00-00"); else sprintf (temp," 0000-00-00"); if (dateform == EP_ISO) sprintf (temp,"T00:00"); } else { temp1 = ep2fd (epoch); if (dateform == EP_FD && strlen (temp1) > 10) temp1[10] = (char) 0; if (dateform == EP_ISO && strlen (temp1) > 16) temp1[16] = (char) 0; if (tabout) sprintf (temp, " %s", temp1); else sprintf (temp, " %s", temp1); free (temp1); } } return (temp); } /* SEARCHLIM-- Set RA and Dec limits for search given center and dimensions */ void SearchLim (cra, cdec, dra, ddec, syscoor, ra1, ra2, dec1, dec2, verbose) double cra, cdec; /* Center of search area in degrees */ double dra, ddec; /* Horizontal and vertical half-widths in degrees */ int syscoor; /* Coordinate system */ double *ra1, *ra2; /* Right ascension limits in degrees */ double *dec1, *dec2; /* Declination limits in degrees */ int verbose; /* 1 to print limits, else 0 */ { double dec; /* Set right ascension limits for search */ *ra1 = cra - dra; *ra2 = cra + dra; /* Keep right ascension between 0 and 360 degrees */ if (syscoor != WCS_XY) { if (*ra1 < 0.0) *ra1 = *ra1 + 360.0; if (*ra2 > 360.0) *ra2 = *ra2 - 360.0; } /* Set declination limits for search */ *dec1 = cdec - ddec; *dec2 = cdec + ddec; /* dec1 is always the smallest declination */ if (*dec1 > *dec2) { dec = *dec1; *dec1 = *dec2; *dec2 = dec; } /* Search zones which include the poles cover 360 degrees in RA */ if (syscoor != WCS_XY) { if (*dec1 < -90.0) { *dec1 = -90.0; *ra1 = 0.0; *ra2 = 359.99999; } if (*dec2 > 90.0) { *dec2 = 90.0; *ra1 = 0.0; *ra2 = 359.99999; } } if (verbose) { char rstr1[16],rstr2[16],dstr1[16],dstr2[16]; if (syscoor == WCS_XY) { num2str (rstr1, *ra1, 10, 5); num2str (dstr1, *dec1, 10, 5); num2str (rstr2, *ra2, 10, 5); num2str (dstr2, *dec2, 10, 5); } else if (degout) { deg2str (rstr1, 16, *ra1, 6); deg2str (dstr1, 16, *dec1, 6); deg2str (rstr2, 16, *ra2, 6); deg2str (dstr2, 16, *dec2, 6); } else { ra2str (rstr1, 16, *ra1, 3); dec2str (dstr1, 16, *dec1, 2); ra2str (rstr2, 16, *ra2, 3); dec2str (dstr2, 16, *dec2, 2); } fprintf (stderr,"SearchLim: RA: %s - %s Dec: %s - %s\n", rstr1,rstr2,dstr1,dstr2); } return; } /* REFLIM-- Set limits in reference catalog coordinates given search coords */ void RefLim (cra, cdec, dra, ddec, sysc, sysr, eqc, eqr, epc, epr, secmarg, ramin, ramax, decmin, decmax, wrap, verbose) double cra, cdec; /* Center of search area in degrees */ double dra, ddec; /* Horizontal and vertical half-widths of area */ int sysc, sysr; /* System of search, catalog coordinates */ double eqc, eqr; /* Equinox of search, catalog coordinates in years */ double epc, epr; /* Epoch of search, catalog coordinates in years */ double secmarg; /* Margin in arcsec/century to catch moving stars */ double *ramin,*ramax; /* Right ascension search limits in degrees (returned)*/ double *decmin,*decmax; /* Declination search limits in degrees (returned) */ int *wrap; /* 1 if search passes through 0:00:00 RA */ int verbose; /* 1 to print limits, else 0 */ { double ra, ra1, ra2, ra3, ra4, dec1, dec2, dec3, dec4; double dec, acdec, adec, adec1, adec2, dmarg, dist, dra1; int nrot; /* Deal with all or nearly all of the sky */ if (ddec > 80.0 && dra > 150.0) { *ramin = 0.0; *ramax = 360.0; *decmin = -90.0; *decmax = 90.0; *wrap = 0; if (verbose) fprintf (stderr,"RefLim: RA: 0.0 - 360.0 Dec: -90.0 - 90.0\n"); return; } /* Set declination limits for search */ dec1 = cdec - ddec; dec2 = cdec + ddec; /* dec1 is always the smallest declination */ if (dec1 > dec2) { dec = dec1; dec1 = dec2; dec2 = dec; } dec3 = dec2; dec4 = dec1; /* Deal with south pole */ if (dec1 < -90.0) { dec1 = -90.0 - (dec1 + 90.0); if (dec1 > dec2) dec2 = dec1; dec1 = -90.0; dra1 = 180.0; } /* Deal with north pole */ if (dec2 > 90.0) { dec2 = 90.0 - (dec2 - 90.0); if (dec2 < dec1) dec1 = dec2; dec2 = 90.0; dra1 = 180.0; } /* Adjust width in right ascension to that at max absolute declination */ adec1 = fabs (dec1); adec2 = fabs (dec2); if (adec1 > adec2) adec = adec1; else adec = adec2; acdec = fabs (cdec); if (adec < 90.0 && adec > acdec) dra1 = dra * (cos (degrad(acdec)) / cos (degrad(adec))); else if (adec == 90.0) dra1 = 180.0; /* Set right ascension limits for search */ ra1 = cra - dra1; ra2 = cra + dra1; /* Keep right ascension limits between 0 and 360 degrees */ if (ra1 < 0.0) { nrot = 1 - (int) (ra1 / 360.0); ra1 = ra1 + (360.0 * (double) nrot); } if (ra1 > 360.0) { nrot = (int) (ra1 / 360.0); ra1 = ra1 - (360.0 * (double) nrot); } if (ra2 < 0.0) { nrot = 1 - (int) (ra2 / 360.0); ra2 = ra2 + (360.0 * (double) nrot); } if (ra2 > 360.0) { nrot = (int) (ra2 / 360.0); ra2 = ra2 - (360.0 * (double) nrot); } if (ra1 > ra2) *wrap = 1; else *wrap = 0; ra3 = ra1; ra4 = ra2; /* Convert search corners to catalog coordinate system and equinox */ ra = cra; dec = cdec; wcscon (sysc, sysr, eqc, eqr, &ra, &dec, epc); wcscon (sysc, sysr, eqc, eqr, &ra1, &dec1, epc); wcscon (sysc, sysr, eqc, eqr, &ra2, &dec2, epc); wcscon (sysc, sysr, eqc, eqr, &ra3, &dec3, epc); wcscon (sysc, sysr, eqc, eqr, &ra4, &dec4, epc); /* Find minimum and maximum right ascensions to search */ *ramin = ra1; if (ra3 < *ramin) *ramin = ra3; *ramax = ra2; if (ra4 > *ramax) *ramax = ra4; /* Add margins to RA limits to get most stars which move */ if (secmarg > 0.0 && epc != 0.0) { dmarg = (secmarg / 3600.0) * fabs (epc - epr); *ramin = *ramin - (dmarg * cos (degrad (cdec))); *ramax = *ramax + (dmarg * cos (degrad (cdec))); } else dmarg = 0.0; if (*wrap) { ra = *ramax; *ramax = *ramin; *ramin = ra; } /* Find minimum and maximum declinatons to search */ *decmin = dec1; if (dec2 < *decmin) *decmin = dec2; if (dec3 < *decmin) *decmin = dec3; if (dec4 < *decmin) *decmin = dec4; *decmax = dec1; if (dec2 > *decmax) *decmax = dec2; if (dec3 > *decmax) *decmax = dec3; if (dec4 > *decmax) *decmax = dec4; /* Add margins to Dec limits to get most stars which move */ if (dmarg > 0.0) { *decmin = *decmin - dmarg; *decmax = *decmax + dmarg; } /* Check for pole */ dist = wcsdist (ra, dec, *ramax, *decmax); if (dec + dist > 90.0) { *ramin = 0.0; *ramax = 359.99999; *decmax = 90.0; *wrap = 0; } else if (dec - dist < -90.0) { *ramin = 0.0; *ramax = 359.99999; *decmin = -90.0; *wrap = 0; } /* Search zones which include the poles cover 360 degrees in RA */ else if (*decmin < -90.0) { *decmin = -90.0; *ramin = 0.0; *ramax = 359.99999; *wrap = 0; } else if (*decmax > 90.0) { *decmax = 90.0; *ramin = 0.0; *ramax = 359.99999; *wrap = 0; } if (verbose) { char rstr1[16],rstr2[16],dstr1[16],dstr2[16]; if (degout) { deg2str (rstr1, 16, *ramin, 6); deg2str (dstr1, 16, *decmin, 6); deg2str (rstr2, 16, *ramax, 6); deg2str (dstr2, 16, *decmax, 6); } else { ra2str (rstr1, 16, *ramin, 3); dec2str (dstr1, 16, *decmin, 2); ra2str (rstr2, 16, *ramax, 3); dec2str (dstr2, 16, *decmax, 2); } fprintf (stderr,"RefLim: RA: %s - %s Dec: %s - %s", rstr1,rstr2,dstr1,dstr2); if (*wrap) fprintf (stderr," wrap\n"); else fprintf (stderr,"\n"); } return; } /* RANGEINIT -- Initialize range structure from string */ struct Range * RangeInit (string, ndef) char *string; /* String containing numbers separated by , and - */ int ndef; /* Maximum allowable range value */ { struct Range *range; int ip, irange; char *slast; double first, last, step; if (!isrange (string) && !isnum (string)) return (NULL); ip = 0; range = (struct Range *)calloc (1, sizeof (struct Range)); range->irange = -1; range->nvalues = 0; range->nranges = 0; range->valmax = -1000000000000.0; range->valmin = 1000000000000.0; for (irange = 0; irange < MAXRANGE; irange++) { /* Default to entire list */ first = 1.0; last = ndef; step = 1.0; /* Skip delimiters to start of range */ while (string[ip] == ' ' || string[ip] == ' ' || string[ip] == ',') ip++; /* Get first limit * Must be a number, '-', 'x', or EOS. If not return ERR */ if (string[ip] == (char)0) { /* end of list */ if (irange == 0) { /* Null string defaults */ range->ranges[0] = first; if (first < 1) range->ranges[1] = first; else range->ranges[1] = last; range->ranges[2] = step; range->nvalues = range->nvalues + 1 + ((range->ranges[1]-range->ranges[0])/step); range->nranges++; return (range); } else return (range); } else if (string[ip] > (char)47 && string[ip] < 58) { first = strtod (string+ip, &slast); ip = slast - string; } else if (strchr ("-:x", string[ip]) == NULL) { free (range); return (NULL); } /* Skip delimiters */ while (string[ip] == ' ' || string[ip] == ' ' || string[ip] == ',') ip++; /* Get last limit * Must be '-', or 'x' otherwise last = first */ if (string[ip] == '-' || string[ip] == ':') { ip++; while (string[ip] == ' ' || string[ip] == ' ' || string[ip] == ',') ip++; if (string[ip] == (char)0) last = first + ndef; else if (string[ip] > (char)47 && string[ip] < 58) { last = strtod (string+ip, &slast); ip = slast - string; } else if (string[ip] != 'x') last = first + ndef; } else if (string[ip] != 'x') last = first; /* Skip delimiters */ while (string[ip] == ' ' || string[ip] == ' ' || string[ip] == ',') ip++; /* Get step * Must be 'x' or assume default step. */ if (string[ip] == 'x') { ip++; while (string[ip] == ' ' || string[ip] == ' ' || string[ip] == ',') ip++; if (string[ip] == (char)0) step = 1.0; else if (string[ip] > (char)47 && string[ip] < 58) { step = strtod (string+ip, &slast); ip = slast - string; } else if (string[ip] != '-' && string[ip] != ':') step = 1.0; } /* Output the range triple */ range->ranges[irange*3] = first; range->ranges[irange*3 + 1] = last; range->ranges[irange*3 + 2] = step; range->nvalues = range->nvalues + ((last-first+(0.1*step)) / step + 1); range->nranges++; if (step > 0.0) { if (first < range->valmin) range->valmin = first; if (last > range->valmax) range->valmax = last; } else { if (first > range->valmax) range->valmax = first; if (last < range->valmin) range->valmin = last; } } return (range); } /* ISRANGE -- Return 1 if string is a range, else 0 */ int isrange (string) char *string; /* String which might be a range of numbers */ { int i, lstr; /* If string is NULL or empty, return 0 */ if (string == NULL || strlen (string) == 0) return (0); /* If range separators present, check to make sure string is range */ else if (strchr (string+1, '-') || strchr (string+1, ',')) { lstr = strlen (string); for (i = 0; i < lstr; i++) { if (strchr ("0123456789-,.x", (int)string[i]) == NULL) return (0); } return (1); } else return (0); } /* RSTART -- Restart at beginning of range */ void rstart (range) struct Range *range; /* Range structure */ { range->irange = -1; return; } /* RGETN -- Return number of values from range structure */ int rgetn (range) struct Range *range; /* Range structure */ { return (range->nvalues); } /* RGETR8 -- Return next number from range structure as 8-byte f.p. number */ double rgetr8 (range) struct Range *range; /* Range structure */ { int i; if (range == NULL) return (0.0); else if (range->irange < 0) { range->irange = 0; range->first = range->ranges[0]; range->last = range->ranges[1]; range->step = range->ranges[2]; range->value = range->first; } else { range->value = range->value + range->step; if (range->value > (range->last + (range->step * 0.5))) { range->irange++; if (range->irange < range->nranges) { i = range->irange * 3; range->first = range->ranges[i]; range->last = range->ranges[i+1]; range->step = range->ranges[i+2]; range->value = range->first; } else range->value = 0.0; } } return (range->value); } /* RGETI4 -- Return next number from range structure as 4-byte integer */ int rgeti4 (range) struct Range *range; /* Range structure */ { double value; value = rgetr8 (range); return ((int) (value + 0.000000001)); } /* AGETI4 -- Get integer value from ASCII string where keyword=value anywhere */ int ageti4 (string, keyword, ival) char *string; /* character string containing = */ char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" or ",n" is present, the n'th token in the value is returned. */ int *ival; /* Integer value, returned */ { char value[32]; if (agets (string, keyword, 31, 0, value)) { *ival = atoi (value); return (1); } else return (0); } /* AGETR8 -- Get double value from ASCII string where keyword=value anywhere */ int agetr8 (string, keyword, dval) char *string; /* character string containing = */ char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" or ",n" is present, the n'th token in the value is returned. */ double *dval; /* Double value, returned */ { char value[32]; if (agets (string, keyword, 31, 0, value)) { *dval = atof (value); return (1); } else return (0); } /* AGETS -- Get keyword value from ASCII string with keyword=value anywhere */ int agets (string, keyword0, lval, fillblank, value) char *string; /* character string containing = info */ char *keyword0; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" or ",n" is present, the n'th token in the value is returned. */ int lval; /* Size of value in characters If negative, value ends at end of line */ int fillblank; /* If 0, leave blanks, strip trailing blanks if non-zero, replace blanks with underscores */ char *value; /* String (returned) */ { char keyword[81]; char *pval, *str, *pkey, *pv; char cquot, squot[2], dquot[2], lbracket[2], rbracket[2], comma[2]; char *lastval, *rval, *brack1, *brack2, *lastring, *iquot, *ival; int ipar, i, lkey, fkey; squot[0] = (char) 39; squot[1] = (char) 0; dquot[0] = (char) 34; dquot[1] = (char) 0; lbracket[0] = (char) 91; lbracket[1] = (char) 0; comma[0] = (char) 44; comma[1] = (char) 0; cquot = ' '; rbracket[0] = (char) 93; rbracket[1] = (char) 0; lastring = string + strlen (string); /* Find length of variable name */ strncpy (keyword,keyword0, sizeof(keyword)-1); brack1 = strsrch (keyword,lbracket); brack2 = NULL; if (brack1 == NULL) brack1 = strsrch (keyword,comma); if (brack1 != NULL) { *brack1 = '\0'; brack1++; } lkey = strlen (keyword); /* First check for the existence of the keyword in the string */ pval = NULL; str = string; while (pval == NULL) { pkey = strcsrch (str, keyword); /* If keyword has not been found, return 0 */ if (pkey == NULL) { return (0); } /* If it has been found, check for = or : and preceding characters */ /* Must be at start of file or after control character or space */ if (pkey != string && *(pkey-1) > 32) { str = pkey; pval = NULL; } /* Must have "=" or ":" as next nonspace and nonbracket character */ else { pv = pkey + lkey; while (*pv == ' ' || *pv == ']' || *pv == 'o') { pv++; } if (*pv != '=' && *pv != ':' && *pv != 10 && *pv != 'f') { str = pkey; pval = NULL; } /* If found, bump pointer past keyword, operator, and spaces */ else { pval = pv + 1; while (*pval == '=' || *pval == ' ') { pval++; } break; } } str = str + lkey; if (str > lastring) { break; } } if (pval == NULL) { return (0); } /* Drop leading spaces */ while (*pval == ' ') pval++; /* Pad quoted material with _; drop leading and trailing quotes */ iquot = NULL; if (*pval == squot[0]) { pval++; iquot = strsrch (pval, squot); } if (*pval == dquot[0]) { pval++; iquot = strsrch (pval, dquot); } if (iquot != NULL) { cquot = *iquot; *iquot = (char) 0; if (fillblank) { for (ival = pval; ival < iquot; ival++) { if (*ival == ' ') { *ival = '_'; } } } } /* If keyword has brackets, figure out which token to extract */ if (brack1 != NULL) { brack2 = strsrch (brack1,rbracket); if (brack2 != NULL) { *brack2 = '\0'; } ipar = atoi (brack1); } else { ipar = 1; } /* Move to appropriate token */ for (i = 1; i < ipar; i++) { while (*pval != ' ' && *pval != '/' && pval < lastring) { pval++; } /* Drop leading spaces or / */ while (*pval == ' ' || *pval == '/') { pval++; } } /* Transfer token value to returned string */ rval = value; if (lval < 0) { lastval = value - lval - 1; while (*pval != '\n' && pval < lastring && rval < lastval) { if (lval > 0 && *pval == ' ') { break; } *rval++ = *pval++; } } else { lastval = value + lval - 1; while (*pval != '\n' && *pval != '/' && pval < lastring && rval < lastval) { if (lval > 0 && *pval == ' ') { break; } *rval++ = *pval++; } } if (rval < lastval) { *rval = (char) 0; } else { *lastval = 0; } /* Drop trailing spaces/underscores */ if (!fillblank) { lval = strlen (value); for (ival = value+lval-1; ival > value; ival--) { if (*ival == '_') { *ival = (char) 0; } else if (*ival == ' ') { *ival = (char) 0; } else { break; } } } if (iquot != NULL) { *iquot = cquot; } if (brack1 != NULL) { *brack1 = lbracket[0]; } if (brack2 != NULL) { *brack2 = rbracket[0]; } return (1); } char sptbv[468]={"O5O8B0B0B0B1B1B1B2B2B2B3B3B3B4B5B5B6B6B6B7B7B8B8B8B9B9B9B9A0A0A0A0A0A0A0A0A0A2A2A2A2A2A2A2A2A5A5A5A5A6A7A7A7A7A7A7A7A7A7A7F0F0F0F0F0F0F0F2F2F2F2F2F2F2F5F5F5F5F5F5F5F5F5F8F8F8F8F8F8G0G5G5G2G2G2G3G3G4G4G5G5G5G6G6G6G6G6K6K6K6K6K7K7K7K7K7K7K7K7K7K7K7K7K7K7K8K8K8K8K8K8K8K8K8K8K8K8K8K8K8K8K8K8K8K5K5K5K5K5K6K6K6K6K6K6K6K7K7K7K7K7K7K7K8K8K8K8K9K9K9M0M0M0M0M0M0M1M1M1M1M1M2M2M2M2M3M3M4M4M5M5M5M2M2M2M3M3M4M4M5M5M5M6M6M6M6M6M6M6M6M6M7M7M7M7M7M7M7M7M7M7M7M7M7M7M8M8M8M8M8M8M8"}; void bv2sp (bv, b, v, isp) double *bv; /* B-V Magnitude */ double b; /* B Magnitude used if bv is NULL */ double v; /* V Magnitude used if bv is NULL */ char *isp; /* Spectral type */ { double bmv; /* B - V magnitude */ int im; if (bv == NULL) bmv = b - v; else bmv = *bv; if (bmv < -0.32) { isp[0] = '_'; isp[1] = '_'; } else if (bmv > 2.00) { isp[0] = '_'; isp[1] = '_'; } else if (bmv < 0) { im = 2 * (32 + (int)(bmv * 100.0 - 0.5)); isp[0] = sptbv[im]; isp[1] = sptbv[im+1]; } else { im = 2 * (32 + (int)(bmv * 100.0 + 0.5)); isp[0] = sptbv[im]; isp[1] = sptbv[im+1]; } return; } char sptbr1[96]={"O5O8O9O9B0B0B0B0B0B1B1B1B2B2B2B2B2B3B3B3B3B3B3B5B5B5B5B6B6B6B7B7B7B7B8B8B8B8B8B9B9B9B9B9A0A0A0"}; char sptbr2[904]={"A0A0A0A0A0A0A0A0A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A5A5A5A5A5A5A5A5A5A5A5A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F2F2F2F2F2F2F2F2F2F2F2F5F5F5F5F5F5F5F5F5F5F5F5F5F5F8F8F8F8F8F8F8F8F8F8F8F8F8F8G0G0G0G0G0G0G0G0G2G2G2G2G2G5G5G5G5G5G5G5G5G8G8G8G8G8G8G8G8G8G8G8G8G8G8K0K0K0K0K0K0K0K0K0K0K0K0K0K0K0K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K2K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K5K7K7K7K7K7K7K7K7K7K7K7K7K7K7K7K7K7K7K7K7K7K7K7K7K7M0M0M0M0M0M0M0M0M0M0M0M0M0M0M0M0M0M0M0M0M0M0M0M0M1M1M1M1M1M1M1M1M1M1M1M1M1M1M1M2M2M2M2M2M2M2M2M2M2M2M2M2M2M2M3M3M3M3M3M3M3M3M3M3M3M4M4M4M4M4M4M4M4M4M4M4M4M4M4M5M5M5M5M5M5M5M5M5M5M5M5M5M5M5M5M5M5M5M5M6M6M6M6M6M6M6M6M6M6M6M6M6M6M6M6M6M6M6M6M6M6M6M6M6M6M6M6M6M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M7M8M8M8M8M8M8M8M8M8M8M8M8M8M8M8M8M8M8M8M8M8M8M8M8"}; void br2sp (br, b, r, isp) double *br; /* B-R Magnitude */ double b; /* B Magnitude used if br is NULL */ double r; /* R Magnitude used if br is NULL */ char *isp; /* Spectral type */ { double bmr; /* B - R magnitude */ int im; if (br == NULL) bmr = b - r; else bmr = *br; if (b == 0.0 && r > 2.0) { isp[0] = '_'; isp[1] = '_'; } else if (bmr < -0.47) { isp[0] = '_'; isp[1] = '_'; } else if (bmr > 4.50) { isp[0] = '_'; isp[1] = '_'; } else if (bmr < 0) { im = 2 * (47 + (int)(bmr * 100.0 - 0.5)); isp[0] = sptbr1[im]; isp[1] = sptbr1[im+1]; } else { im = 2 * ((int)(bmr * 100.0 + 0.49)); isp[0] = sptbr2[im]; isp[1] = sptbr2[im+1]; } return; } void CatTabHead (refcat,sysout,nnfld,mprop,nmag,ranges,keyword,gcset,tabout, classd,printxy,gobj1,fd) int refcat; /* Catalog being searched */ int sysout; /* Output coordinate system */ int nnfld; /* Number of characters in ID column */ int mprop; /* 1 if proper motion in catalog */ int nmag; /* Number of magnitudes */ char *ranges; /* Catalog numbers to print */ char *keyword; /* Column to add to tab table output */ int gcset; /* 1 if there are any values in gc[] */ int tabout; /* 1 if output is tab-delimited */ int classd; /* GSC object class to accept (-1=all) */ int printxy; /* 1 if X and Y included in output */ char **gobj1; /* Pointer to array of object names; NULL if none */ FILE *fd; /* Output file descriptor; none if NULL */ { int typecol; char headline[160]; /* Set flag for plate, class, type, or 3rd magnitude column */ if (refcat == BINCAT || refcat == SAO || refcat == PPM || refcat == ACT || refcat == TYCHO2 || refcat == BSC) typecol = 1; else if ((refcat == GSC || refcat == GSCACT) && classd < -1) typecol = 3; else if (refcat == TMPSC) typecol = 4; else if (refcat == GSC || refcat == GSCACT || refcat == UJC || refcat == IRAS || refcat == USAC || refcat == USA1 || refcat == USA2 || refcat == UAC || refcat == UA1 || refcat == UA2 || refcat == BSC || (refcat == TABCAT&&gcset)) typecol = 2; else typecol = 0; /* Print column headings */ if (refcat == ACT) strcpy (headline, "act_id "); else if (refcat == BSC) strcpy (headline, "bsc_id "); else if (refcat == GSC || refcat == GSCACT) strcpy (headline, "gsc_id "); else if (refcat == USAC) strcpy (headline,"usac_id "); else if (refcat == USA1) strcpy (headline,"usa1_id "); else if (refcat == USA2) strcpy (headline,"usa2_id "); else if (refcat == UAC) strcpy (headline,"usnoa_id "); else if (refcat == UA1) strcpy (headline,"usnoa1_id "); else if (refcat == UA2) strcpy (headline,"usnoa2_id "); else if (refcat == UJC) strcpy (headline,"usnoj_id "); else if (refcat == TMPSC) strcpy (headline,"2mass_id "); else if (refcat == TMXSC) strcpy (headline,"2mx_id "); else if (refcat == SAO) strcpy (headline,"sao_id "); else if (refcat == PPM) strcpy (headline,"ppm_id "); else if (refcat == IRAS) strcpy (headline,"iras_id "); else if (refcat == TYCHO) strcpy (headline,"tycho_id "); else if (refcat == TYCHO2) strcpy (headline,"tycho2_id "); else if (refcat == HIP) strcpy (headline,"hip_id "); else strcpy (headline,"id "); headline[nnfld] = (char) 0; if (sysout == WCS_GALACTIC) strcat (headline," long_gal lat_gal "); else if (sysout == WCS_ECLIPTIC) strcat (headline," long_ecl lat_ecl "); else if (sysout == WCS_B1950) strcat (headline," ra1950 dec1950 "); else strcat (headline," ra dec "); if (refcat == USAC || refcat == USA1 || refcat == USA2 || refcat == UAC || refcat == UA1 || refcat == UA2) strcat (headline," magb magr plate"); if (refcat == TMPSC) strcat (headline," magj magh magk"); else if (refcat==TYCHO || refcat==TYCHO2 || refcat==HIP || refcat==ACT) strcat (headline," magb magv"); else if (refcat == GSC || refcat == GSCACT) strcat (headline," mag class band N"); else if (refcat == UJC) strcat (headline," mag plate"); else strcat (headline," mag"); if (typecol == 1) strcat (headline," type"); if (mprop) strcat (headline," Ura Udec "); if (ranges == NULL) strcat (headline," arcsec"); if (refcat == TABCAT && keyword != NULL) { strcat (headline," "); strcat (headline, keyword); } if (gobj1 != NULL) strcat (headline," object"); if (printxy) strcat (headline, " x y "); if (tabout) { printf ("%s\n", headline); if (fd != NULL) fprintf (fd, "%s\n", headline); } strcpy (headline, "---------------------"); headline[nnfld] = (char) 0; strcat (headline," ------------ ------------"); if (nmag == 2) strcat (headline," ----- -----"); else strcat (headline," -----"); if (refcat == GSC || refcat == GSCACT) strcat (headline," ----- ---- -"); else if (typecol == 1) strcat (headline," ----"); else if (typecol == 2) strcat (headline," -----"); else if (typecol == 4) strcat (headline," -----"); if (mprop) strcat (headline," ------- ------"); if (ranges == NULL) strcat (headline, " ------"); if (refcat == TABCAT && keyword != NULL) strcat (headline," ------"); if (printxy) strcat (headline, " ------- -------"); if (tabout) { printf ("%s\n", headline); if (fd != NULL) fprintf (fd, "%s\n", headline); } } /* TMCID -- Return 1 if string is 2MASS ID, else 0 */ int tmcid (string, ra, dec) char *string; /* Character string to check */ double *ra; /* Right ascension (returned) */ double *dec; /* Declination (returned) */ { char *sdec; char csign; int idec, idm, ids, ira, irm, irs; /* Check first character */ if (string[0] != 'J' && string[0] != 'j') return (0); /* Find declination sign */ sdec = strsrch (string, "-"); if (sdec == NULL) sdec = strsrch (string,"+"); if (sdec == NULL) return (0); /* Parse right ascension */ csign = *sdec; *sdec = (char) 0; ira = atoi (string+1); irs = ira % 10000; ira = ira / 10000; irm = ira % 100; ira = ira / 100; *ra = (double) ira + ((double) irm) / 60.0 + ((double) irs) / 360000.0; *ra = *ra * 15.0; /* Parse declination */ idec = atoi (sdec+1); ids = idec % 1000; idec = idec / 1000; idm = idec % 100; idec = idec / 100; *dec = (double) idec + ((double) idm) / 60.0 + ((double) ids) / 36000.0; return (1); } int vothead (refcat, refcatname, mprop, typecol, ns, cra, cdec, drad) int refcat; /* Catalog code */ char *refcatname; /* Name of catalog */ int mprop; /* Proper motion flag */ int typecol; /* Flag for spectral type */ int ns; /* Number of sources found in catalog */ double cra; /* Search center right ascension */ double cdec; /* Search center declination */ double drad; /* Radius to search in degrees */ { char *catalog = CatName (refcat, refcatname); int nf = 0; printf ("\n"); printf ("\n"); printf (" SAO/TDC %s Cone Search Response\n", catalog); printf (" \n"); printf (" \n"); printf (" \n"); printf (" \n"); printf (" \n"); printf (" \n"); printf (" \n"); printf (" %d objects within %.6f degrees of ra=%010.6f dec=%09.6f\n", ns, drad, cra, cdec); printf (" \n"); printf ("\n"); if (refcat == USAC || refcat == USA1 || refcat == USA2 || refcat == UAC || refcat == UA1 || refcat == UA2 || refcat == UB1) printf (" USNO Object Identifier\n"); else if (refcat == TYCHO2) printf (" Tycho-2 Object Identifier\n"); else if (refcat == GSC2) printf (" GSC II Object Identifier\n"); else if (refcat == TMPSC) printf (" 2MASS Point Source Identifier\n"); else if (refcat == GSC || refcat == GSCACT) printf (" GSC Object Identifier\n"); else if (refcat == SAO) printf (" SAO Catalog Number\n"); else if (refcat == PPM) printf (" PPM Catalog Number\n"); else printf (" Object Identifier\n"); printf ("\n"); printf ("\n"); printf (" Right Ascension of Object (J2000)\n"); printf ("\n"); printf ("\n"); printf (" Declination of Object (J2000)\n"); printf ("\n"); if (refcat == USAC || refcat == USA1 || refcat == USA2 || refcat == UAC || refcat == UA1 || refcat == UA2) { printf ("\n"); printf (" Photographic B Magnitude of Object\n"); printf ("\n"); printf ("\n"); printf (" Photographic R Magnitude of Object\n"); printf ("\n"); printf ("\n"); printf (" USNO Plate ID of star\n"); printf ("\n"); nf = 7; } else if (refcat == TYCHO2) { printf ("\n"); printf (" Tycho-2 BT magnitude \n"); printf ("\n"); printf ("\n"); printf (" Tycho-2 VT magnitude \n"); nf = 8; } else if (refcat == GSC || refcat == GSCACT) { printf ("\n"); printf (" GSC V magnitude \n"); printf ("\n"); nf = 8; } else if (refcat == GSC2) { } else if (refcat == TMPSC) { printf ("\n"); printf (" Johnson J magnitude \n"); printf ("\n"); printf ("\n"); printf (" Johnson H magnitude \n"); printf ("\n"); printf ("\n"); printf (" Johnson K magnitude \n"); printf ("\n"); nf = 7; } else if (refcat == SAO) { printf ("\n"); printf (" SAO Catalog V magnitude (7)\n"); printf ("\n"); nf = 8; } else if (refcat == PPM) { printf ("\n"); printf (" PPM Catalog V magnitude (7)\n"); printf ("\n"); nf = 8; } if (typecol == 1) { printf ("\n"); printf (" Spectral Type from catalog\n"); printf ("\n"); } printf ("\n"); printf (" Radial distance from requested position\n"); printf ("\n"); printf (" \n"); return (nf); } void vottail () { printf (" \n"); printf ("
\n"); printf ("
\n"); printf ("
\n"); return; } /* Polynomial least squares fitting program, almost identical to the * one in Bevington, "Data Reduction and Error Analysis for the * Physical Sciences," page 141. The argument list was changed and * the weighting removed. * y = a(1) + a(2)*(x-x0) + a(3)*(x-x0)**2 + a(3)*(x-x0)**3 + . . . */ static double determ(); void polfit (x, y, x0, npts, nterms, a, stdev) double *x; /* Array of independent variable points */ double *y; /* Array of dependent variable points */ double x0; /* Offset to independent variable */ int npts; /* Number of data points to fit */ int nterms; /* Number of parameters to fit */ double *a; /* Vector containing current fit values */ double *stdev; /* Standard deviation of fit (returned) */ { double sigma2sum; double xterm,yterm,xi,yi; double *sumx, *sumy; double *array; int i,j,k,l,n,nmax; double delta; /* accumulate weighted sums */ nmax = 2 * nterms - 1; sumx = (double *) calloc (nmax, sizeof(double)); sumy = (double *) calloc (nterms, sizeof(double)); for (n = 0; n < nmax; n++) sumx[n] = 0.0; for (j = 0; j < nterms; j++) sumy[j] = 0.0; for (i = 0; i < npts; i++) { xi = x[i] - x0; yi = y[i]; xterm = 1.0; for (n = 0; n < nmax; n++) { sumx[n] = sumx[n] + xterm; xterm = xterm * xi; } yterm = yi; for (n = 0; n < nterms; n++) { sumy[n] = sumy[n] + yterm; yterm = yterm * xi; } } /* Construct matrices and calculate coeffients */ array = (double *) calloc (nterms*nterms, sizeof(double)); for (j = 0; j < nterms; j++) { for (k = 0; k < nterms; k++) { n = j + k; array[j+k*nterms] = sumx[n]; } } delta = determ (array, nterms); if (delta == 0.0) { *stdev = 0.; for (j = 0; j < nterms; j++) a[j] = 0. ; free (array); free (sumx); free (sumy); return; } for (l = 0; l < nterms; l++) { for (j = 0; j < nterms; j++) { for (k = 0; k < nterms; k++) { n = j + k; array[j+k*nterms] = sumx[n]; } array[j+l*nterms] = sumy[j]; } a[l] = determ (array, nterms) / delta; } /* Calculate sigma */ sigma2sum = 0.0; for (i = 0; i < npts; i++) { yi = polcomp (x[i], x0, nterms, a); sigma2sum = sigma2sum + ((y[i] - yi) * (y[i] - yi)); } *stdev = sqrt (sigma2sum / (double) (npts - 1)); free (array); free (sumx); free (sumy); return; } /*--- Calculate the determinant of a square matrix * This subprogram destroys the input matrix array * From Bevington, page 294. */ static double determ (array, norder) double *array; /* Input matrix array */ int norder; /* Order of determinant (degree of matrix) */ { double save, det; int i,j,k,k1, zero; det = 1.0; for (k = 0; k < norder; k++) { /* Interchange columns if diagonal element is zero */ if (array[k+k*norder] == 0) { zero = 1; for (j = k; j < norder; j++) { if (array[k+j*norder] != 0.0) zero = 0; } if (zero) return (0.0); for (i = k; i < norder; i++) { save = array[i+j*norder]; array[i+j*norder] = array[i+k*norder]; array[i+k*norder] = save ; } det = -det; } /* Subtract row k from lower rows to get diagonal matrix */ det = det * array[k+k*norder]; if (k < norder - 1) { k1 = k + 1; for (i = k1; i < norder; i++) { for (j = k1; j < norder; j++) { array[i+j*norder] = array[i+j*norder] - (array[i+k*norder] * array[k+j*norder] / array[k+k*norder]); } } } } return (det); } /* POLCOMP -- Polynomial evaluation * Y = A(1) + A(2)*X + A(3)*X**2 + A(3)*X**3 + . . . */ double polcomp (xi, x0, norder, a) double xi; /* Independent variable */ double x0; /* Offset to independent variable */ int norder; /* Number of coefficients */ double *a; /* Vector containing coeffiecients */ { double xterm, x, y; int iterm; /* Accumulate polynomial value */ x = xi - x0; y = 0.0; xterm = 1.0; for (iterm = 0; iterm < norder; iterm++) { y = y + a[iterm] * xterm; xterm = xterm * x; } return (y); } /* MOVEB -- Copy nbytes bytes from source+offs to dest+offd (any data type) */ void movebuff (source, dest, nbytes, offs, offd) char *source; /* Pointer to source */ char *dest; /* Pointer to destination */ int nbytes; /* Number of bytes to move */ int offs; /* Offset in bytes in source from which to start copying */ int offd; /* Offset in bytes in destination to which to start copying */ { char *from, *last, *to; from = source + offs; to = dest + offd; last = from + nbytes; while (from < last) *(to++) = *(from++); return; } /* Mar 2 1998 Make number and second magnitude optional * Oct 21 1998 Add RefCat() to set reference catalog code * Oct 26 1998 Include object names in star catalog entry structure * Oct 29 1998 Return coordinate system and title from RefCat * Nov 20 1998 Add USNO A-2.0 catalog and return different code * Dec 9 1998 Add Hipparcos and Tycho catalogs * * Jan 26 1999 Add subroutines to deal with ranges of numbers * Feb 8 1999 Fix bug initializing ACT catalog * Feb 11 1999 Change starcat.insys to starcat.coorsys * May 19 1999 Separate catalog subroutines into separate file * May 19 1999 Add CatNum() to return properly formatted catalog number * May 20 1999 Add date/time conversion subroutines translated from Fortran * May 28 1999 Fix bug in CatNum() which omitted GSC * Jun 3 1999 Add return to CatNum() * Jun 3 1999 Add CatNumLen() * Jun 16 1999 Add SearchLim(), used by all catalog search subroutines * Jun 30 1999 Add isrange() to check to see whether a string is a range * Jul 1 1999 Move date and time utilities to dateutil.c * Jul 15 1999 Add getfilebuff() * Jul 23 1999 Add Bright Star Catalog * Aug 16 1999 Add RefLim() to set catalog search limits * Sep 21 1999 In isrange(), check for x * Oct 5 1999 Add setoken(), nextoken(), and getoken() * Oct 15 1999 Fix format eror in error message * Oct 20 1999 Use strchr() in range decoding * Oct 21 1999 Fix declarations after lint * Oct 21 1999 Fix arguments to catopen() and catclose() after lint * Nov 3 1999 Fix bug which lost last character on a line in getoken * Dec 9 1999 Add next_token(); set pointer to next token in first_token * * Jan 11 2000 Use nndec for Starbase files, too * Feb 10 2000 Read coordinate system, epoch, and equinox from Starbase files * Mar 1 2000 Add isfile() to tell whether string is name of readable file * Mar 1 2000 Add agets() to return value from keyword = value in string * Mar 1 2000 Add isfile() to tell if a string is the name of a readable file * Mar 1 2000 Add agets() to read a parameter from a comment line of a file * Mar 8 2000 Add ProgCat() to return catalog flag from program name * Mar 13 2000 Add PropCat() to return whether catalog has proper motions * Mar 27 2000 Clean up code after lint * May 22 2000 Add bv2sp() to approximate main sequence spectral type from B-V * May 25 2000 Add Tycho 2 catalog * May 26 2000 Add field size argument to CatNum() and CatNumLen() * Jun 2 2000 Set proper motion for all catalog types in RefCat() * Jun 26 2000 Add XY image coordinate system * Jul 26 2000 Include math.h to get strtod() on SunOS machines * Aug 2 2000 Allow up to 14 digits in catalog IDs * Sep 1 2000 Add option in CatNum to print leading zeroes if nnfld > 0 * Sep 22 2000 Add br2sp() to approximate main sequence spectral type from B-R * Oct 24 2000 Add USNO option to RefCat() * Nov 21 2000 Clean up logic in RefCat() * Nov 28 2000 Try PPMra and SAOra in RefCat() as well as PPM and SAO * Dec 13 2000 Add StrNdec() to get number of decimal places in star numbers * * Jan 17 2001 Add vertical bar (|) as column separator * Feb 28 2001 Separate .usno stars from usa stars * Mar 1 2001 Add CatName() * Mar 19 2001 Fix setting of ra-sorted PPM catalog in RefCat() * Mar 27 2001 Add option to omit leading spaces in CatNum() * May 8 2001 Fix bug in setokens() which failed to deal with quoted tokens * May 18 2001 Fix bug in setokens() which returned on ntok < maxtok * May 22 2001 Add GSC-ACT catalog * May 24 2001 Add 2MASS Point Source Catalog * Jun 7 2001 Return proper motion flag and number of magnitudes from RefCat() * Jun 13 2001 Fix rounding problem in rgetr8() * Jun 13 2001 Use strncasecmp() instead of two calls to strncmp() in RefCat() * Jun 15 2001 Add CatName() and CatID() * Jun 18 2001 Add maximum length of returned string to getoken(), nextoken() * Jun 18 2001 Pad returned string in getoken(), nextoken() * Jun 19 2001 Treat "bar" like "tab" as special single character terminator * Jun 19 2001 Allow tab table options for named catalogs in RefCat() * Jun 19 2001 Change number format to integer for Hipparcos catalog * Jun 19 2001 Add refcatname as argument to CatName() * Jun 20 2001 Add GSC II * Jun 25 2001 Fix GSC II number padding * Aug 20 2001 Add NumNdec() and guess number of decimal places if needed * Sep 20 2001 Add CatMagName() * Sep 25 2001 Move isfile() to fileutil.c * * Feb 26 2002 Fix agets() to work with keywords at start of line * Feb 26 2002 Add option in agets() to return value to end of line or / * Mar 25 2002 Fix bug in agets() to find second occurence of string * Apr 10 2002 Add CatMagNum() to translate single letters to mag sequence number * May 13 2002 In agets(), allow arbitrary number of spaces around : or = * Jun 10 2002 In isrange(), return 0 if string is null or empty * Aug 1 2002 In agets(), read through / if reading to end of line * Sep 18 2002 Add vothead() and vottail() for VOTable output from scat * Oct 26 2002 Fix bugs in vothead() * * Jan 23 2003 Add USNO-B1.0 Catalog * Jan 27 2003 Adjust dra in RefLimit to max width in RA seconds in region * Mar 10 2003 Clean up RefLim() to better represent region to be searched * Mar 24 2003 Add CatCode() to separate catalog type from catalog parameters * Apr 14 2003 Add setrevmsg() and getrevmsg() * Apr 24 2003 Add UCAC1 Catalog * Apr 24 2003 Return 5 magnitudes for GSC II, including epoch * Apr 24 2003 Fix bug dealing with HST GSC * May 21 2003 Add TMIDR2=2MASS IDR2, and new 2MASS=TMPSC * May 28 2003 Fix bug checking for TMIDR2=2MASS IDR2; 11 digits for TMPSC * May 30 2003 Add UCAC2 catalog * Sep 19 2003 Fix bug which shrank search width in RefLim() * Sep 26 2003 In RefLim() do not use cos(90) * Sep 29 2003 Add proper motion margins and wrap arguments to RefLim() * Oct 1 2003 Add code in RefLim() for all-sky images * Oct 6 2003 Add code in RefLim() to cover near-polar searches * Dec 4 2003 Implement GSC 2.3 and USNO-YB6 * Dec 15 2003 Set refcat to 0 if no catalog name and refcatname to NULL * * Jan 5 2004 Add SDSS catalog * Jan 12 2004 Add 2MASS Extended Source Catalog * Jan 14 2004 Add CatSource() * Jan 22 2004 Add global flag degout to print limits in degrees * * May 12 2005 Add tmcid() to decode 2MASS ID strings * May 18 2005 Change Tycho-2 magnitudes to include B and V errors * Jul 27 2005 Add DateString() to convert epoch to desired format * Aug 2 2005 Fix setoken() to deal with whitespace before end of line * Aug 2 2005 Use static maxtokens set to header MAXTOKENS * Aug 5 2005 Add code to support magnitude errors in Tycho2 and 2MASS PSC * Aug 11 2005 Add setdateform() so date can be formatted anywhere * Aug 11 2005 Add full FITS ISO date as EP_ISO * Aug 16 2005 Make all string matches case-independent * * Mar 15 2006 Clean up VOTable code * Mar 17 2006 Return number of fields from vothead() * Apr 7 2006 Keep quoted character strings together as a single token * Jun 6 2006 Add SKY2000 catalog for wide fields * Jun 20 2006 In CatSource() increase catalog descriptor from 32 to 64 chars * * Jan 10 2007 Add polynomial fitting subroutines from polfit.c * Jan 11 2007 Move token access subroutines to fileutil.c * Mar 13 2007 Set title accordingly for gsc22 and gsc23 and gsc2 options * Jul 8 2007 Set up 8 magnitudes for GSC 2.3 from GALEX * Jul 13 2007 Add SkyBot solar system object search * Nov 28 2006 Add moveb() from binread.c * * Aug 19 2009 If pole is included, set RA range to 360 degrees in RefLim() * Sep 25 2009 Change name of moveb() to movebuff() * Sep 28 2009 For 2MASS Extended Source catalog, use 2mx_id, not 2mass_id * Sep 30 2009 Add UCAC3 catalog * Oct 26 2009 Do not wrap in RefLim() if dra=360 * Nov 6 2009 Add UCAC3 catalog to ProgCat() * Nov 13 2009 Add UCAC3 and UCAC2 to CatMagName() and CatMagNum() * * Mar 31 2010 Fix south pole search * Apr 06 2010 Add fillblank argument to agets() * Apr 06 2010 In agets() search until keyword[: or =] or end of string * Sep 14 2010 Add BSC radius of 7200 to CatRad() and number field of 4 * * May 16 2012 Save maximum value in range data structure * Jul 26 2012 Fix xterm computation in polcomp() from + to * * (found by Raymond Carlberg of U.Toronto) * Oct 02 2012 Skip trailing right bracket in aget*() * Oct 23 2012 Add "of" as possible connector in aget*() * * Feb 15 2013 Add UCAC4 catalog * Sep 23 2013 Finish adding UCAC4 catalog * * Nov 25 2015 Add tab as an assignment character in agets() */ wcstools-3.9.5/libwcs/cel.c0000664000016200001660000003572511750060473014664 0ustar minkoirsys/*============================================================================= * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-2002, Mark Calabretta * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Correspondence concerning WCSLIB may be directed to: * Internet email: mcalabre@atnf.csiro.au * Postal address: Dr. Mark Calabretta, * Australia Telescope National Facility, * P.O. Box 76, * Epping, NSW, 2121, * AUSTRALIA * *============================================================================= * * C routines which implement the FITS World Coordinate System (WCS) * convention. * * Summary of routines * ------------------- * These routines are provided as drivers for the lower level spherical * coordinate transformation and projection routines. There are separate * driver routines for the forward, celfwd(), and reverse, celrev(), * transformations. * * An initialization routine, celset(), computes intermediate values from * the transformation parameters but need not be called explicitly - see the * explanation of cel.flag below. * * * Initialization routine; celset() * -------------------------------- * Initializes members of a celprm data structure which hold intermediate * values. Note that this routine need not be called directly; it will be * invoked by celfwd() and celrev() if the "flag" structure member is * anything other than a predefined magic value. * * Given: * pcode[4] const char * WCS projection code (see below). * * Given and returned: * cel celprm* Spherical coordinate transformation parameters * (see below). * prj prjprm* Projection parameters (usage is described in the * prologue to "proj.c"). * * Function return value: * int Error status * 0: Success. * 1: Invalid coordinate transformation parameters. * 2: Ill-conditioned coordinate transformation * parameters. * * Forward transformation; celfwd() * -------------------------------- * Compute (x,y) coordinates in the plane of projection from celestial * coordinates (lng,lat). * * Given: * pcode[4] const char * WCS projection code (see below). * lng,lat const double * Celestial longitude and latitude of the projected * point, in degrees. * * Given and returned: * cel celprm* Spherical coordinate transformation parameters * (see below). * * Returned: * phi, double* Longitude and latitude in the native coordinate * theta system of the projection, in degrees. * * Given and returned: * prj prjprm* Projection parameters (usage is described in the * prologue to "proj.c"). * * Returned: * x,y double* Projected coordinates, "degrees". * * Function return value: * int Error status * 0: Success. * 1: Invalid coordinate transformation parameters. * 2: Invalid projection parameters. * 3: Invalid value of (lng,lat). * * Reverse transformation; celrev() * -------------------------------- * Compute the celestial coordinates (lng,lat) of the point with projected * coordinates (x,y). * * Given: * pcode[4] const char * WCS projection code (see below). * x,y const double * Projected coordinates, "degrees". * * Given and returned: * prj prjprm* Projection parameters (usage is described in the * prologue to "proj.c"). * * Returned: * phi, double* Longitude and latitude in the native coordinate * theta system of the projection, in degrees. * * Given and returned: * cel celprm* Spherical coordinate transformation parameters * (see below). * * Returned: * lng,lat double* Celestial longitude and latitude of the projected * point, in degrees. * * Function return value: * int Error status * 0: Success. * 1: Invalid coordinate transformation parameters. * 2: Invalid projection parameters. * 3: Invalid value of (x,y). * * Coordinate transformation parameters * ------------------------------------ * The celprm struct consists of the following: * * int flag * The celprm struct contains pointers to the forward and reverse * projection routines as well as intermediaries computed from the * reference coordinates (see below). Whenever the projection code * (pcode) or any of ref[4] are set or changed then this flag must be * set to zero to signal the initialization routine, celset(), to * redetermine the function pointers and recompute intermediaries. * Once this has been done pcode itself is ignored. * * double ref[4] * The first pair of values should be set to the celestial longitude * and latitude (usually right ascension and declination) of the * reference point of the projection. These are given by the CRVALn * keywords in FITS. * * The second pair of values are the native longitude of the celestial * pole and the celestial latitude of the native pole and correspond to * FITS keywords LONPOLE and LATPOLE. * * LONPOLE defaults to 0 degrees if the celestial latitude of the * reference point of the projection is greater than the native * latitude, otherwise 180 degrees. (This is the condition for the * celestial latitude to increase in the same direction as the native * latitude at the reference point.) ref[2] may be set to 999.0 to * indicate that the correct default should be substituted. * * In some circumstances the celestial latitude of the native pole may * be determined by the first three values only to within a sign and * LATPOLE is used to choose between the two solutions. LATPOLE is * set in ref[3] and the solution closest to this value is used to * reset ref[3]. It is therefore legitimate, for example, to set * ref[3] to 999.0 to choose the more northerly solution - the default * if the LATPOLE card is omitted from the FITS header. For the * special case where the reference point of the projection is at * native latitude zero, its celestial latitude is zero, and * LONPOLE = +/- 90 then the celestial latitude of the pole is not * determined by the first three reference values and LATPOLE * specifies it completely. * * The remaining members of the celprm struct are maintained by the * initialization routines and should not be modified. This is done for the * sake of efficiency and to allow an arbitrary number of contexts to be * maintained simultaneously. * * double euler[5] * Euler angles and associated intermediaries derived from the * coordinate reference values. * * * WCS projection codes * -------------------- * Zenithals/azimuthals: * AZP: zenithal/azimuthal perspective * TAN: gnomonic * STG: stereographic * SIN: synthesis (generalized orthographic) * ARC: zenithal/azimuthal equidistant * ZPN: zenithal/azimuthal polynomial * ZEA: zenithal/azimuthal equal area * AIR: Airy * * Cylindricals: * CYP: cylindrical perspective * CEA: cylindrical equal area * CAR: Cartesian * MER: Mercator * * Pseudo-cylindricals: * SFL: Sanson-Flamsteed * PAR: parabolic * MOL: Mollweide * * Conventional: * AIT: Hammer-Aitoff * * Conics: * COP: conic perspective * COD: conic equidistant * COE: conic equal area * COO: conic orthomorphic * * Polyconics: * BON: Bonne * PCO: polyconic * * Quad-cubes: * TSC: tangential spherical cube * CSC: COBE quadrilateralized spherical cube * QSC: quadrilateralized spherical cube * * Author: Mark Calabretta, Australia Telescope National Facility * $Id: cel.c,v 2.14 2002/04/03 01:25:29 mcalabre Exp $ *===========================================================================*/ #include #include #include "wcslib.h" /* Map error number to error message for each function. */ const char *celset_errmsg[] = { 0, "Invalid coordinate transformation parameters", "Ill-conditioned coordinate transformation parameters"}; const char *celfwd_errmsg[] = { 0, "Invalid coordinate transformation parameters", "Invalid projection parameters", "Invalid value of (lng,lat)"}; const char *celrev_errmsg[] = { 0, "Invalid coordinate transformation parameters", "Invalid projection parameters", "Invalid value of (x,y)"}; int celset(pcode, cel, prj) const char pcode[4]; struct celprm *cel; struct prjprm *prj; { int dophip; const double tol = 1.0e-10; double clat0, cphip, cthe0, slat0, sphip, sthe0; double latp, latp1, latp2; double u, v, x, y, z; /* Initialize the projection driver routines. */ if (prjset(pcode, prj)) { return 1; } /* Set default for native longitude of the celestial pole? */ dophip = (cel->ref[2] == 999.0); /* Compute celestial coordinates of the native pole. */ if (prj->theta0 == 90.0) { /* Reference point is at the native pole. */ if (dophip) { /* Set default for longitude of the celestial pole. */ cel->ref[2] = 180.0; } latp = cel->ref[1]; cel->ref[3] = latp; cel->euler[0] = cel->ref[0]; cel->euler[1] = 90.0 - latp; } else { /* Reference point away from the native pole. */ /* Set default for longitude of the celestial pole. */ if (dophip) { cel->ref[2] = (cel->ref[1] < prj->theta0) ? 180.0 : 0.0; } clat0 = cosdeg (cel->ref[1]); slat0 = sindeg (cel->ref[1]); cphip = cosdeg (cel->ref[2]); sphip = sindeg (cel->ref[2]); cthe0 = cosdeg (prj->theta0); sthe0 = sindeg (prj->theta0); x = cthe0*cphip; y = sthe0; z = sqrt(x*x + y*y); if (z == 0.0) { if (slat0 != 0.0) { return 1; } /* latp determined by LATPOLE in this case. */ latp = cel->ref[3]; } else { if (fabs(slat0/z) > 1.0) { return 1; } u = atan2deg (y,x); v = acosdeg (slat0/z); latp1 = u + v; if (latp1 > 180.0) { latp1 -= 360.0; } else if (latp1 < -180.0) { latp1 += 360.0; } latp2 = u - v; if (latp2 > 180.0) { latp2 -= 360.0; } else if (latp2 < -180.0) { latp2 += 360.0; } if (fabs(cel->ref[3]-latp1) < fabs(cel->ref[3]-latp2)) { if (fabs(latp1) < 90.0+tol) { latp = latp1; } else { latp = latp2; } } else { if (fabs(latp2) < 90.0+tol) { latp = latp2; } else { latp = latp1; } } cel->ref[3] = latp; } cel->euler[1] = 90.0 - latp; z = cosdeg (latp)*clat0; if (fabs(z) < tol) { if (fabs(clat0) < tol) { /* Celestial pole at the reference point. */ cel->euler[0] = cel->ref[0]; cel->euler[1] = 90.0 - prj->theta0; } else if (latp > 0.0) { /* Celestial pole at the native north pole.*/ cel->euler[0] = cel->ref[0] + cel->ref[2] - 180.0; cel->euler[1] = 0.0; } else if (latp < 0.0) { /* Celestial pole at the native south pole. */ cel->euler[0] = cel->ref[0] - cel->ref[2]; cel->euler[1] = 180.0; } } else { x = (sthe0 - sindeg (latp)*slat0)/z; y = sphip*cthe0/clat0; if (x == 0.0 && y == 0.0) { return 1; } cel->euler[0] = cel->ref[0] - atan2deg (y,x); } /* Make euler[0] the same sign as ref[0]. */ if (cel->ref[0] >= 0.0) { if (cel->euler[0] < 0.0) cel->euler[0] += 360.0; } else { if (cel->euler[0] > 0.0) cel->euler[0] -= 360.0; } } cel->euler[2] = cel->ref[2]; cel->euler[3] = cosdeg (cel->euler[1]); cel->euler[4] = sindeg (cel->euler[1]); cel->flag = CELSET; /* Check for ill-conditioned parameters. */ if (fabs(latp) > 90.0+tol) { return 2; } return 0; } /*--------------------------------------------------------------------------*/ int celfwd(pcode, lng, lat, cel, phi, theta, prj, x, y) const char pcode[4]; const double lng, lat; struct celprm *cel; double *phi, *theta; struct prjprm *prj; double *x, *y; { int err; if (cel->flag != CELSET) { if (celset(pcode, cel, prj)) return 1; } /* Compute native coordinates. */ sphfwd(lng, lat, cel->euler, phi, theta); /* Apply forward projection. */ if ((err = prj->prjfwd(*phi, *theta, prj, x, y))) { return err == 1 ? 2 : 3; } return 0; } /*--------------------------------------------------------------------------*/ int celrev(pcode, x, y, prj, phi, theta, cel, lng, lat) const char pcode[4]; const double x, y; struct prjprm *prj; double *phi, *theta; struct celprm *cel; double *lng, *lat; { int err; if (cel->flag != CELSET) { if(celset(pcode, cel, prj)) return 1; } /* Apply reverse projection. */ if ((err = prj->prjrev(x, y, prj, phi, theta))) { return err == 1 ? 2 : 3; } /* Compute native coordinates. */ sphrev(*phi, *theta, cel->euler, lng, lat); return 0; } /* Dec 20 1999 Doug Mink - Change cosd() and sind() to cosdeg() and sindeg() * Dec 20 1999 Doug Mink - Include wcslib.h, which includes wcsmath.h and cel.h * * Dec 18 2000 Doug Mink - Include string.h for strcmp() * * Mar 20 2001 Doug Mink - Add () around err assignments in if statements * Sep 19 2001 Doug Mink - Add above changes to WCSLIB-2.7 cel.c * * Mar 12 2002 Doug Mink - Add changes to WCSLIB-2.8.2 cel.c */ wcstools-3.9.5/libwcs/ctgread.c0000664000016200001660000017360613041771745015541 0ustar minkoirsys/*** File libwcs/ctgread.c *** January 24, 2017 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1998-2017 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ /* int ctgread() Read catalog stars in specified region of the sky * int ctgrnum() Read catalog stars with specified numbers * int ctgopen() Open catalog, returning number of entries * int ctgstar() Get ASCII catalog entry for one star * int ctgsize() Return length of file in bytes * int isacat() Return 1 if file is ASCII catalog, else 0 */ #include #include #include #include #include #include #include "wcs.h" #include "fitsfile.h" #include "wcscat.h" /* default pathname for catalog, used if catalog file not found in current working directory, but overridden by WCS_CATDIR environment variable */ char catdir[64]="/data/catalogs"; #define MAX_LTOK 80 static double ctg2ra(); static double ctg2dec(); static int ctgsize(); double dt2ep(); /* Julian Date to epoch (fractional year) */ static char newline = 10; /* CTGREAD -- Read ASCII stars in specified region */ int ctgread (catfile, refcat, distsort, cra, cdec, dra, ddec, drad, dradi, sysout, eqout, epout, mag1, mag2, sortmag, nsmax, starcat, tnum, tra, tdec, tpra, tpdec, tmag, tc, tobj, nlog) char *catfile; /* Name of reference star catalog file */ int refcat; /* Catalog code from wcscat.h */ int distsort; /* 1 to sort stars by distance from center */ double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ double dradi; /* Inner edge of annulus in degrees (ignore if 0) */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Number of magnitude by which to limit and sort */ int nsmax; /* Maximum number of stars to be returned */ struct StarCat **starcat; /* Catalog data structure */ double *tnum; /* Array of ID numbers (returned) */ double *tra; /* Array of right ascensions (returned) */ double *tdec; /* Array of declinations (returned) */ double *tpra; /* Array of right ascension proper motions (returned) */ double *tpdec; /* Array of declination proper motions (returned) */ double **tmag; /* 2-D array of magnitudes (returned) */ int *tc; /* Array of fluxes (returned) */ char **tobj; /* Array of object names (returned) */ int nlog; { double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ double dist = 0.0; /* Distance from search center in degrees */ double faintmag=0.0; /* Faintest magnitude */ double maxdist=0.0; /* Largest distance */ int faintstar=0; /* Faintest star */ int farstar=0; /* Most distant star */ double *tdist; /* Array of distances to stars */ int sysref; /* Catalog coordinate system */ double eqref; /* Catalog equinox */ double epref; /* Catalog epoch */ char cstr[32]; struct Star *star; struct StarCat *sc; /* Catalog data structure */ char *objname; int nameobj; /* Save object name if 1, else do not */ int lname; int wrap; int imag; int jstar; int nstar; int magsort; double ra,dec,rapm,decpm; double mag; double num; double rdist, ddist; int i; int istar; int verbose; int isp = 0; int pass; nstar = 0; /* Call the appropriate search program if not TDC ASCII catalog */ if (refcat != TXTCAT) { if (refcat == GSC || refcat == GSCACT) nstar = gscread (refcat,cra,cdec,dra,ddec,drad,dradi,distsort, sysout,eqout,epout,mag1,mag2,nsmax, tnum,tra,tdec,tmag,tc,nlog); else if (refcat == GSC2) nstar = gsc2read (catfile,cra,cdec,dra,ddec,drad,dradi,distsort, sysout,eqout,epout,mag1,mag2,sortmag,nsmax, tnum,tobj,tra,tdec,tpra,tpdec,tmag,tc,nlog); else if (refcat == SDSS) nstar = sdssread (cra,cdec,dra,ddec,drad,dradi,distsort, sysout,eqout,epout,mag1,mag2,sortmag,nsmax, tnum,tobj,tra,tdec,tmag,tc,nlog); else if (refcat == USAC || refcat == USA1 || refcat == USA2 || refcat == UAC || refcat == UA1 || refcat == UA2) nstar = uacread (catfile,distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nsmax,tnum, tra,tdec,tmag,tc,nlog); else if (refcat == UJC || refcat == USNO) nstar = ujcread (catfile,cra,cdec,dra,ddec,drad,dradi,distsort, sysout,eqout,epout,mag1,mag2,nsmax, tnum,tra,tdec,tmag,tc,nlog); else if (refcat == UB1 || refcat == YB6) nstar = ubcread (catfile,distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nsmax,tnum, tra,tdec,tpra,tpdec,tmag,tc,nlog); else if (refcat == UCAC1 || refcat == UCAC2 || refcat == UCAC3 || refcat == UCAC4) nstar = ucacread (catfile,cra,cdec,dra,ddec,drad,dradi,distsort, sysout,eqout,epout,mag1,mag2,sortmag,nsmax, tnum,tra,tdec,tpra,tpdec,tmag,tc,nlog); else if (refcat == TMPSC || refcat == TMIDR2 || refcat == TMXSC || refcat == TMPSCE) nstar = tmcread (refcat,cra,cdec,dra,ddec,drad,dradi,distsort, sysout,eqout,epout,mag1,mag2,sortmag,nsmax, tnum,tra,tdec,tmag,tc,nlog); else if (refcat == ACT) nstar = actread (cra,cdec,dra,ddec,drad,dradi,distsort, sysout,eqout,epout,mag1, mag2,sortmag,nsmax, tnum,tra,tdec,tpra,tpdec,tmag,tc,nlog); else if (refcat == TYCHO2 || refcat == TYCHO2E) nstar = ty2read (refcat, cra,cdec,dra,ddec,drad,dradi,distsort, sysout,eqout,epout,mag1,mag2,sortmag,nsmax, tnum,tra,tdec,tpra,tpdec,tmag,tc,nlog); else if (refcat == SAO) nstar = binread ("SAOra", distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nsmax,starcat, tnum,tra,tdec,tpra,tpdec,tmag,tc,NULL,nlog); else if (refcat == PPM) nstar = binread ("PPMra",distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nsmax,starcat, tnum,tra,tdec,tpra,tpdec,tmag,tc,NULL,nlog); else if (refcat == SKY2K) nstar = binread ("sky2kra",distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nsmax,starcat, tnum,tra,tdec,tpra,tpdec,tmag,tc,NULL,nlog); else if (refcat == IRAS) nstar = binread ("IRAS", distsort, cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nsmax,starcat, tnum,tra,tdec,tpra,tpdec,tmag,tc,NULL,nlog); else if (refcat == TYCHO) nstar = binread ("tychora", distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nsmax,starcat, tnum,tra,tdec,tpra,tpdec,tmag,tc,NULL,nlog); else if (refcat == HIP) nstar = binread("hipparcosra",distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nsmax,starcat, tnum,tra,tdec,tpra,tpdec,tmag,tc,NULL,nlog); else if (refcat == BSC) nstar = binread ("BSC5ra", distsort, cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nsmax,starcat, tnum,tra,tdec,tpra,tpdec,tmag,tc,NULL,nlog); else if (refcat == BINCAT) nstar = binread (catfile, distsort, cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nsmax,starcat, tnum,tra,tdec,tpra,tpdec,tmag,tc,tobj,nlog); else if (refcat == TABCAT || refcat == WEBCAT) nstar = tabread (catfile, distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nsmax,starcat, tnum,tra,tdec,tpra,tpdec,tmag,tc,tobj,nlog); else if (refcat == SKYBOT) nstar = skybotread (cra,cdec,dra,ddec,drad,distsort, sysout,eqout,epout,mag1,mag2,sortmag,nsmax, tnum,tobj,tra,tdec,tpra,tpdec,tmag,tc,nlog); return (nstar); } star = NULL; sc = *starcat; if (nlog > 0) verbose = 1; else verbose = 0; wcscstr (cstr, sysout, eqout, epout); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* If RA range includes zero, split it in two */ wrap = 0; if (ra1 > ra2) wrap = 1; else wrap = 0; /* Search zones which include the poles cover 360 degrees in RA */ if (cdec - ddec < -90.0) { if (dec1 > dec2) dec2 = dec1; dec1 = -90.0; ra1 = 0.0; ra2 = 359.99999; wrap = 0; } if (cdec + ddec > 90.0) { if (dec2 < dec1) dec1 = dec2; dec2 = 90.0; ra1 = 0.0; ra2 = 359.99999; wrap = 0; } /* mag1 is always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; /* Logging interval */ tdist = (double *) malloc (nsmax * sizeof (double)); /* Open catalog file */ if (sc == NULL) { if ((sc = ctgopen (catfile, refcat)) == NULL) { fprintf (stderr,"CTGRNUM: Cannot read catalog %s\n", catfile); *starcat = sc; return (0); } } *starcat = sc; if (sc->nstars <= 0) { free (sc); if (star != NULL) free (star); sc = NULL; return (0); } if (sortmag > 0 && sortmag <= sc->nmag) magsort = sortmag - 1; else magsort = 1; jstar = 0; if (tobj == NULL || sc->ignore) nameobj = 0; else nameobj = 1; /* Loop through catalog */ for (istar = 1; istar <= sc->nstars; istar++) { if (ctgstar (istar, sc, star)) { fprintf (stderr,"\nCTGREAD: Cannot read %s star %d\n", sc->isfil, istar); break; } /* Magnitude */ mag = star->xmag[magsort]; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; /* Set coordinate system for this star */ if (pass) { sysref = star->coorsys; eqref = star->equinox; epref = star->epoch; /* Extract selected fields */ num = star->num; ra = star->ra; dec = star->dec; rapm = star->rapm; decpm = star->decpm; /* If catalog is RA-sorted, stop reading if past highest RA */ if (sc->rasorted && !wrap && ra > ra2) break; /* Get position in output coordinate system, equinox, and epoch */ if (sc->inform != 'X') { if (sc->mprop == 1) wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); else wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); } /* Compute distance from search center */ if (drad > 0 || distsort) { if (sc->inform == 'X') dist = sqrt ((ra-cra)*(ra-cra) + (dec-cdec)*(dec-cdec)); else dist = wcsdist (cra,cdec,ra,dec); } else dist = 0.0; /* Check radial distance to search center */ if (drad > 0) { if (dist > drad) pass = 0; if (dradi > 0.0 && dist < dradi) pass = 0; } /* Check distance along RA and Dec axes */ else { ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } } /* Check magnitude and position limits */ if (pass) { /* Spectral type */ if (sc->sptype) isp = (1000 * (int) star->isp[0]) + (int)star->isp[1]; /* Save star position and magnitude in table */ if (nstar < nsmax) { tnum[nstar] = num; tra[nstar] = ra; tdec[nstar] = dec; for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][nstar] = star->xmag[imag]; } if (sc->mprop == 1) { tpra[nstar] = rapm; tpdec[nstar] = decpm; } if (sc->sptype) tc[nstar] = isp; tdist[nstar] = dist; if (nameobj) { lname = strlen (star->objname) + 1; if (lname > 1) { objname = (char *)calloc (lname, 1); strcpy (objname, star->objname); tobj[nstar] = objname; } else tobj[nstar] = NULL; } if (dist > maxdist) { maxdist = dist; farstar = nstar; } if (mag > faintmag) { faintmag = mag; faintstar = nstar; } } /* If too many stars and distance sorting, replace furthest star */ else if (distsort) { if (dist < maxdist) { tnum[farstar] = num; tra[farstar] = ra; tdec[farstar] = dec; if (sc->mprop == 1) { tpra[farstar] = rapm; tpdec[farstar] = decpm; } for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][farstar] = star->xmag[imag]; } if (sc->sptype) tc[farstar] = isp; tdist[farstar] = dist; if (nameobj) { free (tobj[farstar]); lname = strlen (star->objname) + 1; if (lname > 1) { objname = (char *)calloc (lname, 1); strcpy (objname, star->objname); tobj[farstar] = objname; } else tobj[farstar] = NULL; } /* Find new farthest star */ maxdist = 0.0; for (i = 0; i < nsmax; i++) { if (tdist[i] > maxdist) { maxdist = tdist[i]; farstar = i; } } } } /* If too many stars, replace faintest star */ else if (mag < faintmag) { tnum[faintstar] = num; tra[faintstar] = ra; tdec[faintstar] = dec; if (sc->mprop == 1) { tpra[faintstar] = rapm; tpdec[faintstar] = decpm; } for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][faintstar] = star->xmag[imag]; } if (sc->sptype) tc[faintstar] = isp; tdist[faintstar] = dist; if (nameobj) { free (tobj[faintstar]); lname = strlen (star->objname) + 1; if (lname > 1) { objname = (char *)calloc (lname, 1); strcpy (objname, star->objname); tobj[faintstar] = objname; } else tobj[faintstar] = NULL; } faintmag = 0.0; /* Find new faintest star */ for (i = 0; i < nsmax; i++) { if (tmag[magsort][i] > faintmag) { faintmag = tmag[magsort][i]; faintstar = i; } } } nstar++; jstar++; if (nlog == 1) fprintf (stderr,"CTGREAD: %11.6f: %9.5f %9.5f %s %5.2f \n", num,ra,dec,cstr,mag); /* End of accepted star processing */ } /* Log operation */ if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"CTGREAD: %5d / %5d / %5d sources catalog %s\r", jstar,istar,sc->nstars,catfile); /* End of star loop */ } /* Summarize search */ if (nlog > 0) { fprintf (stderr,"CTGREAD: Catalog %s : %d / %d / %d found\n", catfile,jstar,istar,sc->nstars); if (nstar > nsmax) fprintf (stderr,"CTGREAD: %d stars found; only %d returned\n", nstar,nsmax); } free ((char *)tdist); free (star); return (nstar); } /* CTGRNUM -- Read ASCII stars with specified numbers */ int ctgrnum (catfile,refcat, nnum,sysout,eqout,epout,match,starcat, tnum,tra,tdec,tpra,tpdec,tmag,tc,tobj,tpath,nlog) char *catfile; /* Name of reference star catalog file */ int refcat; /* Catalog code from wcscat.h */ int nnum; /* Number of stars to look for */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ int match; /* 1 to match star number exactly, else sequence num.*/ struct StarCat **starcat; /* Catalog data structure */ double *tnum; /* Array of star numbers to look for */ double *tra; /* Array of right ascensions (returned) */ double *tdec; /* Array of declinations (returned) */ double *tpra; /* Array of right ascension proper motions (returned) */ double *tpdec; /* Array of declination proper motions (returned) */ double **tmag; /* 2-D Array of magnitudes (returned) */ int *tc; /* Array of fluxes (returned) */ char **tobj; /* Array of object names (returned) */ char **tpath; /* Array of object pathnames (returned) */ int nlog; { int jnum; int nstar; double ra,dec; double rapm, decpm; int istar; int sysref; /* Catalog coordinate system */ double eqref; /* Catalog equinox */ double epref; /* Catalog epoch */ char cstr[32]; struct StarCat *sc; struct Star *star; char *objname; char *datapath; int imag; int lname; int starfound; int nameobj; int pathobj; nstar = 0; /* Call the appropriate search program if not TDC ASCII catalog */ if (refcat != TXTCAT) { if (refcat == GSC || refcat == GSCACT) nstar = gscrnum (refcat,nnum,sysout,eqout,epout, tnum,tra,tdec,tmag,tc,nlog); else if (refcat == GSC2) nstar = 0; else if (refcat == USAC || refcat == USA1 || refcat == USA2 || refcat == UAC || refcat == UA1 || refcat == UA2) nstar = uacrnum (catfile,nnum,sysout,eqout,epout, tnum,tra,tdec,tmag,tc,nlog); else if (refcat == UB1 || refcat == YB6) nstar = ubcrnum (catfile,nnum,sysout,eqout,epout, tnum,tra,tdec,tpra,tpdec,tmag,tc,nlog); else if (refcat == UJC || refcat == USNO) nstar = ujcrnum (catfile,nnum,sysout,eqout,epout, tnum,tra,tdec,tmag,tc,nlog); else if (refcat == UCAC1 || refcat == UCAC2 || refcat == UCAC3 || refcat == UCAC4) nstar = ucacrnum (catfile,nnum,sysout,eqout,epout, tnum,tra,tdec,tpra,tpdec,tmag,tc,nlog); else if (refcat == TMPSC || refcat == TMPSCE || refcat == TMIDR2 || refcat == TMXSC) nstar = tmcrnum (refcat,nnum,sysout,eqout,epout, tnum,tra,tdec,tmag,tc,nlog); else if (refcat == SAO) nstar = binrnum ("SAO",nnum,sysout,eqout,epout,match, tnum,tra,tdec,tpra,tpdec,tmag,tc,NULL,nlog); else if (refcat == PPM) nstar = binrnum ("PPM",nnum,sysout,eqout,epout,match, tnum,tra,tdec,tpra,tpdec,tmag,tc,NULL,nlog); else if (refcat == SKY2K) nstar = binrnum ("sky2k",nnum,sysout,eqout,epout,match, tnum,tra,tdec,tpra,tpdec,tmag,tc,NULL,nlog); else if (refcat == IRAS) nstar = binrnum ("IRAS",nnum,sysout,eqout,epout,match, tnum,tra,tdec,tpra,tpdec,tmag,tc,NULL,nlog); else if (refcat == TYCHO) nstar = binrnum ("tycho",nnum,sysout,eqout,epout,match, tnum,tra,tdec,tpra,tpdec,tmag,tc,NULL,nlog); else if (refcat == HIP) nstar = binrnum ("hipparcos",nnum,sysout,eqout,epout,match, tnum,tra,tdec,tpra,tpdec,tmag,tc,NULL,nlog); else if (refcat == BSC) nstar = binrnum ("BSC5",nnum,sysout,eqout,epout,match, tnum,tra,tdec,tpra,tpdec,tmag,tc,NULL,nlog); else if (refcat == ACT) nstar = actrnum (nnum,sysout,eqout,epout, tnum,tra,tdec,tpra,tpdec,tmag,tc,nlog); else if (refcat == TYCHO2 || refcat == TYCHO2E) nstar = ty2rnum (refcat,nnum,sysout,eqout,epout, tnum,tra,tdec,tpra,tpdec,tmag,tc,nlog); else if (refcat == TABCAT || refcat == WEBCAT) nstar = tabrnum (catfile,nnum,sysout,eqout,epout,starcat,match, tnum,tra,tdec,tpra,tpdec,tmag,tc,tobj,nlog); else if (refcat == BINCAT) nstar = binrnum (catfile,nnum,sysout,eqout,epout,match, tnum,tra,tdec,tpra,tpdec,tmag,tc,tobj,nlog); return (nstar); } sc = *starcat; if (sc == NULL) { if ((sc = ctgopen (catfile, refcat)) == NULL) { fprintf (stderr,"CTGRNUM: Cannot read catalog %s\n", catfile); *starcat = sc; return (0); } } *starcat = sc; sysref = sc->coorsys; eqref = sc->equinox; epref = sc->epoch; if (!sysout) sysout = sysref; if (!eqout) eqout = eqref; if (!epout) epout = epref; /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; if (tobj == NULL || sc->ignore) nameobj = 0; else nameobj = 1; if (tpath == NULL || sc->ignore) pathobj = 0; else pathobj = 1; /* Loop through star list */ for (jnum = 0; jnum < nnum; jnum++) { /* Loop through catalog to star */ starfound = 0; if (match && sc->stnum > 0) { for (istar = 1; istar <= sc->nstars; istar++) { if (ctgstar (istar, sc, star)) { fprintf (stderr,"CTGRNUM: Cannot read star %d\n", istar); break; } if (star->num == tnum[jnum]) { starfound = 1; break; } } } else { istar = (int) (tnum[jnum] + 0.5); if (ctgstar (istar, sc, star)) { fprintf (stderr,"CTGRNUM: Cannot read star %d\n", istar); continue; } starfound = 1; } /* If star has been found in catalog */ if (starfound) { /* Extract selected fields */ ra = star->ra; dec = star->dec; rapm = star->rapm; decpm = star->decpm; /* Set coordinate system for this star */ sysref = star->coorsys; eqref = star->equinox; epref = star->epoch; if (sc->inform != 'X') { if (sc->mprop == 1) wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); else wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); } /* Save star position and magnitude in table */ tnum[nstar] = star->num; tra[nstar] = ra; tdec[nstar] = dec; if (sc->mprop == 1) { tpra[nstar] = rapm; tpdec[nstar] = decpm; } for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][nstar] = star->xmag[imag]; } /* Spectral type */ if (sc->sptype) tc[nstar] = (1000 * (int) star->isp[0]) + (int)star->isp[1]; /* Object name */ if (nameobj) { lname = strlen (star->objname) + 1; if (lname > 1) { objname = (char *)calloc (lname, 1); strcpy (objname, star->objname); tobj[nstar] = objname; } else tobj[nstar] = NULL; } /* Object data pathname */ if (pathobj) { lname = strlen (star->datapath) + 1; if (lname > 1) { datapath = (char *)calloc (lname, 1); strcpy (datapath, star->datapath); tpath[nstar] = datapath; } else tpath[nstar] = NULL; } nstar++; if (nlog == 1) fprintf (stderr,"CTGRNUM: %11.6f: %9.5f %9.5f %s %5.2f \n", star->num,ra,dec,cstr,star->xmag[0]); /* End of accepted star processing */ } /* Log operation */ if (nlog > 0 && jnum%nlog == 0) fprintf (stderr,"CTGRNUM: %5d / %5d / %5d sources catalog %s\r", nstar,jnum,sc->nstars,catfile); /* End of star loop */ } /* Summarize search */ if (nlog > 0) fprintf (stderr,"CTGRNUM: Catalog %s : %d / %d found\n", catfile,nstar,sc->nstars); free (star); return (nstar); } /* CTGRDATE -- Read ASCII stars with specified date range */ int ctgrdate (catfile,refcat,sysout,eqout,epout,starcat,date1,date2, nmax,tnum,tra,tdec,tpra,tpdec,tmag,tc,tobj,nlog) char *catfile; /* Name of reference star catalog file */ int refcat; /* Catalog code from wcscat.h */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ struct StarCat **starcat; /* Catalog data structure */ double date1; /* Start time as Modified Julian Date or Julian Date */ double date2; /* End time as Modified Julian Date or Julian Date */ int nmax; /* Maximum number of stars to look for */ double *tnum; /* Array of star numbers to look for */ double *tra; /* Array of right ascensions (returned) */ double *tdec; /* Array of declinations (returned) */ double *tpra; /* Array of right ascension proper motions (returned) */ double *tpdec; /* Array of declination proper motions (returned) */ double **tmag; /* 2-D Array of magnitudes (returned) */ int *tc; /* Array of fluxes (returned) */ char **tobj; /* Array of object names (returned) */ int nlog; { int nstar; double ra,dec; double rapm, decpm; int istar; int sysref; /* Catalog coordinate system */ double eqref; /* Catalog equinox */ double epref; /* Catalog epoch */ double epoch1, epoch2; char cstr[32]; struct StarCat *sc; struct Star *star; char *objname; int imag; int lname; int starfound; int nameobj; nstar = 0; /* Call the appropriate search program if not TDC ASCII catalog if (refcat != TXTCAT) { if (refcat == TABCAT || refcat == WEBCAT) nstar = tabrdate (catfile,sysout,eqout,epout,starcat,date1,date2, nmax,tnum,tra,tdec,tpra,tpdec,tmag,tc,tobj,nlog); else if (refcat == BINCAT) nstar = binrdate (catfile,nnum,sysout,eqout,epout,date1,date2, nmax,tnum,tra,tdec,tpra,tpdec,tmag,tc,tobj,nlog); return (nstar); } */ sc = *starcat; if (sc == NULL) { if ((sc = ctgopen (catfile, refcat)) == NULL) { fprintf (stderr,"CTGRDATE: Cannot read catalog %s\n", catfile); *starcat = sc; return (0); } } *starcat = sc; sysref = sc->coorsys; eqref = sc->equinox; epref = sc->epoch; if (!sysout) sysout = sysref; if (!eqout) eqout = eqref; if (!epout) epout = epref; /* Convert date limits to fractional year for easy testing */ if (date1 < 3000.0 && date1 > 0.0) epoch1 = date1; else if (date1 < 100000.0) epoch1 = mjd2ep (date1); else epoch1 = jd2ep (date1); if (date2 < 3000.0 && date2 > 0.0) epoch2 = date2; else if (date2 < 100000.0) epoch2 = mjd2ep (date2); else epoch2 = jd2ep (date2); /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; if (tobj == NULL || sc->ignore) nameobj = 0; else nameobj = 1; /* Loop through catalog to star from first date */ starfound = 0; nstar = 0; for (istar = 1; istar <= sc->nstars; istar++) { if (ctgstar (istar, sc, star)) { fprintf (stderr,"CTGRDATE: Cannot read star %d\n", istar); break; } /* If before start date, skip to next star */ if (star->epoch < epoch1) { continue; } /* If past starting date, drop out of reading loop */ else if (star->epoch > epoch2) { break; } /* Extract selected fields */ ra = star->ra; dec = star->dec; rapm = star->rapm; decpm = star->decpm; /* Set coordinate system for this star */ sysref = star->coorsys; eqref = star->equinox; epref = star->epoch; if (sc->inform != 'X') { if (sc->mprop == 1) wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); else wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); } /* Save star position and magnitude in table */ tnum[nstar] = star->num; tra[nstar] = ra; tdec[nstar] = dec; if (sc->mprop == 1) { tpra[nstar] = rapm; tpdec[nstar] = decpm; } for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][nstar] = star->xmag[imag]; } /* Spectral type */ if (sc->sptype) tc[nstar] = (1000 * (int) star->isp[0]) + (int)star->isp[1]; if (nameobj) { lname = strlen (star->objname) + 1; if (lname > 1) { objname = (char *)calloc (lname, 1); strcpy (objname, star->objname); tobj[nstar] = objname; } else tobj[nstar] = NULL; } nstar++; if (nlog == 1) fprintf (stderr,"CTGRDATE: %11.6f: %9.5f %9.5f %s %5.2f \n", star->num,ra,dec,cstr,star->xmag[0]); /* Log operation */ else if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"CTGRDATE: %5d / %5d / %5d sources catalog %s\r", nstar,istar,sc->nstars,catfile); /* End of star loop */ } /* Summarize search */ if (nlog > 0) fprintf (stderr,"CTGRDATE: Catalog %s : %d / %d found\n", catfile,nstar,sc->nstars); free (star); return (nstar); } /* CTGBIN -- Fill a FITS WCS image with stars from catalog */ int ctgbin (catfile,refcat,wcs,header,image,mag1,mag2,sortmag,magscale,nlog) char *catfile; /* Name of reference star catalog file */ int refcat; /* Catalog code from wcscat.h */ struct WorldCoor *wcs; /* World coordinate system for image */ char *header; /* FITS header for output image */ char *image; /* Output FITS image */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Number of magnitude by which to limit and sort */ double magscale; /* Scaling factor for magnitude to pixel flux * (number of catalog objects per bin if 0) */ int nlog; { double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ int sysref; /* Catalog coordinate system */ double eqref; /* Catalog equinox */ double epref; /* Catalog epoch */ char cstr[32]; struct Star *star; struct StarCat *sc; /* Catalog data structure */ int wrap; int jstar; int nstar; int magsort; double ra,dec,rapm,decpm; double mag; double num; double rdist, ddist; int istar; int verbose; int pass; int ix, iy; double xpix, ypix, flux; int offscl; int bitpix, w, h; /* Image bits/pixel and pixel width and height */ double logt = log(10.0); nstar = 0; /* Call the appropriate search program if not TDC ASCII catalog */ if (refcat != TXTCAT) { if (refcat == GSC || refcat == GSCACT) nstar = gscbin (refcat,wcs,header,image,mag1,mag2,magscale,nlog); else if (refcat == USAC || refcat == USA1 || refcat == USA2 || refcat == UAC || refcat == UA1 || refcat == UA2) nstar = uacbin (catfile,wcs,header,image,mag1,mag2,sortmag,magscale,nlog); else if (refcat == UJC || refcat == USNO) nstar = ujcbin (catfile,wcs,header,image,mag1,mag2,magscale,nlog); else if (refcat == UB1 || refcat == YB6) nstar = ubcbin (catfile,wcs,header,image,mag1,mag2,sortmag,magscale,nlog); else if (refcat == UCAC1 || refcat == UCAC2 || refcat == UCAC3 || refcat == UCAC4) nstar = ucacbin (catfile,wcs,header,image,mag1,mag2,sortmag,magscale,nlog); else if (refcat == TMPSC || refcat == TMIDR2 || refcat == TMXSC) nstar = tmcbin (refcat,wcs,header,image,mag1,mag2,sortmag,magscale,nlog); else if (refcat == ACT) nstar = actbin (wcs,header,image,mag1,mag2,sortmag,magscale,nlog); else if (refcat == TYCHO2 || refcat == TYCHO2E) nstar = ty2bin (wcs,header,image,mag1,mag2,sortmag,magscale,nlog); else if (refcat == SDSS || refcat == GSC2) nstar = -1; else if (refcat == SAO) nstar = binbin ("SAOra",wcs,header,image,mag1,mag2,sortmag,magscale,nlog); else if (refcat == PPM) nstar = binbin ("PPMra",wcs,header,image,mag1,mag2,sortmag,magscale,nlog); else if (refcat == SKY2K) nstar = binbin ("sky2kra",wcs,header,image,mag1,mag2,sortmag,magscale,nlog); else if (refcat == IRAS) nstar = binbin ("IRAS",wcs,header,image,mag1,mag2,sortmag,magscale,nlog); else if (refcat == TYCHO) nstar = binbin ("tychora",wcs,header,image,mag1,mag2,sortmag,magscale,nlog); else if (refcat == HIP) nstar = binbin("hipparcosra",wcs,header,image,mag1,mag2,sortmag,magscale,nlog); else if (refcat == BSC) nstar = binbin ("BSC5ra",wcs,header,image,mag1,mag2,sortmag,magscale,nlog); else if (refcat == BINCAT) nstar = binbin (catfile,wcs,header,image,mag1,mag2,sortmag,magscale,nlog); else if (refcat == TABCAT || refcat == WEBCAT) nstar = tabbin (catfile,wcs,header,image,mag1,mag2,sortmag,magscale,nlog); return (nstar); } star = NULL; if (nlog > 0) verbose = 1; else verbose = 0; /* Set image parameters */ bitpix = 0; (void)hgeti4 (header, "BITPIX", &bitpix); w = 0; (void)hgeti4 (header, "NAXIS1", &w); h = 0; (void)hgeti4 (header, "NAXIS2", &h); /* Set catalog search limits from image WCS information */ sysout = wcs->syswcs; eqout = wcs->equinox; epout = wcs->epoch; wcscstr (cstr, sysout, eqout, epout); wcssize (wcs, &cra, &cdec, &dra, &ddec); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* If RA range includes zero, split it in two */ wrap = 0; if (ra1 > ra2) wrap = 1; else wrap = 0; /* Search zones which include the poles cover 360 degrees in RA */ if (cdec - ddec < -90.0) { if (dec1 > dec2) dec2 = dec1; dec1 = -90.0; ra1 = 0.0; ra2 = 359.99999; wrap = 0; } if (cdec + ddec > 90.0) { if (dec2 < dec1) dec1 = dec2; dec2 = 90.0; ra1 = 0.0; ra2 = 359.99999; wrap = 0; } /* mag1 is always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; /* Open catalog file */ if ((sc = ctgopen (catfile, refcat)) == NULL) { fprintf (stderr,"CTGRNUM: Cannot read catalog %s\n", catfile); return (0); } if (sc->nstars <= 0) { free (sc); if (star != NULL) free (star); sc = NULL; return (0); } if (sortmag > 0 && sortmag <= sc->nmag) magsort = sortmag - 1; else magsort = 1; jstar = 0; /* Loop through catalog */ for (istar = 1; istar <= sc->nstars; istar++) { if (ctgstar (istar, sc, star)) { fprintf (stderr,"\nCTGBIN: Cannot read %s star %d\n", sc->isfil, istar); break; } /* Magnitude */ mag = star->xmag[magsort]; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; /* Set coordinate system for this star */ if (pass) { sysref = star->coorsys; eqref = star->equinox; epref = star->epoch; /* Extract selected fields */ num = star->num; ra = star->ra; dec = star->dec; rapm = star->rapm; decpm = star->decpm; /* If catalog is RA-sorted, stop reading if past highest RA */ if (sc->rasorted && !wrap && ra > ra2) break; /* Get position in output coordinate system, equinox, and epoch */ if (sc->inform != 'X') { if (sc->mprop == 1) wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); else wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); } /* Check distance along RA and Dec axes */ ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } /* Save star in FITS image */ if (pass) { wcs2pix (wcs, ra, dec, &xpix, &ypix, &offscl); if (!offscl) { if (magscale > 0.0) flux = magscale * exp (logt * (-mag / 2.5)); else flux = 1.0; ix = (int) (xpix + 0.5); iy = (int) (ypix + 0.5); addpix1 (image, bitpix, w,h, 0.0,1.0, xpix,ypix, flux); nstar++; jstar++; } else { ix = 0; iy = 0; } if (nlog == 1) { fprintf (stderr,"CTGBIN: %11.6f: %9.5f %9.5f %s", num,ra,dec,cstr); if (magscale > 0.0) fprintf (stderr, " %5.2f", mag); if (!offscl) flux = getpix1 (image, bitpix, w, h, 0.0, 1.0, ix, iy); else flux = 0.0; fprintf (stderr," (%d,%d): %f\n", ix, iy, flux); } /* End of accepted star processing */ } /* Log operation */ if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"CTGBIN: %5d / %5d / %5d sources catalog %s\r", jstar,istar,sc->nstars,catfile); /* End of star loop */ } /* Summarize search */ if (nlog > 0) { fprintf (stderr,"CTGBIN: Catalog %s : %d / %d / %d found\n", catfile,jstar,istar,sc->nstars); } free (star); return (nstar); } /* CTGOPEN -- Open ASCII catalog, returning number of entries */ struct StarCat * ctgopen (catfile, refcat) char *catfile; /* ASCII catalog file name */ int refcat; /* Catalog code from wcscat.h (TXTCAT,BINCAT,TABCAT) */ { struct StarCat *sc; struct Tokens tokens; FILE *fcat; char header[80]; char catpath[128]; /* Full pathname for catalog file */ char *catname; char *str; int nr, lfile, lhead, ldesc; char *catnew, *catdesc; char ctemp, *line, *linend, *cdot; char token[MAX_LTOK]; int ntok; int ltok; if (refcat != TXTCAT) { if (refcat == BINCAT) sc = binopen (catfile); else if (refcat == TABCAT) sc = tabcatopen (catfile, NULL, 0); else sc = NULL; return (sc); } /* Find length of ASCII catalog */ lfile = ctgsize (catfile); /* If catalog is not in current directory, look elsewhere */ if (lfile < 2) { /* Prepend directory name file not in working directory */ if ((str = getenv("WCS_CATDIR")) != NULL ) strcpy (catpath, str); else strcpy (catpath, catdir); strcat (catpath, "/"); strcat (catpath, catfile); lfile = ctgsize (catpath); if (lfile < 2) { fprintf (stderr,"CTGOPEN: ASCII catalog %s has no entries\n",catfile); return (NULL); } } else strcpy (catpath, catfile); /* Allocate catalog data structure */ sc = (struct StarCat *) calloc (1, sizeof (struct StarCat)); /* Open ASCII catalog */ if (!(fcat = fopen (catpath, "r"))) { fprintf (stderr,"CTGOPEN: ASCII catalog %s cannot be read\n",catfile); free (sc); return (NULL); } /* Allocate buffer to hold entire catalog and read it */ if ((sc->catbuff = malloc (lfile+2)) == NULL) { fprintf (stderr,"CTGOPEN: Cannot allocate memory for ASCII catalog %s\n", catfile); fclose (fcat); free (sc); return (NULL); } sc->catbuff[lfile] = (char) 0; sc->catbuff[lfile+1] = (char) 0; /* Separate filename from pathname and save in structure */ catname = strrchr (catfile,'/'); if (catname) catname = catname + 1; else catname = catfile; if (strlen (catname) < 24) strcpy (sc->isfil, catname); else strncpy (sc->isfil, catname, 23); /* Read entire catalog into memory at once */ nr = fread (sc->catbuff, 1, lfile, fcat); if (nr < lfile) { fprintf (stderr,"CTGOPEN: read only %d / %d bytes of file %s\n", nr, lfile, catfile); (void) fclose (fcat); free (sc); return (NULL); } /* Extract catalog information from first line */ sc->inform = 'H'; sc->coorsys = WCS_B1950; sc->epoch = 1950.0; sc->equinox = 1950.0; sc->nmag = 1; sc->mprop = 0; sc->rasorted = 0; sc->sptype = 0; sc->stnum = 1; sc->entepoch = 0; sc->entrv = 0; sc->entpath = 0; catdesc = strchr (sc->catbuff, newline) + 1; lhead = catdesc - sc->catbuff; if (lhead > 79) lhead = 79; if (sc->catbuff[0] == '#' && sc->catbuff[1] == ' ') { strncpy (header, sc->catbuff+2, lhead-2); header[lhead-2] = (char) 0; } else if (sc->catbuff[0] == '#') { strncpy (header, sc->catbuff+1, lhead-1); header[lhead-1] = (char) 0; } else { strncpy (header, sc->catbuff, lhead); header[lhead] = (char) 0; } /* Catalog positions are in radians */ if (strsrch (header, "/a") || strsrch (header, "/A")) sc->inform = 'R'; /* Catalog positions are in B1950 (FK4) coordinates */ if (strsrch (header, "/b") || strsrch (header, "/B")) { sc->coorsys = WCS_B1950; sc->epoch = 1950.0; sc->equinox = 1950.0; } /* Catalog positions are in degrees */ if (strsrch (header, "/d") || strsrch (header, "/D")) sc->inform = 'D'; /* Catalog positions are in ecliptic coordinates */ if (strsrch (header, "/e") || strsrch (header, "/E")) { sc->coorsys = WCS_ECLIPTIC; sc->inform = 'D'; sc->epoch = 2000.0; sc->equinox = 2000.0; } /* Catalog positions are in hh.mm and fractional degrees */ if (strsrch (header, "/f") || strsrch (header, "/F")) sc->inform = 'F'; /* Catalog positions are galactic coordinates */ if (strsrch (header, "/g") || strsrch (header, "/G")) { sc->coorsys = WCS_GALACTIC; sc->inform = 'D'; sc->epoch = 2000.0; sc->equinox = 2000.0; } /* Catalog positions are in hh.mmsssss dd.mmssss format */ if (strsrch (header, "/h") || strsrch (header, "/H")) sc->inform = 'H'; /* Ignore information after position and magnitude */ if (strsrch (header, "/i") || strsrch (header, "/I")) sc->ignore = 1; else sc->ignore = 0; /* Catalog positions are J2000 (FK5) coordinates */ if (strsrch (header, "/j") || strsrch (header, "/J")) { sc->coorsys = WCS_J2000; sc->epoch = 2000.0; sc->equinox = 2000.0; } /* Catalog positions are in fractional hours and fractional degrees */ if (strsrch (header, "/k") || strsrch (header, "/K")) sc->inform = 'K'; /* No magnitude */ if (strsrch (header, "/m") || strsrch (header, "/M")) sc->nmag = 0; else if (strsrch (header, "/2")) sc->nmag = 2; else if (strsrch (header, "/3")) sc->nmag = 3; else if (strsrch (header, "/4")) sc->nmag = 4; else if (strsrch (header, "/5")) sc->nmag = 5; else if (strsrch (header, "/6")) sc->nmag = 6; else if (strsrch (header, "/7")) sc->nmag = 7; else if (strsrch (header, "/8")) sc->nmag = 8; else if (strsrch (header, "/9")) sc->nmag = 9; /* No number in first column, RA or object name first */ if (strsrch (header, "/n") || strsrch (header, "/N")) sc->stnum = 0; /* Object name instead of number in first column */ if (strsrch (header, "/o") || strsrch (header, "/O")) sc->stnum = -16; /* Proper motion */ if (strsrch (header, "/p") || strsrch (header, "/P")) sc->mprop = 1; if (strsrch (header, "/q") || strsrch (header, "/Q")) { sc->coorsys = 0; sc->epoch = 0.0; sc->equinox = 0.0; } /* RA-sorted catalog */ if (strsrch (header, "/r") || strsrch (header, "/R")) sc->rasorted = 1; /* Spectral type present */ if (strsrch (header, "/s") || strsrch (header, "/S")) sc->sptype = 1; /* Table format (hh mm ss dd mm ss) */ if (strsrch (header, "/t") || strsrch (header, "/T")) sc->inform = 'T'; /* Catalog positions are in hhmmss.s ddmmss.s (UZC) */ if (strsrch (header, "/u") || strsrch (header, "/U")) sc->inform = 'U'; /* Radial velocity is included after magnitude(s) */ if (strsrch (header, "/v") || strsrch (header, "/V")) { sc->mprop = 2; sc->entrv = 1; } /* X Y format (x.xxxxxx y.yyyyy) */ if (strsrch (header, "/x") || strsrch (header, "/X")) { sc->inform = 'X'; sc->coorsys = WCS_XY; } /* Epoch per catalog object as yyyy.mmdd */ if (strsrch (header, "/y") || strsrch (header, "/Y")) sc->nepoch = 1; else sc->nepoch = 0; /* Second line is description */ sc->catdata = strchr (catdesc, newline) + 1; ldesc = sc->catdata - catdesc; if (ldesc > 63) ldesc = 63; if (catdesc[0] == '#' && catdesc[1] == ' ') { strncpy (sc->isname, catdesc+2, ldesc-2); sc->isname[ldesc-2] = (char) 0; } else if (catdesc[0] == '#') { strncpy (sc->isname, catdesc+1, ldesc-1); sc->isname[ldesc-1] = (char) 0; } else { strncpy (sc->isname, catdesc, ldesc); sc->isname[ldesc] = (char) 0; } if (sc->entrv > 0 && sc->nmag < 10) { sc->nmag = sc->nmag + 1; strcpy (sc->keymag[sc->nmag-1], "velocity"); } if (sc->nepoch > 0 && sc->nmag < 10) { sc->nmag = sc->nmag + 1; strcpy (sc->keymag[sc->nmag-1], "epoch"); } /* Enumerate entries in ASCII catalog by counting newlines */ catnew = sc->catdata; sc->nstars = 0; while ((catnew = strchr (catnew, newline)) != NULL) { catnew = catnew + 1; if (*catnew != '#') sc->nstars = sc->nstars + 1; } sc->catline = sc->catdata; sc->catlast = sc->catdata + lfile; sc->istar = 1; /* Check number of decimal places in star number, if present */ if (sc->stnum == 1) { /* Temporarily terminate line with 0 */ line = sc->catline; linend = strchr (sc->catline, newline); if (linend == NULL) linend = sc->catlast; ctemp = *linend; *linend = (char) 0; /* Extract information from line of catalog */ ntok = setoken (&tokens, line, NULL); ltok = nextoken (&tokens, token, MAX_LTOK); sc->nnfld = ltok; if (ltok > 0) { sc->nndec = 0; if ((cdot = strchr (token,'.')) != NULL) { while (*(++cdot) != (char)0) sc->nndec++; } } else sc->nndec = 0; *linend = ctemp; } sc->refcat = TXTCAT; (void) fclose (fcat); return (sc); } /* CTGCLOSE -- Close ASCII catalog and free associated data structures */ void ctgclose (sc) struct StarCat *sc; { if (sc == NULL) return; else if (sc->refcat == BINCAT) binclose (sc); else if (sc->refcat == TABCAT) tabcatclose (sc); else if (sc->refcat == TXTCAT) { free (sc->catbuff); free (sc); } else free (sc); sc = NULL; return; } /* CTGSTAR -- Get ASCII catalog entry for one star; return 0 if successful */ int ctgstar (istar, sc, st) int istar; /* Star sequence number in ASCII catalog */ struct StarCat *sc; /* Star catalog data structure */ struct Star *st; /* Star data structure, updated on return */ { struct Tokens tokens; double ydate, dtemp; char *line; char *nextline; char token[80]; char ctemp, *linend; int ntok, itok; int ltok; int imag, nmag; /* Return error if requested number beyond catalog */ if (istar > sc->nstars) { fprintf (stderr, "CTGSTAR: %d is not in catalog\n",istar); return (-1); } /* If star is 0, read next star in catalog */ else if (istar < 1) { line = strchr (sc->catline, newline) + 1; while (*line == '#') line = strchr (line, newline) + 1; if (line == NULL) return (-1); else sc->catline = line; } /* If star is before current star, read from start of catalog */ else if (istar < sc->istar) { sc->istar = 1; sc->catline = sc->catdata; nextline = sc->catline; while (sc->istar < istar) { nextline = strchr (nextline, newline) + 1; while (*nextline == '#') nextline = strchr (nextline, newline) + 1; if (nextline == NULL) return (-1); sc->catline = nextline; sc->istar++; } } /* If star is after current star, read forward to it */ else if (istar > sc->istar) { nextline = sc->catline; while (sc->istar < istar) { nextline = strchr (nextline, newline) + 1; while (*nextline == '#') nextline = strchr (nextline, newline) + 1; if (nextline == NULL) return (-1); sc->catline = nextline; sc->istar++; } } /* Temporarily terminate line with 0 */ line = sc->catline; linend = strchr (sc->catline, newline); if (linend == NULL) linend = sc->catlast; ctemp = *linend; *linend = (char) 0; st->objname[0] = (char) 0; st->datapath[0] = (char) 0; /* Extract information from line of catalog */ ntok = setoken (&tokens, line, NULL); /* Source number */ if (sc->stnum > 0) { ltok = nextoken (&tokens, token, MAX_LTOK); if (ltok > 0) { st->num = atof (token); if (st->num - ((double) ((int) st->num)) < 0.000001) sc->stnum = 1; else sc->stnum = 2; } } else st->num = (double) sc->istar; /* Object name, if at start of line */ if (sc->stnum < 0) { ltok = nextoken (&tokens, token, MAX_LTOK); if (ltok > 31) { strncpy (st->objname, token, 31); st->objname[31] = 0; } else if (ltok > 0) strcpy (st->objname, token); } /* Right ascension or longitude */ ltok = nextoken (&tokens, token, MAX_LTOK); if (ltok < 1) return (-1); /* Translate 3-token right ascension (hh mm ss.ss) */ if (sc->inform == 'T') { int hr, mn; double sec; hr = (int) (atof (token) + 0.5); ltok = nextoken (&tokens, token, MAX_LTOK); if (ltok < 1) return (-1); mn = (int) (atof (token) + 0.5); ltok = nextoken (&tokens, token, MAX_LTOK); if (ltok < 1) return (-1); sec = atof (token); st->ra = 15.0 * ((double) hr + ((double) mn / 60.0) + (sec / 3600.0)); } /* Translate single-token right ascension from hhmmss.ss */ else if (sc->inform == 'U') { dtemp = 0.0001 * atof (token); sprintf (token, "%.6f", dtemp); st->ra = ctg2ra (token); } /* Translate single-token right ascension as degrees */ else if (sc->inform == 'D') st->ra = atof (token); /* Translate single-token right ascension as hh.mm */ else if (sc->inform == 'F') st->ra = ctg2ra (token); /* Translate single-token right ascension as fractional hours */ else if (sc->inform == 'K') st->ra = 15.0 * atof (token); /* Translate single-token right ascension as radians */ else if (sc->inform == 'R') st->ra = raddeg (atof (token)); /* Translate single-token right ascension as X image coordinate */ else if (sc->inform == 'X') st->ra = atof (token); /* Translate single-token right ascension (hh:mm:ss.ss or hh.mmssss) */ else st->ra = ctg2ra (token); /* Declination or latitude */ ltok = nextoken (&tokens, token, MAX_LTOK); if (ltok < 1) return (-1); /* Translate 3-token declination (sdd mm ss.ss) */ if (sc->inform == 'T') { int deg, min; int decsgn = 0; double sec; if (strchr (token, '-') != NULL) { decsgn = 1; deg = (int) (atof (token) - 0.5); } else deg = (int) (atof (token) + 0.5); ltok = nextoken (&tokens, token, MAX_LTOK); if (ltok < 1) return (-1); min = (int) (atof (token) + 0.5); ltok = nextoken (&tokens, token, MAX_LTOK); if (ltok < 1) return (-1); sec = atof (token); st->dec = (double) deg + ((double) min / 60.0) + (sec / 3600.0); if (deg > -1 && decsgn) st->dec = -st->dec; } /* Translate single-token declination as Y image coordinate */ else if (sc->inform == 'X') st->dec = atof (token); /* Translate single-token declination as degrees */ else if (sc->inform == 'D' || sc->inform == 'F' || sc->inform == 'K') st->dec = atof (token); /* Translate single-token declination as radians */ else if (sc->inform == 'R') st->dec = raddeg (atof (token)); /* Translate single-token declination from ddmmss.ss */ else if (sc->inform == 'U') { dtemp = 0.0001 * atof (token); sprintf (token, "%.6f", dtemp); st->dec = ctg2dec (token); } /* Translate single-token declination (dd:mm:ss.ss or dd.mmssss) */ else st->dec = ctg2dec (token); /* Equinox, if not set by header flag */ if (sc->coorsys == 0) { ltok = nextoken (&tokens, token, MAX_LTOK); if (ltok < 1) return (-1); st->coorsys = wcscsys (token); st->equinox = wcsceq (token); st->epoch = sc->epoch; if (st->epoch == 0.0) st->epoch = st->equinox; } else { st->coorsys = sc->coorsys; st->equinox = sc->equinox; st->epoch = sc->epoch; } /* Magnitude, if present */ nmag = sc->nmag; if (sc->nmag > 0 && sc->mprop == 2) nmag = nmag - 1; if (sc->nmag > 0 && sc->nepoch) nmag = nmag - 1; if (nmag > 0) { for (imag = 0; imag < nmag; imag++) { ltok = nextoken (&tokens, token, MAX_LTOK); if (ltok > 0) st->xmag[imag] = atof (token); else st->xmag[imag] = 0.0; } } /* Spectral type, if present */ if (sc->sptype > 0) { ltok = nextoken (&tokens, token, MAX_LTOK); if (ltok > 0) { if (token[0] == ' ' && token[1] == ' ') { st->isp[0] = '_'; st->isp[1] = '_'; } else { st->isp[0] = token[0]; st->isp[1] = token[1]; } } } /* Radial velocity, if present */ if (sc->entrv > 0) { ltok = nextoken (&tokens, token, MAX_LTOK); if (ltok > 0) st->radvel = atof (token); else st->radvel = 0.0; st->xmag[nmag] = st->radvel; } /* Proper motion, if present */ if (sc->mprop == 1) { ltok = nextoken (&tokens, token, MAX_LTOK); if (ltok > 1) st->rapm = atof (token) / 3600.0; ltok = nextoken (&tokens, token, MAX_LTOK); if (ltok > 1) st->decpm = atof (token) / 3600.0; } /* Epoch, if present */ if (sc->nepoch) { ltok = nextoken (&tokens, token, MAX_LTOK); if (strchr (token, '-') != NULL) st->epoch = fd2ep (token); else { ydate = atof (token); if (ydate < 3000.0 && ydate > 0.0) st->epoch = dt2ep (ydate, 12.0); else if (ydate < 100000.0) st->epoch = mjd2ep (ydate); else st->epoch = jd2ep (ydate); } if (sc->entrv > 0) st->xmag[nmag+1] = st->epoch; else st->xmag[nmag] = st->epoch; } /* Object name */ itok = tokens.itok; if (itok < ntok && !sc->ignore) { if (sc->stnum > 0) { itok = -(itok+1); ltok = getoken (&tokens, itok, token, MAX_LTOK); if (ltok > 79) { strncpy (st->objname, token, 79); st->objname[79] = 0; } else if (ltok > 0) strcpy (st->objname, token); } else { itok = -(itok+1); ltok = getoken (&tokens, itok, token, MAX_LTOK); if (ltok > 79) { strncpy (st->datapath, token, 79); st->datapath[79] = 0; } else if (ltok > 0) strcpy (st->datapath, token); } } *linend = ctemp; return (0); } /* CTGSIZE -- return size of ASCII catalog file in bytes */ static int ctgsize (filename) char *filename; /* Name of file for which to find size */ { FILE *diskfile; long filesize; /* Open file */ if ((diskfile = fopen (filename, "r")) == NULL) return (-1); /* Move to end of the file */ if (fseek (diskfile, 0, 2) == 0) /* Position is the size of the file */ filesize = ftell (diskfile); else filesize = -1; fclose (diskfile); return (filesize); } /* ISACAT -- Return 1 if file is likely to be an ASCII catalog */ int isacat (catpath) char *catpath; { char buf[100]; char *errc; FILE *fcat; /* Open ASCII catalog */ if (!(fcat = fopen (catpath, "r"))) { return (0); } errc = fgets (buf, 100, fcat); fclose (fcat); if (isnum (buf)) return (0); else return (1); } /* CTG2RA -- Read the right ascension, ra, in sexagesimal hours from in[] */ static double ctg2ra (in) char *in; /* Character string */ { double ra; /* Right ascension in degrees (returned) */ ra = ctg2dec (in); ra = ra * 15.0; return (ra); } /* CTG2DEC -- Read the declination, dec, in sexagesimal degrees from in[] */ static double ctg2dec (in) char *in; /* Character string */ { double dec; /* Declination in degrees (returned) */ double deg, min, sec, sign; char *value, *c1; dec = 0.0; /* Translate value from ASCII colon-delimited string to binary */ if (!in[0]) return (dec); else value = in; /* Set sign */ if (!strchr (value,'-')) sign = 1.0; else { sign = -1.0; value = strchr (value,'-') + 1; } /* Translate value from ASCII colon-delimited string to binary */ if ((c1 = strchr (value,':')) != NULL) { *c1 = 0; deg = (double) atoi (value); *c1 = ':'; value = c1 + 1; if ((c1 = strchr (value,':')) != NULL) { *c1 = 0; min = (double) atoi (value); *c1 = ':'; value = c1 + 1; sec = atof (value); } else { sec = 0.0; if ((c1 = strchr (value,'.')) != NULL) min = atof (value); if (strlen (value) > 0) min = (double) atoi (value); } dec = sign * (deg + (min / 60.0) + (sec / 3600.0)); } /* Translate value from dd.mmssss */ else if ((c1 = strchr (value,'.')) != NULL) { double xnum, deg, min, sec; xnum = atof (value); deg = (double)((int) (xnum + 0.000000001)); xnum = (xnum - deg) * 100.0; min = (double)((int) (xnum + 0.000000001)); sec = (xnum - min) * 100.0; dec = sign * (deg + (min / 60.0) + (sec / 3600.0)); } /* Translate integer */ else dec = sign * (double) atoi (value); return (dec); } /* Oct 16 1998 New subroutines * Oct 20 1998 Clean up error messages * Oct 26 1998 Return object names in catread() and catrnum() * Oct 29 1998 Correctly assign numbers when too many stars are found * Oct 30 1998 Fix epoch and equinox for J2000 * Nov 9 1998 Drop out of star loop if rasorted catalog and past max RA * Dec 8 1998 Do not declare catsize() static * Dec 21 1998 Fix parsing so first character of line is not dropped * Jan 20 1999 Use strchr() instead of strsrch() for single char searches * Jan 29 1999 Default to star id number present * Feb 1 1999 Rewrite tokenizing subroutines for clarity * Feb 1 1999 Add match argument to catrnum() * Feb 2 1999 Add code to count decimal places in numbers * Feb 2 1999 Set sysout, eqout, and epout in catrnum() if not set * Feb 10 1999 Implement per star coordinate system * Feb 11 1999 Change starcat.insys to starcat.coorsys for consistency * Feb 17 1999 Fix per star coordinate system bugs * May 20 1999 Add option to read epoch of coordinates * Jun 16 1999 Use SearchLim() * Aug 16 1999 Fix bug to fix failure to search across 0:00 RA * Aug 25 1999 Return real number of stars from catread() * Sep 13 1999 Use these subroutines for general catalog access * Sep 16 1999 Fix bug which didn't always return closest stars * Sep 16 1999 Add distsort argument so brightest stars in circle works, too * Oct 5 1999 Move token subroutines to catutil.c * Oct 15 1999 Fix calls to catclose(); eliminate dno in catstar() * Oct 22 1999 Fix declarations after lint * Oct 22 1999 Rename subroutines from cat* to ctg* to avoid system conflict * Nov 16 1999 Transfer dec degree sign if table format * * Jan 10 2000 Add second magnitude to tabread() and tabrnum() * Mar 10 2000 Add proper motions to ctgread(), ctgrnum(), tabread(), tabrnum() * Mar 15 2000 Add proper motions to binread(), binrnum(), actread(), actrnum() * Apr 3 2000 Implement fractional degrees (/d) for positions * Apr 3 2000 Add /i option to ignore stuff at end of line * Apr 3 2000 Ignore leading # on first two lines of ASCII catalog file * May 20 2000 Add Tycho 2 catalog support * Jun 23 2000 Ignore any line with # as first character, not just heading * Jun 26 2000 Implement /X catalog flag to avoid conversions * Jun 26 2000 Add coordinate system to SearchLim() arguments * Jun 26 2000 Ignore lines starting with # when counting stars in catalog * Jul 12 2000 Add star catalog data structure to ctgread() argument list * Jul 25 2000 Pass star catalog address of data structure address * Sep 20 2000 Implement multiple catalog magnitudes; return only first 2 * Sep 20 2000 Add isacat() subroutine to detect ASCII catalogs * Sep 25 2000 Add spectral type with flag /s * Oct 17 2000 Add missing arguments in generic binrnum() call * Oct 24 2000 Use ujcread() and ujcrnum() for USNO plate catalogs * Nov 21 2000 Add WEBCAT as tab catalog results returned from the Web * Nov 28 2000 Add starcat structure to *rnum() calls * Dec 18 2000 Include math.h for sqrt() * * Feb 14 2001 Search all around RA if either pole is included * Feb 16 2001 Update comments * May 22 2001 Add GSC-ACT catalog; pass refcat to gscread() and gscrnum() * May 23 2001 Add 2MASS Point Source Catalog * May 29 2001 Save length of star i.d. number in ctgopen() * Jun 18 2001 Add maximum length of returned string to getoken(), nextoken() * Jun 20 2001 Add GSC II to ctgread() and ctgrnum() * Aug 8 2001 Add /v option to return radial velocity * Aug 8 2001 Add /f option for hhmmss.s ddmmss.s coordinates * Aug 24 2001 Use STNUM < 0 instead of STNUM ==5 for object name not number * Sep 11 2001 Allow an arbitrary number of magnitudes * Sep 11 2001 Add sort magnitude as argument to *read() subroutines * Sep 19 2001 Drop fitshead.h; it is in wcs.h * Sep 27 2001 Fix bug which reset number of magnitudes to 1 if /m not last * Oct 17 2001 Fix argument sequence bug in ty2read() call * Dec 11 2001 Set magsort which was unitialized in ctgread() * * Jan 31 2002 Always return NULL for object if no object name in catalog * Mar 12 2002 Add /a flag for positions in radians * May 6 2002 Allow object names to be up to 79 characters * Aug 6 2002 Change keymag to avector of strings * Oct 29 2002 Change UZC format to /u; add /f as fractional hours and degrees * Oct 30 2002 Read epoch as MJD or ISO data+time as well as yyyy.ddmm for /y * * Jan 16 2003 Add USNO-B1.0 Catalog * Mar 11 2003 Improve position filtering * Apr 3 2003 Drop call to gsc2rnum(); it didn't do anything anyway * Apr 23 2003 Add ucacread() and ucacrnum() * May 21 2003 Pass catalog names for UCAC and 2MASS PSC * Aug 22 2003 Add radi argument for inner edge of search annulus * Sep 25 2003 Add ctgbin() to fill an image with sources * Nov 18 2003 Initialize image size and bits/pixel from header in ctgbin() * Dec 3 2003 Add filename to gsc2read() call; add USNO YB6 Catalog * Dec 12 2003 Fix bug in wcs2pix() call in ctgbin(); fix ujcread() call * * Jan 5 2004 Add SDSS catalog to ctgread() * Jan 12 2004 Add 2MASS Extended Source Catalog to ctgread() and ctgrnum() * Apr 23 2004 Add ctgrdate() to read by date range * Apr 23 2004 Fix bug in ctgrnum() to index all returns on nstar, not jnum * Nov 5 2004 Finish implementing proper motion in ASCII catalogs * * Jan 18 2005 Fix bug dealing with negative declinations in ASCII table format * Aug 5 2005 Add additional catalog codes for Tycho-2 and 2MASS w/mag errs * Jun 6 2006 Add SKY2000 catalog * Jun 20 2006 Drop unused variables * Jun 30 2006 Add match argument to tabrnum() to enable sequential reads * Nov 6 2006 Add object name to sdssread() call to deal with long IDs * Nov 15 2006 Fix binning * Nov 16 2006 Return -1 for SDSS and GSC2; binning subroutines do not exist * * Jan 9 2007 Fix reference to refcat code in wcscat.h * Jan 9 2007 Drop catfile from call to sdssread() * Mar 13 2007 Add object name array tobj to gsc2read() call * Jul 13 2007 Add skybotread() for SkyBot solar system object search * * Aug 27 2009 Add /k option for fractional hours of RA and degrees of Dec * Sep 30 2009 Add UCAC3 * * May 22 2012 Accept up to 9 magnitudes per entry instead of 4 * * Feb 15 2013 Add UCAC4 * * Jan 24 2017 Add datapath return from catalog in tpath */ wcstools-3.9.5/libwcs/fitsfile.h0000664000016200001660000017707312351116227015733 0ustar minkoirsys/*** File fitsfile.h FITS and IRAF file access subroutines *** June 20, 2014 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2014 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #ifndef fitsfile_h_ #define fitsfile_h_ #include "fitshead.h" /* Declarations for subroutines in fitsfile.c, imhfile.c, imio.c, * fileutil.c, and dateutil.c */ #define FITSBLOCK 2880 /* FITS table keyword structure */ struct Keyword { char kname[10]; /* Keyword for table entry */ int lname; /* Length of keyword name */ int kn; /* Index of entry on line */ int kf; /* Index in line of first character of entry */ int kl; /* Length of entry value */ char kform[8]; /* Format for this value */ }; /* Structure for access to tokens within a string */ #define MAXTOKENS 1000 /* Maximum number of tokens to parse */ #define MAXWHITE 20 /* Maximum number of different whitespace characters */ struct Tokens { char *line; /* Line which has been parsed */ int lline; /* Number of characters in line */ int ntok; /* Number of tokens on line */ int nwhite; /* Number of whitespace characters */ char white[MAXWHITE]; /* Whitespace (separator) characters */ char *tok1[MAXTOKENS]; /* Pointers to start of tokens */ int ltok[MAXTOKENS]; /* Lengths of tokens */ int itok; /* Current token number */ }; #ifdef __cplusplus /* C++ prototypes */ extern "C" { #endif #ifdef __STDC__ /* Full ANSI prototypes */ /* Declarations for subroutines in fitsfile.c, imhfile.c, imio.c, * fileutil.c, and dateutil.c */ /* FITS file access subroutines in fitsfile.c */ int fitsropen( /* Open a FITS file for reading, returning a FILE pointer */ char *inpath); /* Pathname for FITS tables file to read */ char *fitsrhead( /* Read a FITS header */ char *filename, /* Name of FITS image file */ int *lhead, /* Allocated length of FITS header in bytes (returned) */ int *nbhead); /* Number of bytes before start of data (returned) */ char *fitsrtail( /* Read FITS header appended to graphics file */ char *filename, /* Name of FITS image file */ int *lhead, /* Allocated length of FITS header in bytes (returned) */ int *nbhead); /* Number of bytes before start of data (returned) */ char *fitsrimage( /* Read a FITS image */ char *filename, /* Name of FITS image file */ int nbhead, /* Actual length of image header(s) in bytes */ char *header); /* FITS header for image (previously read) */ char *fitsrfull( /* Read a FITS image of any dimension */ char *filename, /* Name of FITS image file */ int nbhead, /* Actual length of image header(s) in bytes */ char *header); /* FITS header for image (previously read) */ char *fitsrsect( /* Read a piece of a FITS image, header */ char *filename, /* Name of FITS image file */ char *header, /* FITS header for image (previously read) */ int nbhead, /* Actual length of image header(s) in bytes */ int x0, /* FITS image X coordinate of first pixel */ int y0, /* FITS image Y coordinate of first pixel */ int nx, /* Number of columns to read (less than NAXIS1) */ int ny, /* Number of rows to read (less than NAXIS2) */ int nlog); /* Note progress mod this rows */ int fitswhead( /* Write FITS header; keep file open for further writing */ char *filename, /* Name of FITS image file */ char *header); /* FITS header for image (previously read) */ int fitswexhead( /* Write FITS header in place */ char *filename, /* Name of FITS image file */ char *header); /* FITS header for image */ int fitswext( /* Write FITS header and image as extension to a file */ char *filename, /* Name of FITS image file */ char *header, /* FITS image header */ char *image); /* FITS image pixels */ int fitswhdu( /* Write FITS head and image as extension */ int fd, /* File descriptor */ char *filename, /* Name of FITS image file */ char *header, /* FITS image header */ char *image); /* FITS image pixels */ int fitswimage( /* Write FITS header and image */ char *filename, /* Name of FITS image file */ char *header, /* FITS image header */ char *image); /* FITS image pixels */ int fitscimage( /* Write FITS header and copy FITS image */ char *filename, /* Name of output FITS image file */ char *header, /* FITS image header */ char *filename0); /* Name of input FITS image file */ int isfits( /* Return 1 if file is a FITS file */ char *filename); /* Name of file to check */ void fitserr(); /* Print FITS error message to stderr */ void setfitsinherit( /* Set flag to append primary data header */ int inh); /* 1 to inherit primary data header, else 0 */ int fitsheadsize( /* Return size of fitsheader in bytes */ char *header); /* FITS image header */ /* FITS table file access subroutines in fitsfile.c */ int fitsrtopen( /* Open FITS table file and fill structure with * pointers to selected keywords * Return file descriptor (-1 if unsuccessful) */ char *inpath, /* Pathname for FITS tables file to read */ int *nk, /* Number of keywords to use */ struct Keyword **kw, /* Structure for desired entries */ int *nrows, /* Number of rows in table (returned) */ int *nchar, /* Number of characters in one table row (returned) */ int *nbhead); /* Number of characters before table starts */ int fitsrthead( /* Read pointers to selected keywords * from FITS table header */ char *header, /* Header for FITS tables file */ int *nk, /* Number of keywords to use */ struct Keyword **kw, /* Structure for desired entries */ int *nrows, /* Number of rows in table (returned) */ int *nchar); /* Number of characters in one table row (returned) */ void fitsrtlset(void); /* Reset FITS Table buffer limits from start of data */ int fitsrtline( /* Return specified line of FITS table */ int fd, /* File descriptor for FITS file */ int nbhead, /* Number of bytes in FITS header */ int lbuff, /* Number of bytes in table buffer */ char *tbuff, /* FITS table buffer */ int irow, /* Number of table row to read */ int nbline, /* Number of bytes to read for this line */ char *line); /* One line of FITS table (returned) */ short ftgeti2( /* Extract column for keyword from FITS table line * as short */ char *entry, /* Row or entry from table */ struct Keyword *kw); /* Table column information from FITS header */ int ftgeti4( /* Extract column for keyword from FITS table line * as int */ char *entry, /* Row or entry from table */ struct Keyword *kw); /* Table column information from FITS header */ float ftgetr4( /* Extract column for keyword from FITS table line * as float */ char *entry, /* Row or entry from table */ struct Keyword *kw); /* Table column information from FITS header */ double ftgetr8( /* Extract column for keyword from FITS table line * as double */ char *entry, /* Row or entry from table */ struct Keyword *kw); /* Table column information from FITS header */ int ftgetc( /* Extract column for keyword from FITS table line * as char string */ char *entry, /* Row or entry from table */ struct Keyword *kw, /* Table column information from FITS header */ char *string, /* Returned string */ int maxchar); /* Maximum number of characters in returned string */ void moveb ( /* Copy nbytes bytes from source+offs to dest+offd */ char *source, /* Pointer to source */ char *dest, /* Pointer to destination */ int nbytes, /* Number of bytes to move */ int offs, /* Offset in bytes in source from which to start copying */ int offd); /* Offset in bytes in destination to which to start copying */ /* IRAF file access subroutines in imhfile.c */ char *irafrhead( /* Read IRAF .imh header file and translate to FITS header */ char *filename, /* Name of IRAF header file */ int *lihead); /* Length of IRAF image header in bytes (returned) */ char *irafrimage( /* Read IRAF image pixels (call after irafrhead) */ char *fitsheader); /* FITS image header (filled) */ int irafwhead( /* Write IRAF .imh header file */ char *hdrname, /* Name of IRAF header file */ int lhead, /* Length of IRAF header */ char *irafheader, /* IRAF header */ char *fitsheader); /* FITS image header */ int irafwimage( /* Write IRAF .imh header file and .pix image file */ char *hdrname, /* Name of IRAF header file */ int lhead, /* Length of IRAF header */ char *irafheader, /* IRAF header */ char *fitsheader, /* FITS image header */ char *image); /* IRAF image */ int isiraf( /* return 1 if IRAF imh file, else 0 */ char *filename); /* Name of file to check */ char *iraf2fits( /* Convert IRAF image header to FITS image header, * returning FITS header */ char *hdrname, /* IRAF header file name (may be path) */ char *irafheader, /* IRAF image header */ int nbiraf, /* Number of bytes in IRAF header */ int *nbfits); /* Number of bytes in FITS header (returned) */ char *fits2iraf( /* Convert FITS image header to IRAF image header, * returning IRAF header */ char *fitsheader, /* FITS image header */ char *irafheader, /* IRAF image header (returned updated) */ int nbhead, /* Length of IRAF header */ int *nbiraf); /* Length of returned IRAF header */ /* Image pixel access subroutines in imio.c */ double getpix( /* Read one pixel from any data type 2-D array (0,0)*/ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel * 16 = short, -16 = unsigned short, 32 = int * -32 = float, -64 = double */ int w, /* Image width in pixels */ int h, /* Image height in pixels */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int x, /* Zero-based horizontal pixel number */ int y); /* Zero-based vertical pixel number */ double getpix1( /* Read one pixel from any data type 2-D array (1,1)*/ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ int w, /* Image width in pixels */ int h, /* Image height in pixels */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int x, /* One-based horizontal pixel number */ int y); /* One-based vertical pixel number */ double maxvec( /* Get maximum value in vector from a image */ char *image, /* Image array from which to extract vector */ int bitpix, /* Number of bits per pixel in image */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int pix1, /* Offset of first pixel to extract */ int npix); /* Number of pixels to extract */ double minvec( /* Get minimum value in vector from a image */ char *image, /* Image array from which to extract vector */ int bitpix, /* Number of bits per pixel in image */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int pix1, /* Offset of first pixel to extract */ int npix); /* Number of pixels to extract */ void putpix( /* Write one pixel to any data type 2-D array (0,0)*/ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ int w, /* Image width in pixels */ int h, /* Image height in pixels */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int x, /* Zero-based horizontal pixel number */ int y, /* Zero-based vertical pixel number */ double dpix); /* Value to put into image pixel */ void putpix1( /* Write one pixel to any data type 2-D array (1,1) */ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ int w, /* Image width in pixels */ int h, /* Image height in pixels */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int x, /* One-based horizontal pixel number */ int y, /* One-based vertical pixel number */ double dpix); /* Value to put into image pixel */ void addpix( /* Add to one pixel in any data type 2-D array (0,0)*/ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ int w, /* Image width in pixels */ int h, /* Image height in pixels */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int x, /* Zero-based horizontal pixel number */ int y, /* Zero-based vertical pixel number */ double dpix); /* Value to add to image pixel */ void addpix1( /* Add to one pixel in any data type 2-D array (1,1)*/ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ int w, /* Image width in pixels */ int h, /* Image height in pixels */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int x, /* One-based horizontal pixel number */ int y, /* One-based vertical pixel number */ double dpix); /* Value to add to image pixel */ void movepix( /* Move one pixel value between two 2-D arrays (0,0) */ char *image1, /* Pointer to first pixel in input image */ int bitpix1, /* Bits per input pixel (FITS codes) */ int w1, /* Number of horizontal pixels in input image */ int x1, /* Zero-based row for input pixel */ int y1, /* Zero-based column for input pixel */ char *image2, /* Pointer to first pixel in output image */ int bitpix2, /* Bits per output pixel (FITS codes) */ int w2, /* Number of horizontal pixels in output image */ int x2, /* Zero-based row for output pixel */ int y2); /* Zero-based column for output pixel */ void movepix1( /* Move one pixel value between two 2-D arrays (1,1) */ char *image1, /* Pointer to first pixel in input image */ int bitpix1, /* Bits per input pixel (FITS codes) */ int w1, /* Number of horizontal pixels in input image */ int x1, /* One-based row for input pixel */ int y1, /* One-based column for input pixel */ char *image2, /* Pointer to first pixel in output image */ int bitpix2, /* Bits per output pixel (FITS codes) */ int w2, /* Number of horizontal pixels in output image */ int x2, /* One-based row for output pixel */ int y2); /* One-based column for output pixel */ /* Image vector processing subroutines in imio.c */ void addvec( /* Add constant to vector from 2-D array */ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int pix1, /* Offset of first pixel to which to add */ int npix, /* Number of pixels to which to add */ double dpix); /* Value to add to pixels */ void multvec( /* Multiply vector from 2-D array by a constant */ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int pix1, /* Offset of first pixel to multiply */ int npix, /* Number of pixels to multiply */ double dpix); /* Value to add to pixels */ void getvec( /* Read vector from 2-D array */ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int pix1, /* Offset of first pixel to extract */ int npix, /* Number of pixels to extract */ double *dvec0); /* Vector of pixels (returned) */ void putvec( /* Write vector into 2-D array */ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int pix1, /* Offset of first pixel to insert */ int npix, /* Number of pixels to insert */ double *dvec0); /* Vector of pixels to insert */ void fillvec( /* Write constant into a vector */ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int pix1, /* Zero-based offset of first pixel to multiply */ int npix, /* Number of pixels to multiply */ double dpix); /* Value to which to set pixels */ void fillvec1( /* Write constant into a vector */ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int pix1, /* One-based offset of first pixel to multiply */ int npix, /* Number of pixels to multiply */ double dpix); /* Value to which to set pixels */ /* Image pixel byte-swapping subroutines in imio.c */ void imswap( /* Swap alternating bytes in a vector */ int bitpix, /* Number of bits per pixel */ char *string, /* Address of starting point of bytes to swap */ int nbytes); /* Number of bytes to swap */ void imswap2( /* Swap bytes in a vector of 2-byte (short) integers */ char *string, /* Address of starting point of bytes to swap */ int nbytes); /* Number of bytes to swap */ void imswap4( /* Reverse bytes in a vector of 4-byte numbers */ char *string, /* Address of starting point of bytes to swap */ int nbytes); /* Number of bytes to swap */ void imswap8( /* Reverse bytes in a vector of 8-byte numbers */ char *string, /* Address of starting point of bytes to swap */ int nbytes); /* Number of bytes to swap */ int imswapped(void); /* Return 1 if machine byte order is not FITS order */ /* File utilities from fileutil.c */ int getfilelines( /* Return number of lines in an ASCII file */ char *filename); /* Name of file to check */ char *getfilebuff( /* Return entire file contents in a character string */ char *filename); /* Name of file to read */ int getfilesize( /* Return size of a binary or ASCII file */ char *filename); /* Name of file to check */ int isimlist( /* Return 1 if file is list of FITS or IRAF image files, else 0 */ char *filename); /* Name of file to check */ int isimlistd( /* Return 1 if file is list of FITS or IRAF image files, else 0 */ char *filename, /* Name of file to check */ char *rootdir); /* Name of root directory for files in list */ int isfilelist( /* Return 1 if list of readable files, else 0 */ char *filename, /* Name of file to check */ char *rootdir); /* Name of root directory for files in list */ int isfile( /* Return 1 if file is a readable file, else 0 */ char *filename); /* Name of file to check */ int istiff( /* Return 1 if TIFF image file, else 0 */ char *filename); /* Name of file to check */ int isjpeg( /* Return 1 if JPEG image file, else 0 */ char *filename); /* Name of file to check */ int isgif( /* Return 1 if GIF image file, else 0 */ char *filename); /* Name of file to check */ int next_line ( /* Return the next line of an ASCII file */ FILE *diskfile, /* File descriptor for ASCII file */ int ncmax, /* Maximum number of characters returned */ char *line); /* Next line (returned) */ int first_token( /* Return first token from the next line of an ASCII file */ FILE *diskfile, /* File descriptor for ASCII file */ int ncmax, /* Maximum number of characters returned */ char *token); /* First token on next line (returned) */ int stc2s ( /* Replace character in string with space */ char *spchar, /* Character to replace with spaces */ char *string); /* Character string to process */ int sts2c ( /* Replace spaces in string with character */ char *spchar, /* Character with which to replace spaces */ char *string); /* Character string to process */ /* Subroutines for access to tokens within a string from fileutil.c */ int setoken( /* Tokenize a string for easy decoding */ struct Tokens *tokens, /* Token structure returned */ char *string, /* character string to tokenize */ char *cwhite); /* additional whitespace characters * if = tab, disallow spaces and commas */ int nextoken( /* Get next token from tokenized string */ struct Tokens *tokens, /* Token structure returned */ char *token, /* token (returned) */ int maxchars); /* Maximum length of token */ int getoken( /* Get specified token from tokenized string */ struct Tokens *tokens, /* Token structure returned */ int itok, /* token sequence number of token * if <0, get whole string after token -itok * if =0, get whole string */ char *token, /* token (returned) */ int maxchars); /* Maximum length of token */ /* Subroutines for translating dates and times in dateutil.c */ /* Subroutines to convert between floating point and vigesimal angles */ void ang2hr ( /* Fractional degrees to hours as hh:mm:ss.ss */ double angle, /* Angle in fractional degrees */ int lstr, /* Maximum number of characters in string */ char *string); /* Character string (hh:mm:ss.ss returned) */ void ang2deg ( /* Fractional degrees to degrees as dd:mm:ss.ss */ double angle, /* Angle in fractional degrees */ int lstr, /* Maximum number of characters in string */ char *string); /* Character string (dd:mm:ss.ss returned) */ double deg2ang ( /* Degrees as dd:mm:ss.ss to fractional degrees */ char *angle); /* Angle as dd:mm:ss.ss */ double hr2ang ( /* Hours as hh:mm:ss.ss to fractional degrees */ char *angle); /* Angle in sexigesimal hours (hh:mm:ss.sss) */ /* Subroutines to convert from year and day of year */ void doy2dt( /* Year and day of year to yyyy.mmdd hh.mmss */ int year, /* Year */ double doy, /* Day of year with fraction */ double *date, /* Date as yyyy.mmdd (returned) */ double *time); /* Time as hh.mmssxxxx (returned) */ double doy2ep( /* Year and day of year to fractional year (epoch) */ int year, /* Year */ double doy); /* Day of year with fraction */ double doy2epb( /* year and day of year to Besselian epoch */ int year, /* Year */ double doy); /* Day of year with fraction */ double doy2epj( /* year and day of year to Julian epoch */ int year, /* Year */ double doy); /* Day of year with fraction */ char *doy2fd( /* year and day of year to FITS date */ int year, /* Year */ double doy); /* Day of year with fraction */ double doy2jd( /* year and day of year to Julian Day */ int year, /* Year */ double doy); /* Day of year with fraction */ double doy2mjd( /* year and day of year to Modified Julian Day */ int year, /* Year */ double doy); /* Day of year with fraction */ double doy2ts( /* year and day of year to seconds since 1950.0 */ int year, /* Year */ double doy); /* Day of year with fraction */ int doy2tsi( /* year and day of year to IRAF seconds since 1980-01-01 */ int year, /* Year */ double doy); /* Day of year with fraction */ time_t doy2tsu( /* year and day of year to Unix seconds since 1970-01-01 */ int year, /* Year */ double doy); /* Day of year with fraction */ /* Subroutines to convert from date and time */ void dt2doy( /* yyyy.mmdd hh.mmss to year and day of year */ double date, /* Date as yyyy.mmdd * yyyy = calendar year (e.g. 1973) * mm = calendar month (e.g. 04 = april) * dd = calendar day (e.g. 15) */ double time, /* Time as hh.mmssxxxx * if time<0, it is time as -(fraction of a day) * hh = hour of day (0 .le. hh .le. 23) * nn = minutes (0 .le. nn .le. 59) * ss = seconds (0 .le. ss .le. 59) * xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ int *year, /* Year (returned) */ double *doy); /* Day of year with fraction (returned) */ double dt2ep( /* yyyy.ddmm and hh.mmsss to fractional year (epoch) */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ double dt2epb( /* yyyy.ddmm and hh.mmsss to Besselian epoch */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ double dt2epj( /* yyyy.ddmm and hh.mmsss to Julian epoch */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ char *dt2fd( /* yyyy.ddmm and hh.mmsss to FITS date string */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ void dt2i( /* yyyy.ddmm and hh.mmsss to year, month, day, hrs, min, sec */ double date, /* Date as yyyy.mmdd */ double time, /* Time as hh.mmssxxxx */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ double dt2jd( /* yyyy.ddmm and hh.mmsss to Julian Day */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ double dt2mjd( /* yyyy.ddmm and hh.mmsss to Modified Julian Day */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ double dt2ts( /* yyyy.ddmm and hh.mmsss to seconds since 1950.0 */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ int dt2tsi( /* yyyy.ddmm and hh.mmsss to IRAF seconds since 1980-01-01 */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ time_t dt2tsu( /* yyyy.ddmm and hh.mmsss to Unix seconds since 1970-01-01 */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ /* Subroutines to convert from epoch (various types of fractional year) */ void ep2dt( /* Fractional year to yyyy.mmdd hh.mmssss */ double epoch, /* Date as fractional year */ double *date, /* Date as yyyy.mmdd (returned) */ double *time); /* Time as hh.mmssxxxx (returned) */ void epb2dt( /* Besselian epoch to yyyy.mmdd hh.mmssss */ double epoch, /* Besselian epoch (fractional 365.242198781-day years) */ double *date, /* Date as yyyy.mmdd (returned) */ double *time); /* Time as hh.mmssxxxx (returned) */ void epj2dt( /* Julian epoch to yyyy.mmdd hh.mmssss */ double epoch, /* Julian epoch (fractional 365.25-day years) */ double *date, /* Date as yyyy.mmdd (returned)*/ double *time); /* Time as hh.mmssxxxx (returned) */ char *ep2fd( /* Fractional year to FITS date string yyyy-mm-ddThh:mm:ss.ss */ double epoch); /* Date as fractional year */ char *epb2fd( /* Besselian epoch to FITS date string yyyy-mm-ddThh:mm:ss.ss */ double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ char *epj2fd( /* Julian epoch to FITS date string yyyy-mm-ddThh:mm:ss.ss */ double epoch); /* Julian epoch (fractional 365.25-day years) */ void ep2i( /* Fractional year to year, month, day, hours, min., sec. */ double epoch, /* Date as fractional year */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ void epb2i( /* Besselian epoch to year, month, day, hours, min., sec. */ double epoch, /* Besselian epoch (fractional 365.242198781-day years) */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ void epj2i( /* Julian epoch to year, month, day, hours, min., sec. */ double epoch, /* Julian epoch (fractional 365.25-day years) */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ double ep2jd( /* Fractional year to Julian Date */ double epoch); /* Date as fractional year */ double epb2jd( /* Besselian epoch to Julian Date */ double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ double epj2jd( /* Julian epoch to Julian Date */ double epoch); /* Julian epoch (fractional 365.25-day years) */ double ep2mjd( /* Fractional year to Modified Julian Date */ double epoch); /* Date as fractional year */ double epb2mjd( /* Besselian epoch to Modified Julian Date */ double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ double epj2mjd( /* Julian epoch to Modified Julian Date */ double epoch); /* Julian epoch (fractional 365.25-day years) */ double ep2epb( /* Fractional year to Besselian epoch */ double epoch); /* Date as fractional year */ double ep2epj( /* Fractional year to Julian epoch */ double epoch); /* Date as fractional year */ double epb2epj( /* Besselian epoch to Julian epoch */ double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ double epj2epb( /* Julian epoch to Besselian epoch */ double epoch); /* Julian epoch (fractional 365.25-day years) */ double epb2ep( /* Besselian epoch to fractional year */ double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ double epj2ep( /* Julian epoch to fractional year */ double epoch); /* Julian epoch (fractional 365.25-day years) */ double ep2ts( /* Fractional year to seconds since 1950.0 */ double epoch); /* Date as fractional year */ double epb2ts( /* Besselian epoch to seconds since 1950.0 */ double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ double epj2ts( /* Julian epoch to seconds since 1950.0 */ double epoch); /* Julian epoch (fractional 365.25-day years) */ /* Convert from FITS standard date string */ void fd2dt( /* FITS standard date string to date and time */ char *string, /* FITS date string, which may be: * fractional year * dd/mm/yy (FITS standard before 2000) * dd-mm-yy (nonstandard use before 2000) * yyyy-mm-dd (FITS standard after 1999) * yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ double *date, /* Date as yyyy.mmdd (returned)*/ double *time); /* Time as hh.mmssxxxx (returned) */ void fd2doy( /* FITS standard date string to year, day of year */ char *string, /* FITS date string */ int *year, /* Year (returned) */ double *doy); /* Day of year with fraction (returned) */ double fd2ep( /* FITS standard date string to fractional year (epoch) */ char *string); /* FITS date string */ double fd2epb( /* FITS standard date string to Besselian epoch */ char *string); /* FITS date string */ double fd2epj( /* FITS standard date string to Julian epoch */ char *string); /* FITS date string */ char *fd2fd( /* Any FITS standard date string to ISO FITS date string */ char *string); /* FITS date string */ char *fd2of( /* Any FITS standard date string to old FITS date and time */ char *string); /* FITS date string */ char *fd2ofd( /* Any FITS standard date string to old FITS date string */ char *string); /* FITS date string */ char *fd2oft( /* Any FITS standard date string to old FITS time string */ char *string); /* FITS date string */ void fd2i( /* FITS standard date string to year, mon, day, hrs, min, sec */ char *string, /* FITS date string */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ double fd2jd( /* FITS standard date string to Julian Day */ char *string); /* FITS date string */ double fd2mjd( /* FITS standard date string to Modified Julian Day */ char *string); /* FITS date string */ double fd2ts( /* FITS standard date to seconds since 1950-01-01 */ char *string); /* FITS date string */ int fd2tsi( /* FITS standard date to IRAF seconds since 1980-01-01 */ char *string); /* FITS date string */ time_t fd2tsu( /* FITS standard date to Unix seconds since 1970-01-01 */ char *string); /* FITS date string */ /* Convert from Julian Day */ void jd2doy( /* Julian Day to year and day of year */ double dj, /* Julian Day */ int *year, /* Year (returned) */ double *doy); /* Day of year with fraction (returned) */ void jd2dt( /* Julian Day to yyyy.mmdd hh.mmssss */ double dj, /* Julian Day */ double *date, /* Date as yyyy.mmdd (returned)*/ double *time); /* Time as hh.mmssxxxx (returned) */ double jd2ep( /* Julian Day to fractional year */ double dj); /* Julian Day */ double jd2epb( /* Julian Day to Besselian epoch */ double dj); /* Julian Day */ double jd2epj( /* Julian Day to Julian epoch */ double dj); /* Julian Day */ char *jd2fd( /* Julian Day to FITS date string yyyy-mm-ddThh:mm:ss.ss */ double dj); /* Julian Day */ void jd2i( /* Julian Day to year, month, day, hours, min., sec. */ double dj, /* Julian Day */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ double jd2mjd( /* Julian Day to Modified Julian day */ double dj); /* Julian Day */ double jd2ts( /* Julian Day to seconds since 1950.0 */ double dj); /* Julian Day */ time_t jd2tsu( /* Julian Day to Unix seconds since 1970-01-01T00:00 */ double dj); /* Julian Day */ int jd2tsi( /* Julian Day to IRAF seconds since 1980-01-01T00:00 */ double dj); /* Julian Day */ /* Convert current local time to various formats */ void lt2dt( /* Current local time to date (yyyy.mmdd), time (hh.mmsss) */ double *date, /* Date as yyyy.mmdd (returned) */ double *time); /* Time as hh.mmssxxxx (returned) */ char *lt2fd(void); /* Current local time to FITS ISO date string */ int lt2tsi(void); /* Current local time to IRAF seconds since 1980-01-01T00:00 */ time_t lt2tsu(void); /* Current local time to Unix seconds since 1970-01-01T00:00 */ double lt2ts(void); /* Current local time to IRAF seconds since 1950-01-01T00:00 */ /* Convert from Modified Julian Day (JD - 2400000.5) */ void mjd2doy( /* Modified Julian Day to year and day of year */ double dj, /* Modified Julian Day */ int *year, /* Year (returned) */ double *doy); /* Day of year with fraction (returned) */ void mjd2dt( /* Modified Julian Day to yyyy.mmdd hh.mmssss */ double dj, /* Modified Julian Date */ double *date, /* Date as yyyy.mmdd (returned)*/ double *time); /* Time as hh.mmssxxxx (returned) */ double mjd2ep( /* Modified Julian Day to fractional year */ double dj); /* Modified Julian Date */ double mjd2epb( /* Modified Julian Day to Besselian epoch */ double dj); /* Modified Julian Date */ double mjd2epj( /* Modified Julian Day to Julian epoch */ double dj); /* Modified Julian Date */ char *mjd2fd( /* Modified Julian Day to FITS date yyyy-mm-ddThh:mm:ss.ss */ double dj); /* Modified Julian Date */ void mjd2i( /* Modified Julian Day to year, month, day, hours, min, sec */ double dj, /* Modified Julian Date */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ double mjd2jd( /* Modified Julian Day to Julian day */ double dj); /* Modified Julian Date */ double mjd2ts( /* Modified Julian Day to seconds since 1950.0 */ double dj); /* Modified Julian Date */ /* Convert from seconds since 1950-01-01 0:00 (JPL Ephemeris time) */ void ts2dt( /* Seconds since 1950.0 to yyyy.mmdd hh.mmssss */ double tsec, /* seconds since 1950.0 */ double *date, /* Date as yyyy.mmdd (returned)*/ double *time); /* Time as hh.mmssxxxx (returned) */ double ts2ep( /* Seconds since 1950.0 to fractional year */ double tsec); /* seconds since 1950.0 */ double ts2epb( /* Seconds since 1950.0 to Besselian epoch */ double tsec); /* seconds since 1950.0 */ double ts2epj( /* Seconds since 1950.0 to Julian epoch */ double tsec); /* seconds since 1950.0 */ char *ts2fd( /* Seconds since 1950.0 to FITS date, yyyy-mm-ddT00:00:00.000 */ double tsec); /* seconds since 1950.0 */ void ts2i( /* Seconds since 1950.0 to year, month, day, hours, min, sec */ double tsec, /* seconds since 1950.0 */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ double ts2jd( /* Seconds since 1950.0 to Julian Day */ double tsec); /* seconds since 1950.0 */ double ts2mjd( /* Seconds since 1950.0 to Modified Julian Day */ double tsec); /* seconds since 1950.0 */ /* Convert from IRAF time (seconds since 1980-01-01 0:00 UT) */ char *tsi2fd( /* Seconds since 1980-01-01 to FITS standard date string */ int isec); /* Seconds past 1980-01-01 */ double tsi2ts( /* Seconds since 1980-01-01 to seconds since 1950-01-01 */ int isec); /* Seconds past 1980-01-01 */ void tsi2dt( /* Seconds since 1980-01-01 to date yyyy.mmdd, time hh.mmssss */ int isec, /* Seconds past 1980-01-01 */ double *date, /* Date as yyyy.mmdd (returned) */ double *time); /* Time as hh.mmssxxxx (returned) */ /* Convert from Unix time (seconds since 1970-01-01 0:00 UT) */ void tsu2dt( /* Seconds since 1970-01-01 to date yyyy.ddmm, time hh.mmsss */ time_t isec, /* Seconds past 1970-01-01 */ double *date, /* Date as yyyy.mmdd (returned) */ double *time); /* Time as hh.mmssxxxx (returned) */ char *tsu2fd( /* Seconds since 1970-01-01 to FITS standard date string */ time_t isec); /* Seconds past 1970-01-01 */ double tsu2ts( /* Seconds since 1970-01-01 to seconds since 1950-01-01 */ time_t isec); /* Seconds past 1970-01-01 */ int tsu2tsi( /* Seconds since 1970-01-01 to local seconds since 1980-01-01 */ time_t isec); /* Seconds past 1970-01-01 */ /* Convert times within a day */ char *tsd2fd( /* Seconds since start of day to FITS standard time string */ double tsec); /* Seconds since start of day */ double tsd2dt( /* Seconds since start of day to hh.mmsssss */ double tsec); /* Seconds since start of day */ /* Convert from current Universal Time */ void ut2dt( /* Current Universal Time to date (yyyy.mmdd), time (hh.mmsss) */ double *date, /* Date as yyyy.mmdd (returned) */ double *time); /* Time as hh.mmssxxxx (returned) */ void ut2doy( /* Current Universal Time to year, day of year */ int *year, /* Year (returned) */ double *doy); /* Day of year (returned) */ double ut2ep(void); /* Current Universal Time to fractional year */ double ut2epb(void); /* Current Universal Time to Besselian Epoch */ double ut2epj(void); /* Current Universal Time to Julian Epoch */ char *ut2fd(void); /* Current Universal Time to FITS ISO date string */ double ut2jd(void); /* Current Universal Time to Julian Date */ double ut2mjd(void); /* Current Universal Time to Modified Julian Date */ int ut2tsi(void); /* Current UT to IRAF seconds since 1980-01-01T00:00 */ time_t ut2tsu(void); /* Current UT to Unix seconds since 1970-01-01T00:00 */ double ut2ts(void); /* Current UT to seconds since 1950-01-01T00:00 */ int isdate( /* Return 1 if string is FITS old or ISO date */ char *string); /* Possible FITS date string, which may be: * dd/mm/yy (FITS standard before 2000) * dd-mm-yy (nonstandard FITS use before 2000) * yyyy-mm-dd (FITS standard after 1999) * yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ /* Ephemeris time conversions (ET, TT, and TDT) */ char *et2fd( /* ET (or TDT or TT) in FITS format to UT in FITS format */ char *string); /* Ephemeris Time as FITS date string (E not T) */ char *fd2et( /* UT in FITS format to ET (or TDT or TT) in FITS format */ char *string); /* FITS date string */ void dt2et( /* yyyy.ddmm and hh.mmsss to Ephemeris Time */ double *date, /* Date as yyyy.mmdd */ double *time); /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ double jd2jed( /* Convert from Julian Date to Julian Ephemeris Date */ double dj); /* Julian Date */ double jed2jd( /* Convert from Julian Ephemeris Date to Julian Date */ double dj); /* Julian Ephemeris Date */ double ets2ts( /* ET in seconds since 1950-01-01 to UT in same format */ double tsec); /* ET in seconds since 1950-01-01 */ double ts2ets( /* UT in seconds since 1950-01-01 to ET in same format */ double tsec); /* UT in seconds since 1950-01-01 */ void edt2dt( /* yyyy.ddmm and hh.mmsss Ephemeris Time to UT */ double *date, /* Date as yyyy.mmdd */ double *time); /* Time as hh.mmssxxxx * If time<0, it is time as -(fraction of a day) */ double utdt( /* Compute difference between UT and dynamical time (ET-UT) */ double dj); /* Julian Date (UT) */ /* Sidereal Time conversions */ char *fd2gst( /* Convert from FITS UT date to Greenwich Sidereal Time */ char *string); /* FITS date string */ void dt2gst( /* Convert from UT as yyyy.mmdd hh.mmssss to Greenwich Sidereal Time */ double *date, /* Date as yyyy.mmdd */ double *time); /* Time as hh.mmssxxxx * If time<0, it is time as -(fraction of a day) */ double jd2gst( /* Calculate Greenwich Sidereal Time given Julian Date */ double dj); /* Julian Date (UT) */ double ts2gst( /* Calculate Greenwich Sidereal Time given Universal Time */ double tsec); /* Time since 1950.0 in UT seconds */ char *fd2lst( /* Convert from FITS UT date to Local Sidereal Time */ char *string); /* FITS date string */ void dt2lst( /* Convert from UT as yyyy.mmdd hh.mmssss to Local Sidereal Time */ double *date, /* Date as yyyy.mmdd */ double *time); /* Time as hh.mmssxxxx * If time<0, it is time as -(fraction of a day) */ double ts2lst( /* Calculate Local Sidereal Time given Universal Time */ double tsec); /* Time since 1950.0 in UT seconds */ double jd2lst( /* Calculate Local Sidereal Time given Julian Date */ double dj); /* Julian Date (UT) */ double eqeqnx( /* Compute equation of eqinoxes from Julian Date */ double dj); /* Julian Date (UT) */ char *fd2mst( /* Convert from FITS UT date to Mean Sidereal Time */ char *string); /* FITS date string */ double jd2mst( /* Convert from Julian Date to Mean Sidereal Time */ double dj); /* Julian Date (UT) */ double jd2mst2( /* Convert from Julian Date to Mean Sidereal Time */ double dj); /* Julian Date (UT) */ void dt2mst( /* Convert from UT as yyyy.mmdd hh.mmssss to Mean Sidereal Time */ double *date, /* Date as yyyy.mmdd */ double *time); /* Time as hh.mmssxxxx * If time<0, it is time as -(fraction of a day) */ double lst2dt( /* Calculate UT as hh.mmsss given UT date and * Local Sidereal Time */ double date0, /* UT date as yyyy.mmdd */ double time0); /* LST as hh.mmssss */ double lst2jd( /* Calculate UT as Julian Date given UT date and * Local Sidereal Time */ double sdj); /* Julian Date of desired day at 0:00 UT + sidereal time */ char *lst2fd( /* Calculate FITS UT date and time given UT date and * Local Sidereal Time */ char *string); /* UT Date, LST as yyyy-mm-ddShh:mm:ss.ss */ char *gst2fd( /* Calculate FITS UT date and time given Greenwich Sidereal Time */ char *string); /* UT Date, GST as yyyy-mm-ddShh:mm:ss.ss */ double gst2jd( /* Calculate FITS UT Julian Date given Greenwich Sidereal Time */ double sdj); /* UT Date, GST as Julian Date */ char *mst2fd( /* Calculate FITS UT date and time given Mean Sidereal Time */ char *string); /* UT Date, MST as yyyy-mm-ddShh:mm:ss.ss */ double mst2jd( /* Calculate FITS UT Julian Date given Mean Sidereal Time */ double sdj); /* UT Date, MST as Julian Date */ double ts2mst( /* Calculate Mean Sidereal Time given Universal Time */ double tsec); /* time since 1950.0 in UT seconds */ void setlongitude( /* Longitude for sidereal time in or out */ double longitude); /* longitude of observatory in degrees (+=west) */ void compnut( /* Compute nutation in longitude and obliquity and mean obliquity*/ double dj, /* TDB (loosely ET or TT) as Julian Date */ double *dpsi, /* Nutation in longitude in radians (returned) */ double *deps, /* Nutation in obliquity in radians (returned) */ double *eps0); /* Mean obliquity in radians (returned) */ /* Heliocentric Julian Date conversions */ double mjd2mhjd( /* Convert from Modified Julian Date to Heliocentric MJD */ double mjd, /* Julian date (geocentric) */ double ra, /* Right ascension (degrees) */ double dec, /* Declination (degrees) */ int sys); /* J2000, B1950, GALACTIC, ECLIPTIC */ double mjd2hjd( /* Convert from Modified Julian Date to Heliocentric JD */ double mjd, /* Julian date (geocentric) */ double ra, /* Right ascension (degrees) */ double dec, /* Declination (degrees) */ int sys); /* J2000, B1950, GALACTIC, ECLIPTIC */ double mhjd2mjd( /* Convert from Heliocentric Modified Julian Date to MJD */ double mhjd, /* Modified Heliocentric Julian date */ double ra, /* Right ascension (degrees) */ double dec, /* Declination (degrees) */ int sys); /* J2000, B1950, GALACTIC, ECLIPTIC */ double jd2hjd( /* Convert from Julian Date to Heliocentric Julian Date */ double dj, /* Julian date (geocentric) */ double ra, /* Right ascension (degrees) */ double dec, /* Declination (degrees) */ int sys); /* J2000, B1950, GALACTIC, ECLIPTIC */ double hjd2jd( /* Convert from Heliocentric Julian Date to Julian Date */ double dj, /* Heliocentric Julian date */ double ra, /* Right ascension (degrees) */ double dec, /* Declination (degrees) */ int sys); /* J2000, B1950, GALACTIC, ECLIPTIC */ void setdatedec( /* Set number of decimal places in FITS dates */ int nd); /* Number of decimal places in FITS dates */ #else /* K&R prototypes */ /* FITS file access subroutines in fitsfile.c */ extern int fitsropen(); extern char *fitsrhead(); extern char *fitsrtail(); extern char *fitsrimage(); extern char *fitsrfull(); extern char *fitsrsect(); extern int fitswhead(); extern int fitswexhead(); extern int fitswext(); extern int fitswhdu(); extern int fitswimage(); extern int fitscimage(); extern int isfits(); /* Return 1 if file is a FITS file */ extern void fitserr(); /* Print FITS error message to stderr */ extern void setfitsinherit(); /* Set flag to append primary data header */ extern int fitsheadsize(); /* Return size of fitsheader in bytes */ /* FITS table file access subroutines in fitsfile.c */ extern int fitsrtopen(); extern int fitsrthead(); extern void fitsrtlset(); extern int fitsrtline(); extern short ftgeti2(); extern int ftgeti4(); extern float ftgetr4(); extern double ftgetr8(); extern int ftgetc(); extern void moveb(); /* Copy nbytes bytes from source+offs to dest+offd */ /* IRAF file access subroutines in imhfile.c */ extern char *irafrhead(); extern char *irafrimage(); extern int irafwhead(); extern int irafwimage(); extern int isiraf(); extern char *iraf2fits(); extern char *fits2iraf(); /* Image pixel access subroutines in imio.c */ extern double getpix(); /* Read one pixel from any data type 2-D array (0,0)*/ extern double getpix1(); /* Read one pixel from any data type 2-D array (1,1)*/ extern double maxvec(); /* Get maximum value in vector from a image */ extern double minvec(); /* Get minimum value in vector from a image */ extern void putpix(); /* Write one pixel to any data type 2-D array (0,0)*/ extern void putpix1(); /* Write one pixel to any data type 2-D array (1,1) */ extern void addpix(); /* Add to one pixel in any data type 2-D array (0,0)*/ extern void addpix1(); /* Add to one pixel in any data type 2-D array (1,1)*/ extern void movepix(); /* Move one pixel value between two 2-D arrays (0,0) */ extern void movepix1(); /* Move one pixel value between two 2-D arrays (1,1) */ extern void addvec(); /* Add constant to vector from 2-D array */ extern void multvec(); /* Multiply vector from 2-D array by a constant */ extern void getvec(); /* Read vector from 2-D array */ extern void putvec(); /* Write vector into 2-D array */ extern void fillvec(); /* Write constant into a vector */ extern void fillvec1(); /* Write constant into a vector */ extern void imswap(); /* Swap alternating bytes in a vector */ extern void imswap2(); /* Swap bytes in a vector of 2-byte (short) integers */ extern void imswap4(); /* Reverse bytes in a vector of 4-byte numbers */ extern void imswap8(); /* Reverse bytes in a vector of 8-byte numbers */ extern int imswapped(); /* Return 1 if machine byte order is not FITS order */ /* File utilities from fileutil.c */ extern int getfilelines(); extern char *getfilebuff(); extern int getfilesize(); extern int isimlist(); extern int isimlistd(); extern int isfilelist(); extern int isfile(); extern int istiff(); extern int isjpeg(); extern int isgif(); extern int next_line(); extern int first_token(); /* Subroutines for access to tokens within a string from fileutil.c */ int setoken(); /* Tokenize a string for easy decoding */ int nextoken(); /* Get next token from tokenized string */ int getoken(); /* Get specified token from tokenized string */ /* Subroutines for translating dates and times in dateutil.c */ void ang2hr(); /* Fractional degrees to hours as hh:mm:ss.ss */ void ang2deg(); /* Fractional degrees to degrees as dd:mm:ss.ss */ double deg2ang(); /* Degrees as dd:mm:ss.ss to fractional degrees */ double hr2ang(); /* Hours as hh:mm:ss.ss to fractional degrees */ void doy2dt(); /* year and day of year to yyyy.mmdd hh.mmss */ double doy2ep(); /* year and day of year to fractional year (epoch) */ double doy2epb(); /* year and day of year to Besselian epoch */ double doy2epj(); /* year and day of year to Julian epoch */ char *doy2fd(); /* year and day of year to FITS date */ double doy2jd(); /* year and day of year to Julian date */ double doy2mjd(); /* year and day of year to modified Julian date */ double doy2ts(); /* year and day of year to seconds since 1950.0 */ int doy2tsi(); /* year and day of year to IRAF seconds since 1980-01-01 */ time_t doy2tsu(); /* year and day of year to Unix seconds since 1970-01-01 */ void dt2doy(); /* yyyy.mmdd hh.mmss to year and day of year */ double dt2ep(); /* yyyy.ddmm and hh.mmsss to fractional year (epoch) */ double dt2epb(); /* yyyy.ddmm and hh.mmsss to Besselian epoch */ double dt2epj(); /* yyyy.ddmm and hh.mmsss to Julian epoch */ char *dt2fd(); /* yyyy.ddmm and hh.mmsss to FITS date string */ void dt2i(); /* yyyy.ddmm and hh.mmsss to year, month, day, hrs, min, sec */ double dt2jd(); /* yyyy.ddmm and hh.mmsss to Julian date */ double dt2mjd(); /* yyyy.ddmm and hh.mmsss to modified Julian date */ double dt2ts(); /* yyyy.ddmm and hh.mmsss to seconds since 1950.0 */ int dt2tsi(); /* yyyy.ddmm and hh.mmsss to IRAF seconds since 1980-01-01 */ time_t dt2tsu(); /* yyyy.ddmm and hh.mmsss to Unix seconds since 1970-01-01 */ void ep2dt(); /* Fractional year to yyyy.mmdd hh.mmssss */ void epb2dt(); /* Besselian epoch to yyyy.mmdd hh.mmssss */ void epj2dt(); /* Julian epoch to yyyy.mmdd hh.mmssss */ char *ep2fd(); /* Fractional year to FITS date string yyyy-mm-ddThh:mm:ss.ss */ char *epb2fd(); /* Besselian epoch to FITS date string yyyy-mm-ddThh:mm:ss.ss */ char *epj2fd(); /* Julian epoch to FITS date string yyyy-mm-ddThh:mm:ss.ss */ void ep2i(); /* Fractional year to year, month, day, hours, min., sec. */ void epb2i(); /* Besselian epoch to year, month, day, hours, min., sec. */ void epj2i(); /* Julian epoch to year, month, day, hours, min., sec. */ double ep2jd(); /* Fractional year to Julian Date */ double epb2jd(); /* Besselian epoch to Julian Date */ double epj2jd(); /* Julian epoch to Julian Date */ double ep2mjd(); /* Fractional year to modified Julian Date */ double epb2mjd(); /* Besselian epoch to modified Julian Date */ double epj2mjd(); /* Julian epoch to modified Julian Date */ double ep2epb(); /* Fractional year to Besselian epoch */ double ep2epj(); /* Fractional year to Julian epoch */ double epb2epj(); /* Besselian epoch to Julian epoch */ double epj2epb(); /* Julian epoch to Besselian epoch */ double epb2ep(); /* Besselian epoch to fractional year */ double epj2ep(); /* Julian epoch to fractional year */ double ep2ts(); /* Fractional year to seconds since 1950.0 */ double epb2ts(); /* Besselian epoch to seconds since 1950.0 */ double epj2ts(); /* Julian epoch to seconds since 1950.0 */ void fd2dt(); /* FITS standard date string to Julian date */ void fd2doy(); /* FITS standard date string to year, day of year */ double fd2ep(); /* FITS standard date string to fractional year (epoch) */ double fd2epb(); /* FITS standard date string to Besselian epoch */ double fd2epj(); /* FITS standard date string to Julian epoch */ char *fd2fd(); /* Any FITS standard date string to ISO FITS date string */ char *fd2of(); /* Any FITS standard date string to old FITS date and time */ char *fd2ofd(); /* Any FITS standard date string to old FITS date string */ char *fd2oft(); /* Any FITS standard date string to old FITS time string */ void fd2i(); /* FITS standard date string to year, mon, day, hrs, min, sec */ double fd2jd(); /* FITS standard date string to Julian date */ double fd2mjd(); /* FITS standard date string to modified Julian date */ double fd2ts(); /* FITS standard date to seconds since 1950-01-01 */ int fd2tsi(); /* FITS standard date to IRAF seconds since 1980-01-01 */ time_t fd2tsu(); /* FITS standard date to Unix seconds since 1970-01-01 */ void jd2doy(); /* Julian date to year and day of year */ void jd2dt(); /* Julian date to yyyy.mmdd hh.mmssss */ double jd2ep(); /* Julian date to fractional year */ double jd2epb(); /* Julian date to Besselian epoch */ double jd2epj(); /* Julian date to Julian epoch */ char *jd2fd(); /* Julian date to FITS date string yyyy-mm-ddThh:mm:ss.ss */ void jd2i(); /* Julian date to year, month, day, hours, min., sec. */ double jd2mjd(); /* Julian date to modified Julian date */ double jd2ts(); /* Julian date to seconds since 1950.0 */ time_t jd2tsu(); /* Julian date to Unix seconds since 1970-01-01T00:00 */ int jd2tsi(); /* Julian date to IRAF seconds since 1980-01-01T00:00 */ void lt2dt(); /* Current local time to date (yyyy.mmdd), time (hh.mmsss) */ char *lt2fd(); /* Current local time to FITS ISO date string */ int lt2tsi(); /* Current local time to IRAF seconds since 1980-01-01T00:00 */ time_t lt2tsu(); /* Current local time to Unix seconds since 1970-01-01T00:00 */ double lt2ts(); /* Current local time to IRAF seconds since 1950-01-01T00:00 */ void mjd2doy(); /* Convert from Modified Julian Date to Day of Year */ void mjd2dt(); /* Modified Julian date to yyyy.mmdd hh.mmssss */ double mjd2ep(); /* Modified Julian date to fractional year */ double mjd2epb(); /* Modified Julian date to Besselian epoch */ double mjd2epj(); /* Modified Julian date to Julian epoch */ char *mjd2fd(); /* Modified Julian date to FITS date yyyy-mm-ddThh:mm:ss.ss */ void mjd2i(); /* Modified Julian date to year, month, day, hours, min, sec */ double mjd2jd(); /* Modified Julian date to Julian date */ double mjd2ts(); /* Modified Julian date to seconds since 1950.0 */ void ts2dt(); /* Seconds since 1950.0 to yyyy.mmdd hh.mmssss */ double ts2ep(); /* Seconds since 1950.0 to fractional year */ double ts2epb(); /* Seconds since 1950.0 to Besselian epoch */ double ts2epj(); /* Seconds since 1950.0 to Julian epoch */ char *ts2fd(); /* Seconds since 1950.0 to FITS date, yyyy-mm-ddT00:00:00.000 */ void ts2i(); /* Seconds since 1950.0 to year, month, day, hours, min, sec */ double ts2jd(); /* Seconds since 1950.0 to Julian date */ double ts2mjd(); /* Seconds since 1950.0 to modified Julian date */ char *tsi2fd(); /* Seconds since 1980-01-01 to FITS standard date string */ double tsi2ts(); /* Seconds since 1980-01-01 to seconds since 1950-01-01 */ double tsi2ts(); /* Seconds since 1980-01-01 to seconds since 1950-01-01 */ void tsi2dt(); /* Seconds since 1980-01-01 to date yyyy.mmdd, time hh.mmssss */ void tsu2dt(); /* Seconds since 1970-01-01 to date yyyy.ddmm, time hh.mmsss */ char *tsu2fd(); /* Seconds since 1970-01-01 to FITS standard date string */ char *tsd2fd(); /* Seconds since start of day to FITS standard time string */ double tsd2dt(); /* Seconds since start of day to hh.mmsssss */ double tsu2ts(); /* Seconds since 1970-01-01 to seconds since 1950-01-01 */ int tsu2tsi(); /* Seconds since 1970-01-01 to local seconds since 1980-01-01 */ int isdate(); /* Return 1 if string is FITS old or ISO date */ void ut2dt(); /* Current Universal Time to date (yyyy.mmdd), time (hh.mmsss) */ void ut2doy(); /* Current Universal Time to year, day of year */ double ut2ep(); /* Current Universal Time to fractional year */ double ut2epb(); /* Current Universal Time to Besselian Epoch */ double ut2epj(); /* Current Universal Time to Julian Epoch */ char *ut2fd(); /* Current Universal Time to FITS ISO date string */ double ut2jd(); /* Current Universal Time to Julian Date */ double ut2mjd(); /* Current Universal Time to Modified Julian Date */ int ut2tsi(); /* Current UT to IRAF seconds since 1980-01-01T00:00 */ time_t ut2tsu(); /* Current UT to Unix seconds since 1970-01-01T00:00 */ double ut2ts(); /* Current UT to IRAF seconds since 1950-01-01T00:00 */ int sts2c(); /* Replaces spaces in a string with a specified character */ int stc2s(); /* Replaces a specified character in a string with spaces */ char *et2fd(); /* ET (or TDT or TT) in FITS format to UT in FITS format */ char *fd2et(); /* UT in FITS format to ET (or TDT or TT) in FITS format */ double jd2jed(); /* Convert from Julian Date to Julian Ephemeris Date */ double jed2jd(); /* Convert from Julian Ephemeris Date to Julian Date */ double ets2ts(); /* ET in seconds since 1950-01-01 to UT in same format */ double ts2ets(); /* UT in seconds since 1950-01-01 to ET in same format */ void dt2et(); /* yyyy.ddmm and hh.mmsss to Ephemeris Time */ void edt2dt(); /* yyyy.ddmm and hh.mmsss Ephemeris Time to UT */ double utdt(); /* Compute difference between UT and dynamical time (ET-UT) */ char *fd2gst(); /* Convert from FITS UT date to Greenwich Sidereal Time */ void dt2gst(); /* Convert from UT as yyyy.mmdd hh.mmssss to Greenwich Sidereal Time */ double jd2gst(); /* Calculate Greenwich Sidereal Time given Julian Date */ double ts2gst(); /* Calculate Greenwich Sidereal Time given Universal Time */ char *fd2lst(); /* Convert from FITS UT date to Local Sidereal Time */ void dt2lst(); /* Convert from UT as yyyy.mmdd hh.mmssss to Local Sidereal Time */ double ts2lst(); /* Calculate Local Sidereal Time given Universal Time */ double jd2lst(); /* Calculate Local Sidereal Time given Julian Date */ double eqeqnx(); /* Compute equation of eqinoxes from Julian Date */ char *fd2mst(); /* Convert from FITS UT date to Mean Sidereal Time */ double jd2mst(); /* Convert from Julian Date to Mean Sidereal Time */ double jd2mst2(); /* Convert from Julian Date to Mean Sidereal Time */ void dt2mst(); /* Convert from UT as yyyy.mmdd hh.mmssss to Mean Sidereal Time */ double lst2ts(); /* Calculate Universal Time given Local Sidereal Time */ double lst2dt(); /* Calculate UT as yyyy.mmdd hh.mmsss given UT date and Local Sidereal Time */ double lst2jd(); /* Calculate UT as Julian Date given UT date and Local Sidereal Time */ char *lst2fd(); /* Calculate FITS UT date and time given UT date and Local Sidereal Time */ char *gst2fd(); /* Calculate FITS UT date and time given Greenwich Sidereal Time */ double gst2jd(); /* Calculate FITS UT Julian Date given Greenwich Sidereal Time */ char *mst2fd(); /* Calculate FITS UT date and time given Mean Sidereal Time */ double mst2jd(); /* Calculate FITS UT Julian Date given Mean Sidereal Time */ char *fd2mst(); /* Convert from FITS UT date to Mean Sidereal Time */ void dt2mst(); /* Convert from UT as yyyy.mmdd hh.mmssss to Mean Sidereal Time */ double ts2mst(); /* Calculate Mean Sidereal Time given Universal Time */ double mjd2mhjd(); /* Convert from Modified Julian Date to Heliocentric MJD */ double mjd2hjd(); /* Convert from Modified Julian Date to Heliocentric JD */ double mhjd2mjd(); /* Convert from Heliocentric Modified Julian Date to MJD */ double jd2hjd(); /* Convert from Julian Date to Heliocentric Julian Date */ double jd2mhjd(); /* Convert from Julian Date to Modified Heliocentric JD */ double hjd2jd(); /* Convert from Heliocentric Julian Date to Julian Date */ double hjd2mjd(); /* Convert from Heliocentric Julian Date to Modified JD */ double hjd2mhjd(); /* Convert from Heliocentric Julian Date to Modified HJD */ void setdatedec(); /* Set number of decimal places in FITS dates */ void setlongitude(); /* Longitude for sidereal time in or out */ void compnut(); /* Compute nutation in longitude and obliquity and mean obliquity*/ #endif /* __STDC__ */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* fitsfile_h_ */ /* May 31 1996 Use stream I/O for reading as well as writing * Jun 12 1996 Add byte-swapping subroutines * Jul 10 1996 FITS header now allocated in subroutines * Jul 17 1996 Add FITS table column extraction subroutines * Aug 6 1996 Add MOVEPIX, HDEL and HCHANGE declarations * * Oct 10 1997 FITS file opening subroutines now return int instead of FILE * * * May 27 1998 Split off fitsio and imhio subroutines to fitsio.h * Jun 4 1998 Change fits2iraf from int to int * * Jul 24 1998 Make IRAF header char instead of int * Aug 18 1998 Change name to fitsfile.h from fitsio.h * Oct 5 1998 Add isiraf() and isfits() * Oct 7 1998 Note separation of imhfile.c into two files * * Jul 15 1999 Add fileutil.c subroutines * Sep 28 1999 Add (1,1)-based image access subroutines * Oct 21 1999 Add fitswhead() * Nov 2 1999 Add date utilities from wcscat.h * Nov 23 1999 Add fitscimage() * Dec 15 1999 Fix misdeclaration of *2fd() subroutines, add fd2i(), dt2i() * Dec 20 1999 Add isdate() * * Jan 20 2000 Add conversions to and from Besselian and Julian epochs * Jan 21 2000 Add conversions to old FITS date and time * Jan 26 2000 Add conversion to modified Julian date (JD - 2400000.5 * Mar 22 2000 Add lt2* and ut2* to get current time as local and UT * Mar 24 2000 Add tsi2* and tsu2* to convert IRAF and Unix seconds * Sep 8 2000 Improve comments * * Apr 24 2001 Add length of column name to column data structure * May 22 2001 Add day of year date conversion subroutines * Sep 25 2001 Add isfilelist() and isfile() * * Jan 8 2002 Add sts2c() and stc2s() * Apr 8 2002 Change all long declarations to time_t for compatibility * Jun 18 2002 Add fitserr() to print error messages * Aug 30 2002 Add Ephemeris Time date conversions * Sep 10 2002 Add Sidereal Time conversions * Oct 21 2002 Add fitsrsect() to read sections of FITS images * * Mar 5 2003 Add isimlistd() to check image lists with root directory * Aug 20 2003 Add fitsrfull() to read n-dimensional simple FITS images * * Feb 27 2004 Add fillvec() and fillvec1() * May 3 2004 Add setfitsinherit() * May 6 2004 Add fitswexhead() * Aug 27 2004 Add fitsheadsize() * * Oct 14 2005 Add tsd2fd(), tsd2dt(), epj2ep(), epb2ep(), tsi2dt() * * Feb 23 2006 Add fitsrtail() to read appended FITS header * Feb 23 2006 Add istiff(), isjpeg(), isgif() to check TIFF, JPEG, GIF files * Sep 6 2006 Add heliocentric time conversions * Oct 5 2006 Add local sidereal time conversions * * Jan 9 2007 Add ANSI prototypes * Jan 11 2007 Add token subroutines from catutil.c/wcscat.h to fileutil.c * Jun 11 2007 Add minvec() subroutine in imio.c * Nov 28 2007 Add kform format to FITS table keyword data structure * * Sep 8 2008 Add ag2hr(), ang2deg(), deg2ang(), and hr2ang() * * Sep 25 2009 Add moveb() * * Jun 20 2014 Add next_line() */ wcstools-3.9.5/libwcs/fitshead.h0000664000016200001660000004735711750060645015722 0ustar minkoirsys/*** File fitshead.h FITS header access subroutines *** January 9, 2007 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2007 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ /* Declarations for subroutines in hget.c, hput.c, and iget.c */ #ifndef _fitshead_h_ #define _fitshead_h_ #include #ifdef __cplusplus /* C++ prototypes */ extern "C" { #endif #ifdef __STDC__ /* Full ANSI prototypes */ /* Subroutines in hget.c */ int hgeti2( /* Extract short value from FITS header */ const char* hstring, /* FITS header string */ const char* keyword, /* FITS keyword */ short* val); /* short integer value (returned) */ int hgeti4c( /* Extract int value from FITS header */ const char* hstring, /* FITS header string */ const char* keyword, /* FITS keyword */ const char* wchar, /* WCS to use (A-Z or null) */ int* val); /* integer value (returned) */ int hgeti4( /* Extract int value from FITS header */ const char* hstring, /* FITS header string */ const char* keyword, /* FITS keyword */ int* val); /* integer value (returned) */ int hgetr4( /* Extract float value from FITS header */ const char* hstring, /* FITS header string */ const char* keyword, /* FITS keyword */ float* val); /* float value (returned) */ int hgetr8c( /* Extract double value from FITS header */ const char* hstring, /* FITS header string */ const char* keyword, /* FITS keyword */ const char* wchar, /* WCS to use (A-Z or null) */ double* val); /* double value (returned) */ int hgetr8( /* Extract double value from FITS header */ const char* hstring, /* FITS header string */ const char* keyword, /* FITS keyword */ double* val); /* double value (returned) */ int hgetra( /* Extract right ascension from FITS header */ const char* hstring, /* FITS header string */ const char* keyword, /* FITS keyword */ double* ra); /* RA in degrees (returned) */ int hgetdec( /* Extract declination from FITS header */ const char* hstring, /* FITS header string */ const char* keyword, /* FITS keyword */ double* dec); /* Dec in degrees (returned) */ int hgetdate( /* Extract date from FITS header */ const char* hstring, /* FITS header string */ const char* keyword, /* FITS keyword */ double* date); /* Date in fractional years (returned) */ int hgetl( /* Extract boolean value from FITS header */ const char* hstring, /* FITS header string */ const char* keyword, /* FITS keyword */ int* lval); /* 1 if T, 0 if F (returned) */ int hgetsc( /* Extract string value from FITS header */ const char* hstring, /* FITS header string */ const char* keyword, /* FITS keyword */ const char* wchar, /* WCS to use (A-Z or null) */ const int lstr, /* maximum length of returned string */ char* string); /* null-terminated string value (returned) */ int hgets( /* Extract string value from FITS header */ const char* hstring, /* FITS header string */ const char* keyword, /* FITS keyword */ const int lstr, /* maximum length of returned string */ char* string); /* null-terminated string value (returned) */ int hgetm ( /* Extract string from multiple keywords */ const char* hstring, /* FITS header string */ const char* keyword, /* FITS keyword */ const int lstr, /* maximum length of returned string */ char* string); /* null-terminated string value (returned) */ int hgetndec( /* Find number of decimal places in FITS value*/ const char* hstring, /* FITS header string */ const char* keyword, /* FITS keyword */ int* ndec); /* number of decimal places (returned) */ char* hgetc( /* Return pointer to value for FITS keyword */ const char* hstring, /* FITS header string */ const char* keyword); /* FITS keyword */ char* ksearch( /* Return pointer to keyword in FITS header */ const char* hstring, /* FITS header string */ const char* keyword); /* FITS keyword */ char *blsearch ( const char* hstring, /* FITS header string */ const char* keyword); /* FITS keyword */ char *strsrch ( /* Find string s2 within string s1 */ const char* s1, /* String to search */ const char* s2); /* String to look for */ char *strnsrch ( /* Find string s2 within string s1 */ const char* s1, /* String to search */ const char* s2, /* String to look for */ const int ls1); /* Length of string being searched */ char *strcsrch ( /* Find string s2 within string s1 (no case) */ const char* s1, /* String to search */ const char* s2); /* String to look for */ char *strncsrch ( /* Find string s2 within string s1 (no case) */ const char* s1, /* String to search */ const char* s2, /* String to look for */ const int ls1); /* Length of string being searched */ int hlength( /* Set length of unterminated FITS header */ const char *header, /* FITS header */ const int lhead); /* Allocated length of FITS header */ int gethlength( /* Get length of current FITS header */ char* header); /* FITS header */ double str2ra( /* Return RA in degrees from string */ const char* in); /* Character string (hh:mm:ss.sss or dd.dddd) */ double str2dec( /* Return Dec in degrees from string */ const char* in); /* Character string (dd:mm:ss.sss or dd.dddd) */ int isnum( /* Return 1 if number, else 0 */ const char* string); /* Character string which may be a number */ int notnum( /* Return 0 if number, else 1 */ const char* string); /* Character string which may be a number */ int numdec( /* Return number of decimal places in number */ const char* string); /* Character string which may be a number */ void strfix( /* Clean up extraneous characters in string */ char* string, /* Character string which may be a number */ int fillblank, /* If 1, blanks are replaced by underscores */ int dropzero); /* If 1, drop trailing zeroes from string */ char *getltime(void); /* Return current local time in ISO format */ char *getutime(void); /* Return current UT as an ISO-format string */ /* Subroutines in iget.c */ int mgetstr( /* Extract string from multiline FITS keyword */ const char* hstring, /* FITS header string */ const char* mkey, /* FITS keyword root _n added for extra lines */ const char* keyword, /* IRAF keyword */ const int lstr, /* maximum length of returned string */ char* string); /* null-terminated string value (returned) */ int mgeti4( /* Extract int from multiline FITS keyword */ const char* hstring, /* FITS header string */ const char* mkey, /* FITS keyword root _n added for extra lines */ const char* keyword, /* IRAF keyword */ int* ival); /* int keyword value (returned) */ int mgetr8( /* Extract double from multiline FITS keyword */ const char* hstring, /* FITS header string */ const char* mkey, /* FITS keyword root _n added for extra lines */ const char* keyword, /* IRAF keyword */ double* dval); /* double keyword value (returned) */ int igeti4( /* Extract int from IRAF keyword string */ const char* hstring, /* Multiline IRAF keyword string value */ const char* keyword, /* IRAF keyword */ int* val); /* int value (returned) */ int igetr4( /* Extract float from IRAF keyword string */ const char* hstring, /* Multiline IRAF keyword string value */ const char* keyword, /* IRAF keyword */ float* val); /* float value (returned) */ int igetr8( /* Extract double from IRAF keyword string */ const char* hstring, /* Multiline IRAF keyword string value */ const char* keyword, /* IRAF keyword */ double* val); /* double value (returned) */ int igets( /* Extract string from IRAF keyword string */ const char* hstring, /* Multiline IRAF keyword string value */ const char* keyword, /* IRAF keyword */ const int lstr, /* maximum length of returned string */ char* string); /* null-terminated string value (returned) */ char *igetc( /* Extract string from IRAF keyword string */ const char* hstring, /* Multiline IRAF keyword string value */ const char* keyword); /* IRAF keyword */ /* Subroutines in hput.c */ /* All hput* routines return 0 if successful, else -1 */ int hputi2( /* Implant short value into FITS header */ char* hstring, /* FITS header string (modified) */ const char* keyword, /* FITS keyword */ short ival); /* short value */ int hputi4( /* Implant int value into FITS header */ char* hstring, /* FITS header string (modified) */ const char* keyword, /* FITS keyword */ const int ival); /* int value */ int hputr4( /* Implant float value into FITS header */ char* hstring, /* FITS header string (modified) */ const char* keyword, /* FITS keyword */ const float* rval); /* float (4 byte) value */ int hputr8( /* Implant short into FITS header */ char* hstring, /* FITS header string (modified) */ const char* keyword, /* FITS keyword */ const double dval); /* double value */ int hputnr8( /* double with specified number of decimal places */ char* hstring, /* FITS header string (modified) */ const char* keyword, /* FITS keyword */ const int ndec, /* Number of decimal places in keyword value */ const double dval); /* double value */ int hputs( /* Quoted character string into FITS header */ char* hstring, /* FITS header string (modified) */ const char* keyword, /* FITS keyword */ const char* cval); /* Character string value */ int hputm( /* Quoted character string, mutiple keywords */ char* hstring, /* FITS header string (modified) */ const char* keyword, /* FITS keyword */ const char* cval); /* Character string value */ int hputcom( /* Add comment to keyword line in FITS header */ char* hstring, /* FITS header string (modified) */ const char* keyword, /* FITS keyword */ const char* comment); /* Comment string */ int hputra( /* Right ascension in degrees into hh:mm:ss.sss */ char* hstring, /* FITS header string (modified) */ const char* keyword, /* FITS keyword */ const double ra); /* Right ascension in degrees */ int hputdec( /* Declination in degrees into dd:mm:ss.ss */ char* hstring, /* FITS header string (modified) */ const char* keyword, /* FITS keyword */ const double dec); /* Declination in degrees */ int hputl( /* Implant boolean value into FITS header */ char* hstring, /* FITS header string (modified) */ const char* keyword, /* FITS keyword */ const int lval); /* 0->F, else ->T */ int hputc( /* Implant character string without quotes */ char* hstring, /* FITS header string (modified) */ const char* keyword, /* FITS keyword */ const char* cval); /* Character string value */ int hdel( /* Delete a keyword line from a FITS header */ char* hstring, /* FITS header string (modified) */ const char* keyword); /* FITS keyword to delete */ int hadd( /* Add a keyword line from a FITS header */ char* hplace, /* Location in FITS header string (modified) */ const char* keyword); /* FITS keyword to add */ int hchange( /* Change a keyword name in a FITS header */ char* hstring, /* FITS header string (modified) */ const char* keyword1, /* Current FITS keyword name */ const char* keyword2); /* New FITS keyword name */ void ra2str( /* Convert degrees to hh:mm:ss.ss */ char *string, /* Character string (returned) */ int lstr, /* Length of string */ const double ra, /* Right ascension in degrees */ const int ndec); /* Number of decimal places in seconds */ void dec2str( /* Convert degrees to dd:mm:ss.ss */ char *string, /* Character string (returned) */ int lstr, /* Length of string */ const double dec, /* Declination in degrees */ const int ndec); /* Number of decimal places in arcseconds */ void deg2str( /* Format angle into decimal degrees string */ char *string, /* Character string (returned) */ int lstr, /* Length of string */ const double deg, /* Angle in degrees */ const int ndec); /* Number of decimal places in degrees */ void num2str( /* Format number into string */ char *string, /* Character string (returned) */ const double num, /* Number */ const int field, /* Total field size in characters */ const int ndec); /* Number of decimal places */ void setheadshrink( /* 0 to keep blank line when keyword deleted */ const int hsh); /* 1 to shrink header by one line */ void setleaveblank( /* 1 to keep blank line where keyword deleted */ const int hsh); /* 0 to shrink header by one line */ #else /* K&R prototypes */ /* Subroutines in hget.c */ /* Extract a value from a FITS header for given keyword */ extern int hgeti4(); /* int (Multiple WCS) */ extern int hgeti4c(); /* int */ extern int hgeti2(); /* short */ extern int hgetr4(); /* float */ extern int hgetr8(); /* double */ extern int hgetr8c(); /* double (Multiple WCS) */ extern int hgetra(); /* Right ascension in degrees from string */ extern int hgetdec(); /* Declination in degrees from string */ extern int hgetdate(); /* Date in years from FITS date string */ extern int hgetl(); /* T->1, F->0 from FITS logical entry */ extern int hgets(); /* Previously allocated string */ extern int hgetsc(); /* Previously allocated string (Multiple WCS) */ extern int hgetm(); /* Previously allocated string from multiple keywords */ extern char *hgetc(); /* Return pointer to string */ extern int hgetndec(); /* Number of decimal places in keyword value */ /* Subroutines to convert strings to RA and Dec in degrees */ extern double str2ra(); extern double str2dec(); /* Check to see whether a string is a number or not */ extern int isnum(); extern int notnum(); extern int decnum(); /* Find given keyword entry in FITS header */ extern char *ksearch(); /* Find beginning of fillable blank line before FITS header keyword */ extern char *blsearch(); /* Search for substring s2 within string s1 */ extern char *strsrch (); /* s1 null-terminated */ extern char *strnsrch (); /* s1 ls1 characters long */ extern char *strcsrch (); /* s1 null-terminated (case-insensitive) */ extern char *strncsrch (); /* s1 ls1 characters long (case-insensitive) */ extern void strfix(); /* Drop or change extraneous characters in string */ /* Set length of header which is not null-terminated */ extern int hlength(); /* Get length of current FITS header */ extern int gethlength(); /* Subroutines in iget.c */ extern int mgetstr(); /* Previously allocated string from multiline keyword */ extern int mgetr8(); /* double from multiline keyword */ extern int mgeti4(); /* int from multiline keyword */ extern int igeti4(); /* long integer from IRAF compound keyword value */ extern int igetr4(); /* real from IRAF compound keyword value */ extern int igetr8(); /* double from IRAF compound keyword value */ extern int igets(); /* character string from IRAF compound keyword value */ extern char *igetc(); /* Extract string from IRAF keyword string */ /* Subroutines in hput.c */ /* Implant a value into a FITS header for given keyword */ extern int hputi4(); /* int */ extern int hputi2(); /* short */ extern int hputr4(); /* float */ extern int hputr8(); /* double */ extern int hputnr8(); /* double with specified number of decimal places */ extern int hputra(); /* Right ascension in degrees into hh:mm:ss.sss */ extern int hputdec(); /* Declination in degrees into dd:mm:ss.ss */ extern int hputl(); /* 0 -> F, else T FITS logical entry */ extern int hputs(); /* Quoted character string */ extern int hputm(); /* Quoted character string into mutiple keywords */ extern int hputc(); /* Character string without quotes (returns 0 if OK) */ extern int hputcom(); /* Comment after keyword=value (returns 0 if OK) */ extern int hdel(); /* Delete a keyword line from a FITS header */ extern int hadd(); /* Add a keyword line to a FITS header */ extern int hchange(); /* Change a keyword name in a FITS header */ extern void setheadshrink(); /* Set flag for deleted keyword space disposition*/ extern void setleaveblank(); /* Set flag for deleted keyword space disposition*/ /* Subroutines to convert RA and Dec in degrees to strings */ extern void ra2str(); extern void dec2str(); extern void deg2str(); extern void num2str(); extern int numdec(); /* Return number of decimal places in number */ extern char *getltime(); /* Return current local time in ISO format */ extern char *getutime(); /* Return current UT as an ISO-format string */ #endif /* __STDC__ */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* fitshead_h_ */ /* Apr 26 1996 Add HGETDATE to get year from date string * May 22 1996 Return double from STR2RA and STR2DEC * May 31 1996 Use stream I/O for reading as well as writing * Jun 12 1996 Add byte-swapping subroutines * Jul 10 1996 FITS header now allocated in subroutines * Jul 17 1996 Add FITS table column extraction subroutines * Jul 19 1996 Add declarations for header implanting subroutines * Aug 5 1996 Add HLENGTH for FITS headers which are not null-terminated * Aug 5 1996 Add STRNSRCH for FITS headers which are not null-terminated * Aug 6 1996 Add HPUTNR8 to save a specified number of decimal places * Aug 6 1996 Add MOVEPIX, HDEL and HCHANGE declarations * Nov 1 1996 Add DEG2STR * Dec 12 1996 Add ISNUM * * Oct 10 1997 FITS file opening subroutines now return int instead of FILE * * * Mar 12 1998 Add NOTNUM * Apr 30 1998 Clean up declarations and add more comments * May 12 1998 Add MGETS, MGETR8, MGETI4 for IRAF multi-line keywords * May 26 1998 Add HGETNDEC for number of decimal places in keyword value * May 27 1998 Add BLSEARCH to find usable blank lines in header * May 27 1998 Split off fitsio and imhio subroutines to fitsio.h * May 27 1998 Add all subroutines in hget.c, hput.c, and iget.c to C++ dec. * Jun 24 1998 Add string lengths to ra2str(), dec2str, and deg2str() calls * Jun 25 1998 Fix other C++ declarations with added string lengths * Aug 31 1998 Add current date subroutines getltime() and getutime() * Oct 28 1998 Add missing hgetc() to non c++ declarations * * Oct 6 1999 Add gethlength() to return current size of header * Oct 14 1999 All HPUT subroutines now return an error code, 0 if OK, else -1 * Oct 15 1999 Add hputcom() declaration * Oct 21 1999 Add hgetm() declaration * * Mar 22 2000 Add int to iget*() declarations * Mar 27 2000 Add hputm() declaration * * Apr 3 2002 Add hgeti4c(), hgetr8c(), and hgetsc() * Apr 8 2002 Include sys/types.h * Aug 30 2002 Add strcsrch() and strncsrch() * * Sep 23 2003 Change mgets() to mgetstr() to avoid name collision at UCO Lick * Oct 20 2003 Add numdec() to return the number of decimal places in a string * * Feb 26 2004 Add igetc(), formerly internal to iget.c * Jul 1 2004 Add setheadshrink() for hdel() * Aug 30 2004 Add numdec() to non-C++ declarations * * May 22 2006 Add setleaveblank() to leave blank line where keyword is deleted * Jun 28 2006 Add strfix() to clean up characters in strings * Nov 29 2006 Drop semicolon at end of C++ ifdef * * Jan 9 2007 Fix declarations so ANSI prototypes are not just for C++ */ wcstools-3.9.5/libwcs/imio.h0000664000016200001660000000571411750060645015057 0ustar minkoirsys/*** imio.h memory access subroutines *** September 27, 1999 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2002 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #ifndef imio_h_ #define imio_h_ /* Image pixel access subroutines in imio.c */ extern double getpix(); /* Read one pixel from any data type 2-D array (0,0)*/ extern double getpix1(); /* Read one pixel from any data type 2-D array (1,1)*/ extern void putpix(); /* Write one pixel to any data type 2-D array (0,0)*/ extern void putpix1(); /* Write one pixel to any data type 2-D array (1,1) */ extern void addpix(); /* Add to one pixel in any data type 2-D array (0,0)*/ extern void addpix1(); /* Add to one pixel in any data type 2-D array (1,1)*/ extern void movepix(); /* Move one pixel value between two 2-D arrays (0,0) */ extern void movepix1(); /* Move one pixel value between two 2-D arrays (1,1) */ extern void getvec(); /* Read vector from a 2-D array */ extern void putvec(); /* Write vector into a 2-D array */ extern void fillvec(); /* Write constant into a vector */ extern void fillvec1(); /* Write constant into a vector */ extern void imswap(); /* Swap alternating bytes in a vector */ extern void imswap2(); /* Swap bytes in a vector of 2-byte (short) integers */ extern void imswap4(); /* Reverse bytes in a vector of 4-byte numbers */ extern void imswap8(); /* Reverse bytes in a vector of 8-byte numbers */ extern int imswapped(); /* Return 1 if machine byte order is not FITS order */ #endif /* imio_h_ */ /* May 31 1996 Use stream I/O for reading as well as writing * Jun 12 1996 Add byte-swapping subroutines * Aug 6 1996 Add MOVEPIX, HDEL and HCHANGE declarations * * May 27 1998 Split off imio subroutines to imio.h * Sep 27 1999 Add Fortran-indexed (1,1), not (0,0) image access *1() * Sep 28 1999 Add addpix() * * Feb 27 2004 Add fillvec() */ wcstools-3.9.5/libwcs/lwcs.h0000664000016200001660000000646411750060645015075 0ustar minkoirsys/*** File lwcs.h *** April 25, 2006 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1999-2006 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ /* The following are used in star finding (findstar.c) */ #define NSTATPIX 25 /* Stats are computed for +- this many pixels */ #define ISTATPIX 10 /* Stats are computed every this many pixels */ #define MAXWALK 20 /* Farthest distance to walk from seed */ #define BURNEDOUT 0 /* Clamp pixels brighter than this, if > 0 */ #define NITERATE 5 /* Number of iterations for sigma clipping */ #define RNOISE 50 /* Mean noise is from center +- this many pixels */ #define STARSIGMA 5.0 /* Stars must be this many sigmas above mean */ #define BORDER 10 /* Ignore this much of the edge */ #define MAXRAD 20 /* Maximum radius for a star */ #define MINRAD 1 /* Minimum radius for a star */ #define MINPEAK 10 /* Minimum peak for a star */ #define MINSEP 10 /* Minimum separations for stars */ /* The following are used in star matching (matchstar.c) */ #define FTOL 0.0000001 /* Fractional change of chisqr() to be done */ #define NMAX 3000 /* Maximum number of minimization iterations */ #define NPEAKS 20 /* Binning peak history */ #define MINMATCH 50 /* Stars to match to drop out of loop */ /* The following are used in world coordinate system fitting (imsetwcs.c) */ #define MINSTARS 3 /* Minimum stars from reference and image */ #define MAXSTARS 50 /* Default max star pairs to try matching */ #define MAGLIM1 0.0 /* Faintest reference catalog magnitude to use*/ #define MAGLIM2 0.0 /* Faintest reference catalog magnitude to use*/ #define PIXDIFF 10 /* +- this many pixels is a match */ #define PSCALE 0 /* Plate scale in arcsec/pixel */ /* (if nonzero, this overrides image header) */ #define NXYDEC 2 /* Number of decimal places in image coords */ #define MAXCAT 100 /* Max reference stars to keep in scat or imcat */ /* Jun 11 1999 Set BURNEDOUT to 0 so it is ignored * * Feb 15 2000 Drop MAXREF; add MAXCAT for imcat and scat; MAXSTARS from 25 to 50 * * Oct 31 2001 Add MINMATCH and set default value to 50 * * Mar 30 2006 Add NXYDEC and set default to 2 (constant value was 1) * Apr 25 2006 Add RNOISE and set default to previous constant value of 50 */ wcstools-3.9.5/libwcs/wcs.h0000664000016200001660000014170512732777020014722 0ustar minkoirsys/*** File libwcs/wcs.h *** June 23, 2016 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1994-2016 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #ifndef _wcs_h_ #define _wcs_h_ #include "wcslib.h" #include "fitshead.h" #define MAXNKWD 500 /* SIRTF distortion matrix coefficients */ #define DISTMAX 10 struct Distort { int a_order; /* max power for the 1st dimension */ double a[DISTMAX][DISTMAX]; /* coefficient array of 1st dimension */ int b_order; /* max power for 1st dimension */ double b[DISTMAX][DISTMAX]; /* coefficient array of 2nd dimension */ int ap_order; /* max power for the 1st dimension */ double ap[DISTMAX][DISTMAX]; /* coefficient array of 1st dimension */ int bp_order; /* max power for 1st dimension */ double bp[DISTMAX][DISTMAX]; /* coefficient array of 2nd dimension */ }; struct WorldCoor { double xref; /* X reference coordinate value (deg) */ double yref; /* Y reference coordinate value (deg) */ double xrefpix; /* X reference pixel */ double yrefpix; /* Y reference pixel */ double xinc; /* X coordinate increment (deg) */ double yinc; /* Y coordinate increment (deg) */ double rot; /* rotation around axis (deg) (N through E) */ double cd[4]; /* rotation matrix */ double dc[4]; /* inverse rotation matrix */ double equinox; /* Equinox of coordinates default to 1950.0 */ double epoch; /* Epoch of coordinates default to equinox */ double nxpix; /* Number of pixels in X-dimension of image */ double nypix; /* Number of pixels in Y-dimension of image */ double plate_ra; /* Right ascension of plate center */ double plate_dec; /* Declination of plate center */ double plate_scale; /* Plate scale in arcsec/mm */ double x_pixel_offset; /* X pixel offset of image lower right */ double y_pixel_offset; /* Y pixel offset of image lower right */ double x_pixel_size; /* X pixel_size */ double y_pixel_size; /* Y pixel_size */ double ppo_coeff[6]; /* pixel to plate coefficients for DSS */ double x_coeff[20]; /* X coefficients for plate model */ double y_coeff[20]; /* Y coefficients for plate model */ double xpix; /* X (RA) coordinate (pixels) */ double ypix; /* Y (dec) coordinate (pixels) */ double zpix; /* Z (face) coordinate (pixels) */ double xpos; /* X (RA) coordinate (deg) */ double ypos; /* Y (dec) coordinate (deg) */ double crpix[9]; /* Values of CRPIXn keywords */ double crval[9]; /* Values of CRVALn keywords */ double cdelt[9]; /* Values of CDELTn keywords */ double pc[81]; /* Values of PCiiijjj keywords */ double projp[10]; /* Constants for various projections */ int pvfail; /* If non-zero, significant inaccuracy likely to occur in projection */ double projppv[2*MAXPV]; /* SCAMP constants for the PV coordinates */ struct poly *inv_x; /* SCAMP projection correction polynom in x */ struct poly *inv_y; /* SCAMP projection correction polynom in y */ double longpole; /* Longitude of North Pole in degrees */ double latpole; /* Latitude of North Pole in degrees */ double rodeg; /* Radius of the projection generating sphere */ double imrot; /* Rotation angle of north pole */ double pa_north; /* Position angle of north (0=horizontal) */ double pa_east; /* Position angle of east (0=horizontal) */ double radvel; /* Radial velocity (km/sec away from observer)*/ double zvel; /* Radial velocity (v/c away from observer)*/ double zpzd; /* Colat of FIP (degs) */ double zpr; /* Radius of FIP (degs) */ int imflip; /* If not 0, image is reflected around axis */ int prjcode; /* projection code (-1-32) */ int latbase; /* Latitude base 90 (NPA), 0 (LAT), -90 (SPA) */ int ncoeff1; /* Number of x-axis plate fit coefficients */ int ncoeff2; /* Number of y-axis plate fit coefficients */ int zpnp; /* ZP polynomial order (0-9) */ int changesys; /* 1 for FK4->FK5, 2 for FK5->FK4 */ /* 3 for FK4->galactic, 4 for FK5->galactic */ int printsys; /* 1 to print coordinate system, else 0 */ int ndec; /* Number of decimal places in PIX2WCST */ int degout; /* 1 to always print degrees in PIX2WCST */ int tabsys; /* 1 to put tab between RA & Dec, else 0 */ int rotmat; /* 0 if CDELT, CROTA; 1 if CD */ int coorflip; /* 0 if x=RA, y=Dec; 1 if x=Dec, y=RA */ int offscl; /* 0 if OK, 1 if offscale */ int wcson; /* 1 if WCS is set, else 0 */ int naxis; /* Number of axes in image (for WCSLIB 3.0) */ int naxes; /* Number of axes in image */ int wcsproj; /* WCS_OLD: AIPS worldpos() and worldpix() WCS_NEW: Mark Calabretta's WCSLIB subroutines WCS_BEST: WCSLIB for all but CAR,COE,NCP WCS_ALT: AIPS for all but CAR,COE,NCP */ int linmode; /* 0=system only, 1=units, 2=system+units */ int detector; /* Instrument detector number */ char instrument[32]; /* Instrument name */ char ctype[9][16]; /* Values of CTYPEn keywords */ char c1type[8]; /* 1st coordinate type code: RA--, GLON, ELON */ char c2type[8]; /* 2nd coordinate type code: DEC-, GLAT, ELAT */ char ptype[8]; /* projection type code: SIN, TAN, ARC, NCP, GLS, MER, AIT, etc */ char units[9][32]; /* Units if LINEAR */ char radecsys[32]; /* Reference frame: FK4, FK4-NO-E, FK5, GAPPT*/ char radecout[32]; /* Output reference frame: FK4,FK5,GAL,ECL */ char radecin[32]; /* Input reference frame: FK4,FK5,GAL,ECL */ double eqin; /* Input equinox (match sysin if 0.0) */ double eqout; /* Output equinox (match sysout if 0.0) */ int sysin; /* Input coordinate system code */ int syswcs; /* WCS coordinate system code */ int sysout; /* Output coordinate system code */ /* WCS_B1950, WCS_J2000, WCS_ICRS, WCS_GALACTIC, * WCS_ECLIPTIC, WCS_LINEAR, WCS_ALTAZ */ char center[32]; /* Center coordinates (with frame) */ struct wcsprm wcsl; /* WCSLIB main projection parameters */ struct linprm lin; /* WCSLIB image/pixel conversion parameters */ struct celprm cel; /* WCSLIB projection type */ struct prjprm prj; /* WCSLIB projection parameters */ struct IRAFsurface *lngcor; /* RA/longitude correction structure */ struct IRAFsurface *latcor; /* Dec/latitude correction structure */ int distcode; /* Distortion code 0=none 1=SIRTF */ struct Distort distort; /* SIRTF distortion coefficients */ char *command_format[10]; /* WCS command formats */ /* where %s is replaced by WCS coordinates */ /* where %f is replaced by the image filename */ /* where %x is replaced by image coordinates */ double ltm[4]; /* Image rotation matrix */ double ltv[2]; /* Image offset */ int idpix[2]; /* First pixel to use in image (x, y) */ int ndpix[2]; /* Number of pixels to use in image (x, y) */ struct WorldCoor *wcs; /* WCS upon which this WCS depends */ struct WorldCoor *wcsdep; /* WCS depending on this WCS */ char *wcsname; /* WCS name (defaults to NULL pointer) */ char wcschar; /* WCS character (A-Z, null, space) */ int logwcs; /* 1 if DC-FLAG is set for log wavelength */ }; /* Projections (1-26 are WCSLIB) (values for wcs->prjcode) */ #define WCS_PIX -1 /* Pixel WCS */ #define WCS_LIN 0 /* Linear projection */ #define WCS_AZP 1 /* Zenithal/Azimuthal Perspective */ #define WCS_SZP 2 /* Zenithal/Azimuthal Perspective */ #define WCS_TAN 3 /* Gnomonic = Tangent Plane */ #define WCS_SIN 4 /* Orthographic/synthesis */ #define WCS_STG 5 /* Stereographic */ #define WCS_ARC 6 /* Zenithal/azimuthal equidistant */ #define WCS_ZPN 7 /* Zenithal/azimuthal PolyNomial */ #define WCS_ZEA 8 /* Zenithal/azimuthal Equal Area */ #define WCS_AIR 9 /* Airy */ #define WCS_CYP 10 /* CYlindrical Perspective */ #define WCS_CAR 11 /* Cartesian */ #define WCS_MER 12 /* Mercator */ #define WCS_CEA 13 /* Cylindrical Equal Area */ #define WCS_COP 14 /* Conic PerSpective (COP) */ #define WCS_COD 15 /* COnic equiDistant */ #define WCS_COE 16 /* COnic Equal area */ #define WCS_COO 17 /* COnic Orthomorphic */ #define WCS_BON 18 /* Bonne */ #define WCS_PCO 19 /* Polyconic */ #define WCS_SFL 20 /* Sanson-Flamsteed (GLobal Sinusoidal) */ #define WCS_PAR 21 /* Parabolic */ #define WCS_AIT 22 /* Hammer-Aitoff */ #define WCS_MOL 23 /* Mollweide */ #define WCS_CSC 24 /* COBE quadrilateralized Spherical Cube */ #define WCS_QSC 25 /* Quadrilateralized Spherical Cube */ #define WCS_TSC 26 /* Tangential Spherical Cube */ #define WCS_NCP 27 /* Special case of SIN from AIPS*/ #define WCS_GLS 28 /* Same as SFL from AIPS*/ #define WCS_DSS 29 /* Digitized Sky Survey plate solution */ #define WCS_PLT 30 /* Plate fit polynomials (SAO) */ #define WCS_TNX 31 /* Tangent Plane (NOAO corrections) */ #define WCS_ZPX 32 /* Zenithal Azimuthal Polynomial (NOAO corrections) */ #define WCS_TPV 33 /* Tangent Plane (SCAMP corrections) */ #define NWCSTYPE 34 /* Number of WCS types (-1 really means no WCS) */ /* Coordinate systems */ #define WCS_J2000 1 /* J2000(FK5) right ascension and declination */ #define WCS_B1950 2 /* B1950(FK4) right ascension and declination */ #define WCS_GALACTIC 3 /* Galactic longitude and latitude */ #define WCS_ECLIPTIC 4 /* Ecliptic longitude and latitude */ #define WCS_ALTAZ 5 /* Azimuth and altitude/elevation */ #define WCS_LINEAR 6 /* Linear with optional units */ #define WCS_NPOLE 7 /* Longitude and north polar angle */ #define WCS_SPA 8 /* Longitude and south polar angle */ #define WCS_PLANET 9 /* Longitude and latitude on planet */ #define WCS_XY 10 /* X-Y Cartesian coordinates */ #define WCS_ICRS 11 /* ICRS right ascension and declination */ /* Method to use */ #define WCS_BEST 0 /* Use best WCS projections */ #define WCS_ALT 1 /* Use not best WCS projections */ #define WCS_OLD 2 /* Use AIPS WCS projections */ #define WCS_NEW 3 /* Use WCSLIB 2.5 WCS projections */ /* Distortion codes (values for wcs->distcode) */ #define DISTORT_NONE 0 /* No distortion coefficients */ #define DISTORT_SIRTF 1 /* SIRTF distortion matrix */ #ifndef PI #define PI 3.141592653589793238462643 #endif /* pi/(180*3600): arcseconds to radians */ #define AS2R 4.8481368110953e-6 /* Conversions among hours of RA, degrees and radians. */ #define degrad(x) ((x)*PI/180.) #define raddeg(x) ((x)*180./PI) #define hrdeg(x) ((x)*15.) #define deghr(x) ((x)/15.) #define hrrad(x) degrad(hrdeg(x)) #define radhr(x) deghr(raddeg(x)) #define secrad(x) ((x)*AS2R) /* TNX/ZPX surface fitting structure and flags */ struct IRAFsurface { double xrange; /* 2. / (xmax - xmin), polynomials */ double xmaxmin; /* - (xmax + xmin) / 2., polynomials */ double yrange; /* 2. / (ymax - ymin), polynomials */ double ymaxmin; /* - (ymax + ymin) / 2., polynomials */ int type; /* type of curve to be fitted */ int xorder; /* order of the fit in x */ int yorder; /* order of the fit in y */ int xterms; /* cross terms for polynomials */ int ncoeff; /* total number of coefficients */ double *coeff; /* pointer to coefficient vector */ double *xbasis; /* pointer to basis functions (all x) */ double *ybasis; /* pointer to basis functions (all y) */ }; /* TNX/ZPX permitted types of surfaces */ #define TNX_CHEBYSHEV 1 #define TNX_LEGENDRE 2 #define TNX_POLYNOMIAL 3 /* TNX/ZPX cross-terms flags */ #define TNX_XNONE 0 /* no x-terms (old no) */ #define TNX_XFULL 1 /* full x-terms (new yes) */ #define TNX_XHALF 2 /* half x-terms (new) */ #ifdef __cplusplus /* C++ prototypes */ extern "C" { #endif #ifdef __STDC__ /* Full ANSI prototypes */ /* WCS data structure initialization subroutines in wcsinit.c */ struct WorldCoor *wcsinit ( /* set up WCS structure from a FITS image header */ const char* hstring); struct WorldCoor *wcsninit ( /* set up WCS structure from a FITS image header */ const char* hstring, /* FITS header */ int len); /* Length of FITS header */ struct WorldCoor *wcsinitn ( /* set up WCS structure from a FITS image header */ const char* hstring, /* FITS header */ const char* wcsname); /* WCS name */ struct WorldCoor *wcsninitn ( /* set up WCS structure from a FITS image header */ const char* hstring, /* FITS header */ int len, /* Length of FITS header */ const char* wcsname); /* WCS name */ struct WorldCoor *wcsinitc ( /* set up WCS structure from a FITS image header */ const char* hstring, /* FITS header */ char *wcschar); /* WCS character (A-Z) */ struct WorldCoor *wcsninitc ( /* set up WCS structure from a FITS image header */ const char* hstring, /* FITS header */ int len, /* Length of FITS header */ char *wcschar); /* WCS character (A-Z) */ char *uppercase ( /* Convert string of any case to uppercase */ const char *string); /* String to convert */ /* WCS subroutines in wcs.c */ void wcsfree ( /* Free a WCS structure and its contents */ struct WorldCoor *wcs); /* World coordinate system structure */ int wcstype( /* Set projection type from header CTYPEs */ struct WorldCoor *wcs, /* World coordinate system structure */ char *ctype1, /* FITS WCS projection for axis 1 */ char *ctype2); /* FITS WCS projection for axis 2 */ int iswcs( /* Returns 1 if wcs structure set, else 0 */ struct WorldCoor *wcs); /* World coordinate system structure */ int nowcs( /* Returns 0 if wcs structure set, else 1 */ struct WorldCoor *wcs); /* World coordinate system structure */ int pix2wcst ( /* Convert pixel coordinates to World Coordinate string */ struct WorldCoor *wcs, /* World coordinate system structure */ double xpix, /* Image horizontal coordinate in pixels */ double ypix, /* Image vertical coordinate in pixels */ char *wcstring, /* World coordinate string (returned) */ int lstr); /* Length of world coordinate string (returned) */ void pix2wcs ( /* Convert pixel coordinates to World Coordinates */ struct WorldCoor *wcs, /* World coordinate system structure */ double xpix, /* Image horizontal coordinate in pixels */ double ypix, /* Image vertical coordinate in pixels */ double *xpos, /* Longitude/Right Ascension in degrees (returned) */ double *ypos); /* Latitude/Declination in degrees (returned) */ void wcsc2pix ( /* Convert World Coordinates to pixel coordinates */ struct WorldCoor *wcs, /* World coordinate system structure */ double xpos, /* Longitude/Right Ascension in degrees */ double ypos, /* Latitude/Declination in degrees */ char *coorsys, /* Coordinate system (B1950, J2000, etc) */ double *xpix, /* Image horizontal coordinate in pixels (returned) */ double *ypix, /* Image vertical coordinate in pixels (returned) */ int *offscl); void wcs2pix ( /* Convert World Coordinates to pixel coordinates */ struct WorldCoor *wcs, /* World coordinate system structure */ double xpos, /* Longitude/Right Ascension in degrees */ double ypos, /* Latitude/Declination in degrees */ double *xpix, /* Image horizontal coordinate in pixels (returned) */ double *ypix, /* Image vertical coordinate in pixels (returned) */ int *offscl); double wcsdist( /* Compute angular distance between 2 sky positions */ double ra1, /* First longitude/right ascension in degrees */ double dec1, /* First latitude/declination in degrees */ double ra2, /* Second longitude/right ascension in degrees */ double dec2); /* Second latitude/declination in degrees */ double wcsdist1( /* Compute angular distance between 2 sky positions */ double ra1, /* First longitude/right ascension in degrees */ double dec1, /* First latitude/declination in degrees */ double ra2, /* Second longitude/right ascension in degrees */ double dec2); /* Second latitude/declination in degrees */ double wcsdiff( /* Compute angular distance between 2 sky positions */ double ra1, /* First longitude/right ascension in degrees */ double dec1, /* First latitude/declination in degrees */ double ra2, /* Second longitude/right ascension in degrees */ double dec2); /* Second latitude/declination in degrees */ struct WorldCoor* wcsxinit( /* set up a WCS structure from arguments */ double cra, /* Center right ascension in degrees */ double cdec, /* Center declination in degrees */ double secpix, /* Number of arcseconds per pixel */ double xrpix, /* Reference pixel X coordinate */ double yrpix, /* Reference pixel X coordinate */ int nxpix, /* Number of pixels along x-axis */ int nypix, /* Number of pixels along y-axis */ double rotate, /* Rotation angle (clockwise positive) in degrees */ int equinox, /* Equinox of coordinates, 1950 and 2000 supported */ double epoch, /* Epoch of coordinates, used for FK4/FK5 conversion * no effect if 0 */ char *proj); /* Projection */ struct WorldCoor* wcskinit( /* set up WCS structure from keyword values */ int naxis1, /* Number of pixels along x-axis */ int naxis2, /* Number of pixels along y-axis */ char *ctype1, /* FITS WCS projection for axis 1 */ char *ctype2, /* FITS WCS projection for axis 2 */ double crpix1, /* Reference pixel coordinates */ double crpix2, /* Reference pixel coordinates */ double crval1, /* Coordinate at reference pixel in degrees */ double crval2, /* Coordinate at reference pixel in degrees */ double *cd, /* Rotation matrix, used if not NULL */ double cdelt1, /* scale in degrees/pixel, if cd is NULL */ double cdelt2, /* scale in degrees/pixel, if cd is NULL */ double crota, /* Rotation angle in degrees, if cd is NULL */ int equinox, /* Equinox of coordinates, 1950 and 2000 supported */ double epoch); /* Epoch of coordinates, for FK4/FK5 conversion */ void wcsshift( /* Change center of WCS */ struct WorldCoor *wcs, /* World coordinate system structure */ double cra, /* New center right ascension in degrees */ double cdec, /* New center declination in degrees */ char *coorsys); /* FK4 or FK5 coordinates (1950 or 2000) */ void wcsfull( /* Return RA and Dec of image center, size in degrees */ struct WorldCoor *wcs, /* World coordinate system structure */ double *cra, /* Right ascension of image center (deg) (returned) */ double *cdec, /* Declination of image center (deg) (returned) */ double *width, /* Width in degrees (returned) */ double *height); /* Height in degrees (returned) */ void wcscent( /* Print the image center and size in WCS units */ struct WorldCoor *wcs); /* World coordinate system structure */ void wcssize( /* Return image center and size in RA and Dec */ struct WorldCoor *wcs, /* World coordinate system structure */ double *cra, /* Right ascension of image center (deg) (returned) */ double *cdec, /* Declination of image center (deg) (returned) */ double *dra, /* Half-width in right ascension (deg) (returned) */ double *ddec); /* Half-width in declination (deg) (returned) */ void wcsrange( /* Return min and max RA and Dec of image in degrees */ struct WorldCoor *wcs, /* World coordinate system structure */ double *ra1, /* Min. right ascension of image (deg) (returned) */ double *ra2, /* Max. right ascension of image (deg) (returned) */ double *dec1, /* Min. declination of image (deg) (returned) */ double *dec2); /* Max. declination of image (deg) (returned) */ void wcscdset( /* Set scaling and rotation from CD matrix */ struct WorldCoor *wcs, /* World coordinate system structure */ double *cd); /* CD matrix, ignored if NULL */ void wcsdeltset( /* set scaling, rotation from CDELTi, CROTA2 */ struct WorldCoor *wcs, /* World coordinate system structure */ double cdelt1, /* degrees/pixel in first axis (or both axes) */ double cdelt2, /* degrees/pixel in second axis if nonzero */ double crota); /* Rotation counterclockwise in degrees */ void wcspcset( /* set scaling, rotation from CDELTs and PC matrix */ struct WorldCoor *wcs, /* World coordinate system structure */ double cdelt1, /* degrees/pixel in first axis (or both axes) */ double cdelt2, /* degrees/pixel in second axis if nonzero */ double *pc); /* Rotation matrix, ignored if NULL */ void setwcserr( /* Set WCS error message for later printing */ char *errmsg); /* Error mesage < 80 char */ void wcserr(void); /* Print WCS error message to stderr */ void setdefwcs( /* Set flag to use AIPS WCS instead of WCSLIB */ int oldwcs); /* 1 for AIPS WCS subroutines, else WCSLIB */ int getdefwcs(void); /* Return flag for AIPS WCS set by setdefwcs */ char *getradecsys( /* Return name of image coordinate system */ struct WorldCoor *wcs); /* World coordinate system structure */ void wcsoutinit( /* Set output coordinate system for pix2wcs */ struct WorldCoor *wcs, /* World coordinate system structure */ char *coorsys); /* Coordinate system (B1950, J2000, etc) */ char *getwcsout( /* Return current output coordinate system */ struct WorldCoor *wcs); /* World coordinate system structure */ void wcsininit( /* Set input coordinate system for wcs2pix */ struct WorldCoor *wcs, /* World coordinate system structure */ char *coorsys); /* Coordinate system (B1950, J2000, etc) */ char *getwcsin( /* Return current input coordinate system */ struct WorldCoor *wcs); /* World coordinate system structure */ int setwcsdeg( /* Set WCS coordinate output format */ struct WorldCoor *wcs, /* World coordinate system structure */ int degout); /* 1= degrees, 0= hh:mm:ss dd:mm:ss */ int wcsndec( /* Set or get number of output decimal places */ struct WorldCoor *wcs, /* World coordinate system structure */ int ndec); /* Number of decimal places in output string if < 0, return current ndec unchanged */ int wcsreset( /* Change WCS using arguments */ struct WorldCoor *wcs, /* World coordinate system data structure */ double crpix1, /* Horizontal reference pixel */ double crpix2, /* Vertical reference pixel */ double crval1, /* Reference pixel horizontal coordinate in degrees */ double crval2, /* Reference pixel vertical coordinate in degrees */ double cdelt1, /* Horizontal scale in degrees/pixel, ignored if cd is not NULL */ double cdelt2, /* Vertical scale in degrees/pixel, ignored if cd is not NULL */ double crota, /* Rotation angle in degrees, ignored if cd is not NULL */ double *cd); /* Rotation matrix, used if not NULL */ void wcseqset( /* Change equinox of reference pixel coordinates in WCS */ struct WorldCoor *wcs, /* World coordinate system data structure */ double equinox); /* Desired equinox as fractional year */ void setwcslin( /* Set pix2wcst() mode for LINEAR coordinates */ struct WorldCoor *wcs, /* World coordinate system structure */ int mode); /* 0: x y linear, 1: x units x units 2: x y linear units */ int wcszin( /* Set third dimension for cube projections */ int izpix); /* Set coordinate in third dimension (face) */ int wcszout ( /* Return coordinate in third dimension */ struct WorldCoor *wcs); /* World coordinate system structure */ void wcscominit( /* Initialize catalog search command set by -wcscom */ struct WorldCoor *wcs, /* World coordinate system structure */ int i, /* Number of command (0-9) to initialize */ char *command); /* command with %s where coordinates will go */ void wcscom( /* Execute catalog search command set by -wcscom */ struct WorldCoor *wcs, /* World coordinate system structure */ int i, /* Number of command (0-9) to execute */ char *filename, /* Image file name */ double xfile, /* Horizontal image pixel coordinates for WCS command */ double yfile, /* Vertical image pixel coordinates for WCS command */ char *wcstring); /* WCS String from pix2wcst() */ void savewcscom( /* Save WCS shell command */ int i, /* i of 10 possible shell commands */ char *wcscom); /* Shell command using output WCS string */ char *getwcscom( /* Return WCS shell command */ int i); /* i of 10 possible shell commands */ void setwcscom( /* Set WCS shell commands from stored values */ struct WorldCoor *wcs); /* World coordinate system structure */ void freewcscom( /* Free memory storing WCS shell commands */ struct WorldCoor *wcs); /* World coordinate system structure */ void setwcsfile( /* Set filename for WCS error message */ char *filename); /* FITS or IRAF file name */ int cpwcs ( /* Copy WCS keywords with no suffix to ones with suffix */ char **header, /* Pointer to start of FITS header */ char *cwcs); /* Keyword suffix character for output WCS */ void savewcscoor( /* Save output coordinate system */ char *wcscoor); /* coordinate system (J2000, B1950, galactic) */ char *getwcscoor(void); /* Return output coordinate system */ /* Coordinate conversion subroutines in wcscon.c */ void wcsconv( /* Convert between coordinate systems and equinoxes */ int sys1, /* Input coordinate system (J2000, B1950, ECLIPTIC, GALACTIC */ int sys2, /* Output coordinate system (J2000, B1950, ECLIPTIC, G ALACTIC */ double eq1, /* Input equinox (default of sys1 if 0.0) */ double eq2, /* Output equinox (default of sys2 if 0.0) */ double ep1, /* Input Besselian epoch in years */ double ep2, /* Output Besselian epoch in years */ double *dtheta, /* Longitude or right ascension in degrees Input in sys1, returned in sys2 */ double *dphi, /* Latitude or declination in degrees Input in sys1, returned in sys2 */ double *ptheta, /* Longitude or right ascension proper motion in deg/year Input in sys1, returned in sys2 */ double *pphi, /* Latitude or declination proper motion in deg/year */ double *px, /* Parallax in arcseconds */ double *rv); /* Radial velocity in km/sec */ void wcsconp( /* Convert between coordinate systems and equinoxes */ int sys1, /* Input coordinate system (J2000, B1950, ECLIPTIC, GALACTIC */ int sys2, /* Output coordinate system (J2000, B1950, ECLIPTIC, G ALACTIC */ double eq1, /* Input equinox (default of sys1 if 0.0) */ double eq2, /* Output equinox (default of sys2 if 0.0) */ double ep1, /* Input Besselian epoch in years */ double ep2, /* Output Besselian epoch in years */ double *dtheta, /* Longitude or right ascension in degrees Input in sys1, returned in sys2 */ double *dphi, /* Latitude or declination in degrees Input in sys1, returned in sys2 */ double *ptheta, /* Longitude or right ascension proper motion in degrees/year Input in sys1, returned in sys2 */ double *pphi); /* Latitude or declination proper motion in degrees/year Input in sys1, returned in sys2 */ void wcscon( /* Convert between coordinate systems and equinoxes */ int sys1, /* Input coordinate system (J2000, B1950, ECLIPTIC, GALACTIC */ int sys2, /* Output coordinate system (J2000, B1950, ECLIPTIC, G ALACTIC */ double eq1, /* Input equinox (default of sys1 if 0.0) */ double eq2, /* Output equinox (default of sys2 if 0.0) */ double *dtheta, /* Longitude or right ascension in degrees Input in sys1, returned in sys2 */ double *dphi, /* Latitude or declination in degrees Input in sys1, returned in sys2 */ double epoch); /* Besselian epoch in years */ void fk425e ( /* Convert B1950(FK4) to J2000(FK5) coordinates */ double *ra, /* Right ascension in degrees (B1950 in, J2000 out) */ double *dec, /* Declination in degrees (B1950 in, J2000 out) */ double epoch); /* Besselian epoch in years */ void fk524e ( /* Convert J2000(FK5) to B1950(FK4) coordinates */ double *ra, /* Right ascension in degrees (J2000 in, B1950 out) */ double *dec, /* Declination in degrees (J2000 in, B1950 out) */ double epoch); /* Besselian epoch in years */ int wcscsys( /* Return code for coordinate system in string */ char *coorsys); /* Coordinate system (B1950, J2000, etc) */ double wcsceq ( /* Set equinox from string (return 0.0 if not obvious) */ char *wcstring); /* Coordinate system (B1950, J2000, etc) */ void wcscstr ( /* Set coordinate system type string from system and equinox */ char *cstr, /* Coordinate system string (returned) */ int syswcs, /* Coordinate system code */ double equinox, /* Equinox of coordinate system */ double epoch); /* Epoch of coordinate system */ void d2v3 ( /* Convert RA and Dec in degrees and distance to vector */ double rra, /* Right ascension in degrees */ double rdec, /* Declination in degrees */ double r, /* Distance to object in same units as pos */ double pos[3]); /* x,y,z geocentric equatorial position of object (returned) */ void s2v3 ( /* Convert RA and Dec in radians and distance to vector */ double rra, /* Right ascension in radians */ double rdec, /* Declination in radians */ double r, /* Distance to object in same units as pos */ double pos[3]); /* x,y,z geocentric equatorial position of object (returned) */ void v2d3 ( /* Convert vector to RA and Dec in degrees and distance */ double pos[3], /* x,y,z geocentric equatorial position of object */ double *rra, /* Right ascension in degrees (returned) */ double *rdec, /* Declination in degrees (returned) */ double *r); /* Distance to object in same units as pos (returned) */ void v2s3 ( /* Convert vector to RA and Dec in radians and distance */ double pos[3], /* x,y,z geocentric equatorial position of object */ double *rra, /* Right ascension in radians (returned) */ double *rdec, /* Declination in radians (returned) */ double *r); /* Distance to object in same units as pos (returned) */ /* Distortion model subroutines in distort.c */ void distortinit ( /* Set distortion coefficients from FITS header */ struct WorldCoor *wcs, /* World coordinate system structure */ const char* hstring); /* FITS header */ void setdistcode ( /* Set WCS distortion code string from CTYPEi value */ struct WorldCoor *wcs, /* World coordinate system structure */ char *ctype); /* CTYPE value from FITS header */ char *getdistcode ( /* Return distortion code string for CTYPEi */ struct WorldCoor *wcs); /* World coordinate system structure */ int DelDistort ( /* Delete all distortion-related fields */ char *header, /* FITS header */ int verbose); /* If !=0, print keywords as deleted */ void pix2foc ( /* Convert pixel to focal plane coordinates */ struct WorldCoor *wcs, /* World coordinate system structure */ double x, /* Image pixel horizontal coordinate */ double y, /* Image pixel vertical coordinate */ double *u, /* Focal plane horizontal coordinate(returned) */ double *v); /* Focal plane vertical coordinate (returned) */ void foc2pix ( /* Convert focal plane to pixel coordinates */ struct WorldCoor *wcs, /* World coordinate system structure */ double u, /* Focal plane horizontal coordinate */ double v, /* Focal plane vertical coordinate */ double *x, /* Image pixel horizontal coordinate(returned) */ double *y); /* Image pixel vertical coordinate (returned) */ /* Other projection subroutines */ /* 8 projections using AIPS algorithms (worldpos.c) */ int worldpos ( /* Convert from pixel location to RA,Dec */ double xpix, /* x pixel number (RA or long without rotation) */ double ypix, /* y pixel number (Dec or lat without rotation) */ struct WorldCoor *wcs, /* WCS parameter structure */ double *xpos, /* x (RA) coordinate (deg) (returned) */ double *ypos); /* y (dec) coordinate (deg) (returned) */ int worldpix ( /* Convert from RA,Dec to pixel location */ double xpos, /* x (RA) coordinate (deg) */ double ypos, /* y (dec) coordinate (deg) */ struct WorldCoor *wcs, /* WCS parameter structure */ double *xpix, /* x pixel number (RA or long without rotation) */ double *ypix); /* y pixel number (dec or lat without rotation) */ /* Digital Sky Survey projection (dsspos.c) */ int dsspos ( /* Convert from pixel location to RA,Dec */ double xpix, /* x pixel number (RA or long without rotation) */ double ypix, /* y pixel number (Dec or lat without rotation) */ struct WorldCoor *wcs, /* WCS parameter structure */ double *xpos, /* x (RA) coordinate (deg) (returned) */ double *ypos); /* y (dec) coordinate (deg) (returned) */ int dsspix ( /* Convert from RA,Dec to pixel location */ double xpos, /* x (RA) coordinate (deg) */ double ypos, /* y (dec) coordinate (deg) */ struct WorldCoor *wcs, /* WCS parameter structure */ double *xpix, /* x pixel number (RA or long without rotation) */ double *ypix); /* y pixel number (dec or lat without rotation) */ /* SAO TDC TAN projection with higher order terms (platepos.c) */ int platepos ( /* Convert from pixel location to RA,Dec */ double xpix, /* x pixel number (RA or long without rotation) */ double ypix, /* y pixel number (Dec or lat without rotation) */ struct WorldCoor *wcs, /* WCS parameter structure */ double *xpos, /* x (RA) coordinate (deg) (returned) */ double *ypos); /* y (dec) coordinate (deg) (returned) */ int platepix ( /* Convert from RA,Dec to pixel location */ double xpos, /* x (RA) coordinate (deg) */ double ypos, /* y (dec) coordinate (deg) */ struct WorldCoor *wcs, /* WCS parameter structure */ double *xpix, /* x pixel number (RA or long without rotation) */ double *ypix); /* y pixel number (dec or lat without rotation) */ void SetFITSPlate ( /* Set FITS header plate fit coefficients from structure */ char *header, /* Image FITS header */ struct WorldCoor *wcs); /* WCS structure */ int SetPlate ( /* Set plate fit coefficients in structure from arguments */ struct WorldCoor *wcs, /* World coordinate system structure */ int ncoeff1, /* Number of coefficients for x */ int ncoeff2, /* Number of coefficients for y */ double *coeff); /* Plate fit coefficients */ int GetPlate ( /* Return plate fit coefficients from structure in arguments */ struct WorldCoor *wcs, /* World coordinate system structure */ int *ncoeff1, /* Number of coefficients for x */ int *ncoeff2, /* Number of coefficients for y) */ double *coeff); /* Plate fit coefficients */ /* IRAF TAN projection with higher order terms (tnxpos.c) */ int tnxinit ( /* initialize the gnomonic forward or inverse transform */ const char *header, /* FITS header */ struct WorldCoor *wcs); /* pointer to WCS structure */ int tnxpos ( /* forward transform (physical to world) gnomonic projection. */ double xpix, /* Image X coordinate */ double ypix, /* Image Y coordinate */ struct WorldCoor *wcs, /* pointer to WCS descriptor */ double *xpos, /* Right ascension (returned) */ double *ypos); /* Declination (returned) */ int tnxpix ( /* Inverse transform (world to physical) gnomonic projection */ double xpos, /* Right ascension */ double ypos, /* Declination */ struct WorldCoor *wcs, /* Pointer to WCS descriptor */ double *xpix, /* Image X coordinate (returned) */ double *ypix); /* Image Y coordinate (returned) */ /* IRAF ZPN projection with higher order terms (zpxpos.c) */ int zpxinit ( /* initialize the zenithal forward or inverse transform */ const char *header, /* FITS header */ struct WorldCoor *wcs); /* pointer to WCS structure */ int zpxpos ( /* forward transform (physical to world) */ double xpix, /* Image X coordinate */ double ypix, /* Image Y coordinate */ struct WorldCoor *wcs, /* pointer to WCS descriptor */ double *xpos, /* Right ascension (returned) */ double *ypos); /* Declination (returned) */ int zpxpix ( /* Inverse transform (world to physical) */ double xpos, /* Right ascension */ double ypos, /* Declination */ struct WorldCoor *wcs, /* Pointer to WCS descriptor */ double *xpix, /* Image X coordinate (returned) */ double *ypix); /* Image Y coordinate (returned) */ #else /* K&R prototypes */ /* WCS subroutines in wcs.c */ struct WorldCoor *wcsinit(); /* set up a WCS structure from a FITS image header */ struct WorldCoor *wcsninit(); /* set up a WCS structure from a FITS image header */ struct WorldCoor *wcsinitn(); /* set up a WCS structure from a FITS image header */ struct WorldCoor *wcsninitn(); /* set up a WCS structure from a FITS image header */ struct WorldCoor *wcsinitc(); /* set up a WCS structure from a FITS image header */ struct WorldCoor *wcsninitc(); /* set up a WCS structure from a FITS image header */ struct WorldCoor *wcsxinit(); /* set up a WCS structure from arguments */ struct WorldCoor *wcskinit(); /* set up a WCS structure from keyword values */ char *uppercase(); /* Convert string of any case to uppercase */ void wcsfree(void); /* Free a WCS structure and its contents */ int wcstype(); /* Set projection type from header CTYPEs */ void wcscdset(); /* Set scaling and rotation from CD matrix */ void wcsdeltset(); /* set scaling and rotation from CDELTs and CROTA2 */ void wcspcset(); /* set scaling and rotation from CDELTs and PC matrix */ int iswcs(); /* Return 1 if WCS structure is filled, else 0 */ int nowcs(); /* Return 0 if WCS structure is filled, else 1 */ void wcsshift(); /* Reset the center of a WCS structure */ void wcscent(); /* Print the image center and size in WCS units */ void wcssize(); /* Return RA and Dec of image center, size in RA and Dec */ void wcsfull(); /* Return RA and Dec of image center, size in degrees */ void wcsrange(); /* Return min and max RA and Dec of image in degrees */ double wcsdist(); /* Distance in degrees between two sky coordinates */ double wcsdist1(); /* Compute angular distance between 2 sky positions */ double wcsdiff(); /* Distance in degrees between two sky coordinates */ void wcscominit(); /* Initialize catalog search command set by -wcscom */ void wcscom(); /* Execute catalog search command set by -wcscom */ char *getradecsys(); /* Return current value of coordinate system */ void wcsoutinit(); /* Initialize WCS output coordinate system for use by pix2wcs */ char *getwcsout(); /* Return current value of WCS output coordinate system */ void wcsininit(); /* Initialize WCS input coordinate system for use by wcs2pix */ char *getwcsin(); /* Return current value of WCS input coordinate system */ int setwcsdeg(); /* Set WCS output in degrees (1) or hh:mm:ss dd:mm:ss (0) */ int wcsndec(); /* Set or get number of output decimal places */ int wcsreset(); /* Change WCS using arguments */ void wcseqset(); /* Change equinox of reference pixel coordinates in WCS */ void wcscstr(); /* Return system string from system code, equinox, epoch */ void setwcslin(); /* Set output string mode for LINEAR coordinates */ int pix2wcst(); /* Convert pixel coordinates to World Coordinate string */ void pix2wcs(); /* Convert pixel coordinates to World Coordinates */ void wcsc2pix(); /* Convert World Coordinates to pixel coordinates */ void wcs2pix(); /* Convert World Coordinates to pixel coordinates */ void setdefwcs(); /* Call to use AIPS classic WCS (also not PLT/TNX/ZPX */ int getdefwcs(); /* Call to get flag for AIPS classic WCS */ int wcszin(); /* Set coordinate in third dimension (face) */ int wcszout(); /* Return coordinate in third dimension */ void wcserr(); /* Print WCS error message to stderr */ void setwcserr(); /* Set WCS error message for later printing */ void savewcscoor(); /* Save output coordinate system */ char *getwcscoor(); /* Return output coordinate system */ void savewcscom(); /* Save WCS shell command */ char *getwcscom(); /* Return WCS shell command */ void setwcscom(); /* Set WCS shell commands from stored values */ void freewcscom(); /* Free memory used to store WCS shell commands */ void setwcsfile(); /* Set filename for WCS error message */ int cpwcs(); /* Copy WCS keywords with no suffix to ones with suffix */ /* Coordinate conversion subroutines in wcscon.c */ void wcscon(); /* Convert between coordinate systems and equinoxes */ void wcsconp(); /* Convert between coordinate systems and equinoxes */ void wcsconv(); /* Convert between coordinate systems and equinoxes */ void fk425e(); /* Convert B1950(FK4) to J2000(FK5) coordinates */ void fk524e(); /* Convert J2000(FK5) to B1950(FK4) coordinates */ int wcscsys(); /* Set coordinate system from string */ double wcsceq(); /* Set equinox from string (return 0.0 if not obvious) */ void d2v3(); /* Convert RA and Dec in degrees and distance to vector */ void s2v3(); /* Convert RA and Dec in radians and distance to vector */ void v2d3(); /* Convert vector to RA and Dec in degrees and distance */ void v2s3(); /* Convert vector to RA and Dec in radians and distance */ /* Distortion model subroutines in distort.c */ void distortinit(); /* Set distortion coefficients from FITS header */ void setdistcode(); /* Set WCS distortion code string from CTYPEi value */ char *getdistcode(); /* Return distortion code string for CTYPEi */ int DelDistort(); /* Delete all distortion-related fields */ void pix2foc(); /* pixel coordinates -> focal plane coordinates */ void foc2pix(); /* focal plane coordinates -> pixel coordinates */ /* Other projection subroutines */ /* 8 projections using AIPS algorithms (worldpos.c) */ extern int worldpos(); /* Convert from pixel location to RA,Dec */ extern int worldpix(); /* Convert from RA,Dec to pixel location */ /* Digital Sky Survey projection (dsspos.c) */ extern int dsspos(); /* Convert from pixel location to RA,Dec */ extern int dsspix(); /* Convert from RA,Dec to pixel location */ /* SAO TDC TAN projection with higher order terms (platepos.c) */ extern int platepos(); /* Convert from pixel location to RA,Dec */ extern int platepix(); /* Convert from RA,Dec to pixel location */ extern void SetFITSPlate(); /* Set FITS header plate fit coefficients from structure */ extern int SetPlate(); /* Set plate fit coefficients in structure from arguments */ extern int GetPlate(); /* Return plate fit coefficients from structure in arguments */ /* IRAF TAN projection with higher order terms (tnxpos.c) */ extern int tnxinit(); /* initialize the gnomonic forward or inverse transform */ extern int tnxpos(); /* forward transform (physical to world) gnomonic projection. */ extern int tnxpix(); /* Inverse transform (world to physical) gnomonic projection */ /* IRAF ZPN projection with higher order terms (zpxpos.c) */ extern int zpxinit(); /* initialize the gnomonic forward or inverse transform */ extern int zpxpos(); /* forward transform (physical to world) gnomonic projection. */ extern int zpxpix(); /* Inverse transform (world to physical) gnomonic projection */ #endif /* __STDC__ */ #ifdef __cplusplus } #endif #endif /* _wcs_h_ */ /* Oct 26 1994 New file * Dec 21 1994 Add rotation matrix * Dec 22 1994 Add flag for coordinate reversal * Mar 6 1995 Add parameters for Digital Sky Survey plate fit * Jun 8 1995 Add parameters for coordinate system change * Jun 21 1995 Add parameter for plate scale * Jul 6 1995 Add parameter to note whether WCS is set * Aug 8 1995 Add parameter to note whether to print coordinate system * Oct 16 1995 Add parameters to save image dimensions and center coordinates * Feb 15 1996 Add coordinate conversion functions * Feb 20 1996 Add flag for tab tables * Apr 26 1996 Add epoch of positions (actual date of image) * Jul 5 1996 Add subroutine declarations * Jul 19 1996 Add WCSFULL declaration * Aug 5 1996 Add WCSNINIT to initialize WCS for non-terminated header * Oct 31 1996 Add DCnn inverse rotation matrix * Nov 1 1996 Add NDEC number of decimal places in output * * May 22 1997 Change range of pcode from 1-8 to -1-8 for linear transform * Sep 12 1997 Add chip rotation MROT, XMPIX, YMPIX * * Jan 7 1998 Add INSTRUME and DETECTOR for HST metric correction * Jan 16 1998 Add Mark Calabretta's WCSLIB data structures * Jan 16 1998 Add LONGPOLE, LATPOLE, and PROJP constants for Calabretta * Jan 22 1998 Add ctype[], crpix[], crval[], and cdelt[] for Calabretta * Jan 23 1998 Change wcsset() to wcsxinit() and pcode to prjcode * Jan 23 1998 Define projection type flags * Jan 26 1998 Remove chip rotation * Jan 26 1998 Add chip correction polynomial * Feb 3 1998 Add number of coefficients for residual fit * Feb 5 1998 Make cd and dc matrices vectors, not individual elements * Feb 19 1998 Add projection names * Feb 23 1998 Add TNX projection from NOAO * Mar 3 1998 Add NOAO plate fit and residual fit * Mar 12 1998 Add variables for TNX correction surface * Mar 23 1998 Add PLT plate fit polynomial projection; reassign DSS * Mar 23 1998 Drop plate_fit flag from structure * Mar 25 1998 Add npcoeff to wcs structure for new plate fit WCS * Apr 7 1998 Change amd_i_coeff to i_coeff * Apr 8 1998 Add wcseqset() and wcsreset() subroutine declarations * Apr 10 1998 Rearrange order of nonstandard WCS types * Apr 13 1998 Add setdefwcs() subroutine declaration * Apr 14 1998 Add coordinate systems and wcscoor() * Apr 24 1998 Add units * Apr 28 1998 Change coordinate system flags to WCS_* * Apr 28 1998 Change projection flags to WCS_* * Apr 28 1998 Add wcsc2pix() * May 7 1998 Add C++ declarations * May 13 1998 Add eqin and eqout for conversions to and from equinoxes * May 14 1998 Add declarations for coordinate conversion subroutines * May 27 1998 Add blsearch() * May 27 1998 Change linear projection back to WCS_LIN from WCS_LPR * May 27 1998 Move hget.c and hput.c C++ declarations to fitshead.h * May 27 1998 Include fitshead.h * May 29 1998 Add wcskinit() * Jun 1 1998 Add wcserr() * Jun 11 1998 Add initialization support subroutines * Jun 18 1998 Add wcspcset() * Jun 25 1998 Add wcsndec() * Jul 6 1998 Add wcszin() and wcszout() to use third dimension of images * Jul 7 1998 Change setdegout() to setwcsdeg(); setlinmode() to setwcslin() * Jul 17 1998 Add savewcscoor(), getwcscoor(), savewcscom(), and getwcscom() * Aug 14 1998 Add freewcscom(), setwcscom(), and multiple WCS commands * Sep 3 1998 Add pa_north, pa_east, imrot and imflip to wcs structure * Sep 14 1998 Add latbase for AXAF North Polar angle (NPOL not LAT-) * Sep 16 1998 Make WCS_system start at 1; add NPOLE * Sep 17 1998 Add wcscstr() * Sep 21 1998 Add wcsconp() to convert proper motions, too. * Dec 2 1998 Add WCS type for planet surface * Jan 20 1999 Add declaration of wcsfree() * Jun 16 1999 Add declaration of wcsrange() * Oct 21 1999 Add declaration of setwcsfile() * * Jan 28 2000 Add flags for choice of WCS projection subroutines * Jun 26 2000 Add XY coordinate system * Nov 2 2000 Add wcsconv() to convert coordinates when parallax or rv known * * Jan 17 2001 Add idpix and ndpix for trim section, ltm for readout rotation * Jan 31 2001 Add wcsinitn(), wcsninitn(), wcsinitc(), and wcsninitc() * Feb 20 2001 Add wcs->wcs to main data structure * Mar 20 2001 Close unclosed comment in wcsconv() argument list * * Apr 3 2002 Add SZP and second GLS/SFL projection * Apr 9 2002 Add wcs->wcsdep for pointer to WCS depending on this WCS * Apr 26 2002 Add wcs->wcsname and wcs->wcschar to identify WCS structure * May 9 2002 Add wcs->radvel and wcs->zvel for radial velocity in km/sec * * Apr 1 2003 Add wcs->distort Distort structure for distortion correction * Apr 1 2003 Add foc2pix() and pix2foc() subroutines for distortion correction * May 1 2003 Add missing semicolons after C++ declarations of previous two functions * Oct 1 2003 Rename wcs->naxes to wcs->naxis to match WCSLIB 3.2 * Nov 3 2003 Add distinit(), setdistcode(), and getdistcode() to distort.c * Dec 3 2003 Add back wcs->naxes for backward compatibility * * Aug 30 2004 Add DelDistort() * * Nov 1 2005 Add WCS_ICRS * * Jan 5 2006 Add secrad() * Apr 21 2006 Increase maximum number of axes from 4 to 8 * Apr 24 2006 Increase maximum number of axes to 9 * Nov 29 2006 Drop semicolon at end of C++ ifdef * Dec 21 2006 Add cpwcs() * * Jan 4 2007 Drop extra declaration of wcscstr() * Jan 4 2007 Fix declarations so ANSI prototypes are not just for C++ * Jan 9 2007 Add fk425e() and fk524e() subroutines * Jan 9 2007 Add worldpos.c, dsspos.c, platepos.c, and tnxpos.c subroutines * Jan 10 2007 Add ANSI prototypes for all subroutines * Feb 1 2007 Add wcs.wcslog for log wavelength * Jul 25 2007 Add v2s3(), s2v3(), d2v3(), v2d3() for coordinate-vector conversion * * Mar 31 2010 Add wcsdist1(), an alternate method * Apr 07 2010 Add NWCSTYPE to keep it aligned with actual number of WCS types * * Mar 11 2011 Add NOAO ZPX projection parameters and subroutines (Frank Valdes) * Mar 14 2011 Add SCAMP polynomial projection coefficients * Sep 1 2011 Add TPV TAN projectioin with SCAT PV terms * Sep 9 2011 Fix comment on TPV declaration * * Feb 1 2013 Add uppercase() from wcsinit() * Feb 25 2013 Pass const string to uppercase() * * Jun 8 2016 Increase projection code from 9 to 16 characters for SIP distortion * Jun 23 2016 Set MAXNKWD here; used for copying keywords in cpwcs() */ wcstools-3.9.5/libwcs/wcscat.h0000664000016200001660000026426313041771411015407 0ustar minkoirsys/*** File libwcs/wcscat.h *** February 15, 2013 *** By Jessica Mink, jmink@cfa.harvard.edu *** Copyright (C) 1998-2013 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #ifndef _wcscat_h_ #define _wcscat_h_ #define MAXNMAG 20 /* Data structure for SAO TDC ASCII and binary star catalog entries */ struct Star { float rdum; float xno; /* Catalog number */ double ra; /* Right Ascension (degrees) */ double dec; /* Declination (degrees) */ double errra; /* Right Ascension (degrees) */ double errdec; /* Declination (degrees) */ char isp[24]; /* Spectral type or other 2-char identifier */ short mag[MAXNMAG+1]; /* Up to MAXNMAG Magnitudes * 100 */ double rapm; /* RA proper motion (degrees per year) */ double decpm; /* Dec proper motion (degrees per year) */ double errpmr; /* RA proper motion error (degrees per year) */ double errpmd; /* Dec proper motion error (degrees per year) */ double xmag[MAXNMAG+1]; /* Up to MAXNMAG Magnitudes */ double num; /* Actual star number */ int coorsys; /* Coordinate system (WCS_J2000, WCS_B1950,...) */ double equinox; /* Equinox of coordinate system as fractional year */ double epoch; /* Epoch of position as fractional year */ double parallax; /* Parallax in arcseconds */ double pxerror; /* Parallax error in arcseconds */ double radvel; /* Radial velocity in km/sec, positive away */ double dist; /* Distance from search center in arcseconds */ double size; /* Semi-major axis in arcseconds */ int nimage; /* Number of images for catalog position */ int ncat; /* Number of catalogs for catalog proper motion */ char *entry; /* Line copied from input catalog */ char objname[80]; /* Object name */ char datapath[80]; /* File pathname to data */ int peak; /* Peak flux per pixel in star image */ }; /* Catalog proper motion units */ #define PM_MASYR 1 /* milliarcseconds per year */ #define PM_ARCSECYR 2 /* arcseconds per year */ #define PM_DEGYR 3 /* degrees per year */ #define PM_RADYR 4 /* radians per year */ #define PM_TSECYR 5 /* seconds of time (RA) per century */ #define PM_ARCSECCEN 6 /* arcseconds per year */ #define PM_TSECCEN 7 /* seconds of time (RA) per century */ #define PM_MTSYR 8 /* milliseconds of time (RA) per year */ #define PM_ARCSECHR 9 /* arcseconds per hour (solar system) */ /* Data structure for SAO TDC ASCII and binary star catalogs */ struct StarCat { int star0; /* Subtract from star number for file sequence number */ int star1; /* First star number in file */ int nstars; /* Number of stars in file */ int stnum; /* Star number format in catalog file: <0: -stnum-character name at end instead of number 0: no star i.d. numbers 1: Real*4 star i.d. numbers 2: Integer*4 3: Integer*4 4: Integer*4 5: Character ID instead of number in ASCII files */ int mprop; /* 1 if proper motion is included */ /* 2 if radial velocity is included */ int nmag; /* Number of magnitudes present Negative for J2000 catalog */ int nbent; /* Number of bytes per star entry */ int rasorted; /* 1 if RA-sorted, else 0 */ int ignore; /* 1 if ignoring info after position and magnitude */ FILE *ifcat; /* File descriptor for catalog file */ char isfil[24]; /* Star catalog file name */ char isname[64]; /* Star catalog description */ int byteswapped; /* 1 if catalog is byte-reversed from CPU */ int refcat; /* Code for type of catalog (TXTCAT, BINCAT, etc.) */ int coorsys; /* Coordinate system B1950 J2000 Galactic Ecliptic */ double epoch; /* Epoch of catalog coordinates in years */ double equinox; /* Equinox of catalog coordinates in years */ char inform; /* Coordinate format (B>inary D>egrees H>MS T>able U>SNO) */ char incdir[128]; /* Catalog directory pathname */ char incfile[32]; /* Catalog file name */ int ncobj; /* Length of object name in binary star entry */ int nnfld; /* Length of star number */ int nndec; /* Number of decimal places in star number */ int nepoch; /* 1 if epoch of coordinates is present */ int sptype; /* 1 if spectral type is present in catalog */ int plate; /* 1 if plate or field number is present in catalog */ char *catbuff; /* Pointer to start of catalog */ char *catdata; /* Pointer to first entry in catalog */ char *catline; /* Pointer to current entry in catalog */ char *catlast; /* Pointer to one past end of last entry in catalog */ int istar; /* Number of current catalog entry */ struct TabTable *startab; /* Structure for tab table catalog */ int entid; /* Entry number for ID */ int entra; /* Entry number for right ascension */ int entdec; /* Entry number for declination */ int entmag[MAXNMAG+1]; /* Entry numbers for up to MAXNMAG magnitudes */ int entpeak; /* Entry number for peak counts */ int entepoch; /* Entry number for epoch of observation */ int entdate; /* Entry number for FITS-format date of observation */ int entname; /* Entry number for object name */ int entadd; /* Entry number for additional keyword */ int entrpm; /* Entry number for proper motion in right ascension */ int entdpm; /* Entry number for proper motion in declination */ int entpx; /* Entry number for parallax */ int entpxe; /* Entry number for parallax error */ int entrv; /* Entry number for radial velocity */ int enttype; /* Entry number for spectral type */ int entsize; /* Entry number for size of object */ int entpath; /* Entry number for object data pathname */ int rpmunit; /* Units for RA proper motion (PM_x) */ int dpmunit; /* Units for DEC proper motion (PM_x) */ char *caturl; /* set if web search, else NULL */ char keyid[16]; /* Entry name for ID */ char keyra[16]; /* Entry name for right ascension */ char keydec[16]; /* Entry name for declination */ char keymag[MAXNMAG+1][16]; /* Entry name for up to MAXNMAG magnitudes */ char keyrpm[16]; /* Entry name for right ascension proper motion */ char keydpm[16]; /* Entry name for declination proper motion */ char keypeak[16]; /* Entry name for integer code */ char keytype[16]; /* Entry name for spectral type */ char keyrv[16]; /* Entry name for radial velocity */ char keyadd[16]; /* Entry name for additional keyword */ char keyepoch[16]; /* Entry name for epoch */ }; /* Data structure for tab table files */ struct TabTable { char *filename; /* Name of tab table file */ int nlines; /* Number of entries in table */ char *tabname; /* Name of this table or NULL */ char *tabbuff; /* Pointer to start of saved tab table in memory */ char *tabheader; /* Pointer to start of line containing table header */ char *tabhead; /* Pointer to start of line containing column heading */ char *tabdash; /* Pointer to start of line with dashes after column headings */ char *tabdata; /* Pointer to start of first line of table data */ int lhead; /* Number of bytes before first data line */ int iline; /* Number of current line (1=first) */ int lline; /* Length in bytes of line buffer */ char *tabline; /* Pointer to start of current line */ FILE *tcat; /* File descriptor for tab table file */ int ncols; /* Number of columns per table entry */ char **colname; /* Column names */ int *lcol; /* Lengths of column header names */ int *lcfld; /* Number of columns in field (hyphens) */ int lbuff; /* Number of bytes in entire tab table */ }; /* Source catalog flags and subroutines */ /* Source catalog flags returned from CatCode */ #define GSC 1 /* HST Guide Star Catalog */ #define UJC 2 /* USNO UJ Star Catalog */ #define UAC 3 /* USNO A Star Catalog */ #define USAC 4 /* USNO SA Star Catalog */ #define SAO 5 /* SAO Star Catalog */ #define IRAS 6 /* IRAS Point Source Catalog */ #define PPM 7 /* PPM Star Catalog */ #define TYCHO 8 /* Tycho Star Catalog */ #define UA1 9 /* USNO A-1.0 Star Catalog */ #define UA2 10 /* USNO A-2.0 Star Catalog */ #define USA1 11 /* USNO SA-1.0 Star Catalog */ #define USA2 12 /* USNO SA-2.0 Star Catalog */ #define HIP 13 /* Hipparcos Star Catalog */ #define ACT 14 /* USNO ACT Star Catalog */ #define BSC 15 /* Yale Bright Star Catalog */ #define TYCHO2 16 /* Tycho-2 Star Catalog */ #define USNO 17 /* USNO-format plate catalog */ #define TMPSC 18 /* 2MASS All-Sky Point Source Catalog */ #define GSCACT 19 /* GSC-ACT revised Guide Star Catalog */ #define GSC2 20 /* GSC II version 2.2 */ #define UB1 21 /* USNO B-1.0 Star Catalog */ #define UCAC1 22 /* USNO CCD Astrograph Catalog 1.0 */ #define UCAC2 23 /* USNO CCD Astrograph Catalog 2.0 */ #define TMIDR2 24 /* 2MASS IDR2 Point Source Catalog */ #define YB6 25 /* USNO YB6 Catalog */ #define SDSS 26 /* Sloan Digital Sky Survey Catalog */ #define TMXSC 27 /* 2MASS Extended Source Catalog */ #define TMPSCE 28 /* 2MASS Point Source Catalog with mag errors */ #define TYCHO2E 29 /* Tycho-2 Star Catalog with magnitude errors */ #define SKY2K 30 /* SKY2000 Master Catalog */ #define SKYBOT 31 /* SKYBOT Solar System Objects */ #define UCAC3 32 /* USNO CCD Astrograph Catalog 3.0 (2009) */ #define UCAC4 33 /* USNO CCD Astrograph Catalog 4.0 (2013) */ #define TABCAT -1 /* StarBase tab table catalog */ #define BINCAT -2 /* TDC binary catalog */ #define TXTCAT -3 /* TDC ASCII catalog */ #define WEBCAT -4 /* Tab catalog via the web */ #define NUMCAT 33 /* Number of predefined catalogs */ #define EP_EP 1 /* Output epoch as fractional year */ #define EP_JD 2 /* Output epoch as Julian Date */ #define EP_MJD 3 /* Ouput epoch as Modified Julian Date */ #define EP_FD 4 /* Output epoch in FITS format (yyyy-mm-dd) */ #define EP_ISO 5 /* Output epoch in ISO format (yyyy-mm-ddThh:mm:ss) */ /* Structure for dealing with ranges */ #define MAXRANGE 20 struct Range { double first; /* Current minimum value */ double last; /* Current maximum value */ double step; /* Current step in value */ double value; /* Current value */ double valmin; /* Minimum value in all ranges */ double valmax; /* Maximum value in all ranges */ double ranges[MAXRANGE*3]; /* nranges sets of first, last, step */ int nvalues; /* Total number of values in all ranges */ int nranges; /* Number of ranges */ int irange; /* Index of current range */ }; /* Flags for sorting catalog search results */ #define SORT_UNSET -1 /* Catalog sort flag not set yet */ #define SORT_NONE 0 /* Do not sort catalog output */ #define SORT_MAG 1 /* Sort output by magnitude */ #define SORT_DIST 2 /* Sort output by distance from center */ #define SORT_RA 3 /* Sort output by right ascension */ #define SORT_DEC 4 /* Sort output by declination */ #define SORT_X 5 /* Sort output by image X coordinate */ #define SORT_Y 6 /* Sort output by image Y coordinate */ #define SORT_ID 7 /* Merge close catalog objects */ #define SORT_MERGE 8 /* Merge close catalog objects */ /* Shapes for SAOimage region file output */ #define WCS_CIRCLE 1 /* circle shape for SAOimage plotting */ #define WCS_SQUARE 2 /* square shape for SAOimage plotting */ #define WCS_DIAMOND 3 /* diamond shape for SAOimage plotting */ #define WCS_CROSS 4 /* cross shape for SAOimage plotting */ #define WCS_EX 5 /* x shape for SAOimage plotting */ #define WCS_VAR 6 /* variable (+ and x) shape for HSTGSC plotting */ #define WCS_PCIRCLE 11 /* pixel circle shape for SAOimage plotting */ #define WCS_PSQUARE 12 /* pixel square shape for SAOimage plotting */ #define WCS_PDIAMOND 13 /* pixel diamond shape for SAOimage plotting */ #define WCS_PCROSS 14 /* pixel cross shape for SAOimage plotting */ #define WCS_PEX 15 /* pixel ex shape for SAOimage plotting */ #define WCS_PVAR 16 /* pixel variable (+ and x) shape for HSTGSC plotting */ /* Subroutines for extracting sources from catalogs */ #ifdef __cplusplus extern "C" { #endif #ifdef __STDC__ /* Full ANSI prototypes */ /* Subroutines for reading any catalogs, including TDC ASCII catalogs */ int ctgread( /* Read sources by sky region from any catalog */ char *catfile, /* Name of reference star catalog file */ int refcat, /* Catalog code from wcscat.h */ int distsort, /* 1 to sort stars by distance from center */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nsmax, /* Maximum number of stars to be returned */ struct StarCat **starcat, /* Catalog data structure */ double *tnum, /* Array of ID numbers (returned) */ double *tra, /* Array of right ascensions (returned) */ double *tdec, /* Array of declinations (returned) */ double *tpra, /* Array of right ascension proper motions (returned) */ double *tpdec, /* Array of declination proper motions (returned) */ double **tmag, /* 2-D array of magnitudes (returned) */ int *tc, /* Array of fluxes (returned) */ char **tobj, /* Array of object names (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ctgrnum( /* Read sources by number from any catalog */ char *catfile, /* Name of reference star catalog file */ int refcat, /* Catalog code from wcscat.h */ int nnum, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ int match, /* 1 to match star number exactly, else sequence num */ struct StarCat **starcat, /* Star catalog data structure */ double *tnum, /* Array of source numbers to look for */ double *tra, /* Array of right ascensions (returned) */ double *tdec, /* Array of declinations (returned) */ double *tpra, /* Array of right ascension proper motions (returned) */ double *tpdec, /* Array of declination proper motions (returned) */ double **tmag, /* 2-D Array of magnitudes (returned) */ int *tpeak, /* Array of peak counts (returned) */ char **tkey, /* Array of values of additional keyword */ char **tpath, /* Array of values of data pathnames */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ctgrdate( /* Read sources by date from SAO TDC ASCII format catalog */ char *catfile, /* Name of reference star catalog file */ int refcat, /* Catalog code from wcscat.h */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ struct StarCat **starcat, /* Star catalog data structure */ double date1, /* Start time as Modified Julian Date or Julian Date */ double date2, /* End time as Modified Julian Date or Julian Date */ int nmax, /* Maximum number of stars to look for */ double *tnum, /* Array of source numbers (returned) */ double *tra, /* Array of right ascensions (returned) */ double *tdec, /* Array of declinations (returned) */ double *tpra, /* Array of right ascension proper motions (returned) */ double *tpdec, /* Array of declination proper motions (returned) */ double **tmag, /* 2-D Array of magnitudes (returned) */ int *tc, /* Array of fluxes (returned) */ char **tobj, /* Array of object names (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ctgbin( /* Bin sources from SAO TDC ASCII format catalog */ char *catfile, /* Name of reference star catalog file */ int refcat, /* Catalog code from wcscat.h */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude by which to sort (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ctgstar( /* Read one star entry from ASCII catalog, 0 if OK */ int istar, /* Star sequence number in ASCII catalog */ struct StarCat *sc, /* Star catalog data structure */ struct Star *st); /* Star data structure, updated on return */ int isacat( /* Return 1 if string is name of ASCII catalog file */ char *catpath); /* Path to file to check */ struct StarCat *ctgopen( /* Open a Starbase, TDC ASCII, or TDC binary catalog */ char *catfile, /* Name of reference star catalog file */ int refcat); /* Catalog code from wcscat.h */ void ctgclose( /* Close Starbase, TDC ASCII, or TDC binary catalog * and free data structures */ struct StarCat *sc); /* Star catalog data structure */ /* Subroutines for extracting sources from HST Guide Star Catalog */ int gscread( /* Read sources by sky region from HST Guide Star Catalog */ int refcat, /* Catalog code from wcscat.h (GSC or GSCACT) */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int nstarmax, /* Maximum number of stars to be returned */ double *gnum, /* Array of ID numbers (returned) */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int gscrnum( /* Read sources by ID number from HST Guide Star Catalog */ int refcat, /* Catalog code from wcscat.h (GSC or GSCACT) */ int nnum, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *gnum, /* Array of source numbers to look for */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if >1, number of sources per log line */ int gscbin( /* Bin sources from HST Guide Star Catalog */ int refcat, /* Catalog code from wcscat.h (GSC or GSCACT) */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if >1, number of sources per log line */ void setgsclass( /* Set GSC object class to return (<0=all) */ int class); /* Class of objects to return */ /* Subroutine to read GSC II catalog over the web */ int gsc2read( /* Read sources by sky region from GSC II Catalog */ char *refcatname, /* Name of catalog (GSC2 for 2.2; GSC2.3 for 2.3) */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *gnum, /* Array of ID numbers (returned) */ char **gobj, /* Array of object IDs (mixed letters and numbers) */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double *gpra, /* Array of right ascension proper motions (returned) */ double *gpdec, /* Array of declination proper motions (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if >1, number of sources per log line */ char *gsc2c2t( /* Convert GSC2 buffer from comma- to tab-separated */ char *csvbuff); /* Input comma-separated table */ char *gsc2t2t( /* Clean up GSC2 tab-separated buffer */ char *tsvbuff); /* Input tab-separated table */ /* Subroutine to read SDSS catalog over the web */ int sdssread( /* Read sources by sky region from SDSS Catalog */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *gnum, /* Array of ID numbers (returned from tabread) */ char **gobj, /* Array of object IDs (too long for integer*4) */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if >1, number of sources per log line */ char *sdssc2t( /* Convert SDSS buffer from comma- to tab-separated */ char *csvbuff); /* Input comma-separated table */ /* Subroutines to read local copy of 2MASS Point Source Catalog */ int tmcread( /* Read sources by sky region from 2MASS Point Source Catalog */ int refcat, /* Catalog code from wcscat.h (TMPSC or TMXSC or TMPSCE) */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *gnum, /* Array of catalog numbers (returned) */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int tmcrnum( /* Read sources by ID number from 2MASS Point Source Catalog */ int refcat, /* Catalog code from wcscat.h (TMPSC or TMXSC or TMPSCE) */ int nstars, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *gnum, /* Array of source numbers to look for */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int tmcbin( /* Bin sources from 2MASS Point Source Catalog */ int refcat, /* Catalog code from wcscat.h (TMPSC or TMXSC or TMPSCE) */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude to use (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ /* Subroutines to read local copies of USNO catalogs */ int uacread( /* Read sources by sky region from USNO A or SA Catalog */ char *refcatname, /* Name of catalog (UAC, USAC, UAC2, USAC2) */ int distsort, /* 1 to sort stars by distance from center */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *unum, /* Array of catalog numbers (returned) */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *uplate, /* Array of plate numbers (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int uacrnum( /* Read sources by ID number from USNO A or SA Catalog */ char *refcatname, /* Name of catalog (UAC, USAC, UAC2, USAC2) */ int nnum, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *unum, /* Array of source numbers to look for */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *uplate, /* Array of plate numbers (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int uacbin( /* Bin sources from USNO A or SA Catalog */ char *refcatname, /* Name of catalog (UAC, USAC, UAC2, USAC2) */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude to use (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ void setuplate( /* Set USNO catalog plate number to search */ int xplate); /* If nonzero, use objects only from this plate */ int getuplate(void); /* Get USNO catalog plate number to search */ int ubcread( /* Read sources by sky region from USNO B Catalog */ char *refcatname, /* Name of catalog (UB1 only for now) */ int distsort, /* 1 to sort stars by distance from center */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *unum, /* Array of ID numbers (returned) */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double *upra, /* Array of right ascension proper motions (returned) */ double *updec, /* Array of declination proper motions (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *upmni, /* Array of number of ids and pm quality (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ubcrnum( /* Read sources by ID number from USNO B Catalog */ char *refcatname, /* Name of catalog (UB1 only for now) */ int nnum, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *unum, /* Array of source numbers to look for */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double *upra, /* Array of right ascension proper motions (returned) */ double *updec, /* Array of declination proper motions (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *upmni, /* Array of number of ids and pm quality (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ubcbin( /* Bin sources from USNO B Catalog */ char *refcatname, /* Name of catalog (UB1 only for now) */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude to use (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ucacread( /* Read sources by sky region from USNO UCAC 1 Catalog */ char *refcatname, /* Name of catalog (UCAC1 or UCAC2) */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *gnum, /* Array of ID numbers (returned) */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double *gpra, /* Array of right ascension proper motions (returned) */ double *gpdec, /* Array of declination proper motions (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ucacrnum( /* Read sources by ID number from USNO UCAC 1 Catalog */ char *refcatname, /* Name of catalog (UCAC1 or UCAC2) */ int nstars, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *gnum, /* Array of source numbers to look for */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double *gpra, /* Array of right ascension proper motions (returned) */ double *gpdec, /* Array of declination proper motions (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ucacbin( /* Bin sources from USNO UCAC 1 Catalog */ char *refcatname, /* Name of catalog (UCAC1 or UCAC2) */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude to use (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ujcread( /* Read sources by sky region from USNO J Catalog */ char *refcatname, /* Name of catalog (UJC, xxxxx.usno) */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int nstarmax, /* Maximum number of stars to be returned */ double *unum, /* Array of catalog numbers (returned) */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *uplate, /* Array of plate numbers (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ujcrnum( /* Read sources by ID number from USNO J Catalog */ char *refcatname, /* Name of catalog (UJC, xxxxx.usno) */ int nnum, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *unum, /* Array of source numbers to look for */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *uplate, /* Array of plate numbers (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ujcbin( /* Bin sources from USNO J Catalog */ char *refcatname, /* Name of catalog (UJC, xxxxx.usno) */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ /* Subroutines to read a local copy of the Tycho-2 catalog */ int ty2read( /* Read sources by sky region from Tycho 2 Catalog */ int refcat, /* Catalog code from wcscat.h (TYCHO2 or TYCHO2E */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *gnum, /* Array of ID numbers (returned) */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double *gpra, /* Array of right ascension proper motions (returned) */ double *gpdec, /* Array of declination proper motions (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ty2rnum( /* Read sources by ID number from Tycho 2 Catalog */ int refcat, /* Catalog code from wcscat.h (TYCHO2 or TYCHO2E */ int nstars, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *gnum, /* Array of source numbers to look for */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double *gpra, /* Array of right ascension proper motions (returned) */ double *gpdec, /* Array of declination proper motions (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ty2bin( /* Bin sources from Tycho 2 Catalog */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude to use (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ /* Subroutines to read a local copy of the ACT catalog */ int actread( /* Read sources by sky region from USNO ACT Catalog */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *gnum, /* Array of ID numbers (returned) */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double *gpra, /* Array of right ascension proper motions (returned) */ double *gpdec, /* Array of declination proper motions (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int actrnum( /* Read sources by ID number from USNO ACT Catalog */ int nstars, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *gnum, /* Array of source numbers to look for */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double *gpra, /* Array of right ascension proper motions (returned) */ double *gpdec, /* Array of declination proper motions (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int actbin( /* Bin sources from USNO ACT Catalog */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude to use (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int skybotread ( /* Find solar system objects from SkyBot */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ int distsort, /* 1 to sort asteroids by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Julian date for positions (current time if zero) */ double mag1, /* Lower limiting magnitude (none if equal to mag2) */ double mag2, /* Upper limiting magnitude (none if equal to mag1) */ int sortmag, /* Magnitude by which to sort (1 to nmag) */ int nstarmax, /* Maximum number of stars to be returned */ double *gnum, /* Array of asteroid numbers (returned) */ char **gobj, /* Array of object IDs (too long for integer*4) */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double *gpra, /* Array of right ascension motions (returned) */ double *gpdec, /* Array of declination motions (returned) */ double **gmag, /* 2-D array of magnitudes and other info (returned) */ int *gtype, /* Array of object classes (returned) */ int nlog); /* 1 for diagnostics */ char *skybot2tab( /* Convert SkyBot buffer from space- to tab-separated */ char *csvbuff); /* Input comma-separated table */ /* Subroutines to read SAO-TDC binary format catalogs */ int binread( /* Read from sky region from SAO TDC binary format catalog */ char *bincat, /* Name of reference star catalog file */ int distsort, /* 1 to sort stars by distance from center */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ struct StarCat **starcat, /* Star catalog data structure */ double *tnum, /* Array of ID numbers (returned) */ double *tra, /* Array of right ascensions (returned) */ double *tdec, /* Array of declinations (returned) */ double *tpra, /* Array of right ascension proper motions (returned) */ double *tpdec, /* Array of declination proper motions (returned) */ double **tmag, /* 2-D array of magnitudes (returned) */ int *tpeak, /* Array of encoded spectral types (returned) */ char **tobj, /* Array of object names (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int binrnum( /* Read sources by ID number from SAO TDC binary format catalog */ char *bincat, /* Name of reference star catalog file */ int nstars, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ int match, /* If 1, match number exactly, else number is sequence*/ double *tnum, /* Array of source numbers to look for */ double *tra, /* Array of right ascensions (returned) */ double *tdec, /* Array of declinations (returned) */ double *tpra, /* Array of right ascension proper motions (returned) */ double *tpdec, /* Array of declination proper motions (returned) */ double **tmag, /* 2-D array of magnitudes (returned) */ int *tpeak, /* Array of encoded spectral types (returned) */ char **tobj, /* Array of object names (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int binbin( /* Bin sources from SAO TDC binary format catalog */ char *bincat, /* Name of reference star catalog file */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude to use (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int binstar( /* Read one star entry from binary catalog, 0 if OK */ struct StarCat *sc, /* Star catalog descriptor */ struct Star *st, /* Current star entry (returned) */ int istar); /* Star sequence number in binary catalog */ struct StarCat *binopen( /* Open binary catalog, returning number of entries */ char *bincat); /* Name of reference star catalog file */ void binclose( /* Close binary catalog */ struct StarCat *sc); /* Star catalog descriptor */ int isbin( /* Return 1 if TDC binary catalog file, else 0 */ char *filename); /* Name of file to check */ /* Subroutines for extracting tab table information (in tabread.c) */ int tabread( /* Read sources from tab table catalog */ char *tabcatname, /* Name of reference star catalog file */ int distsort, /* 1 to sort stars by distance from center */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude by which to sort (1 to nmag) */ int nstarmax, /* Maximum number of stars to be returned */ struct StarCat **starcat, /* Star catalog data structure */ double *tnum, /* Array of source numbers (returned) */ double *tra, /* Array of right ascensions (returned) */ double *tdec, /* Array of declinations (returned) */ double *tpra, /* Array of right ascension proper motions (returned) */ double *tpdec, /* Array of declination proper motions (returned) */ double **tmag, /* 2-D Array of magnitudes (returned) */ int *tpeak, /* Array of peak counts (returned) */ char **tkey, /* Array of values of additional keyword */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int tabrnum( /* Read sources from tab table catalog */ char *tabcatname, /* Name of reference star catalog file */ int nnum, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ struct StarCat **starcat, /* Star catalog data structure */ int match, /* 1 to match star number exactly, else sequence num */ double *tnum, /* Array of source numbers to look for */ double *tra, /* Array of right ascensions (returned) */ double *tdec, /* Array of declinations (returned) */ double *tpra, /* Array of right ascension proper motions (returned) */ double *tpdec, /* Array of declination proper motions (returned) */ double **tmag, /* 2-D Array of magnitudes (returned) */ int *tpeak, /* Array of peak counts (returned) */ char **tkey, /* Array of values of additional keyword */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int tabbin( /* Read sources from tab table catalog */ char *tabcatname, /* Name of reference star catalog file */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude by which to sort (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int tabxyread( /* Read x, y, and magnitude from tab table star list */ char *tabcatname, /* Name of reference star catalog file */ double **xa, /* Array of x coordinates (returned) */ double **ya, /* Array of y coordinates (returned) */ double **ba, /* Array of magnitudes (returned) */ int **pa, /* Array of fluxes (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int tabrkey( /* Keyword values from tab table catalogs */ char *tabcatname, /* Name of reference star catalog file */ struct StarCat **starcat, /* Star catalog data structure */ int nnum, /* Number of stars to look for */ double *tnum, /* Array of source numbers to look for */ char *keyword, /* Keyword for which to return values */ char **tval); /* Returned values for specified keyword */ struct StarCat *tabcatopen( /* Open tab table catalog */ char *tabpath, /* Tab table catalog file pathname */ struct TabTable *tabtable, /* Tab table data structure */ int nbbuff); /* Number of bytes in buffer; 0=read whole file */ void tabcatclose( /* Close tab table catalog */ struct StarCat *sc); /* Source catalog data structure */ int tabstar( /* Read one star entry from tab table catalog, 0 if OK */ int istar, /* Source sequence number in tab table catalog */ struct StarCat *sc, /* Source catalog data structure */ struct Star *st, /* Star data structure, updated on return */ int verbose); /* 1 to print error messages */ struct TabTable *tabopen( /* Open tab table file */ char *tabfile, /* Tab table catalog file name */ int nbbuff); /* Number of bytes in buffer; 0=read whole file */ void tabclose( /* Free all arrays left open by tab table structure */ struct TabTable *tabtable); /* Tab table data structure */ char *gettabline( /* Find a specified line in a tab table */ struct TabTable *tabtable, /* Tab table data structure */ int iline); /* Line sequence number in tab table */ double tabgetra( /* Return right ascension in degrees from tab table*/ struct Tokens *tabtok, /* Line token structure */ int ientry); /* sequence of entry on line */ double tabgetdec( /* Return declination in degrees from tab table*/ struct Tokens *tabtok, /* Line token structure */ int ientry); /* sequence of entry on line */ double tabgetr8( /* Return double number from tab table line */ struct Tokens *tabtok, /* Line token structure */ int ientry); /* sequence of entry on line */ int tabgeti4( /* Return 4-byte integer from tab table line */ struct Tokens *tabtok, /* Line token structure */ int ientry); /* sequence of entry on line */ void settabkey( /* Set tab table keyword to read for object */ char *keyword); /* column header of desired value */ int tabgetk( /* Get tab table entries for named column */ struct TabTable *tabtable, /* Tab table data structure */ struct Tokens *tabtok, /* Line token structure */ char *keyword, /* column header of desired value */ char *string, /* character string (returned) */ int maxchar); /* Maximum number of characters in returned string */ int tabgetc( /* Get tab table entry for named column */ struct Tokens *tabtok, /* Line token structure */ int ientry, /* sequence of entry on line */ char *string, /* character string (returned) */ int maxchar); /* Maximum number of characters in returned string */ int tabparse( /* Aeturn column names and positions in tabtable */ struct TabTable *tabtable); /* Tab table data structure */ int tabcol( /* Find column for name (case-sensitive) */ struct TabTable *tabtable, /* Tab table data structure */ char *keyword); /* column header of desired value */ int tabccol( /* Find column for name (case-insensitive) */ struct TabTable *tabtable, /* Tab table data structure */ char *keyword); /* column header of desired value */ int istab( /* Return 1 if tab table file, else 0 */ char *filename); /* Name of file to check */ char *gettaberr(); /* Return most recent tab table error message */ int gettabndec(); /* Return number of decimal places in tab catalog ids */ /* Subroutines to read catalogs over the web, from SCAT, HST, ESO, or SDSS servers */ int webread( /* Read sources by sky region from WWW catalog */ char *caturl, /* URL of search engine */ char *refcatname, /* Name of catalog */ int distsort, /* 1 to sort stars by distance from center */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *unum, /* Array of ID numbers (returned) */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double *upra, /* Array of right ascension proper motions (returned) */ double *updec, /* Array of declination proper motions (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *utype, /* Array of integer catalog values (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int webrnum( /* Read sources by ID number from WWW catalog */ char *caturl, /* URL of search engine */ char *refcatname, /* Name of catalog */ int nnum, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ int match, /* 1 to match star number exactly, else sequence num */ double *unum, /* Array of source numbers to look for */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double *upra, /* Array of right ascension proper motions (returned) */ double *updec, /* Array of declination proper motions (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *utype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ char *webbuff( /* Read URL into buffer across the web */ char *url, /* URL to read */ int diag, /* 1 to print diagnostic messages */ int *lbuff); /* Length of buffer (returned) */ struct TabTable *webopen( /* Open tab table across the web */ char *caturl, /* URL of search engine */ char *srchpar, /* Search engine parameters to append */ int nlog); /* 1 to print diagnostic messages */ /* Subroutines to read DAOPHOT-style catalogs of sources found in an image */ int daoread( /* Read image source positions from x y mag file */ char *daocat, /* Name of DAOFIND catalog file */ double **xa, /* X and Y coordinates of stars, array returned */ double **ya, /* X and Y coordinates of stars, array returned */ double **ba, /* Instrumental magnitudes of stars, array returned */ int **pa, /* Peak counts of stars in counts, array returned */ int nlog); /* 1 to print each star's position */ int daoopen( /* Open image source position x y mag file */ char *daofile); /* DAOFIND catalog file name */ char *daoline( /* Read line from image source position x y mag file */ int iline, /* Star sequence number in DAOFIND catalog */ char *line); /* Pointer to iline'th entry (returned updated) */ /* Subroutines for sorting tables of star positions and magnitudes from sortstar.c */ void FluxSortStars( /* Sort image stars by decreasing flux */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double *sb, /* Brighness in counts */ int *sc, /* Other 4-byte information */ int ns); /* Number of stars to sort */ void MagSortStars( /* Sort image stars by increasing magnitude */ double *sn, /* Identifying number */ double *sra, /* Right Ascension */ double *sdec, /* Declination */ double *spra, /* Right Ascension proper motion */ double *spdec, /* Declination proper motion */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double **sm, /* Magnitudes */ int *sc, /* Other 4-byte information */ char **sobj, /* Object name */ int ns, /* Number of stars to sort */ int nm, /* Number of magnitudes per star */ int ms); /* Magnitude by which to sort (1 to nmag) */ void IDSortStars( /* Sort image stars by increasing ID Number value */ double *sn, /* Identifying number */ double *sra, /* Right Ascension */ double *sdec, /* Declination */ double *spra, /* Right Ascension proper motion */ double *spdec, /* Declination proper motion */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double **sm, /* Magnitudes */ int *sc, /* Other 4-byte information */ char **sobj, /* Object name */ int ns, /* Number of stars to sort */ int nm); /* Number of magnitudes per star */ void RASortStars( /* Sort image stars by increasing right ascension */ double *sn, /* Identifying number */ double *sra, /* Right Ascension */ double *sdec, /* Declination */ double *spra, /* Right Ascension proper motion */ double *spdec, /* Declination proper motion */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double **sm, /* Magnitudes */ int *sc, /* Other 4-byte information */ char **sobj, /* Object name */ int ns, /* Number of stars to sort */ int nm); /* Number of magnitudes per star */ void DecSortStars( /* Sort image stars by increasing declination */ double *sn, /* Identifying number */ double *sra, /* Right Ascension */ double *sdec, /* Declination */ double *spra, /* Right Ascension proper motion */ double *spdec, /* Declination proper motion */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double **sm, /* Magnitudes */ int *sc, /* Other 4-byte information */ char **sobj, /* Object name */ int ns, /* Number of stars to sort */ int nm); /* Number of magnitudes per star */ void XSortStars( /* Sort image stars by increasing image X value */ double *sn, /* Identifying number */ double *sra, /* Right Ascension */ double *sdec, /* Declination */ double *spra, /* Right Ascension proper motion */ double *spdec, /* Declination proper motion */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double **sm, /* Magnitudes */ int *sc, /* Other 4-byte information */ char **sobj, /* Object name */ int ns, /* Number of stars to sort */ int nm); /* Number of magnitudes per star */ void YSortStars( /* Sort image stars by increasing image Y value */ double *sn, /* Identifying number */ double *sra, /* Right Ascension */ double *sdec, /* Declination */ double *spra, /* Right Ascension proper motion */ double *spdec, /* Declination proper motion */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double **sm, /* Magnitudes */ int *sc, /* Other 4-byte information */ char **sobj, /* Object name */ int ns, /* Number of stars to sort */ int nm); /* Number of magnitudes per star */ int MergeStars( /* Merge multiple entries within given radius * return mean ra, dec, proper motion, and magnitude(s) */ double *sn, /* Identifying number */ double *sra, /* Right Ascension */ double *sdec, /* Declination */ double *spra, /* Right Ascension proper motion */ double *spdec, /* Declination proper motion */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double **sm, /* Magnitudes */ int *sc, /* Other 4-byte information */ char **sobj, /* Object name */ int ns, /* Number of stars to sort */ int nm, /* Number of magnitudes per star */ double rad, /* Maximum separation in arcseconds to merge */ int log); /* If >0, log progress every time mod number written */ /* Catalog utility subroutines from catutil.c */ /* Subroutines for dealing with catalogs */ int RefCat( /* Return catalog type code, title, coord. system */ char *refcatname, /* Name of reference catalog */ char *title, /* Description of catalog (returned) */ int *syscat, /* Catalog coordinate system (returned) */ double *eqcat, /* Equinox of catalog (returned) */ double *epcat, /* Epoch of catalog (returned) */ int *catprop, /* 1 if proper motion in catalog (returned) */ int *nmag); /* Number of magnitudes in catalog (returned) */ int CatCode( /* Return catalog type code */ char *refcatname); /* Name of reference catalog */ char *CatName( /* Return catalog name given catalog type code */ int refcat, /* Catalog code */ char *refcatname); /* Name of reference catalog */ char *CatSource( /* Return catalog source description given catalog type code */ int refcat, /* Catalog code */ char *refcatname); /* Name of reference catalog */ void CatID( /* Return catalog ID keyword given catalog type code */ char *catid, /* Catalog ID (returned) */ int refcat); /* Catalog code */ double CatRad( /* Return default search radius for given catalog */ int refcat); /* Catalog code */ char *ProgName( /* Return program name given program path used */ char *progpath0); /* Pathname by which program is invoked */ char *ProgCat( /* Return catalog name given program name used */ char *progname); /* Program name which might contain catalog code */ void CatNum( /* Return formatted source number */ int refcat, /* Catalog code */ int nnfld, /* Number of characters in number (from CatNumLen) * Print leading zeroes if negative */ int nndec, /* Number of decimal places ( >= 0) * Omit leading spaces if negative */ double dnum, /* Catalog number of source */ char *numstr); /* Formatted number (returned) */ int CatNumLen( /* Return length of source numbers */ int refcat, /* Catalog code */ double maxnum, /* Maximum ID number * (Ignored for standard catalogs) */ int nndec); /* Number of decimal places ( >= 0) */ int CatNdec( /* Return number of decimal places in source numbers */ int refcat); /* Catalog code */ void CatMagName( /* Return name of specified magnitude */ int imag, /* Sequence number of magnitude */ int refcat, /* Catalog code */ char *magname); /* Name of magnitude, returned */ int CatMagNum( /* Returns number of magnitude specified by letter as int */ int imag, /* int of magnitude letter */ int refcat); /* Catalog code */ void CatTabHead ( /* Print heading for catalog search result table */ int refcat, /* Catalog being searched */ int sysout, /* Output coordinate system */ int nnfld, /* Number of characters in ID column */ int mprop, /* 1 if proper motion in catalog */ int nmag, /* Number of magnitudes */ char *ranges, /* Catalog numbers to print */ char *keyword, /* Column to add to tab table output */ int gcset, /* 1 if there are any values in gc[] */ int tabout, /* 1 if output is tab-delimited */ int classd, /* GSC object class to accept (-1=all) */ int printxy, /* 1 if X and Y included in output */ char **gobj1, /* Pointer to array of object names; NULL if none */ FILE *fd); /* Output file descriptor; none if NULL */ int StrNdec( /* Return number of decimal places in numeric string */ char *string); /* Numeric string */ int NumNdec( /* Return number of decimal places in a number */ double number); /* Floating point number */ void setdateform ( /* Set date format code */ int dateform0); /* Date format code */ char *DateString( /* Return string with epoch of position in desired format */ double epoch, /* Date as fraction of a year */ int tabout); /* 1 for tab-preceded output string, else space-preceded */ void setlimdeg( /* Limit output in degrees (1) or hh:mm:ss dd:mm:ss (0) */ int degout); /* 1 for fractional degrees, else sexagesimal hours, degrees */ void SearchLim( /* Compute limiting RA and Dec */ double cra, /* Longitude/Right Ascension of Center of search area in degrees */ double cdec, /* Latitude/Declination of search area in degrees */ double dra, /* Horizontal half-width in degrees */ double ddec, /* Vertical half-width in degrees */ int syscoor, /* Coordinate system */ double *ra1, /* Lower right ascension limit in degrees (returned) */ double *ra2, /* Upper right ascension limit in degrees (returned) */ double *dec1, /* Lower declination limit in degrees (returned) */ double *dec2, /* Upper declination limit in degrees (returned) */ int verbose); /* 1 to print limits, else 0 */ void RefLim( /* Compute limiting RA and Dec in new system */ double cra, /* Longitude/Right Ascension of Center of search area in degrees */ double cdec, /* Latitude/Declination of search area in degrees */ double dra, /* Horizontal half-width in degrees */ double ddec, /* Vertical half-width in degrees */ int sysc, /* System of search coordinates */ int sysr, /* System of reference catalog coordinates */ double eqc, /* Equinox of search coordinates in years */ double eqr, /* Equinox of reference catalog in years */ double epc, /* Epoch of search coordinates in years */ double epr, /* Epoch of reference catalog coordinates in years */ double secmarg, /* Margin in arcsec/century to catch moving stars */ double *ramin, /* Lower right ascension limit in degrees (returned) */ double *ramax, /* Upper right ascension limit in degrees (returned) */ double *decmin, /* Lower declination limit in degrees (returned) */ double *decmax, /* Upper declination limit in degrees (returned) */ int *wrap, /* 1 if search passes through 0:00:00 RA */ int verbose); /* 1 to print limits, else 0 */ void movebuff ( /* Copy nbytes bytes from source+offs to dest+offd */ char *source, /* Pointer to source */ char *dest, /* Pointer to destination */ int nbytes, /* Number of bytes to move */ int offs, /* Offset in bytes in source from which to start copying */ int offd); /* Offset in bytes in destination to which to start copying */ /* Subroutines for dealing with ranges */ struct Range *RangeInit( /* Initialize range structure from string */ char *string, /* String containing numbers separated by , and - */ int ndef); /* Maximum allowable range value */ int isrange( /* Return 1 if string is a range of numbers, else 0 */ char *string); /* String which might be a range of numbers */ void rstart( /* Restart range */ struct Range *range); /* Range structure */ int rgetn( /* Return number of values in all ranges */ struct Range *range); /* Range structure */ int rgeti4( /* Return next number in range as integer */ struct Range *range); /* Range structure */ double rgetr8( /* Return next number in range as double */ struct Range *range); /* Range structure */ /* Subroutines for read values from keyword=value in blocks of text */ int ageti4( /* Extract int value from keyword= value in string */ char *string, /* character string containing = */ char *keyword, /* character string containing the name of the keyword * the value of which is returned. hget searches for a * line beginning with this string. if "[n]" or ",n" is * present, the n'th token in the value is returned. */ int *ival); /* Integer value, returned */ int agetr8( /* Extract double value from keyword= value in string */ char *string, /* character string containing = */ char *keyword, /* character string containing the name of the keyword */ double *dval); /* Double value, returned */ int agets( /* Extract value from keyword= value in string */ char *string, /* character string containing = */ char *keyword, /* character string containing the name of the keyword */ int lval, /* Size of value in characters * If negative, value ends at end of line */ int fillblank, /* If 0, leave blanks, strip trailing blanks if non-zero, replace blanks with underscores */ char *value); /* String (returned) */ int tmcid( /* Return 1 if string is 2MASS ID, else 0 */ char *string, /* Character string to check */ double *ra, /* Right ascension (returned) */ double *dec); /* Declination (returned) */ /* Subroutines for VOTable output */ int vothead( /* Print heading for VOTable SCAT output */ int refcat, /* Catalog code */ char *refcatname, /* Name of catalog */ int mprop, /* Proper motion flag */ int typecol, /* Flag for spectral type */ int ns, /* Number of sources found in catalog */ double cra, /* Search center right ascension */ double cdec, /* Search center declination */ double drad); /* Radius to search in degrees */ void vottail(); /* Terminate VOTable SCAT output */ /* Subroutines for version/date string */ void setrevmsg( /* Set version/date string */ char *revmsg); /* Version/date string */ char *getrevmsg(void); /* Return version/date string */ /* Subroutines for fitting and evaluating polynomials */ void polfit( /* Fit polynomial coefficients */ double *x, /* Array of independent variable points */ double *y, /* Array of dependent variable points */ double x0, /* Offset to independent variable */ int npts, /* Number of data points to fit */ int nterms, /* Number of parameters to fit */ double *a, /* Vector containing current fit values */ double *stdev); /* Standard deviation of fit (returned) */ double polcomp( /* Evaluate polynomial from polfit coefficients */ double xi, /* Independent variable */ double x0, /* Offset to independent variable */ int norder, /* Number of coefficients */ double *a); /* Vector containing coeffiecients */ #else /* K&R prototypes */ /* Subroutines for reading TDC ASCII catalogs (ctgread.c) */ int ctgread(); /* Read sources by sky region from SAO TDC ASCII format catalog */ int ctgrnum(); /* Read sources by number from SAO TDC ASCII format catalog */ int ctgrdate(); /* Read sources by date range from SAO TDC ASCII format catalog */ int ctgbin(); /* Bin sources from SAO TDC ASCII format catalog */ int ctgstar(); /* Read one star entry from ASCII catalog, 0 if OK */ int isacat(); /* Return 1 if string is name of ASCII catalog file */ struct StarCat *ctgopen(); void ctgclose(); /* Subroutines for extracting sources from HST Guide Star Catalog */ int gscread(); /* Read sources by sky region from HST Guide Star Catalog */ int gscrnum(); /* Read sources by ID number from HST Guide Star Catalog */ int gscbin(); /* Bin sources from HST Guide Star Catalog */ void setgsclass(); /* Set GSC object class */ /* Subroutine to read GSC II catalog over the web (gsc2read.c) */ int gsc2read(); /* Read sources by sky region from GSC II Catalog */ char *gsc2c2t(); /* Convert GSC2 buffer from comma- to tab-separated */ char *gsc2t2t(); /* Clean up GSC2 tab-separated buffer */ /* Subroutine to read SDSS catalog over the web (sdssread.c) */ int sdssread(); /* Read sources by sky region from SDSS Catalog */ char *sdssc2t(); /* Convert SDSS buffer from comma- to tab-separated */ /* Subroutines to read local copy of 2MASS Point Source Catalog (tmcread.c) */ int tmcread(); /* Read sources by sky region from 2MASS Point Source Catalog */ int tmcrnum(); /* Read sources by ID number from 2MASS Point Source Catalog */ int tmcbin(); /* Bin sources from 2MASS Point Source Catalog */ /* Subroutines to read local copies of USNO A and SA catalogs (uacread.c) */ int uacread(); /* Read sources by sky region from USNO A or SA Catalog */ int uacrnum(); /* Read sources by ID number from USNO A or SA Catalog */ int uacbin(); /* Bin sources from USNO A or SA Catalog */ void setuplate(); /* Set USNO catalog plate number to search */ int getuplate(); /* Get USNO catalog plate number to search */ /* Subroutines to read local copies of USNO B catalogs (ubcread.c) */ int ubcread(); /* Read sources by sky region from USNO B Catalog */ int ubcrnum(); /* Read sources by ID number from USNO B Catalog */ int ubcbin(); /* Bin sources from USNO B Catalog */ /* Subroutines to read local copies of USNO UCAC catalogs (ucacread.c) */ int ucacread(); /* Read sources by sky region from USNO UCAC 1 Catalog */ int ucacrnum(); /* Read sources by ID number from USNO UCAC 1 Catalog */ int ucacbin(); /* Bin sources from USNO UCAC 1 Catalog */ /* Subroutines to read local copies of USNO UJ catalog (ucacread.c) */ int ujcread(); /* Read sources by sky region from USNO J Catalog */ int ujcrnum(); /* Read sources by ID number from USNO J Catalog */ int ujcbin(); /* Bin sources from USNO J Catalog */ /* Subroutines to read a local copy of the Tycho-2 catalog (ty2read.c) */ int ty2read(); /* Read sources by sky region from Tycho 2 Catalog */ int ty2rnum(); /* Read sources by ID number from Tycho 2 Catalog */ int ty2bin(); /* Bin sources from Tycho 2 Catalog */ /* Subroutines to read a local copy of the ACT catalog (actread.c) */ int actread(); /* Read sources by sky region from USNO ACT Catalog */ int actrnum(); /* Read sources by ID number from USNO ACT Catalog */ int actbin(); /* Bin sources from USNO ACT Catalog */ /* Subroutines to retrieve solar system objects over the web from SkyBot */ int skybotread(); /* Find solar system objects from SkyBot */ char *skybot2tab(); /* Convert SkyBot returned data to Starbase table */ void setobs(); /* Set observatory using IAU code */ void setobsname(); /* Set IAU code from observatory name */ /* Subroutines to read SAO-TDC binary format catalogs (binread.c) */ int binread(); /* Read sources by sky region from SAO TDC binary format catalog */ int binrnum(); /* Read sources by ID number from SAO TDC binary format catalog */ int binbin(); /* Bin sources from SAO TDC binary format catalog */ int binstar(); /* Read one star entry from binary catalog, 0 if OK */ int isbin(); struct StarCat *binopen(); void binclose(); /* Subroutines for extracting tab table information (tabread.c) */ int tabread(); /* Read sources from tab table catalog */ int tabrnum(); /* Read sources from tab table catalog */ int tabbin(); /* Read sources from tab table catalog */ struct TabTable *tabopen(); /* Open tab table file */ struct StarCat *tabcatopen(); /* Open tab table catalog */ void tabcatclose(); /* Close tab table catalog */ int tabxyread(); /* Read x, y, and magnitude from tab table star list */ void settabkey(); /* Set tab table keyword to read for object */ char *gettabline(); /* Find a specified line in a tab table */ int tabrkey(); /* Keyword values from tab table catalogs */ int tabcol(); /* Find column for name (case-sensitive) */ int tabccol(); /* Find column for name (case-insensitive) */ int tabgetk(); /* Get tab table entries for named column */ int tabgetc(); /* Get tab table entry for named column */ int tabgeti4(); /* Return 4-byte integer from tab table line */ int tabparse(); /* Aeturn column names and positions in tabtable */ double tabgetra(); /* Return right ascension in degrees from tab table*/ double tabgetdec(); /* Return declination in degrees from tab table*/ double tabgetr8(); /* Return double number from tab table line */ void tabclose(); /* Free all arrays left open by tab table structure */ char *gettaberr(); /* Return most recent tab table error message */ int istab(); /* Return 1 if tab table file, else 0 */ int gettabndec(); /* Return number of decimal places in tab catalog ids */ /* Subroutines to read catalogs over the web, from SCAT, HST, ESO, or SDSS servers */ int webread(); /* Read sources by sky region from catalog on the World Wide Web */ int webrnum(); /* Read sources by ID number from catalog on the World Wide Web */ char *webbuff(); /* Read URL into buffer across the web */ struct TabTable *webopen(); /* Open tab table across the web */ /* Subroutines to read DAOPHOT-style catalogs of sources found in an image */ int daoread(); /* Read image source positions from x y mag file */ int daoopen(); /* Open image source position x y mag file */ char *daoline(); /* Read line from image source position x y mag file */ /* Subroutines for sorting tables of star positions and magnitudes from sortstar.c */ void FluxSortStars(); /* Sort image stars by decreasing flux */ void MagSortStars(); /* Sort image stars by increasing magnitude */ void IDSortStars(); /* Sort image stars by increasing ID Number value */ void RASortStars(); /* Sort image stars by increasing right ascension */ void DecSortStars(); /* Sort image stars by increasing declination */ void XSortStars(); /* Sort image stars by increasing image X value */ void YSortStars(); /* Sort image stars by increasing image Y value */ int MergeStars(); /* Merge multiple entries within given radius */ /* Catalog utility subroutines from catutil.c */ /* Subroutines for dealing with catalogs */ int CatCode(); /* Return catalog type code */ int RefCat(); /* Return catalog type code, title, coord. system */ char *CatName(); /* Return catalog name given catalog type code */ char *CatSource(); /* Return catalog source description given catalog type code */ char *ProgCat(); /* Return catalog name given program name used */ char *ProgName(); /* Return program name given program path used */ char *CatName(); /* Return catalog name given catalog type code */ void CatID(); /* Return catalog ID keyword given catalog type code */ void CatNum(); /* Return formatted source number */ int CatNumLen(); /* Return length of source numbers */ int CatNdec(); /* Return number of decimal places in source numbers */ void CatMagName(); /* Return name of specified magnitude */ int CatMagNum(); /* Returns number of magnitude specified by letter as int */ double CatRad(); /* Return default search radius for given catalog */ int tmcid(); /* Return 1 if string is 2MASS ID, else 0 */ int NumNdec(); /* Return number of decimal places in a number */ int StrNdec(); /* Return number of decimal places in numeric string */ void setdateform(); /* Set date format code */ void setlimdeg(); /* Limit output in degrees (1) or hh:mm:ss dd:mm:ss (0) */ char *DateString(); /* Convert epoch to output format */ void SearchLim(); /* Compute limiting RA and Dec */ void RefLim(); /* Compute limiting RA and Dec in new system */ int ageti4(); /* Extract int value from keyword= value in string */ int agetr8(); /* Extract double value from keyword= value in string */ int agets(); /* Extract value from keyword= value in string */ void bv2sp(); /* Approximate main sequence spectral type from B - V */ void moveb(); /* Copy nbytes bytes from source+offs to dest+offd */ /* Subroutines for dealing with ranges */ struct Range *RangeInit(); /* Initialize range structure from string */ int isrange(); /* Return 1 if string is a range of numbers, else 0 */ int rgetn(); /* Return number of values in all ranges */ int rgeti4(); /* Return next number in range as integer */ double rgetr8(); /* Return next number in range as double */ void rstart(); /* Restart range */ /* Subroutines for VOTable output */ int vothead(); /* Print heading for VOTable SCAT output */ void vottail(); /* Terminate VOTable SCAT output */ /* Subroutines for version/date string */ void setrevmsg(); /* Set version/date string */ char *getrevmsg(); /* Return version/date string */ /* Subroutines for fitting and evaluating polynomials */ void polfit(); /* Fit polynomial coefficients */ double polcomp(); /* Evaluate polynomial from polfit coefficients */ #endif /* __STDC__ */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* _wcscat_h_ */ /* Sep 22 1998 New header file (star.h) * Oct 16 1998 Add more options for ASCII catalogs * Oct 20 1998 Add object name to binary files * Oct 21 1998 New file (wcscat.h) * Oct 26 1998 Combined wcscat.h and star.h * Oct 27 1998 Add SAOimage region shapes * Nov 9 1998 Add rasorted flag to catalog structure * Nov 20 1998 Add support for USNO A-2.0 and SA-2.0 catalogs * Dec 8 1998 Add support for the Hipparcos and ACT catalogs * * Jan 25 1999 Add declarations for tab table access * Jan 25 1999 Add declarations for dealing with ranges of numbers * Feb 2 1999 Add number of decimal places in star number to StarCat * Feb 11 1999 Add coordinate system info to star structure * Feb 11 1999 Change starcat.insys to starcat.coorsys for consistency * May 14 1999 Update Star and StarCat structure to cover tab tables * May 19 1999 Update StarCat structure to include epoch from catalog * June 4 1999 Add CatNumLen() * Jun 14 1999 Add SearchLim() * Jun 30 1999 Add isrange() * Jul 1 1999 Add declarations for date/time conversions in dateutil.c * Jul 2 1999 Add rstart() * Jul 26 1999 Add Yale Bright Star Catalog * Aug 16 1999 Add RefLim() to get converted search coordinates right * Aug 25 1999 Add ACT catalog * Sep 10 1999 Move special case setting from argument list to subroutines * Sep 13 1999 Add subroutines to access data structure for single stars * Oct 1 1999 Add structure and subroutines for tokenized strings * Oct 22 1999 Change cat*() to ctg*() to avoid system conflict * Oct 29 1999 Add tabget() subroutines * Nov 1 1999 Increase maximum number of tokens on a line from 20 to 100 * Nov 2 1999 Move date utilities to fitsfile.h * * Jan 10 2000 Add column names to catalog data structure * Jan 11 2000 Add gettabndec() * Feb 9 2000 Add proper motion entry information to star data structure * Feb 16 2000 Add gettaberr() to return tab table error message * Mar 1 2000 Add isfile() and agets() to help with ASCII files * Mar 8 2000 Add ProgCat() to return catalog name from program name used * Mar 8 2000 Add ProgName() to extract program name from path used * Mar 10 2000 Add PropCat() to tell whether a catalog has proper motions * Mar 27 2000 Add tabxyread() * Apr 3 2000 Add option in catalog structure to ignore extra info * May 22 2000 Add Tycho 2 support, bv2sp() * May 26 2000 Add separate pointer to header in tab table structure * May 26 2000 Add separate pointer to table name in tab table structure * Jul 12 2000 Add catalog type code to ctalog data structure * Sep 20 2000 Add isacat() to detect ASCII catalog files * Sep 25 2000 Add starcat.sptype to flag spectral type in catalog * Oct 23 2000 Add USNO plate catalog to catalog type table * Oct 26 2000 Add proper motion flags for seconds and arcseconds per century * Oct 31 2000 Add proper motion flags for milliseconds per year * Nov 2 2000 Add parallax and radial velocity to star structure * Nov 21 2000 Add WEBCAT catalog type for tab ctalogs returned from the Web * Nov 22 2000 Add webread() and webrnum() * Nov 28 2000 Add tabparse() * Nov 30 2000 Add spectral type to catalog header; make star->isp 4 char. * Dec 13 2000 Add StrNdec() to get number of decimal places in number strings * Dec 15 2000 Add CatNdec() to get number of decimal places in source numbers * Dec 18 2000 Drop PropCat(), a cludgy proper motion flag * * Mar 22 2001 Add web search flag in catalog data structure * Mar 27 2001 Add shapes in pixels to SAOimage region options * May 14 2001 Add 2MASS Point Source Catalog flags * May 22 2001 Add declination sorting * May 24 2001 Add 2MASS Point Source Catalog subroutines * May 29 2001 Add length of star number to catalog structure * May 30 2001 Add third magnitude for tab tables to catalog structure * Jun 15 2001 Add CatName() and CatID() * Jun 19 2001 Add parallax error to catalog and star structures * Jun 20 2001 Add webopen(), GSC2, fourth magnitude to star and starcat * Jul 12 2001 Add separate web access subroutine, webbuff() * Jul 23 2001 Add ageti4() and agetr8() * Jul 24 2001 Add polfit() and polcomp() * Aug 8 2001 Add keyrv and option to set mprop to 2 to include rv/cz * Sep 10 2001 Add entry line and distance from search center to Star * Sep 13 2001 Add YSortStars() and SORT_Y * Sep 14 2001 Add lbuff to TabTable structure * Sep 20 2001 Add CatMagName() * Sep 25 2001 Move isfile() to fitsfile.h * Oct 16 2001 Add tabdash pointer to tabtable data structure * * Apr 9 2002 Fix typo in gettaberr() declaration * Apr 10 2002 Add CatMagNum() * May 6 2002 Increase object name length from 31 to 79 characters * May 13 2002 Add NumNdec(), gsc2read(), and gsc2rnum() * Aug 6 2002 Make magnitude entries and positions vectors of 10 * Oct 30 2002 Add epoch keyword and FITS date to StarCat data structure * * Jan 16 2003 Add USNO-B1.0 catalog * Mar 24 2003 Add CatCde() to get only catalog code * Apr 3 2003 Add ubcread(), ubcrnum(), and FluxSortStars() * Apr 3 2003 Drop gsc2rnum() * Apr 14 2003 Add setrevmsg() and getrevmsg() * Apr 24 2003 Add UCAC1 and UCAC2, ucacread() and ucacrnum() * May 20 2003 Add TMIDR2 for 2MASS PSC Interim Data Release 2 * Sep 16 2003 Add SORT_MERGE for scat * Sep 25 2003 Add *bin() subroutines for catalog binning * Dec 3 2003 Add USNO YB6 catalog * * Jan 5 2004 Add SDSS catalog * Jan 12 2004 Add 2MASS Extended Source catalog and size to star structure * Jan 14 2004 Add CatSource() subroutine to simplify help message creation * Jan 22 2004 Add setlimdeg() to print limit coordinates in degrees * Mar 16 2004 Add MergeStars() * Apr 23 2004 Add ctgrdate() * Aug 31 2004 Increase MAXTOKENS from 100 to 200 * Sep 2 2004 Increase MAXTOKENS from 200 to 1000 * * Jul 27 2005 Add date format codes and DateString() * Aug 5 2005 Add Tycho-2 and 2MASS PSC with magnitude errors * * Jan 6 2006 Add CatRad() subroutine * Mar 17 2006 Make vothead() int as it now returns the number of fields * Apr 3 2006 Add tmcid() to check for 2MASS identifiers * Apr 3 2006 Add setdateform() to set output date format * Apr 12 2006 Add SORT_ID for scat to sort catalog entries by ID number * Jun 20 2006 Add IDSortStars() * * Jan 10 2006 Add ANSI C function prototypes * Jan 11 2007 Move token access subroutines to fileutil.c/fitsfile.h * Mar 13 2007 Add gsc2c2t() to convert CSV GSC2 buffer to TSV table * Mar 13 2007 Add gobj object name to gsc2read() * Jul 5 2007 Add SKYBOT=31 to catalog list * Jul 13 2007 Add skybotread() and skybot2tab() * Jul 18 2007 Add tabccol() and PM_ARCSECHR for SkyBot * Nov 28 2007 Add moveb() which used to be local to binread() * * Oct 24 2008 Add gsct2t() to clean up tab-separated table from STScI CASB * * Sep 25 2009 Rename moveb() to movebuff() * Sep 25 2009 Add UCAC3 as catalog code 32 * Oct 30 2009 Add position and proper motion error to star structure * Nov 2 2009 Add numbers of images and catalogs to star structure * Nov 3 2009 Parameterize as MAXNMAG the maximum number of magnitudes * * Apr 06 2010 Add fillblank argument to agets() * * May 16 2012 Add valmin and valmax to Range data structure * * Feb 15 2013 Add UCAC4 to list of catalog codes */ wcstools-3.9.5/libwcs/wcslib.h0000664000016200001660000003761412732576255015423 0ustar minkoirsys#ifndef wcslib_h_ #define wcslib_h_ /*============================================================================= * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-2002, Mark Calabretta * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Correspondence concerning WCSLIB may be directed to: * Internet email: mcalabre@atnf.csiro.au * Postal address: Dr. Mark Calabretta, * Australia Telescope National Facility, * P.O. Box 76, * Epping, NSW, 2121, * AUSTRALIA * * Author: Mark Calabretta, Australia Telescope National Facility * $Id: wcs.h,v 2.9 2002/04/03 01:25:29 mcalabre Exp $ *===========================================================================*/ #ifdef __cplusplus extern "C" { #endif #if !defined(__STDC__) && !defined(__cplusplus) #ifndef const #define const #endif #endif #define MAXPV 100 #define WCS_NGRIDPOINTS 12 /* Number of WCS grid points / axis */ #define WCS_NGRIDPOINTS2 (WCS_NGRIDPOINTS*WCS_NGRIDPOINTS) #define WCS_INVMAXDEG 9 /* Maximum inversion polynom degree */ #define WCS_INVACCURACY 0.04 /* Maximum inversion error (pixels) */ #define WCS_NRANGEPOINTS 32 /* Number of WCS range points / axis */ #ifndef PI #define PI 3.1415926535898 /* never met before? */ #endif /* DEG/ARCSEC is now D2S and ARCSEC/DEG is S2D */ /* #define DEG (PI/180.0) 1 deg in radians */ /* #define ARCSEC (DEG/3600.0) 1 arcsec in radians */ #define NAXISPV 2 /* poly.h *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * Part of: A program using polynomial fits * Author: E.BERTIN (IAP) * Contents: Include for poly.c * Last modified: 03/03/2004 *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ #ifndef _POLY_H_ #define _POLY_H_ /*--------------------------------- constants -------------------------------*/ #define POLY_MAXDIM 4 /* Max dimensionality of polynom */ #define POLY_MAXDEGREE 10 /* Max degree of the polynom */ /*---------------------------------- macros ---------------------------------*/ /*--------------------------- structure definitions -------------------------*/ typedef struct poly { double *basis; /* Current values of the basis functions */ double *coeff; /* Polynom coefficients */ int ncoeff; /* Number of coefficients */ int *group; /* Groups */ int ndim; /* dimensionality of the polynom */ int *degree; /* Degree in each group */ int ngroup; /* Number of different groups */ } polystruct; /*---------------------------------- protos --------------------------------*/ extern polystruct *poly_init(int *group,int ndim,int *degree,int ngroup); extern double poly_func(polystruct *poly, double *pos); extern int cholsolve(double *a, double *b, int n), *poly_powers(polystruct *poly); extern void poly_addcste(polystruct *poly, double *cste), poly_end(polystruct *poly), poly_fit(polystruct *poly, double *x, double *y, double *w, int ndata, double *extbasis), poly_solve(double *a, double *b, int n), svdsolve(double *a, double *b, int m, int n, double *vmat, double *wmat); #endif extern int npcode; extern char pcodes[26][4]; struct prjprm { char code[4]; int flag; double phi0, theta0; double r0; double p[10]; double w[20]; int n; int npv; double ppv[2*MAXPV]; struct poly *inv_x; struct poly *inv_y; #if __STDC__ || defined(__cplusplus) int (*prjfwd)(const double, const double, struct prjprm *, double *, double *); int (*prjrev)(const double, const double, struct prjprm *, double *, double *); #else int (*prjfwd)(); int (*prjrev)(); #endif }; #if __STDC__ || defined(__cplusplus) int prjset(const char [], struct prjprm *); int prjfwd(const double, const double, struct prjprm *, double *, double *); int prjrev(const double, const double, struct prjprm *, double *, double *); int azpset(struct prjprm *); int azpfwd(const double, const double, struct prjprm *, double *, double *); int azprev(const double, const double, struct prjprm *, double *, double *); int szpset(struct prjprm *); int szpfwd(const double, const double, struct prjprm *, double *, double *); int szprev(const double, const double, struct prjprm *, double *, double *); int tanset(struct prjprm *); int tanfwd(const double, const double, struct prjprm *, double *, double *); int tanrev(const double, const double, struct prjprm *, double *, double *); int stgset(struct prjprm *); int stgfwd(const double, const double, struct prjprm *, double *, double *); int stgrev(const double, const double, struct prjprm *, double *, double *); int sinset(struct prjprm *); int sinfwd(const double, const double, struct prjprm *, double *, double *); int sinrev(const double, const double, struct prjprm *, double *, double *); int arcset(struct prjprm *); int arcfwd(const double, const double, struct prjprm *, double *, double *); int arcrev(const double, const double, struct prjprm *, double *, double *); int zpnset(struct prjprm *); int zpnfwd(const double, const double, struct prjprm *, double *, double *); int zpnrev(const double, const double, struct prjprm *, double *, double *); int zeaset(struct prjprm *); int zeafwd(const double, const double, struct prjprm *, double *, double *); int zearev(const double, const double, struct prjprm *, double *, double *); int airset(struct prjprm *); int airfwd(const double, const double, struct prjprm *, double *, double *); int airrev(const double, const double, struct prjprm *, double *, double *); int cypset(struct prjprm *); int cypfwd(const double, const double, struct prjprm *, double *, double *); int cyprev(const double, const double, struct prjprm *, double *, double *); int ceaset(struct prjprm *); int ceafwd(const double, const double, struct prjprm *, double *, double *); int cearev(const double, const double, struct prjprm *, double *, double *); int carset(struct prjprm *); int carfwd(const double, const double, struct prjprm *, double *, double *); int carrev(const double, const double, struct prjprm *, double *, double *); int merset(struct prjprm *); int merfwd(const double, const double, struct prjprm *, double *, double *); int merrev(const double, const double, struct prjprm *, double *, double *); int sflset(struct prjprm *); int sflfwd(const double, const double, struct prjprm *, double *, double *); int sflrev(const double, const double, struct prjprm *, double *, double *); int parset(struct prjprm *); int parfwd(const double, const double, struct prjprm *, double *, double *); int parrev(const double, const double, struct prjprm *, double *, double *); int molset(struct prjprm *); int molfwd(const double, const double, struct prjprm *, double *, double *); int molrev(const double, const double, struct prjprm *, double *, double *); int aitset(struct prjprm *); int aitfwd(const double, const double, struct prjprm *, double *, double *); int aitrev(const double, const double, struct prjprm *, double *, double *); int copset(struct prjprm *); int copfwd(const double, const double, struct prjprm *, double *, double *); int coprev(const double, const double, struct prjprm *, double *, double *); int coeset(struct prjprm *); int coefwd(const double, const double, struct prjprm *, double *, double *); int coerev(const double, const double, struct prjprm *, double *, double *); int codset(struct prjprm *); int codfwd(const double, const double, struct prjprm *, double *, double *); int codrev(const double, const double, struct prjprm *, double *, double *); int cooset(struct prjprm *); int coofwd(const double, const double, struct prjprm *, double *, double *); int coorev(const double, const double, struct prjprm *, double *, double *); int bonset(struct prjprm *); int bonfwd(const double, const double, struct prjprm *, double *, double *); int bonrev(const double, const double, struct prjprm *, double *, double *); int pcoset(struct prjprm *); int pcofwd(const double, const double, struct prjprm *, double *, double *); int pcorev(const double, const double, struct prjprm *, double *, double *); int tscset(struct prjprm *); int tscfwd(const double, const double, struct prjprm *, double *, double *); int tscrev(const double, const double, struct prjprm *, double *, double *); int cscset(struct prjprm *); int cscfwd(const double, const double, struct prjprm *, double *, double *); int cscrev(const double, const double, struct prjprm *, double *, double *); int qscset(struct prjprm *); int qscfwd(const double, const double, struct prjprm *, double *, double *); int qscrev(const double, const double, struct prjprm *, double *, double *); int raw_to_pv(struct prjprm *prj, double x, double y, double *xo, double *yo); #else int prjset(), prjfwd(), prjrev(); int azpset(), azpfwd(), azprev(); int szpset(), szpfwd(), szprev(); int tanset(), tanfwd(), tanrev(); int stgset(), stgfwd(), stgrev(); int sinset(), sinfwd(), sinrev(); int arcset(), arcfwd(), arcrev(); int zpnset(), zpnfwd(), zpnrev(); int zeaset(), zeafwd(), zearev(); int airset(), airfwd(), airrev(); int cypset(), cypfwd(), cyprev(); int ceaset(), ceafwd(), cearev(); int carset(), carfwd(), carrev(); int merset(), merfwd(), merrev(); int sflset(), sflfwd(), sflrev(); int parset(), parfwd(), parrev(); int molset(), molfwd(), molrev(); int aitset(), aitfwd(), aitrev(); int copset(), copfwd(), coprev(); int coeset(), coefwd(), coerev(); int codset(), codfwd(), codrev(); int cooset(), coofwd(), coorev(); int bonset(), bonfwd(), bonrev(); int pcoset(), pcofwd(), pcorev(); int tscset(), tscfwd(), tscrev(); int cscset(), cscfwd(), cscrev(); int qscset(), qscfwd(), qscrev(); int raw_to_pv(); #endif extern const char *prjset_errmsg[]; extern const char *prjfwd_errmsg[]; extern const char *prjrev_errmsg[]; #define PRJSET 137 struct celprm { int flag; double ref[4]; double euler[5]; }; #if __STDC__ || defined(__cplusplus) int celset(const char *, struct celprm *, struct prjprm *); int celfwd(const char *, const double, const double, struct celprm *, double *, double *, struct prjprm *, double *, double *); int celrev(const char *, const double, const double, struct prjprm *, double *, double *, struct celprm *, double *, double *); #else int celset(), celfwd(), celrev(); #endif extern const char *celset_errmsg[]; extern const char *celfwd_errmsg[]; extern const char *celrev_errmsg[]; #define CELSET 137 struct linprm { int flag; int naxis; double *crpix; double *pc; double *cdelt; /* Intermediates. */ double *piximg; double *imgpix; }; #if __STDC__ || defined(__cplusplus) int linset(struct linprm *); int linfwd(const double[], struct linprm *, double[]); int linrev(const double[], struct linprm *, double[]); int matinv(const int, const double [], double []); #else int linset(), linfwd(), linrev(), matinv(); #endif extern const char *linset_errmsg[]; extern const char *linfwd_errmsg[]; extern const char *linrev_errmsg[]; #define LINSET 137 struct wcsprm { int flag; char pcode[4]; char lngtyp[5], lattyp[5]; int lng, lat; int cubeface; }; #if __STDC__ || defined(__cplusplus) int wcsset(const int, const char[][16], struct wcsprm *); int wcsfwd(const char[][16], struct wcsprm *, const double[], const double[], struct celprm *, double *, double *, struct prjprm *, double[], struct linprm *, double[]); int wcsrev(const char[][16], struct wcsprm *, const double[], struct linprm *, double[], struct prjprm *, double *, double *, const double[], struct celprm *, double[]); int wcsmix(const char[][16], struct wcsprm *, const int, const int, const double[], const double, int, double[], const double[], struct celprm *, double *, double *, struct prjprm *, double[], struct linprm *, double[]); #else int wcsset(), wcsfwd(), wcsrev(), wcsmix(); #endif extern const char *wcsset_errmsg[]; extern const char *wcsfwd_errmsg[]; extern const char *wcsrev_errmsg[]; extern const char *wcsmix_errmsg[]; #define WCSSET 137 #if __STDC__ || defined(__cplusplus) int sphfwd(const double, const double, const double [], double *, double *); int sphrev(const double, const double, const double [], double *, double *); #else int sphfwd(), sphrev(); #endif #ifdef PI #undef PI #endif #ifdef D2R #undef D2R #endif #ifdef R2D #undef R2D #endif #ifdef SQRT2 #undef SQRT2 #endif #ifdef SQRT2INV #undef SQRT2INV #endif #ifdef D2S #undef D2S #endif #ifdef S2D #undef S2D #endif #define PI 3.141592653589793238462643 #define D2R PI/180.0 #define R2D 180.0/PI #define S2D 1.0/3600.0 #define D2S 3600.0 #define SQRT2 1.4142135623730950488 #define SQRT2INV 1.0/SQRT2 #if !defined(__STDC__) && !defined(__cplusplus) #ifndef const #define const #endif #endif #if __STDC__ || defined(__cplusplus) double cosdeg(const double); double sindeg(const double); double tandeg(const double); double acosdeg(const double); double asindeg(const double); double atandeg(const double); double atan2deg(const double, const double); #else double cosdeg(); double sindeg(); double tandeg(); double acosdeg(); double asindeg(); double atandeg(); double atan2deg(); #endif /* Domain tolerance for asin and acos functions. */ #define WCSTRIG_TOL 1e-10 #ifdef __cplusplus } #endif #endif /* wcslib_h_ */ /* Feb 3 2000 Doug Mink - Make cplusplus ifdefs for braces all-inclusive * * Feb 15 2001 Doug Mink - Undefine math constants if already defined * Sep 19 2001 Doug Mink - Update for WCSLIB 2.7, especially proj.h and cel.h * * Mar 12 2002 Doug Mink - Update for WCSLIB 2.8.2, especially proj.h * Nov 29 2006 Doug Mink - Drop semicolon at end of C++ ifdef * Jan 4 2007 Doug Mink - Drop extra declarations of SZP subroutines * * Mar 30 2011 Doug Mink - Add raw_to_pv() subroutine for SCAMP from Ed Los * * Jun 22 2016 Jessica Mink - Increase length of ctype to 16 to handle distortion */ wcstools-3.9.5/libwcs/daoread.c0000664000016200001660000001304311750060473015505 0ustar minkoirsys/*** File libwcs/daoread.c *** January 11, 2007 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2007 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include #include #include "wcs.h" #include "fitsfile.h" #include "wcscat.h" static int nlines; /* Number of lines in catalog */ #define ABS(a) ((a) < 0 ? (-(a)) : (a)) static char newline = 10; static char *daobuff; /* DAOREAD -- Read DAOFIND file of star positions in an image */ int daoread (daocat, xa, ya, ba, pa, nlog) char *daocat; /* Name of DAOFIND catalog file */ double **xa, **ya; /* X and Y coordinates of stars, array returned */ double **ba; /* Instrumental magnitudes of stars, array returned */ int **pa; /* Peak counts of stars in counts, array returned */ int nlog; /* 1 to print each star's position */ { int nstars; double xi, yi, magi; double flux; int iline; char *line; line = 0; iline = 0; nstars = 0; if (daoopen (daocat) > 0) { line = daobuff; /* Loop through catalog */ for (iline = 1; iline <= nlines; iline++) { line = daoline (iline, line); if (line == NULL) { fprintf (stderr,"DAOREAD: Cannot read line %d\n", iline); break; } else if (line[0] != '#') { /* Extract X, Y, magnitude */ sscanf (line,"%lg %lg %lg", &xi, &yi, &magi); /* Save star position, scaled flux, and magnitude in table */ nstars++; *xa= (double *) realloc(*xa, nstars*sizeof(double)); *ya= (double *) realloc(*ya, nstars*sizeof(double)); *ba= (double *) realloc(*ba, nstars*sizeof(double)); *pa= (int *) realloc(*pa, nstars*sizeof(int)); (*xa)[nstars-1] = xi; (*ya)[nstars-1] = yi; (*ba)[nstars-1] = magi; flux = pow (10.0, (-magi / 2.5)); (*pa)[nstars-1] = (int) flux; if (nlog == 1) fprintf (stderr,"DAOREAD: %6d: %9.5f %9.5f %15.4f %6.2f\n", nstars,xi,yi,flux,magi); } /* Log operation */ if (nlog > 0 && iline%nlog == 0) fprintf (stderr,"DAOREAD: %5d / %5d / %5d stars from catalog %s\r", nstars, iline, nlines, daocat); /* End of star loop */ } /* End of open catalog file */ } /* Summarize search */ if (nlog > 0) fprintf (stderr,"DAOREAD: Catalog %s : %d / %d / %d found\n", daocat, nstars, iline, nlines); free (daobuff); return (nstars); } /* DAOOPEN -- Open DAOFIND catalog, returning number of entries */ int daoopen (daofile) char *daofile; /* DAOFIND catalog file name */ { FILE *fcat; int nr, lfile; char *daonew; /* Find length of DAOFIND catalog */ lfile = getfilesize (daofile); if (lfile < 2) { fprintf (stderr,"DAOOPEN: DAOFIND catalog %s has no entries\n",daofile); return (0); } /* Open DAOFIND catalog */ if (!(fcat = fopen (daofile, "r"))) { fprintf (stderr,"DAOOPEN: DAOFIND catalog %s cannot be read\n",daofile); return (0); } /* Allocate buffer to hold entire catalog and read it */ if ((daobuff = malloc (lfile)) != NULL) { nr = fread (daobuff, 1, lfile, fcat); if (nr < lfile) { fprintf (stderr,"DAOOPEN: read only %d / %d bytes of file %s\n", nr, lfile, daofile); (void) fclose (fcat); return (0); } /* Enumerate entries in DAOFIND catalog by counting newlines */ daonew = daobuff; nlines = 0; while ((daonew = strchr (daonew, newline)) != NULL) { daonew = daonew + 1; nlines = nlines + 1; } } (void) fclose (fcat); return (nlines); } /* DAOLINE -- Get DAOFIND catalog entry for one star; return 0 if successful */ char * daoline (iline, line) int iline; /* Star sequence number in DAOFIND catalog */ char *line; /* Pointer to iline'th entry (returned updated) */ { char *nextline; int i; if (iline > nlines) { fprintf (stderr, "DAOSTAR: %d is not in catalog\n",iline); return (NULL); } else if (iline < 1 && line) { nextline = strchr (line, newline) + 1; } else { nextline = daobuff; for (i = 1; i < iline; i++) { nextline = strchr (nextline, newline) + 1; } } return (nextline); } /* Dec 11 1996 New subroutines * * Mar 20 1997 Removed unused variables, fixed logging after lint * * Jul 20 2001 Return magnitude as well as flux * * May 27 2003 Use getfilesize() to get length of file * * Aug 3 2004 Move daoopen() and daoline() declarations to wcscat.h * Aug 30 2004 Include fitsfile.h * * Jun 19 2006 Initialized uninitialized variable iline * * Jan 10 2007 Include wcs.h * Jan 11 2007 Include fitsfile.h */ wcstools-3.9.5/libwcs/dateutil.c0000664000016200001660000035002712040342555015724 0ustar minkoirsys/*** File libwcs/dateutil.c *** October 19, 2012 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1999-2012 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ /* Date and time conversion routines using the following conventions: ang = Angle in fractional degrees deg = Angle in degrees as dd:mm:ss.ss doy = 2 floating point numbers: year and day, including fraction, of year *** First day of year is 1, not zero. dt = 2 floating point numbers: yyyy.mmdd, hh.mmssssss ep = fractional year, often epoch of a position including proper motion epb = Besselian epoch = 365.242198781-day years based on 1900.0 epj = Julian epoch = 365.25-day years based on 2000.0 fd = FITS date string which may be any of the following: yyyy.ffff (fractional year) dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard FITS use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) hr = Sexigesimal hours as hh:mm:dd.ss jd = Julian Date lt = Local time mjd = modified Julian Date = JD - 2400000.5 ofd = FITS date string (dd/mm/yy before 2000, else no return) time = use fd2* with no date to convert time as hh:mm:ss.ss to sec, day, year ts = UT seconds since 1950-01-01T00:00 (used for ephemeris computations) tsi = local seconds since 1980-01-01T00:00 (used by IRAF as a time tag) tsu = UT seconds since 1970-01-01T00:00 (used as Unix system time) tsd = UT seconds of current day ut = Universal Time (UTC) et = Ephemeris Time (or TDB or TT) = TAI + 32.184 seconds tai = International Atomic Time (Temps Atomique International) = ET - 32.184 seconds gps = GPS time = TAI - 19 seconds mst = Mean Greenwich Sidereal Time gst = Greenwich Sidereal Time (includes nutation) lst = Local Sidereal Time (includes nutation) (longitude must be set) hjd = Heliocentric Julian Date mhjd = modified Heliocentric Julian Date = HJD - 2400000.5 * ang2hr (angle) * Convert angle in decimal floating point degrees to hours as hh:mm:ss.ss * ang2deg (angle) * Convert angle in decimal floating point degrees to degrees as dd:mm:ss.ss * deg2ang (angle as dd:mm:ss.ss) * Convert angle in degrees as dd:mm:ss.ss to decimal floating point degrees * ang2hr (angle) * Convert angle in hours as hh:mm:ss.ss to decimal floating point degrees * * doy2dt (year, doy, date, time) * Convert year and day of year to date as yyyy.ddmm and time as hh.mmsss * doy2ep, doy2epb, doy2epj (date, time) * Convert year and day of year to fractional year * doy2fd (year, doy) * Convert year and day of year to FITS date string * doy2mjd (year, doy) * Convert year and day of year to modified Julian date * * dt2doy (date, time, year, doy) * Convert date as yyyy.ddmm and time as hh.mmsss to year and day of year * dt2ep, dt2epb, dt2epj (date, time) * Convert date as yyyy.ddmm and time as hh.mmsss to fractional year * dt2fd (date, time) * Convert date as yyyy.ddmm and time as hh.mmsss to FITS date string * dt2i (date,time,iyr,imon,iday,ihr,imn,sec, ndsec) * Convert yyyy.mmdd hh.mmssss to year month day hours minutes seconds * dt2jd (date,time) * Convert date as yyyy.ddmm and time as hh.mmsss to Julian date * dt2mjd (date,time) * Convert date as yyyy.ddmm and time as hh.mmsss to modified Julian date * dt2ts (date,time) * Convert date (yyyy.ddmm) and time (hh.mmsss) to seconds since 1950-01-01 * dt2tsi (date,time) * Convert date (yyyy.ddmm) and time (hh.mmsss) to seconds since 1980-01-01 * dt2tsu (date,time) * Convert date (yyyy.ddmm) and time (hh.mmsss) to seconds since 1970-01-01 * * ep2dt, epb2dt, epj2dt (epoch,date, time) * Convert fractional year to date as yyyy.ddmm and time as hh.mmsss * ep2fd, epb2fd, epj2fd (epoch) * Convert epoch to FITS ISO date string * ep2i, epb2i, epj2i (epoch,iyr,imon,iday,ihr,imn,sec, ndsec) * Convert fractional year to year month day hours minutes seconds * ep2jd, epb2jd, epj2jd (epoch) * Convert fractional year as used in epoch to Julian date * ep2mjd, epb2mjd, epj2mjd (epoch) * Convert fractional year as used in epoch to modified Julian date * ep2ts, epb2ts, epj2ts (epoch) * Convert fractional year to seconds since 1950.0 * * et2fd (string) * Convert from ET (or TDT or TT) in FITS format to UT in FITS format * fd2et (string) * Convert from UT in FITS format to ET (or TDT or TT) in FITS format * jd2jed (dj) * Convert from Julian Date to Julian Ephemeris Date * jed2jd (dj) * Convert from Julian Ephemeris Date to Julian Date * dt2et (date, time) * Convert date (yyyy.ddmm) and time (hh.mmsss) to ephemeris time * edt2dt (date, time) * Convert ephemeris date (yyyy.ddmm) and time (hh.mmsss) to UT * dt2tai (date, time) * Convert date (yyyy.ddmm) and time (hh.mmsss) to TAI date and time * tai2dt (date, time) * Convert TAI date (yyyy.ddmm) and time (hh.mmsss) to UT * ts2ets (tsec) * Convert from UT in seconds since 1950-01-01 to ET in same format * ets2ts (tsec) * Convert from ET in seconds since 1950-01-01 to UT in same format * * fd2ep, fd2epb, fd2epj (string) * Convert FITS date string to fractional year * Convert time alone to fraction of Besselian year * fd2doy (string, year, doy) * Convert FITS standard date string to year and day of year * fd2dt (string, date, time) * Convert FITS date string to date as yyyy.ddmm and time as hh.mmsss * Convert time alone to hh.mmssss with date set to 0.0 * fd2i (string,iyr,imon,iday,ihr,imn,sec, ndsec) * Convert FITS standard date string to year month day hours min sec * Convert time alone to hours min sec, year month day are zero * fd2jd (string) * Convert FITS standard date string to Julian date * Convert time alone to fraction of day * fd2mjd (string) * Convert FITS standard date string to modified Julian date * fd2ts (string) * Convert FITS standard date string to seconds since 1950.0 * Convert time alone to seconds of day * fd2fd (string) * Convert FITS standard date string to ISO FITS date string * fd2of (string) * Convert FITS standard date string to old-format FITS date and time * fd2ofd (string) * Convert FITS standard date string to old-format FITS date string * fd2oft (string) * Convert time part of FITS standard date string to FITS date string * * jd2doy (dj, year, doy) * Convert Julian date to year and day of year * jd2dt (dj,date,time) * Convert Julian date to date as yyyy.mmdd and time as hh.mmssss * jd2ep, jd2epb, jd2epj (dj) * Convert Julian date to fractional year as used in epoch * jd2fd (dj) * Convert Julian date to FITS ISO date string * jd2i (dj,iyr,imon,iday,ihr,imn,sec, ndsec) * Convert Julian date to year month day hours min sec * jd2mjd (dj) * Convert Julian date to modified Julian date * jd2ts (dj) * Convert Julian day to seconds since 1950.0 * * lt2dt() * Return local time as yyyy.mmdd and time as hh.mmssss * lt2fd() * Return local time as FITS ISO date string * lt2tsi() * Return local time as IRAF seconds since 1980-01-01 00:00 * lt2tsu() * Return local time as Unix seconds since 1970-01-01 00:00 * lt2ts() * Return local time as Unix seconds since 1950-01-01 00:00 * * mjd2doy (dj,year,doy) * Convert modified Julian date to date as year and day of year * mjd2dt (dj,date,time) * Convert modified Julian date to date as yyyy.mmdd and time as hh.mmssss * mjd2ep, mjd2epb, mjd2epj (dj) * Convert modified Julian date to fractional year as used in epoch * mjd2fd (dj) * Convert modified Julian date to FITS ISO date string * mjd2i (dj,iyr,imon,iday,ihr,imn,sec, ndsec) * Convert modified Julian date to year month day hours min sec * mjd2jd (dj) * Convert modified Julian date to Julian date * mjd2ts (dj) * Convert modified Julian day to seconds since 1950.0 * * ts2dt (tsec,date,time) * Convert seconds since 1950.0 to date as yyyy.ddmm and time as hh.mmsss * ts2ep, ts2epb, ts2epj (tsec) * Convert seconds since 1950.0 to fractional year * ts2fd (tsec) * Convert seconds since 1950.0 to FITS standard date string * ts2i (tsec,iyr,imon,iday,ihr,imn,sec, ndsec) * Convert sec since 1950.0 to year month day hours minutes seconds * ts2jd (tsec) * Convert seconds since 1950.0 to Julian date * ts2mjd (tsec) * Convert seconds since 1950.0 to modified Julian date * tsi2fd (tsec) * Convert seconds since 1980-01-01 to FITS standard date string * tsi2dt (tsec,date,time) * Convert seconds since 1980-01-01 to date as yyyy.ddmm, time as hh.mmsss * tsu2fd (tsec) * Convert seconds since 1970-01-01 to FITS standard date string * tsu2tsi (tsec) * Convert UT seconds since 1970-01-01 to local seconds since 1980-01-01 * tsu2dt (tsec,date,time) * Convert seconds since 1970-01-01 to date as yyyy.ddmm, time as hh.mmsss * * tsd2fd (tsec) * Convert seconds since start of day to FITS time, hh:mm:ss.ss * tsd2dt (tsec) * Convert seconds since start of day to hh.mmssss * * fd2gst (string) * convert from FITS date Greenwich Sidereal Time * dt2gst (date, time) * convert from UT as yyyy.mmdd hh.mmssss to Greenwich Sidereal Time * ts2gst (tsec) * Calculate Greenwich Sidereal Time given Universal Time * in seconds since 1951-01-01T0:00:00 * fd2mst (string) * convert from FITS UT date to Mean Sidereal Time * dt2gmt (date, time) * convert from UT as yyyy.mmdd hh.mmssss to Mean Sidereal Time * ts2mst (tsec) * Calculate Mean Sidereal Time given Universal Time * in seconds since 1951-01-01T0:00:00 * jd2mst (string) * convert from Julian Date to Mean Sidereal Time * mst2fd (string) * convert to current UT in FITS format given Greenwich Mean Sidereal Time * mst2jd (dj) * convert to current UT as Julian Date given Greenwich Mean Sidereal Time * jd2lst (dj) * Calculate Local Sidereal Time from Julian Date * ts2lst (tsec) * Calculate Local Sidereal Time given UT in seconds since 1951-01-01T0:00 * fd2lst (string) * Calculate Local Sidereal Time given Universal Time as FITS ISO date * lst2jd (dj, lst) * Calculate Julian Date given current Julian date and Local Sidereal Time * lst2fd (string, lst) * Calculate Julian Date given current UT date and Local Sidereal Time * gst2fd (string) * Calculate current UT given UT date and Greenwich Sidereal Time * gst2jd (dj) * Calculate current UT given UT date and Greenwich Sidereal Time as JD * * compnut (dj, dpsi, deps, eps0) * Compute the longitude and obliquity components of nutation and * mean obliquity from the IAU 1980 theory * * utdt (dj) * Compute difference between UT and dynamical time (ET-UT) * ut2dt (year, doy) * Current Universal Time to year and day of year * ut2dt (date, time) * Current Universal Time to date (yyyy.mmdd) and time (hh.mmsss) * ut2ep(), ut2epb(), ut2epj() * Current Universal Time to fractional year, Besselian, Julian epoch * ut2fd() * Current Universal Time to FITS ISO date string * ut2jd() * Current Universal Time to Julian Date * ut2mjd() * Current Universal Time to Modified Julian Date * ut2tsi() * Current Universal Time to IRAF seconds since 1980-01-01T00:00 * ut2tsu() * Current Universal Time to Unix seconds since 1970-01-01T00:00 * ut2ts() * Current Universal Time to seconds since 1950-01-01T00:00 * isdate (string) * Return 1 if string is a FITS date (old or ISO) * * Internally-used subroutines * * fixdate (iyr, imon, iday, ihr, imn, sec, ndsec) * Round seconds and make sure date and time numbers are within limits * caldays (year, month) * Calculate days in month 1-12 given year (Gregorian calendar only * dint (dnum) * Return integer part of floating point number * dmod (dnum) * Return Mod of floating point number */ #include #include #include #include #include #include #include "wcs.h" #include "fitsfile.h" static double suntl(); static void fixdate(); static int caldays(); static double dint(); static double dmod(); static double longitude = 0.0; /* longitude of observatory in degrees (+=west) */ void setlongitude (longitude0) double longitude0; { longitude = longitude0; return; } static int ndec = 3; void setdatedec (nd) int nd; { ndec = nd; return; } /* ANG2HR -- Convert angle in fraction degrees to hours as hh:mm:ss.ss */ void ang2hr (angle, lstr, string) double angle; /* Angle in fractional degrees */ int lstr; /* Maximum number of characters in string */ char *string; /* Character string (hh:mm:ss.ss returned) */ { angle = angle / 15.0; dec2str (string, lstr, angle, ndec); return; } /* ANG2DEG -- Convert angle in fraction degrees to degrees as dd:mm:ss.ss */ void ang2deg (angle, lstr, string) double angle; /* Angle in fractional degrees */ int lstr; /* Maximum number of characters in string */ char *string; /* Character string (dd:mm:ss.ss returned) */ { dec2str (string, lstr, angle, ndec); return; } /* DEG2ANG -- Convert angle in degrees as dd:mm:ss.ss to fractional degrees */ double deg2ang (angle) char *angle; /* Angle as dd:mm:ss.ss */ { double deg; deg = str2dec (angle); return (deg); } /* HR2ANG -- Convert angle in hours as hh:mm:ss.ss to fractional degrees */ double hr2ang (angle) char *angle; /* Angle in sexigesimal hours (hh:mm:ss.sss) */ { double deg; deg = str2dec (angle); deg = deg * 15.0; return (deg); } /* DT2FD-- convert vigesimal date and time to FITS date, yyyy-mm-ddThh:mm:ss.ss */ char * dt2fd (date, time) double date; /* Date as yyyy.mmdd yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { int iyr,imon,iday,ihr,imn; double sec; int nf; char *string; char tstring[32], dstring[32]; char outform[64]; dt2i (date, time, &iyr,&imon,&iday,&ihr,&imn,&sec, ndec); /* Convert to ISO date format */ string = (char *) calloc (32, sizeof (char)); /* Make time string */ if (time != 0.0 || ndec > 0) { if (ndec == 0) nf = 2; else nf = 3 + ndec; if (ndec > 0) { sprintf (outform, "%%02d:%%02d:%%0%d.%df", nf, ndec); sprintf (tstring, outform, ihr, imn, sec); } else { sprintf (outform, "%%02d:%%02d:%%0%dd", nf); sprintf (tstring, outform, ihr, imn, (int)(sec+0.5)); } } /* Make date string */ if (date != 0.0) sprintf (dstring, "%4d-%02d-%02d", iyr, imon, iday); /* Make FITS (ISO) date string */ if (date == 0.0) strcpy (string, tstring); else if (time == 0.0 && ndec < 1) strcpy (string, dstring); else sprintf (string, "%sT%s", dstring, tstring); return (string); } /* DT2JD-- convert from date as yyyy.mmdd and time as hh.mmsss to Julian Date * Return fractional days if date is zero */ double dt2jd (date,time) double date; /* Date as yyyy.mmdd yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double dj; /* Julian date (returned) */ double tsec; /* seconds since 1950.0 */ tsec = dt2ts (date, time); if (date == 0.0) dj = tsec / 86400.0; else dj = ts2jd (tsec); return (dj); } /* DT2MJD-- convert from date yyyy.mmdd time hh.mmsss to modified Julian Date * Return fractional days if date is zero */ double dt2mjd (date,time) double date; /* Date as yyyy.mmdd yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double dj; /* Modified Julian date (returned) */ double tsec; /* seconds since 1950.0 */ tsec = dt2ts (date, time); if (date == 0.0) dj = tsec / 86400.0; else dj = ts2jd (tsec); return (dj - 2400000.5); } /* HJD2JD-- convert Heliocentric Julian Date to (geocentric) Julian date */ double hjd2jd (dj, ra, dec, sys) double dj; /* Heliocentric Julian date */ double ra; /* Right ascension (degrees) */ double dec; /* Declination (degrees) */ int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ { double lt; /* Light travel difference to the Sun (days) */ lt = suntl (dj, ra, dec, sys); /* Return Heliocentric Julian Date */ return (dj - lt); } /* JD2HJD-- convert (geocentric) Julian date to Heliocentric Julian Date */ double jd2hjd (dj, ra, dec, sys) double dj; /* Julian date (geocentric) */ double ra; /* Right ascension (degrees) */ double dec; /* Declination (degrees) */ int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ { double lt; /* Light travel difference to the Sun (days) */ lt = suntl (dj, ra, dec, sys); /* Return Heliocentric Julian Date */ return (dj + lt); } /* MHJD2MJD-- convert modified Heliocentric Julian Date to modified geocentric Julian date */ double mhjd2mjd (mhjd, ra, dec, sys) double mhjd; /* Modified Heliocentric Julian date */ double ra; /* Right ascension (degrees) */ double dec; /* Declination (degrees) */ int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ { double lt; /* Light travel difference to the Sun (days) */ double hjd; /* Heliocentric Julian date */ hjd = mjd2jd (mhjd); lt = suntl (hjd, ra, dec, sys); /* Return Heliocentric Julian Date */ return (jd2mjd (hjd - lt)); } /* MJD2MHJD-- convert modified geocentric Julian date tp modified Heliocentric Julian Date */ double mjd2mhjd (mjd, ra, dec, sys) double mjd; /* Julian date (geocentric) */ double ra; /* Right ascension (degrees) */ double dec; /* Declination (degrees) */ int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ { double lt; /* Light travel difference to the Sun (days) */ double dj; /* Julian date (geocentric) */ dj = mjd2jd (mjd); lt = suntl (dj, ra, dec, sys); /* Return Heliocentric Julian Date */ return (jd2mjd (dj + lt)); } /* SUNTL-- compute light travel time to heliocentric correction in days */ /* Translated into C from IRAF SPP noao.astutils.asttools.asthjd.x */ static double suntl (dj, ra, dec, sys) double dj; /* Julian date (geocentric) */ double ra; /* Right ascension (degrees) */ double dec; /* Declination (degrees) */ int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ { double t; /* Number of Julian centuries since J1900 */ double manom; /* Mean anomaly of the Earth's orbit (degrees) */ double lperi; /* Mean longitude of perihelion (degrees) */ double oblq; /* Mean obliquity of the ecliptic (degrees) */ double eccen; /* Eccentricity of the Earth's orbit (dimensionless) */ double eccen2, eccen3; double tanom; /* True anomaly (approximate formula) (radians) */ double slong; /* True longitude of the Sun from the Earth (radians) */ double rs; /* Distance to the sun (AU) */ double lt; /* Light travel difference to the Sun (days) */ double l; /* Longitude of star in orbital plane of Earth (radians) */ double b; /* Latitude of star in orbital plane of Earth (radians) */ double epoch; /* Epoch of obervation */ double rs1,rs2; t = (dj - 2415020.0) / 36525.0; /* Compute earth orbital parameters */ manom = 358.47583 + (t * (35999.04975 - t * (0.000150 + t * 0.000003))); lperi = 101.22083 + (t * (1.7191733 + t * (0.000453 + t * 0.000003))); oblq = 23.452294 - (t * (0.0130125 + t * (0.00000164 - t * 0.000000503))); eccen = 0.01675104 - (t * (0.00004180 + t * 0.000000126)); eccen2 = eccen * eccen; eccen3 = eccen * eccen2; /* Convert to principle angles */ manom = manom - (360.0 * (dint) (manom / 360.0)); lperi = lperi - (360.0 * (dint) (lperi / 360.0)); /* Convert to radians */ manom = degrad (manom); lperi = degrad (lperi); oblq = degrad (oblq); /* True anomaly */ tanom = manom + (2 * eccen - 0.25 * eccen3) * sin (manom) + 1.25 * eccen2 * sin (2 * manom) + 13./12. * eccen3 * sin (3 * manom); /* Distance to the Sun */ rs1 = 1.0 - eccen2; rs2 = 1.0 + (eccen * cos (tanom)); rs = rs1 / rs2; /* True longitude of the Sun seen from the Earth */ slong = lperi + tanom + PI; /* Longitude and latitude of star in orbital plane of the Earth */ epoch = jd2ep (dj); wcscon (sys, WCS_ECLIPTIC, 0.0, 0.0, &ra, &dec, epoch); l = degrad (ra); b = degrad (dec); /* Light travel difference to the Sun */ lt = -0.005770 * rs * cos (b) * cos (l - slong); /* Return light travel difference */ return (lt); } /* JD2DT-- convert Julian date to date as yyyy.mmdd and time as hh.mmssss */ void jd2dt (dj,date,time) double dj; /* Julian date */ double *date; /* Date as yyyy.mmdd (returned) */ double *time; /* Time as hh.mmssxxxx (returned) */ { int iyr,imon,iday,ihr,imn; double sec; /* Convert Julian Date to date and time */ jd2i (dj, &iyr, &imon, &iday, &ihr, &imn, &sec, 4); /* Convert date to yyyy.mmdd */ if (iyr < 0) { *date = (double) (-iyr) + 0.01 * (double) imon + 0.0001 * (double) iday; *date = -(*date); } else *date = (double) iyr + 0.01 * (double) imon + 0.0001 * (double) iday; /* Convert time to hh.mmssssss */ *time = (double) ihr + 0.01 * (double) imn + 0.0001 * sec; return; } /* JD2I-- convert Julian date to date as year, month, and day, and time hours, minutes, and seconds */ /* after Fliegel and Van Flander, CACM 11, 657 (1968) */ void jd2i (dj, iyr, imon, iday, ihr, imn, sec, ndsec) double dj; /* Julian date */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double tsec; double frac, dts, ts, sday; int jd, l, n, i, j; tsec = jd2ts (dj); /* ts2i (tsec, iyr, imon, iday, ihr, imn, sec, ndsec); */ /* Round seconds to 0 - 4 decimal places */ if (tsec < 0.0) dts = -0.5; else dts = 0.5; if (ndsec < 1) ts = dint (tsec + dts); else if (ndsec < 2) ts = dint (tsec * 10.0 + dts) / 10.0; else if (ndsec < 3) ts = dint (tsec * 100.0 + dts) / 100.0; else if (ndsec < 4) ts = dint (tsec * 1000.0 + dts) / 1000.0; else ts = dint (tsec * 10000.0 + dts) / 10000.0; /* Convert back to Julian Date */ dj = ts2jd (ts); /* Compute time from fraction of a day */ frac = dmod (dj, 1.0); if (frac < 0.5) { jd = (int) (dj - frac); sday = (frac + 0.5) * 86400.0; } else { jd = (int) (dj - frac) + 1; sday = (frac - 0.5) * 86400.0; } *ihr = (int) (sday / 3600.0); sday = sday - (double) (*ihr * 3600); *imn = (int) (sday / 60.0); *sec = sday - (double) (*imn * 60); /* Compute day, month, year */ l = jd + 68569; n = (4 * l) / 146097; l = l - (146097 * n + 3) / 4; i = (4000 * (l + 1)) / 1461001; l = l - (1461 * i) / 4 + 31; j = (80 * l) / 2447; *iday = l - (2447 * j) / 80; l = j / 11; *imon = j + 2 - (12 * l); *iyr = 100 * (n - 49) + i + l; return; } /* JD2MJD-- convert Julian Date to Modified Julian Date */ double jd2mjd (dj) double dj; /* Julian Date */ { return (dj - 2400000.5); } /* JD2EP-- convert Julian date to fractional year as used in epoch */ double jd2ep (dj) double dj; /* Julian date */ { double date, time; jd2dt (dj, &date, &time); return (dt2ep (date, time)); } /* JD2EPB-- convert Julian date to Besselian epoch */ double jd2epb (dj) double dj; /* Julian date */ { return (1900.0 + (dj - 2415020.31352) / 365.242198781); } /* JD2EPJ-- convert Julian date to Julian epoch */ double jd2epj (dj) double dj; /* Julian date */ { return (2000.0 + (dj - 2451545.0) / 365.25); } /* LT2DT-- Return local time as yyyy.mmdd and time as hh.mmssss */ void lt2dt(date, time) double *date; /* Date as yyyy.mmdd (returned) */ double *time; /* Time as hh.mmssxxxx (returned) */ { time_t tsec; struct timeval tp; struct timezone tzp; struct tm *ts; gettimeofday (&tp,&tzp); tsec = tp.tv_sec; ts = localtime (&tsec); if (ts->tm_year < 1000) *date = (double) (ts->tm_year + 1900); else *date = (double) ts->tm_year; *date = *date + (0.01 * (double) (ts->tm_mon + 1)); *date = *date + (0.0001 * (double) ts->tm_mday); *time = (double) ts->tm_hour; *time = *time + (0.01 * (double) ts->tm_min); *time = *time + (0.0001 * (double) ts->tm_sec); return; } /* LT2FD-- Return current local time as FITS ISO date string */ char * lt2fd() { time_t tsec; struct tm *ts; struct timeval tp; struct timezone tzp; int month, day, year, hour, minute, second; char *isotime; gettimeofday (&tp,&tzp); tsec = tp.tv_sec; ts = localtime (&tsec); year = ts->tm_year; if (year < 1000) year = year + 1900; month = ts->tm_mon + 1; day = ts->tm_mday; hour = ts->tm_hour; minute = ts->tm_min; second = ts->tm_sec; isotime = (char *) calloc (32, sizeof (char)); sprintf (isotime, "%04d-%02d-%02dT%02d:%02d:%02d", year, month, day, hour, minute, second); return (isotime); } /* LT2TSI-- Return local time as IRAF seconds since 1980-01-01 00:00 */ int lt2tsi() { return ((int)(lt2ts() - 946684800.0)); } /* LT2TSU-- Return local time as Unix seconds since 1970-01-01 00:00 */ time_t lt2tsu() { return ((time_t)(lt2ts() - 631152000.0)); } /* LT2TS-- Return local time as Unix seconds since 1950-01-01 00:00 */ double lt2ts() { double tsec; char *datestring; datestring = lt2fd(); tsec = fd2ts (datestring); free (datestring); return (tsec); } /* MJD2DT-- convert Modified Julian Date to date (yyyy.mmdd) time (hh.mmssss) */ void mjd2dt (dj,date,time) double dj; /* Modified Julian Date */ double *date; /* Date as yyyy.mmdd (returned) yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double *time; /* Time as hh.mmssxxxx (returned) *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double tsec; tsec = jd2ts (dj + 2400000.5); ts2dt (tsec, date, time); return; } /* MJD2I-- convert Modified Julian Date to date as year, month, day and time as hours, minutes, seconds */ void mjd2i (dj, iyr, imon, iday, ihr, imn, sec, ndsec) double dj; /* Modified Julian Date */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double tsec; tsec = jd2ts (dj + 2400000.5); ts2i (tsec, iyr, imon, iday, ihr, imn, sec, ndsec); return; } /* MJD2DOY-- convert Modified Julian Date to Year,Day-of-Year */ void mjd2doy (dj, year, doy) double dj; /* Modified Julian Date */ int *year; /* Year (returned) */ double *doy; /* Day of year with fraction (returned) */ { jd2doy (dj + 2400000.5, year, doy); return; } /* MJD2JD-- convert Modified Julian Date to Julian Date */ double mjd2jd (dj) double dj; /* Modified Julian Date */ { return (dj + 2400000.5); } /* MJD2EP-- convert Modified Julian Date to fractional year */ double mjd2ep (dj) double dj; /* Modified Julian Date */ { double date, time; jd2dt (dj + 2400000.5, &date, &time); return (dt2ep (date, time)); } /* MJD2EPB-- convert Modified Julian Date to Besselian epoch */ double mjd2epb (dj) double dj; /* Modified Julian Date */ { return (1900.0 + (dj - 15019.81352) / 365.242198781); } /* MJD2EPJ-- convert Modified Julian Date to Julian epoch */ double mjd2epj (dj) double dj; /* Modified Julian Date */ { return (2000.0 + (dj - 51544.5) / 365.25); } /* MJD2FD-- convert modified Julian date to FITS date, yyyy-mm-ddThh:mm:ss.ss */ char * mjd2fd (dj) double dj; /* Modified Julian date */ { return (jd2fd (dj + 2400000.5)); } /* MJD2TS-- convert modified Julian date to seconds since 1950.0 */ double mjd2ts (dj) double dj; /* Modified Julian date */ { return ((dj - 33282.0) * 86400.0); } /* EP2FD-- convert fractional year to FITS date, yyyy-mm-ddThh:mm:ss.ss */ char * ep2fd (epoch) double epoch; /* Date as fractional year */ { double tsec; /* seconds since 1950.0 (returned) */ tsec = ep2ts (epoch); return (ts2fd (tsec)); } /* EPB2FD-- convert Besselian epoch to FITS date, yyyy-mm-ddThh:mm:ss.ss */ char * epb2fd (epoch) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ { double dj; /* Julian Date */ dj = epb2jd (epoch); return (jd2fd (dj)); } /* EPJ2FD-- convert Julian epoch to FITS date, yyyy-mm-ddThh:mm:ss.ss */ char * epj2fd (epoch) double epoch; /* Julian epoch (fractional 365.25-day years) */ { double dj; /* Julian Date */ dj = epj2jd (epoch); return (jd2fd (dj)); } /* EP2TS-- convert fractional year to seconds since 1950.0 */ double ep2ts (epoch) double epoch; /* Date as fractional year */ { double dj; dj = ep2jd (epoch); return ((dj - 2433282.5) * 86400.0); } /* EPB2TS-- convert Besselian epoch to seconds since 1950.0 */ double epb2ts (epoch) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ { double dj; dj = epb2jd (epoch); return ((dj - 2433282.5) * 86400.0); } /* EPJ2TS-- convert Julian epoch to seconds since 1950.0 */ double epj2ts (epoch) double epoch; /* Julian epoch (fractional 365.25-day years) */ { double dj; dj = epj2jd (epoch); return ((dj - 2433282.5) * 86400.0); } /* EPB2EP-- convert Besselian epoch to fractional years */ double epb2ep (epoch) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ { double dj; dj = epb2jd (epoch); return (jd2ep (dj)); } /* EP2EPB-- convert fractional year to Besselian epoch */ double ep2epb (epoch) double epoch; /* Fractional year */ { double dj; dj = ep2jd (epoch); return (jd2epb (dj)); } /* EPJ2EP-- convert Julian epoch to fractional year */ double epj2ep (epoch) double epoch; /* Julian epoch (fractional 365.25-day years) */ { double dj; dj = epj2jd (epoch); return (jd2ep (dj)); } /* EP2EPJ-- convert fractional year to Julian epoch */ double ep2epj (epoch) double epoch; /* Fractional year */ { double dj; dj = ep2jd (epoch); return (jd2epj (dj)); } /* EP2I-- convert fractional year to year month day hours min sec */ void ep2i (epoch, iyr, imon, iday, ihr, imn, sec, ndsec) double epoch; /* Date as fractional year */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double date, time; ep2dt (epoch, &date, &time); dt2i (date, time, iyr,imon,iday,ihr,imn,sec, ndsec); return; } /* EPB2I-- convert Besselian epoch to year month day hours min sec */ void epb2i (epoch, iyr, imon, iday, ihr, imn, sec, ndsec) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double date, time; epb2dt (epoch, &date, &time); dt2i (date, time, iyr,imon,iday,ihr,imn,sec, ndsec); return; } /* EPJ2I-- convert Julian epoch to year month day hours min sec */ void epj2i (epoch, iyr, imon, iday, ihr, imn, sec, ndsec) double epoch; /* Julian epoch (fractional 365.25-day years) */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double date, time; epj2dt (epoch, &date, &time); dt2i (date, time, iyr,imon,iday,ihr,imn,sec, ndsec); return; } /* EP2JD-- convert fractional year as used in epoch to Julian date */ double ep2jd (epoch) double epoch; /* Date as fractional year */ { double dj; /* Julian date (returned)*/ double date, time; ep2dt (epoch, &date, &time); dj = dt2jd (date, time); return (dj); } /* EPB2JD-- convert Besselian epoch to Julian Date */ double epb2jd (epoch) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ { return (2415020.31352 + ((epoch - 1900.0) * 365.242198781)); } /* EPJ2JD-- convert Julian epoch to Julian Date */ double epj2jd (epoch) double epoch; /* Julian epoch (fractional 365.25-day years) */ { return (2451545.0 + ((epoch - 2000.0) * 365.25)); } /* EP2MJD-- convert fractional year as used in epoch to modified Julian date */ double ep2mjd (epoch) double epoch; /* Date as fractional year */ { double dj; /* Julian date (returned)*/ double date, time; ep2dt (epoch, &date, &time); dj = dt2jd (date, time); return (dj - 2400000.5); } /* EPB2MJD-- convert Besselian epoch to modified Julian Date */ double epb2mjd (epoch) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ { return (15019.81352 + ((epoch - 1900.0) * 365.242198781)); } /* EPJ2MJD-- convert Julian epoch to modified Julian Date */ double epj2mjd (epoch) double epoch; /* Julian epoch (fractional 365.25-day years) */ { return (51544.5 + ((epoch - 2000.0) * 365.25)); } /* EPB2EPJ-- convert Besselian epoch to Julian epoch */ double epb2epj (epoch) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ { double dj; /* Julian date */ dj = epb2jd (epoch); return (jd2epj (dj)); } /* EPJ2EPB-- convert Julian epoch to Besselian epoch */ double epj2epb (epoch) double epoch; /* Julian epoch (fractional 365.25-day years) */ { double dj; /* Julian date */ dj = epj2jd (epoch); return (jd2epb (dj)); } /* JD2FD-- convert Julian date to FITS date, yyyy-mm-ddThh:mm:ss.ss */ char * jd2fd (dj) double dj; /* Julian date */ { double tsec; /* seconds since 1950.0 (returned) */ tsec = (dj - 2433282.5) * 86400.0; return (ts2fd (tsec)); } /* JD2TS-- convert Julian date to seconds since 1950.0 */ double jd2ts (dj) double dj; /* Julian date */ { return ((dj - 2433282.5) * 86400.0); } /* JD2TSI-- convert Julian date to IRAF seconds since 1980-01-01T0:00 */ int jd2tsi (dj) double dj; /* Julian date */ { double ts; ts = (dj - 2444239.5) * 86400.0; return ((int) ts); } /* JD2TSU-- convert Julian date to Unix seconds since 1970-01-01T0:00 */ time_t jd2tsu (dj) double dj; /* Julian date */ { return ((time_t)((dj - 2440587.5) * 86400.0)); } /* DT2DOY-- convert yyyy.mmdd hh.mmss to year and day of year */ void dt2doy (date, time, year, doy) double date; /* Date as yyyy.mmdd */ double time; /* Time as hh.mmssxxxx */ int *year; /* Year (returned) */ double *doy; /* Day of year with fraction (returned) */ { double dj; /* Julian date */ double dj0; /* Julian date on January 1 0:00 */ double date0; /* January first of date's year */ double dyear; dyear = floor (date); date0 = dyear + 0.0101; dj0 = dt2jd (date0, 0.0); dj = dt2jd (date, time); *year = (int) (dyear + 0.00000001); *doy = dj - dj0 + 1.0; return; } /* DOY2DT-- convert year and day of year to yyyy.mmdd hh.mmss */ void doy2dt (year, doy, date, time) int year; /* Year */ double doy; /* Day of year with fraction */ double *date; /* Date as yyyy.mmdd (returned) */ double *time; /* Time as hh.mmssxxxx (returned) */ { double dj; /* Julian date */ double dj0; /* Julian date on January 1 0:00 */ double date0; /* January first of date's year */ date0 = year + 0.0101; dj0 = dt2jd (date0, 0.0); dj = dj0 + doy - 1.0; jd2dt (dj, date, time); return; } /* DOY2EP-- convert year and day of year to fractional year as used in epoch */ double doy2ep (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double date, time; doy2dt (year, doy, &date, &time); return (dt2ep (date, time)); } /* DOY2EPB-- convert year and day of year to Besellian epoch */ double doy2epb (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj; dj = doy2jd (year, doy); return (jd2epb (dj)); } /* DOY2EPJ-- convert year and day of year to Julian epoch */ double doy2epj (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj; dj = doy2jd (year, doy); return (jd2epj (dj)); } /* DOY2FD-- convert year and day of year to FITS date */ char * doy2fd (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj; /* Julian date */ dj = doy2jd (year, doy); return (jd2fd (dj)); } /* DOY2JD-- convert year and day of year to Julian date */ double doy2jd (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj0; /* Julian date */ double date; /* Date as yyyy.mmdd (returned) */ double time; /* Time as hh.mmssxxxx (returned) */ date = (double) year + 0.0101; time = 0.0; dj0 = dt2jd (date, time); return (dj0 + doy - 1.0); } /* DOY2MJD-- convert year and day of year to Julian date */ double doy2mjd (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj0; /* Julian date */ double date; /* Date as yyyy.mmdd (returned) */ double time; /* Time as hh.mmssxxxx (returned) */ date = (double) year + 0.0101; time = 0.0; dj0 = dt2jd (date, time); return (dj0 + doy - 1.0 - 2400000.5); } /* DOY2TSU-- convert from FITS date to Unix seconds since 1970-01-01T0:00 */ time_t doy2tsu (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj; dj = doy2jd (year, doy); return ((time_t)jd2ts (dj)); } /* DOY2TSI-- convert from FITS date to IRAF seconds since 1980-01-01T0:00 */ int doy2tsi (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj; dj = doy2jd (year, doy); return ((int)jd2tsi (dj)); } /* DOY2TS-- convert year, day of year to seconds since 1950 */ double doy2ts (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj; dj = doy2jd (year, doy); return (jd2ts (dj)); } /* FD2DOY-- convert FITS date to year and day of year */ void fd2doy (string, year, doy) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ int *year; /* Year (returned) */ double *doy; /* Day of year with fraction (returned) */ { double dj; /* Julian date */ dj = fd2jd (string); jd2doy (dj, year, doy); return; } /* JD2DOY-- convert Julian date to year and day of year */ void jd2doy (dj, year, doy) double dj; /* Julian date */ int *year; /* Year (returned) */ double *doy; /* Day of year with fraction (returned) */ { double date; /* Date as yyyy.mmdd (returned) */ double time; /* Time as hh.mmssxxxx (returned) */ double dj0; /* Julian date at 0:00 on 1/1 */ double dyear; jd2dt (dj, &date, &time); *year = (int) date; dyear = (double) *year; dj0 = dt2jd (dyear+0.0101, 0.0); *doy = dj - dj0 + 1.0; return; } /* TS2JD-- convert seconds since 1950.0 to Julian date */ double ts2jd (tsec) double tsec; /* seconds since 1950.0 */ { return (2433282.5 + (tsec / 86400.0)); } /* TS2MJD-- convert seconds since 1950.0 to modified Julian date */ double ts2mjd (tsec) double tsec; /* seconds since 1950.0 */ { return (33282.0 + (tsec / 86400.0)); } /* TS2EP-- convert seconds since 1950.0 to fractional year as used in epoch */ double ts2ep (tsec) double tsec; /* Seconds since 1950.0 */ { double date, time; ts2dt (tsec, &date, &time); return (dt2ep (date, time)); } /* TS2EPB-- convert seconds since 1950.0 to Besselian epoch */ double ts2epb (tsec) double tsec; /* Seconds since 1950.0 */ { double dj; /* Julian Date */ dj = ts2jd (tsec); return (jd2epb (dj)); } /* TS2EPB-- convert seconds since 1950.0 to Julian epoch */ double ts2epj (tsec) double tsec; /* Seconds since 1950.0 */ { double dj; /* Julian Date */ dj = ts2jd (tsec); return (jd2epj (dj)); } /* DT2EP-- convert from date, time as yyyy.mmdd hh.mmsss to fractional year */ double dt2ep (date, time) double date; /* Date as yyyy.mmdd yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double epoch; /* Date as fractional year (returned) */ double dj, dj0, dj1, date0, time0, date1; dj = dt2jd (date, time); if (date == 0.0) epoch = dj / 365.2422; else { time0 = 0.0; date0 = dint (date) + 0.0101; date1 = dint (date) + 1.0101; dj0 = dt2jd (date0, time0); dj1 = dt2jd (date1, time0); epoch = dint (date) + ((dj - dj0) / (dj1 - dj0)); } return (epoch); } /* DT2EPB-- convert from date, time as yyyy.mmdd hh.mmsss to Besselian epoch */ double dt2epb (date, time) double date; /* Date as yyyy.mmdd yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double dj; /* Julian date */ double epoch; /* Date as fractional year (returned) */ dj = dt2jd (date, time); if (date == 0.0) epoch = dj / 365.242198781; else epoch = jd2epb (dj); return (epoch); } /* DT2EPJ-- convert from date, time as yyyy.mmdd hh.mmsss to Julian epoch */ double dt2epj (date, time) double date; /* Date as yyyy.mmdd yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double dj; /* Julian date */ double epoch; /* Date as fractional year (returned) */ dj = dt2jd (date, time); if (date == 0.0) epoch = dj / 365.25; else epoch = jd2epj (dj); return (epoch); } /* EP2DT-- convert from fractional year to date, time as yyyy.mmdd hh.mmsss */ void ep2dt (epoch, date, time) double epoch; /* Date as fractional year */ double *date; /* Date as yyyy.mmdd (returned) yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double *time; /* Time as hh.mmssxxxx (returned) *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double dj, dj0, dj1, date0, time0, date1, epochi, epochf; time0 = 0.0; epochi = dint (epoch); epochf = epoch - epochi; date0 = epochi + 0.0101; date1 = epochi + 1.0101; dj0 = dt2jd (date0, time0); dj1 = dt2jd (date1, time0); dj = dj0 + epochf * (dj1 - dj0); jd2dt (dj, date, time); return; } /* EPB2DT-- convert from Besselian epoch to date, time as yyyy.mmdd hh.mmsss */ void epb2dt (epoch, date, time) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ double *date; /* Date as yyyy.mmdd (returned) yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double *time; /* Time as hh.mmssxxxx (returned) *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double dj; /* Julian date */ dj = epb2jd (epoch); jd2dt (dj, date, time); } /* EPJ2DT-- convert from Julian epoch to date, time as yyyy.mmdd hh.mmsss */ void epj2dt (epoch, date, time) double epoch; /* Julian epoch (fractional 365.25-day years) */ double *date; /* Date as yyyy.mmdd (returned) yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double *time; /* Time as hh.mmssxxxx (returned) *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double dj; /* Julian date */ dj = epj2jd (epoch); jd2dt (dj, date, time); } /* FD2JD-- convert FITS standard date to Julian date */ double fd2jd (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double date, time; fd2dt (string, &date, &time); return (dt2jd (date, time)); } /* FD2MJD-- convert FITS standard date to modified Julian date */ double fd2mjd (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { return (fd2jd (string) - 2400000.5); } /* FD2TSU-- convert from FITS date to Unix seconds since 1970-01-01T0:00 */ time_t fd2tsu (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double date, time; fd2dt (string, &date, &time); return (dt2tsu (date, time)); } /* FD2TSI-- convert from FITS date to IRAF seconds since 1980-01-01T0:00 */ int fd2tsi (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double date, time; fd2dt (string, &date, &time); return (dt2tsi (date, time)); } /* FD2TS-- convert FITS standard date to seconds since 1950 */ double fd2ts (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double date, time; fd2dt (string, &date, &time); return (dt2ts (date, time)); } /* FD2FD-- convert any FITS standard date to ISO FITS standard date */ char * fd2fd (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double date, time; fd2dt (string, &date, &time); return (dt2fd (date, time)); } /* FD2OF-- convert any FITS standard date to old FITS standard date time */ char * fd2of (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { int iyr,imon,iday,ihr,imn; double sec; fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 3); /* Convert to old FITS date format */ string = (char *) calloc (32, sizeof (char)); if (iyr < 1900) sprintf (string, "*** date out of range ***"); else if (iyr < 2000) sprintf (string, "%02d/%02d/%02d %02d:%02d:%06.3f", iday, imon, iyr-1900, ihr, imn, sec); else if (iyr < 2900.0) sprintf (string, "%02d/%02d/%3d %02d:%02d:%6.3f", iday, imon, iyr-1900, ihr, imn, sec); else sprintf (string, "*** date out of range ***"); return (string); } /* TAI-UTC from the U.S. Naval Observatory */ /* ftp://maia.usno.navy.mil/ser7/tai-utc.dat */ static double taijd[26]={2441317.5, 2441499.5, 2441683.5, 2442048.5, 2442413.5, 2442778.5, 2443144.5, 2443509.5, 2443874.5, 2444239.5, 2444786.5, 2445151.5, 2445516.5, 2446247.5, 2447161.5, 2447892.5, 2448257.5, 2448804.5, 2449169.5, 2449534.5, 2450083.5, 2450630.5, 2451179.5, 2453736.5, 2454832.5, 2456293.5}; static double taidt[26]={10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0, 20.0,21.0,22.0,23.0,24.0,25.0,26.0,27.0,28.0,29.0,30.0,31.0,32.0, 33.0,34.0,35.0}; static double dttab[173]={13.7,13.4,13.1,12.9,12.7,12.6,12.5,12.5,12.5,12.5, 12.5,12.5,12.5,12.5,12.5,12.5,12.5,12.4,12.3,12.2,12.0,11.7,11.4, 11.1,10.6,10.2, 9.6, 9.1, 8.6, 8.0, 7.5, 7.0, 6.6, 6.3, 6.0, 5.8, 5.7, 5.6, 5.6, 5.6, 5.7, 5.8, 5.9, 6.1, 6.2, 6.3, 6.5, 6.6, 6.8, 6.9, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.7, 7.8, 7.8,7.88,7.82, 7.54, 6.97, 6.40, 6.02, 5.41, 4.10, 2.92, 1.82, 1.61, 0.10,-1.02, -1.28,-2.69,-3.24,-3.64,-4.54,-4.71,-5.11,-5.40,-5.42,-5.20,-5.46, -5.46,-5.79,-5.63,-5.64,-5.80,-5.66,-5.87,-6.01,-6.19,-6.64,-6.44, -6.47,-6.09,-5.76,-4.66,-3.74,-2.72,-1.54,-0.02, 1.24, 2.64, 3.86, 5.37, 6.14, 7.75, 9.13,10.46,11.53,13.36,14.65,16.01,17.20,18.24, 19.06,20.25,20.95,21.16,22.25,22.41,23.03,23.49,23.62,23.86,24.49, 24.34,24.08,24.02,24.00,23.87,23.95,23.86,23.93,23.73,23.92,23.96, 24.02,24.33,24.83,25.30,25.70,26.24,26.77,27.28,27.78,28.25,28.71, 29.15,29.57,29.97,30.36,30.72,31.07,31.35,31.68,32.18,32.68,33.15, 33.59,34.00,34.47,35.03,35.73,36.54,37.43,38.29,39.20,40.18,41.17, 42.23}; /* TAI2FD-- convert from TAI in FITS format to UT in FITS format */ char * tai2fd (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double dj0, dj, tsec, dt; dj0 = fd2jd (string); dt = utdt (dj0); dj = dj0 - (dt / 86400.0); dt = utdt (dj); tsec = fd2ts (string); tsec = tsec - dt + 32.184; return (ts2fd (tsec)); } /* FD2TAI-- convert from UT in FITS format to TAI in FITS format */ char * fd2tai (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double dj, tsec, dt; dj = fd2jd (string); dt = utdt (dj); tsec = fd2ts (string); tsec = tsec + dt - 32.184; return (ts2fd (tsec)); } /* DT2TAI-- convert from UT as yyyy.mmdd hh.mmssss to TAI in same format */ void dt2tai (date, time) double *date; /* Date as yyyy.mmdd */ double *time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { double dj, dt, tsec; dj = dt2jd (*date, *time); dt = utdt (dj); tsec = dt2ts (*date, *time); tsec = tsec + dt - 32.184; ts2dt (tsec, date, time); return; } /* TAI2DT-- convert from TAI as yyyy.mmdd hh.mmssss to UT in same format */ void tai2dt (date, time) double *date; /* Date as yyyy.mmdd */ double *time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { double dj, dt, tsec, tsec0; dj = dt2jd (*date, *time); dt = utdt (dj); tsec0 = dt2ts (*date, *time); tsec = tsec0 + dt; dj = ts2jd (tsec); dt = utdt (dj); tsec = tsec0 + dt + 32.184; ts2dt (tsec, date, time); return; } /* ET2FD-- convert from ET (or TDT or TT) in FITS format to UT in FITS format */ char * et2fd (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double dj0, dj, tsec, dt; dj0 = fd2jd (string); dt = utdt (dj0); dj = dj0 - (dt / 86400.0); dt = utdt (dj); tsec = fd2ts (string); tsec = tsec - dt; return (ts2fd (tsec)); } /* FD2ET-- convert from UT in FITS format to ET (or TDT or TT) in FITS format */ char * fd2et (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double dj, tsec, dt; dj = fd2jd (string); dt = utdt (dj); tsec = fd2ts (string); tsec = tsec + dt; return (ts2fd (tsec)); } /* DT2ET-- convert from UT as yyyy.mmdd hh.mmssss to ET in same format */ void dt2et (date, time) double *date; /* Date as yyyy.mmdd */ double *time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { double dj, dt, tsec; dj = dt2jd (*date, *time); dt = utdt (dj); tsec = dt2ts (*date, *time); tsec = tsec + dt; ts2dt (tsec, date, time); return; } /* EDT2DT-- convert from ET as yyyy.mmdd hh.mmssss to UT in same format */ void edt2dt (date, time) double *date; /* Date as yyyy.mmdd */ double *time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { double dj, dt, tsec, tsec0; dj = dt2jd (*date, *time); dt = utdt (dj); tsec0 = dt2ts (*date, *time); tsec = tsec0 + dt; dj = ts2jd (tsec); dt = utdt (dj); tsec = tsec0 + dt; ts2dt (tsec, date, time); return; } /* JD2JED-- convert from Julian Date to Julian Ephemeris Date */ double jd2jed (dj) double dj; /* Julian Date */ { double dt; dt = utdt (dj); return (dj + (dt / 86400.0)); } /* JED2JD-- convert from Julian Ephemeris Date to Julian Date */ double jed2jd (dj) double dj; /* Julian Ephemeris Date */ { double dj0, dt; dj0 = dj; dt = utdt (dj); dj = dj0 - (dt / 86400.0); dt = utdt (dj); return (dj - (dt / 86400.0)); } /* TS2ETS-- convert from UT in seconds since 1950-01-01 to ET in same format */ double ts2ets (tsec) double tsec; { double dj, dt; dj = ts2jd (tsec); dt = utdt (dj); return (tsec + dt); } /* ETS2TS-- convert from ET in seconds since 1950-01-01 to UT in same format */ double ets2ts (tsec) double tsec; { double dj, dj0, dt; dj0 = ts2jd (tsec); dt = utdt (dj0); dj = dj0 - (dt / 86400.0); dt = utdt (dj); return (tsec - dt); } /* UTDT-- Compute difference between UT and dynamical time (ET-UT) */ double utdt (dj) double dj; /* Julian Date (UT) */ { double dt, date, time, ts, ts1, ts0, date0, yfrac, diff, cj; int i, iyr, iyear; /* If after 1972-01-01, use tabulated TAI-UT */ if (dj >= 2441317.5) { dt = 0.0; for (i = 22; i > 0; i--) { if (dj >= taijd[i]) dt = taidt[i]; } dt = dt + 32.184; } /* For 1800-01-01 to 1972-01-01, use table of ET-UT from AE */ else if (dj >= 2378496.5) { jd2dt (dj, &date, &time); ts = jd2ts (dj); iyear = (int) date; iyr = iyear - 1800; date0 = (double) iyear + 0.0101; ts0 = dt2ts (date0, 0.0); date0 = (double) (iyear + 1) + 0.0101; ts1 = dt2ts (date0, 0.0); yfrac = (ts - ts0) / (ts1 - ts0); diff = dttab[iyr+1] - dttab[iyr]; dt = dttab[iyr] + (diff * yfrac); } /* Compute back to 1600 using formula from McCarthy and Babcock (1986) */ else if (dj >= 2305447.5) { cj = (dj - 2378496.5) / 36525.0; dt = 5.156 + 13.3066 * (cj - 0.19) * (cj - 0.19); } /* Compute back to 948 using formula from Stephenson and Morrison (1984) */ else if (dj >= 2067309.5) { cj = (dj - 2378496.5) / 36525.0; dt = 25.5 * cj * cj; } /*Compute back to 390 BC using formula from Stephenson and Morrison (1984)*/ else if (dj >= 0.0) { cj = (dj = 2378496.5) / 36525.0; dt = 1360.0 + (320.0 * cj) + (44.3 * cj * cj); } else dt = 0.0; return (dt); } /* FD2OFD-- convert any FITS standard date to old FITS standard date */ char * fd2ofd (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { int iyr,imon,iday,ihr,imn; double sec; fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 3); /* Convert to old FITS date format */ string = (char *) calloc (32, sizeof (char)); if (iyr < 1900) sprintf (string, "*** date out of range ***"); else if (iyr < 2000) sprintf (string, "%02d/%02d/%02d", iday, imon, iyr-1900); else if (iyr < 2900.0) sprintf (string, "%02d/%02d/%3d", iday, imon, iyr-1900); else sprintf (string, "*** date out of range ***"); return (string); } /* FD2OFT-- convert any FITS standard date to old FITS standard time */ char * fd2oft (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { int iyr,imon,iday,ihr,imn; double sec; fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 3); /* Convert to old FITS date format */ string = (char *) calloc (32, sizeof (char)); sprintf (string, "%02d:%02d:%06.3f", ihr, imn, sec); return (string); } /* FD2DT-- convert FITS standard date to date, time as yyyy.mmdd hh.mmsss */ void fd2dt (string, date, time) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ double *date; /* Date as yyyy.mmdd (returned) yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double *time; /* Time as hh.mmssxxxx (returned) *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { int iyr,imon,iday,ihr,imn; double sec; fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 4); /* Convert date to yyyy.mmdd */ if (iyr < 0) { *date = (double) (-iyr) + 0.01 * (double) imon + 0.0001 * (double) iday; *date = -(*date); } else *date = (double) iyr + 0.01 * (double) imon + 0.0001 * (double) iday; /* Convert time to hh.mmssssss */ *time = (double) ihr + 0.01 * (double) imn + 0.0001 * sec; return; } /* FD2EP-- convert from FITS standard date to fractional year */ double fd2ep (string) char *string; /* FITS date string, which may be: yyyy.ffff (fractional year) dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard FITS use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double dj; /* Julian date */ dj = fd2jd (string); if (dj < 1.0) return (dj / 365.2422); else return (jd2ep (dj)); } /* FD2EPB-- convert from FITS standard date to Besselian epoch */ double fd2epb (string) char *string; /* FITS date string, which may be: yyyy.ffff (fractional year) dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard FITS use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double dj; /* Julian date */ dj = fd2jd (string); if (dj < 1.0) return (dj / 365.242198781); else return (jd2epb (dj)); } /* FD2EPJ-- convert from FITS standard date to Julian epoch */ double fd2epj (string) char *string; /* FITS date string, which may be: yyyy.ffff (fractional year) dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard FITS use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double dj; /* Julian date */ dj = fd2jd (string); if (dj < 1.0) return (dj / 365.25); else return (jd2epj (dj)); } /* DT2TSU-- convert from date and time to Unix seconds since 1970-01-01T0:00 */ time_t dt2tsu (date,time) double date; /* Date as yyyy.mmdd */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { return ((time_t)(dt2ts (date, time) - 631152000.0)); } /* DT2TSI-- convert from date and time to IRAF seconds since 1980-01-01T0:00 */ int dt2tsi (date,time) double date; /* Date as yyyy.mmdd */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { return ((int)(dt2ts (date, time) - 946684800.0)); } /* DT2TS-- convert from date, time as yyyy.mmdd hh.mmsss to sec since 1950.0 */ double dt2ts (date,time) double date; /* Date as yyyy.mmdd yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double tsec; /* Seconds past 1950.0 (returned) */ double dh,dm,dd; int iy,im,id; /* Calculate the number of full years, months, and days already * elapsed since 0h, March 1, -1 (up to most recent midnight). */ /* convert time of day to elapsed seconds */ /* If time is < 0, it is assumed to be a fractional day */ if (time < 0.0) tsec = time * -86400.0; else { dh = (int) (time + 0.0000000001); dm = (int) (((time - dh) * 100.0) + 0.0000000001); tsec = (time * 10000.0) - (dh * 10000.0) - (dm * 100.0); tsec = (int) (tsec * 100000.0 + 0.0001) / 100000.0; tsec = tsec + (dm * 60.0) + (dh * 3600.0); } /* Calculate the number of full months elapsed since * the current or most recent March */ if (date >= 0.0301) { iy = (int) (date + 0.0000000001); im = (int) (((date - (double) (iy)) * 10000.0) + 0.00000001); id = im % 100; im = (im / 100) + 9; if (im < 12) iy = iy - 1; im = im % 12; id = id - 1; /* starting with March as month 0 and ending with the following * February as month 11, the calculation of the number of days * per month reduces to a simple formula. the following statement * determines the number of whole days elapsed since 3/1/-1 and then * subtracts the 712163 days between then and 1/1/1950. it converts * the result to seconds and adds the accumulated seconds above. */ id = id + ((im+1+im/6+im/11)/2 * 31) + ((im-im/6-im/11)/2 * 30) + (iy / 4) - (iy / 100) + (iy / 400); dd = (double) id + (365.0 * (double) iy) - 712163.0; tsec = tsec + (dd * 86400.0); } return (tsec); } /* TS2DT-- convert seconds since 1950.0 to date, time as yyyy.mmdd hh.mmssss */ void ts2dt (tsec,date,time) double tsec; /* Seconds past 1950.0 */ double *date; /* Date as yyyy.mmdd (returned) yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double *time; /* Time as hh.mmssxxxx (returned) *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { int iyr,imon,iday,ihr,imn; double sec; ts2i (tsec,&iyr,&imon,&iday,&ihr,&imn,&sec, 4); /* Convert date to yyyy.mmdd */ if (iyr < 0) { *date = (double) (-iyr) + 0.01 * (double) imon + 0.0001 * (double) iday; *date = -(*date); } else *date = (double) iyr + 0.01 * (double) imon + 0.0001 * (double) iday; /* Convert time to hh.mmssssss */ *time = (double) ihr + 0.01 * (double) imn + 0.0001 * sec; return; } /* TSI2DT-- Convert seconds since 1980-01-01 to date yyyy.ddmm, time hh.mmsss */ void tsi2dt (isec,date,time) int isec; /* Seconds past 1980-01-01 */ double *date; /* Date as yyyy.mmdd (returned) */ double *time; /* Time as hh.mmssxxxx (returned) */ { ts2dt (tsi2ts (isec), date, time); } /* TSI2FD-- Convert seconds since 1980-01-01 to FITS standard date string */ char * tsi2fd (isec) int isec; /* Seconds past 1980-01-01 */ { return (ts2fd (tsi2ts (isec))); } /* TSI2TS-- Convert seconds since 1980-01-01 to seconds since 1950-01-01 */ double tsi2ts (isec) int isec; /* Seconds past 1980-01-01 */ { return ((double) isec + 946684800.0); } /* TSU2FD-- Convert seconds since 1970-01-01 to FITS standard date string */ char * tsu2fd (isec) time_t isec; /* Seconds past 1970-01-01 */ { return (ts2fd (tsu2ts (isec))); } /* TSU2DT-- Convert seconds since 1970-01-01 to date yyyy.ddmm, time hh.mmsss */ void tsu2dt (isec,date,time) time_t isec; /* Seconds past 1970-01-01 */ double *date; /* Date as yyyy.mmdd (returned) */ double *time; /* Time as hh.mmssxxxx (returned) */ { ts2dt (tsu2ts (isec), date, time); } /* TSU2TS-- Convert seconds since 1970-01-01 to seconds since 1950-01-01 */ double tsu2ts (isec) time_t isec; /* Seconds past 1970-01-01 */ { return ((double) isec + 631152000.0); } /* TSU2TSI-- UT seconds since 1970-01-01 to local seconds since 1980-01-01 */ int tsu2tsi (isec) time_t isec; /* Seconds past 1970-01-01 */ { double date, time; struct tm *ts; /* Get local time from UT seconds */ ts = localtime (&isec); if (ts->tm_year < 1000) date = (double) (ts->tm_year + 1900); else date = (double) ts->tm_year; date = date + (0.01 * (double) (ts->tm_mon + 1)); date = date + (0.0001 * (double) ts->tm_mday); time = (double) ts->tm_hour; time = time + (0.01 * (double) ts->tm_min); time = time + (0.0001 * (double) ts->tm_sec); return ((int)(dt2ts (date, time) - 631152000.0)); } /* TS2FD-- convert seconds since 1950.0 to FITS date, yyyy-mm-ddThh:mm:ss.ss */ char * ts2fd (tsec) double tsec; /* Seconds past 1950.0 */ { double date, time; ts2dt (tsec, &date, &time); return (dt2fd (date, time)); } /* TSD2FD-- convert seconds since start of day to FITS time, hh:mm:ss.ss */ char * tsd2fd (tsec) double tsec; /* Seconds since start of day */ { double date, time; char *thms, *fdate; int lfd, nbc; ts2dt (tsec, &date, &time); fdate = dt2fd (date, time); thms = (char *) calloc (16, 1); lfd = strlen (fdate); nbc = lfd - 11; strncpy (thms, fdate+11, nbc); return (thms); } /* TSD2DT-- convert seconds since start of day to hh.mmssss */ double tsd2dt (tsec) double tsec; /* Seconds since start of day */ { double date, time; ts2dt (tsec, &date, &time); return (time); } /* DT2I-- convert vigesimal date and time to year month day hours min sec */ void dt2i (date, time, iyr, imon, iday, ihr, imn, sec, ndsec) double date; /* Date as yyyy.mmdd (returned) yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx (returned) *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double t,d; t = time; if (date < 0.0) d = -date; else d = date; /* Extract components of time */ *ihr = dint (t + 0.000000001); t = 100.0 * (t - (double) *ihr); *imn = dint (t + 0.0000001); *sec = 100.0 * (t - (double) *imn); /* Extract components of date */ *iyr = dint (d + 0.00001); d = 100.0 * (d - (double) *iyr); if (date < 0.0) *iyr = - *iyr; *imon = dint (d + 0.001); d = 100.0 * (d - (double) *imon); *iday = dint (d + 0.1); /* Make sure date and time are legal */ fixdate (iyr, imon, iday, ihr, imn, sec, ndsec); return; } /* FD2I-- convert from FITS standard date to year, mon, day, hours, min, sec */ void fd2i (string, iyr, imon, iday, ihr, imn, sec, ndsec) char *string; /* FITS date string, which may be: yyyy.ffff (fractional year) dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard FITS use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double tsec, fday, hr, mn; int i; char *sstr, *dstr, *tstr, *cstr, *nval, *fstr; /* Initialize all returned data to zero */ *iyr = 0; *imon = 0; *iday = 0; *ihr = 0; *imn = 0; *sec = 0.0; /* Return if no input string */ if (string == NULL) return; /* Check for various non-numeric characters */ sstr = strchr (string,'/'); dstr = strchr (string,'-'); if (dstr == string) dstr = strchr (string+1, '-'); fstr = strchr (string, '.'); tstr = strchr (string,'T'); if (tstr == NULL) tstr = strchr (string, 'Z'); if (tstr == NULL) tstr = strchr (string, 'S'); if (fstr != NULL && tstr != NULL && fstr > tstr) fstr = NULL; cstr = strchr (string,':'); /* Original FITS date format: dd/mm/yy */ if (sstr > string) { *sstr = '\0'; *iday = (int) atof (string); if (*iday > 31) { *iyr = *iday; if (*iyr >= 0 && *iyr <= 49) *iyr = *iyr + 2000; else if (*iyr < 1000) *iyr = *iyr + 1900; *sstr = '/'; nval = sstr + 1; sstr = strchr (nval,'/'); if (sstr > string) { *sstr = '\0'; *imon = (int) atof (nval); *sstr = '/'; nval = sstr + 1; *iday = (int) atof (nval); } } else { *sstr = '/'; nval = sstr + 1; sstr = strchr (nval,'/'); if (sstr == NULL) sstr = strchr (nval,'-'); if (sstr > string) { *sstr = '\0'; *imon = (int) atof (nval); *sstr = '/'; nval = sstr + 1; *iyr = (int) atof (nval); if (*iyr >= 0 && *iyr <= 49) *iyr = *iyr + 2000; else if (*iyr < 1000) *iyr = *iyr + 1900; } } tstr = strchr (string,'_'); if (tstr == NULL) return; } /* New FITS date format: yyyy-mm-ddThh:mm:ss[.sss] */ else if (dstr > string) { *dstr = '\0'; *iyr = (int) atof (string); *dstr = '-'; nval = dstr + 1; dstr = strchr (nval,'-'); *imon = 1; *iday = 1; /* Decode year, month, and day */ if (dstr > string) { *dstr = '\0'; *imon = (int) atof (nval); *dstr = '-'; nval = dstr + 1; if (tstr > string) *tstr = '\0'; *iday = (int) atof (nval); /* If fraction of a day is present, turn it into a time */ if (fstr != NULL) { fday = atof (fstr); hr = fday * 24.0; *ihr = (int) hr; mn = 60.0 * (hr - (double) *ihr); *imn = (int) mn; *sec = 60.0 * (mn - (double) *imn); } if (tstr > string) *tstr = 'T'; } /* If date is > 31, it is really year in old format */ if (*iday > 31) { i = *iyr; if (*iday < 100) *iyr = *iday + 1900; else *iyr = *iday; *iday = i; } } /* In rare cases, a FITS time is entered as an epoch */ else if (tstr == NULL && cstr == NULL && isnum (string)) { tsec = ep2ts (atof (string)); ts2i (tsec,iyr,imon,iday,ihr,imn,sec, ndsec); return; } /* Extract time, if it is present */ if (tstr > string || cstr > string) { if (tstr > string) nval = tstr + 1; else nval = string; cstr = strchr (nval,':'); if (cstr > string) { *cstr = '\0'; *ihr = (int) atof (nval); *cstr = ':'; nval = cstr + 1; cstr = strchr (nval,':'); if (cstr > string) { *cstr = '\0'; *imn = (int) atof (nval); *cstr = ':'; nval = cstr + 1; *sec = atof (nval); } else *imn = (int) atof (nval); } else *ihr = (int) atof (nval); } else ndsec = -1; /* Make sure date and time are legal */ fixdate (iyr, imon, iday, ihr, imn, sec, ndsec); return; } /* TS2I-- convert sec since 1950.0 to year month day hours minutes seconds */ void ts2i (tsec,iyr,imon,iday,ihr,imn,sec, ndsec) double tsec; /* seconds since 1/1/1950 0:00 */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double t,days, ts, dts; int nc,nc4,nly,ny,m,im; /* Round seconds to 0 - 4 decimal places */ ts = tsec + 61530883200.0; if (ts < 0.0) dts = -0.5; else dts = 0.5; if (ndsec < 1) t = dint (ts + dts) * 10000.0; else if (ndsec < 2) t = dint (ts * 10.0 + dts) * 1000.0; else if (ndsec < 3) t = dint (ts * 100.0 + dts) * 100.0; else if (ndsec < 4) t = dint (ts * 1000.0 + dts) * 10.0; else t = dint (ts * 10000.0 + dts); ts = t / 10000.0; /* Time of day (hours, minutes, seconds */ *ihr = (int) (dmod (ts/3600.0, 24.0)); *imn = (int) (dmod (ts/60.0, 60.0)); *sec = dmod (ts, 60.0); /* Number of days since 0 hr 0/0/0000 */ days = dint ((t / 864000000.0) + 0.000001); /* Number of leap centuries (400 years) */ nc4 = (int) ((days / 146097.0) + 0.00001); /* Number of centuries since last /400 */ days = days - (146097.0 * (double) (nc4)); nc = (int) ((days / 36524.0) + 0.000001); if (nc > 3) nc = 3; /* Number of leap years since last century */ days = days - (36524.0 * nc); nly = (int) ((days / 1461.0) + 0.0000000001); /* Number of years since last leap year */ days = days - (1461.0 * (double) nly); ny = (int) ((days / 365.0) + 0.00000001); if (ny > 3) ny = 3; /* Day of month */ days = days - (365.0 * (double) ny); if (days < 0) { m = 0; *iday = 29; } else { *iday = (int) (days + 0.00000001) + 1; for (m = 1; m <= 12; m++) { im = (m + ((m - 1) / 5)) % 2; /* fprintf (stderr,"%d %d %d %d\n", m, im, *iday, nc); */ if (*iday-1 < im+30) break; *iday = *iday - im - 30; } } /* Month */ *imon = ((m+1) % 12) + 1; /* Year */ *iyr = nc4*400 + nc*100 + nly*4 + ny + m/11; /* Make sure date and time are legal */ fixdate (iyr, imon, iday, ihr, imn, sec, ndsec); return; } /* UT2DOY-- Current Universal Time as year, day of year */ void ut2doy (year, doy) int *year; /* Year (returned) */ double *doy; /* Day of year (returned) */ { double date, time; ut2dt (&date, &time); dt2doy (date, time, year, doy); return; } /* UT2DT-- Current Universal Time as date (yyyy.mmdd) and time (hh.mmsss) */ void ut2dt(date, time) double *date; /* Date as yyyy.mmdd (returned) */ double *time; /* Time as hh.mmssxxxx (returned) */ { time_t tsec; struct timeval tp; struct timezone tzp; struct tm *ts; gettimeofday (&tp,&tzp); tsec = tp.tv_sec; ts = gmtime (&tsec); if (ts->tm_year < 1000) *date = (double) (ts->tm_year + 1900); else *date = (double) ts->tm_year; *date = *date + (0.01 * (double) (ts->tm_mon + 1)); *date = *date + (0.0001 * (double) ts->tm_mday); *time = (double) ts->tm_hour; *time = *time + (0.01 * (double) ts->tm_min); *time = *time + (0.0001 * (double) ts->tm_sec); return; } /* UT2EP-- Return current Universal Time as fractional year */ double ut2ep() { return (jd2ep (ut2jd())); } /* UT2EPB-- Return current Universal Time as Besselian epoch */ double ut2epb() { return (jd2epb (ut2jd())); } /* UT2EPJ-- Return current Universal Time as Julian epoch */ double ut2epj() { return (jd2epj (ut2jd())); } /* UT2FD-- Return current Universal Time as FITS ISO date string */ char * ut2fd() { int year, month, day, hour, minute, second; time_t tsec; struct timeval tp; struct timezone tzp; struct tm *ts; char *isotime; gettimeofday (&tp,&tzp); tsec = tp.tv_sec; ts = gmtime (&tsec); year = ts->tm_year; if (year < 1000) year = year + 1900; month = ts->tm_mon + 1; day = ts->tm_mday; hour = ts->tm_hour; minute = ts->tm_min; second = ts->tm_sec; isotime = (char *) calloc (32, sizeof (char)); sprintf (isotime, "%04d-%02d-%02dT%02d:%02d:%02d", year, month, day, hour, minute, second); return (isotime); } /* UT2JD-- Return current Universal Time as Julian Date */ double ut2jd() { return (fd2jd (ut2fd())); } /* UT2MJD-- convert current UT to Modified Julian Date */ double ut2mjd () { return (ut2jd() - 2400000.5); } /* UT2TS-- current Universal Time as IRAF seconds since 1950-01-01T00:00 */ double ut2ts() { double tsec; char *datestring; datestring = ut2fd(); tsec = fd2ts (datestring); free (datestring); return (tsec); } /* UT2TSI-- current Universal Time as IRAF seconds since 1980-01-01T00:00 */ int ut2tsi() { return ((int)(ut2ts() - 946684800.0)); } /* UT2TSU-- current Universal Time as IRAF seconds since 1970-01-01T00:00 */ time_t ut2tsu() { return ((time_t)(ut2ts () - 631152000.0)); } /* FD2GST-- convert from FITS date to Greenwich Sidereal Time */ char * fd2gst (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double dj, gsec, date, time; dj = fd2jd (string); gsec = jd2gst (dj); ts2dt (gsec, &date, &time); date = 0.0; return (dt2fd (date, time)); } /* DT2GST-- convert from UT as yyyy.mmdd hh.mmssss to Greenwich Sidereal Time*/ void dt2gst (date, time) double *date; /* Date as yyyy.mmdd */ double *time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { double dj, gsec; dj = dt2ts (*date, *time); gsec = jd2gst (dj); ts2dt (gsec, date, time); *date = 0.0; return; } /* JD2LST - Local Sidereal Time in seconds from Julian Date */ double jd2lst (dj) double dj; /* Julian Date */ { double gst, lst; /* Compute Greenwich Sidereal Time at this epoch */ gst = jd2gst (dj); /* Subtract longitude (degrees to seconds of time) */ lst = gst - (240.0 * longitude); if (lst < 0.0) lst = lst + 86400.0; else if (lst > 86400.0) lst = lst - 86400.0; return (lst); } /* FD2LST - Local Sidereal Time as hh:mm:ss.ss from Universal Time as FITS ISO date */ char * fd2lst (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) */ { double dj, date, time, lst; dj = fd2jd (string); lst = jd2lst (dj); ts2dt (lst, &date, &time); date = 0.0; return (dt2fd (date, time)); } /* DT2LST - Local Sidereal Time as hh.mmssss from Universal Time as yyyy.mmdd hh.mmssss */ void dt2lst (date, time) double *date; /* Date as yyyy.mmdd */ double *time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { double dj, lst, date0; dj = dt2jd (*date, *time); lst = jd2lst (dj); date0 = 0.0; ts2dt (lst, &date0, time); return; } /* TS2LST - Local Sidereal Time in seconds of day * from Universal Time in seconds since 1951-01-01T0:00:00 */ double ts2lst (tsec) double tsec; /* time since 1950.0 in UT seconds */ { double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ double lst; /* Local Sidereal Time in seconds since 0:00 */ double gsec, date; /* Greenwich Sidereal Time */ gsec = ts2gst (tsec); date = 0.0; ts2dt (gsec, &date, &gst); lst = gst - (longitude / 15.0); if (lst < 0.0) lst = lst + 86400.0; else if (lst > 86400.0) lst = lst - 86400.0; return (lst); } /* LST2FD - calculate current UT given Local Sidereal Time * plus date in FITS ISO format (yyyy-mm-dd) * Return UT date and time in FITS ISO format */ char * lst2fd (string) char *string; /* UT Date, LST as yyyy-mm-ddShh:mm:ss.ss */ { double sdj, dj; sdj = fd2jd (string); dj = lst2jd (sdj); return (jd2fd (dj)); } /* LST2JD - calculate current Julian Date given Local Sidereal Time * plus current Julian Date (0.5 at 0:00 UT) * Return UT date and time as Julian Date */ double lst2jd (sdj) double sdj; /* Julian Date of desired day at 0:00 UT + sidereal time */ { double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ double lsd; /* Local Sidereal Time in seconds since 0:00 */ double gst0, tsd, dj1, dj0, eqnx; int idj; /* Julian date at 0:00 UT */ idj = (int) sdj; dj0 = (double) idj + 0.5; if (dj0 > sdj) dj0 = dj0 - 1.0; /* Greenwich Sidereal Time at 0:00 UT in seconds */ gst0 = jd2gst (dj0); /* Sidereal seconds since 0:00 */ lsd = (sdj - dj0) * 86400.0; /* Remove longitude for current Greenwich Sidereal Time in seconds */ /* (convert longitude from degrees to seconds of time) */ gst = lsd + (longitude * 240.0); /* Time since 0:00 UT */ tsd = (gst - gst0) / 1.0027379093; /* Julian Date (UT) */ dj1 = dj0 + (tsd / 86400.0); /* Equation of the equinoxes converted to UT seconds */ eqnx = eqeqnx (dj1) / 1.002739093; /* Remove equation of equinoxes */ dj1 = dj1 - (eqnx / 86400.0); if (dj1 < dj0) dj1 = dj1 + 1.0; return (dj1); } /* MST2FD - calculate current UT given Greenwich Mean Sidereal Time * plus date in FITS ISO format (yyyy-mm-ddShh:mm:ss.ss) * Return UT date and time in FITS ISO format */ char * mst2fd (string) char *string; /* UT Date, MST as yyyy-mm-ddShh:mm:ss.ss */ { double sdj, dj; sdj = fd2jd (string); dj = mst2jd (sdj); return (jd2fd (dj)); } /* MST2JD - calculate current UT given Greenwich Mean Sidereal Time * plus date in Julian Date (0:00 UT + Mean Sidereal Time) * Return UT date and time as Julian Date */ double mst2jd (sdj) double sdj; /* UT Date, MST as Julian Date */ { double tsd, djd, st0, dj0, dj; dj0 = (double) ((int) sdj) + 0.5; /* Greenwich Mean Sidereal Time at 0:00 UT in seconds */ st0 = jd2mst (dj0); /* Mean Sidereal Time in seconds */ tsd = (sdj - dj0) * 86400.0; if (tsd < 0.0) tsd = tsd + 86400.0; /* Convert to fraction of a day since 0:00 UT */ djd = ((tsd - st0) / 1.0027379093) / 86400.0; /* Julian Date */ dj = dj0 + djd; if (dj < dj0) dj = dj + (1.0 / 1.0027379093); return (dj); } /* GST2FD - calculate current UT given Greenwich Sidereal Time * plus date in FITS ISO format (yyyy-mm-ddShh:mm:ss.ss) * Return UT date and time in FITS ISO format */ char * gst2fd (string) char *string; /* UT Date, GST as yyyy-mm-ddShh:mm:ss.ss */ { double sdj, dj; sdj = fd2jd (string); dj = gst2jd (sdj); return (jd2fd (dj)); } /* GST2JD - calculate current UT given Greenwich Sidereal Time * plus date as Julian Date (JD at 0:00 UT + sidereal time) * Return UT date and time as Julian Date */ double gst2jd (sdj) double sdj; /* UT Date, GST as Julian Date */ { double dj, tsd, djd, st0, dj0, eqnx; dj0 = (double) ((int) sdj) + 0.5; /* Greenwich Mean Sidereal Time at 0:00 UT in seconds */ st0 = jd2mst (dj0); /* Mean Sidereal Time in seconds */ tsd = (sdj - dj0) * 86400.0; if (tsd < 0.0) tsd = tsd + 86400.0; /* Convert to fraction of a day since 0:00 UT */ djd = ((tsd - st0) / 1.0027379093) / 86400.0; /* Julian Date */ dj = dj0 + djd; /* Equation of the equinoxes (converted to UT seconds) */ eqnx = eqeqnx (dj) / 1.002737909; dj = dj - eqnx / 86400.0; if (dj < dj0) dj = dj + 1.0; return (dj); } /* LST2DT - calculate current UT given Local Sidereal Time as hh.mmsss * plus date as yyyy.mmdd * Return UT time as hh.mmssss */ double lst2dt (date0, time0) double date0; /* UT date as yyyy.mmdd */ double time0; /* LST as hh.mmssss */ { double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ double lst; /* Local Sidereal Time in seconds since 0:00 */ double date1; /* UT date as yyyy.mmdd */ double time1; /* UT as hh.mmssss */ double tsec0, gst0, tsd, tsec; /* Greenwich Sidereal Time at 0:00 UT */ tsec0 = dt2ts (date0, 0.0); gst0 = ts2gst (tsec0); /* Current Greenwich Sidereal Time in seconds */ /* (convert longitude from degrees to seconds of time) */ lst = dt2ts (0.0, time0); gst = lst + (longitude * 240.0); /* Time since 0:00 UT */ tsd = (gst - gst0) / 1.0027379093; /* UT date and time */ tsec = tsec0 + tsd; ts2dt (tsec, &date1, &time1); return (time1); } /* TS2GST - calculate Greenwich Sidereal Time given Universal Time * in seconds since 1951-01-01T0:00:00 * Return sidereal time of day in seconds */ double ts2gst (tsec) double tsec; /* time since 1950.0 in UT seconds */ { double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ double tsd, eqnx, dj; int its; /* Elapsed time as of 0:00 UT */ if (tsec >= 0.0) { its = (int) (tsec + 0.5); tsd = (double) (its % 86400); } else { its = (int) (-tsec + 0.5); tsd = (double) (86400 - (its % 86400)); } /* Mean sidereal time */ gst = ts2mst (tsec); /* Equation of the equinoxes */ dj = ts2jd (tsec); eqnx = eqeqnx (dj); /* Apparent sidereal time at 0:00 ut */ gst = gst + eqnx; /* Current sidereal time */ gst = gst + (tsd * 1.0027379093); gst = dmod (gst,86400.0); return (gst); } /* FD2MST-- convert from FITS date Mean Sidereal Time */ char * fd2mst (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double gsec, date, time, dj; dj = fd2jd (string); gsec = jd2mst (dj); ts2dt (gsec, &date, &time); date = 0.0; return (dt2fd (date, time)); } /* DT2MST-- convert from UT as yyyy.mmdd hh.mmssss to Mean Sidereal Time in the same format */ void dt2mst (date, time) double *date; /* Date as yyyy.mmdd */ double *time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { double date0, gsec, dj; date0 = *date; dj = dt2jd (*date, *time); gsec = jd2mst (dj); ts2dt (gsec, date, time); *date = date0; return; } /* TS2MST - calculate Greenwich Mean Sidereal Time given Universal Time * in seconds since 1951-01-01T0:00:00 */ double ts2mst (tsec) double tsec; /* time since 1950.0 in UT seconds */ { double dj; dj = ts2jd (tsec); return (jd2mst (dj)); } /* JD2MST - Julian Date to Greenwich Mean Sidereal Time using IAU 2000 * Return sideral time in seconds of time * (from USNO NOVAS package * http://aa.usno.navy.mil/software/novas/novas_info.html */ double jd2mst2 (dj) double dj; /* Julian Date */ { double dt, t, t2, t3, mst, st; dt = dj - 2451545.0; t = dt / 36525.0; t2 = t * t; t3 = t2 * t; /* Compute Greenwich Mean Sidereal Time in seconds */ st = (8640184.812866 * t) + (3155760000.0 * t) - (0.0000062 * t3) + (0.093104 * t2) + 67310.54841; mst = dmod (st, 86400.0); if (mst < 0.0) mst = mst + 86400.0; return (mst); } /* MJD2MST - Modified Julian Date to Greenwich Mean Sidereal Time using IAU 2000 * Return sideral time in seconds of time * (from USNO NOVAS package * http://aa.usno.navy.mil/software/novas/novas_info.html */ double mjd2mst (dj) double dj; /* Modified Julian Date */ { double dt, t, t2, t3, mst, st; dt = dj - 51544.5; t = dt / 36525.0; t2 = t * t; t3 = t2 * t; /* Compute Greenwich Mean Sidereal Time in seconds */ st = (8640184.812866 * t) + (3155760000.0 * t) - (0.0000062 * t3) + (0.093104 * t2) + 67310.54841; mst = dmod (st, 86400.0); if (mst < 0.0) mst = mst + 86400.0; return (mst); } /* JD2GST - Julian Date to Greenwich Sideral Time * Return sideral time in seconds of time * (Jean Meeus, Astronomical Algorithms, Willmann-Bell, 1991, pp 83-84) */ double jd2gst (dj) double dj; /* Julian Date */ { double dj0, gmt, gst, tsd, eqnx, ssd, l0; double ts2ss = 1.00273790935; int ijd; /* Julian date at 0:00 UT */ ijd = (int) dj; dj0 = (double) ijd + 0.5; if (dj0 > dj) dj0 = dj0 - 1.0; /* Greenwich mean sidereal time at 0:00 UT in seconds */ l0 = longitude; longitude = 0.0; gmt = jd2mst (dj0); longitude = l0; /* Equation of the equinoxes */ eqnx = eqeqnx (dj); /* Apparent sidereal time at 0:00 ut */ gst = gmt + eqnx; /* UT seconds since 0:00 */ tsd = (dj - dj0) * 86400.0; ssd = tsd * ts2ss; /* Current sidereal time */ gst = gst + ssd; gst = dmod (gst, 86400.0); return (gst); } /* EQEQNX - Compute equation of the equinoxes for apparent sidereal time */ double eqeqnx (dj) double dj; /* Julian Date */ { double dt, edj, dpsi, deps, obl, eqnx; double rad2tsec = 13750.98708; /* Convert UT to Ephemeris Time (TDB or TT)*/ dt = utdt (dj); edj = dj + dt / 86400.0; /* Nutation and obliquity */ compnut (edj, &dpsi, &deps, &obl); /* Correct obliquity for nutation */ obl = obl + deps; /* Equation of the equinoxes in seconds */ eqnx = (dpsi * cos (obl)) * rad2tsec; return (eqnx); } /* JD2MST - Julian Date to Mean Sideral Time * Return sideral time in seconds of time * (Jean Meeus, Astronomical Algorithms, Willmann-Bell, 1991, pp 83-84) */ double jd2mst (dj) double dj; /* Julian Date */ { double dt, t, mst; dt = dj - 2451545.0; t = dt / 36525.0; /* Compute Greenwich mean sidereal time in degrees (Meeus, page 84) */ mst = 280.46061837 + (360.98564736629 * dt) + (0.000387933 * t * t) - (t * t * t / 38710000.0); /* Keep degrees between 0 and 360 */ while (mst > 360.0) mst = mst - 360.0; while (mst < 0.0) mst = mst + 360.0; /* Convert to time in seconds (3600 / 15) */ mst = mst * 240.0; /* Subtract longitude (degrees to seconds of time) */ mst = mst - (240.0 * longitude); if (mst < 0.0) mst = mst + 86400.0; else if (mst > 86400.0) mst = mst - 86400.0; return (mst); } /* COMPNUT - Compute nutation using the IAU 2000b model */ /* Translated from Pat Wallace's Fortran subroutine iau_nut00b (June 26 2007) into C by Jessica Mink on September 5, 2008 */ #define NLS 77 /* number of terms in the luni-solar nutation model */ void compnut (dj, dpsi, deps, eps0) double dj; /* Julian Date */ double *dpsi; /* Nutation in longitude in radians (returned) */ double *deps; /* Nutation in obliquity in radians (returned) */ double *eps0; /* Mean obliquity in radians (returned) */ /* This routine is translated from the International Astronomical Union's * Fortran SOFA (Standards Of Fundamental Astronomy) software collection. * * notes: * * 1) the nutation components in longitude and obliquity are in radians * and with respect to the equinox and ecliptic of date. the * obliquity at j2000 is assumed to be the lieske et al. (1977) value * of 84381.448 arcsec. (the errors that result from using this * routine with the iau 2006 value of 84381.406 arcsec can be * neglected.) * * the nutation model consists only of luni-solar terms, but includes * also a fixed offset which compensates for certain long-period * planetary terms (note 7). * * 2) this routine is an implementation of the iau 2000b abridged * nutation model formally adopted by the iau general assembly in * 2000. the routine computes the mhb_2000_short luni-solar nutation * series (luzum 2001), but without the associated corrections for * the precession rate adjustments and the offset between the gcrs * and j2000 mean poles. * * 3) the full IAU 2000a (mhb2000) nutation model contains nearly 1400 * terms. the IAU 2000b model (mccarthy & luzum 2003) contains only * 77 terms, plus additional simplifications, yet still delivers * results of 1 mas accuracy at present epochs. this combination of * accuracy and size makes the IAU 2000b abridged nutation model * suitable for most practical applications. * * the routine delivers a pole accurate to 1 mas from 1900 to 2100 * (usually better than 1 mas, very occasionally just outside 1 mas). * the full IAU 2000a model, which is implemented in the routine * iau_nut00a (q.v.), delivers considerably greater accuracy at * current epochs; however, to realize this improved accuracy, * corrections for the essentially unpredictable free-core-nutation * (fcn) must also be included. * * 4) the present routine provides classical nutation. the * mhb_2000_short algorithm, from which it is adapted, deals also * with (i) the offsets between the gcrs and mean poles and (ii) the * adjustments in longitude and obliquity due to the changed * precession rates. these additional functions, namely frame bias * and precession adjustments, are supported by the sofa routines * iau_bi00 and iau_pr00. * * 6) the mhb_2000_short algorithm also provides "total" nutations, * comprising the arithmetic sum of the frame bias, precession * adjustments, and nutation (luni-solar + planetary). these total * nutations can be used in combination with an existing IAU 1976 * precession implementation, such as iau_pmat76, to deliver gcrs-to- * true predictions of mas accuracy at current epochs. however, for * symmetry with the iau_nut00a routine (q.v. for the reasons), the * sofa routines do not generate the "total nutations" directly. * should they be required, they could of course easily be generated * by calling iau_bi00, iau_pr00 and the present routine and adding * the results. * * 7) the IAU 2000b model includes "planetary bias" terms that are fixed * in size but compensate for long-period nutations. the amplitudes * quoted in mccarthy & luzum (2003), namely dpsi = -1.5835 mas and * depsilon = +1.6339 mas, are optimized for the "total nutations" * method described in note 6. the luzum (2001) values used in this * sofa implementation, namely -0.135 mas and +0.388 mas, are * optimized for the "rigorous" method, where frame bias, precession * and nutation are applied separately and in that order. during the * interval 1995-2050, the sofa implementation delivers a maximum * error of 1.001 mas (not including fcn). * * References from original Fortran subroutines: * * Hilton, J. et al., 2006, Celest.Mech.Dyn.Astron. 94, 351 * * Lieske, J.H., Lederle, T., Fricke, W., Morando, B., "Expressions * for the precession quantities based upon the IAU 1976 system of * astronomical constants", Astron.Astrophys. 58, 1-2, 1-16. (1977) * * Luzum, B., private communication, 2001 (Fortran code * mhb_2000_short) * * McCarthy, D.D. & Luzum, B.J., "An abridged model of the * precession-nutation of the celestial pole", Cel.Mech.Dyn.Astron. * 85, 37-49 (2003) * * Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M., * Francou, G., Laskar, J., Astron.Astrophys. 282, 663-683 (1994) * */ { double as2r = 0.000004848136811095359935899141; /* arcseconds to radians */ double dmas2r = as2r / 1000.0; /* milliarcseconds to radians */ double as2pi = 1296000.0; /* arc seconds in a full circle */ double d2pi = 6.283185307179586476925287; /* 2pi */ double u2r = as2r / 10000000.0; /* units of 0.1 microarcsecond to radians */ double dj0 = 2451545.0; /* reference epoch (j2000), jd */ double djc = 36525.0; /* Days per julian century */ /* Miscellaneous */ double t, el, elp, f, d, om, arg, dp, de, sarg, carg; double dpsils, depsls, dpsipl, depspl; int i, j; int nls = NLS; /* number of terms in the luni-solar nutation model */ /* Fixed offset in lieu of planetary terms (radians) */ double dpplan = - 0.135 * dmas2r; double deplan = + 0.388 * dmas2r; /* Tables of argument and term coefficients */ /* Coefficients for fundamental arguments */ /* Luni-solar argument multipliers: */ /* l l' f d om */ static int nals[5*NLS]= {0, 0, 0, 0, 1, 0, 0, 2, -2, 2, 0, 0, 2, 0, 2, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 1, 2, -2, 2, 1, 0, 0, 0, 0, 0, 0, 2, 0, 1, 1, 0, 2, 0, 2, 0, -1, 2, -2, 2, 0, 0, 2, -2, 1, -1, 0, 2, 0, 2, -1, 0, 0, 2, 0, 1, 0, 0, 0, 1, -1, 0, 0, 0, 1, -1, 0, 2, 2, 2, 1, 0, 2, 0, 1, -2, 0, 2, 0, 1, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 0, -2, 2, -2, 2, -2, 0, 0, 2, 0, 2, 0, 2, 0, 2, 1, 0, 2, -2, 2, -1, 0, 2, 0, 1, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 2, 1, 0, 2, 2, -2, 2, 0, 0, -2, 2, 0, 1, 0, 0, -2, 1, 0, -1, 0, 0, 1, -1, 0, 2, 2, 1, 0, 2, 0, 0, 0, 1, 0, 2, 2, 2, -2, 0, 2, 0, 0, 0, 1, 2, 0, 2, 0, 0, 2, 2, 1, 0, -1, 2, 0, 2, 0, 0, 0, 2, 1, 1, 0, 2, -2, 1, 2, 0, 2, -2, 2, -2, 0, 0, 2, 1, 2, 0, 2, 0, 1, 0, -1, 2, -2, 1, 0, 0, 0, -2, 1, -1, -1, 0, 2, 0, 2, 0, 0, -2, 1, 1, 0, 0, 2, 0, 0, 1, 2, -2, 1, 1, -1, 0, 0, 0, -2, 0, 2, 0, 2, 3, 0, 2, 0, 2, 0, -1, 0, 2, 0, 1, -1, 2, 0, 2, 0, 0, 0, 1, 0, -1, -1, 2, 2, 2, -1, 0, 2, 0, 0, 0, -1, 2, 2, 2, -2, 0, 0, 0, 1, 1, 1, 2, 0, 2, 2, 0, 0, 0, 1, -1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 2, 0, 0, -1, 0, 2, -2, 1, 1, 0, 0, 0, 2, -1, 0, 0, 1, 0, 0, 0, 2, 1, 2, -1, 0, 2, 4, 2, -1, 1, 0, 1, 1, 0, -2, 2, -2, 1, 1, 0, 2, 2, 1, -2, 0, 2, 2, 2, -1, 0, 0, 0, 2, 1, 1, 2, -2, 2}; /* Luni-solar nutation coefficients, in 1e-7 arcsec */ /* longitude (sin, t*sin, cos), obliquity (cos, t*cos, sin) */ static double cls[6*NLS]= {-172064161.0, -174666.0, 33386.0, 92052331.0, 9086.0, 15377.0, -13170906.0, -1675.0, -13696.0, 5730336.0, -3015.0, -4587.0, -2276413.0, -234.0, 2796.0, 978459.0, -485.0, 1374.0, 2074554.0, 207.0, -698.0, -897492.0, 470.0, -291.0, 1475877.0, -3633.0, 11817.0, 73871.0, -184.0, -1924.0, -516821.0, 1226.0, -524.0, 224386.0, -677.0, -174.0, 711159.0, 73.0, -872.0, -6750.0, 0.0, 358.0, -387298.0, -367.0, 380.0, 200728.0, 18.0, 318.0, -301461.0, -36.0, 816.0, 129025.0, -63.0, 367.0, 215829.0, -494.0, 111.0, -95929.0, 299.0, 132.0, 128227.0, 137.0, 181.0, -68982.0, -9.0, 39.0, 123457.0, 11.0, 19.0, -53311.0, 32.0, -4.0, 156994.0, 10.0, -168.0, -1235.0, 0.0, 82.0, 63110.0, 63.0, 27.0, -33228.0, 0.0, -9.0, -57976.0, -63.0, -189.0, 31429.0, 0.0, -75.0, -59641.0, -11.0, 149.0, 25543.0, -11.0, 66.0, -51613.0, -42.0, 129.0, 26366.0, 0.0, 78.0, 45893.0, 50.0, 31.0, -24236.0, -10.0, 20.0, 63384.0, 11.0, -150.0, -1220.0, 0.0, 29.0, -38571.0, -1.0, 158.0, 16452.0, -11.0, 68.0, 32481.0, 0.0, 0.0, -13870.0, 0.0, 0.0, -47722.0, 0.0, -18.0, 477.0, 0.0, -25.0, -31046.0, -1.0, 131.0, 13238.0, -11.0, 59.0, 28593.0, 0.0, -1.0, -12338.0, 10.0, -3.0, 20441.0, 21.0, 10.0, -10758.0, 0.0, -3.0, 29243.0, 0.0, -74.0, -609.0, 0.0, 13.0, 25887.0, 0.0, -66.0, -550.0, 0.0, 11.0, -14053.0, -25.0, 79.0, 8551.0, -2.0, -45.0, 15164.0, 10.0, 11.0, -8001.0, 0.0, -1.0, -15794.0, 72.0, -16.0, 6850.0, -42.0, -5.0, 21783.0, 0.0, 13.0, -167.0, 0.0, 13.0, -12873.0, -10.0, -37.0, 6953.0, 0.0, -14.0, -12654.0, 11.0, 63.0, 6415.0, 0.0, 26.0, -10204.0, 0.0, 25.0, 5222.0, 0.0, 15.0, 16707.0, -85.0, -10.0, 168.0, -1.0, 10.0, -7691.0, 0.0, 44.0, 3268.0, 0.0, 19.0, -11024.0, 0.0, -14.0, 104.0, 0.0, 2.0, 7566.0, -21.0, -11.0, -3250.0, 0.0, -5.0, -6637.0, -11.0, 25.0, 3353.0, 0.0, 14.0, -7141.0, 21.0, 8.0, 3070.0, 0.0, 4.0, -6302.0, -11.0, 2.0, 3272.0, 0.0, 4.0, 5800.0, 10.0, 2.0, -3045.0, 0.0, -1.0, 6443.0, 0.0, -7.0, -2768.0, 0.0, -4.0, -5774.0, -11.0, -15.0, 3041.0, 0.0, -5.0, -5350.0, 0.0, 21.0, 2695.0, 0.0, 12.0, -4752.0, -11.0, -3.0, 2719.0, 0.0, -3.0, -4940.0, -11.0, -21.0, 2720.0, 0.0, -9.0, 7350.0, 0.0, -8.0, -51.0, 0.0, 4.0, 4065.0, 0.0, 6.0, -2206.0, 0.0, 1.0, 6579.0, 0.0, -24.0, -199.0, 0.0, 2.0, 3579.0, 0.0, 5.0, -1900.0, 0.0, 1.0, 4725.0, 0.0, -6.0, -41.0, 0.0, 3.0, -3075.0, 0.0, -2.0, 1313.0, 0.0, -1.0, -2904.0, 0.0, 15.0, 1233.0, 0.0, 7.0, 4348.0, 0.0, -10.0, -81.0, 0.0, 2.0, -2878.0, 0.0, 8.0, 1232.0, 0.0, 4.0, -4230.0, 0.0, 5.0, -20.0, 0.0, -2.0, -2819.0, 0.0, 7.0, 1207.0, 0.0, 3.0, -4056.0, 0.0, 5.0, 40.0, 0.0, -2.0, -2647.0, 0.0, 11.0, 1129.0, 0.0, 5.0, -2294.0, 0.0, -10.0, 1266.0, 0.0, -4.0, 2481.0, 0.0, -7.0, -1062.0, 0.0, -3.0, 2179.0, 0.0, -2.0, -1129.0, 0.0, -2.0, 3276.0, 0.0, 1.0, -9.0, 0.0, 0.0, -3389.0, 0.0, 5.0, 35.0, 0.0, -2.0, 3339.0, 0.0, -13.0, -107.0, 0.0, 1.0, -1987.0, 0.0, -6.0, 1073.0, 0.0, -2.0, -1981.0, 0.0, 0.0, 854.0, 0.0, 0.0, 4026.0, 0.0, -353.0, -553.0, 0.0, -139.0, 1660.0, 0.0, -5.0, -710.0, 0.0, -2.0, -1521.0, 0.0, 9.0, 647.0, 0.0, 4.0, 1314.0, 0.0, 0.0, -700.0, 0.0, 0.0, -1283.0, 0.0, 0.0, 672.0, 0.0, 0.0, -1331.0, 0.0, 8.0, 663.0, 0.0, 4.0, 1383.0, 0.0, -2.0, -594.0, 0.0, -2.0, 1405.0, 0.0, 4.0, -610.0, 0.0, 2.0, 1290.0, 0.0, 0.0, -556.0, 0.0, 0.0}; /* Interval between fundamental epoch J2000.0 and given date (JC) */ t = (dj - dj0) / djc; /* Luni-solar nutation */ /* Fundamental (delaunay) arguments from Simon et al. (1994) */ /* Mean anomaly of the moon */ el = fmod (485868.249036 + (1717915923.2178 * t), as2pi) * as2r; /* Mean anomaly of the sun */ elp = fmod (1287104.79305 + (129596581.0481 * t), as2pi) * as2r; /* Mean argument of the latitude of the moon */ f = fmod (335779.526232 + (1739527262.8478 * t), as2pi) * as2r; /* Mean elongation of the moon from the sun */ d = fmod (1072260.70369 + (1602961601.2090 * t), as2pi ) * as2r; /* Mean longitude of the ascending node of the moon */ om = fmod (450160.398036 - (6962890.5431 * t), as2pi ) * as2r; /* Initialize the nutation values */ dp = 0.0; de = 0.0; /* Summation of luni-solar nutation series (in reverse order) */ for (i = nls; i > 0; i=i-1) { j = i - 1; /* Argument and functions */ arg = fmod ( (double) (nals[5*j]) * el + (double) (nals[1+5*j]) * elp + (double) (nals[2+5*j]) * f + (double) (nals[3+5*j]) * d + (double) (nals[4+5*j]) * om, d2pi); sarg = sin (arg); carg = cos (arg); /* Terms */ dp = dp + (cls[6*j] + cls[1+6*j] * t) * sarg + cls[2+6*j] * carg; de = de + (cls[3+6*j] + cls[4+6*j] * t) * carg + cls[5+6*j] * sarg; } /* Convert from 0.1 microarcsec units to radians */ dpsils = dp * u2r; depsls = de * u2r; /* In lieu of planetary nutation */ /* Fixed offset to correct for missing terms in truncated series */ dpsipl = dpplan; depspl = deplan; /* Results */ /* Add luni-solar and planetary components */ *dpsi = dpsils + dpsipl; *deps = depsls + depspl; /* Mean Obliquity in radians (IAU 2006, Hilton, et al.) */ *eps0 = ( 84381.406 + ( -46.836769 + ( -0.0001831 + ( 0.00200340 + ( -0.000000576 + ( -0.0000000434 ) * t ) * t ) * t ) * t ) * t ) * as2r; } /* ISDATE - Return 1 if string is an old or ISO FITS standard date */ int isdate (string) char *string; /* Possible FITS date string, which may be: dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard FITS use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { int iyr = 0; /* year (returned) */ int imon = 0; /* month (returned) */ int iday = 0; /* day (returned) */ int i; char *sstr, *dstr, *tstr, *nval; /* Translate string from ASCII to binary */ if (string == NULL) return (0); sstr = strchr (string,'/'); dstr = strchr (string,'-'); if (dstr == string) dstr = strchr (string+1,'-'); tstr = strchr (string,'T'); /* Original FITS date format: dd/mm/yy */ if (sstr > string) { *sstr = '\0'; iday = (int) atof (string); *sstr = '/'; nval = sstr + 1; sstr = strchr (nval,'/'); if (sstr == NULL) sstr = strchr (nval,'-'); if (sstr > string) { *sstr = '\0'; imon = (int) atof (nval); *sstr = '/'; nval = sstr + 1; iyr = (int) atof (nval); if (iyr < 1000) iyr = iyr + 1900; } if (imon > 0 && iday > 0) return (1); else return (0); } /* New FITS date format: yyyy-mm-ddThh:mm:ss[.sss] */ else if (dstr > string) { *dstr = '\0'; iyr = (int) atof (string); nval = dstr + 1; *dstr = '-'; dstr = strchr (nval,'-'); imon = 0; iday = 0; /* Decode year, month, and day */ if (dstr > string) { *dstr = '\0'; imon = (int) atof (nval); *dstr = '-'; nval = dstr + 1; if (tstr > string) *tstr = '\0'; iday = (int) atof (nval); if (tstr > string) *tstr = 'T'; } /* If day is > 31, it is really year in old format */ if (iday > 31) { i = iyr; if (iday < 100) iyr = iday + 1900; else iyr = iday; iday = i; } if (imon > 0 && iday > 0) return (1); else return (0); } /* If FITS date is entered as an epoch, return 0 anyway */ else return (0); } /* Round seconds and make sure date and time numbers are within limits */ static void fixdate (iyr, imon, iday, ihr, imn, sec, ndsec) int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double days; /* Round seconds to 0 - 4 decimal places (no rounding if <0, >4) */ if (ndsec == 0) *sec = dint (*sec + 0.5); else if (ndsec < 2) *sec = dint (*sec * 10.0 + 0.5) / 10.0; else if (ndsec < 3) *sec = dint (*sec * 100.0 + 0.5) / 100.0; else if (ndsec < 4) *sec = dint (*sec * 1000.0 + 0.5) / 1000.0; else if (ndsec < 5) *sec = dint (*sec * 10000.0 + 0.5) / 10000.0; /* Adjust minutes and hours */ if (*sec > 60.0) { *sec = *sec - 60.0; *imn = *imn + 1; } if (*imn > 60) { *imn = *imn - 60; *ihr = *ihr + 1; } /* Return if no date */ if (*iyr == 0 && *imon == 0 && *iday == 0) return; /* Adjust date */ if (*ihr > 23) { *ihr = *ihr - 24; *iday = *iday + 1; } days = caldays (*iyr, *imon); if (*iday > days) { *iday = *iday - days; *imon = *imon + 1; } if (*iday < 1) { *imon = *imon - 1; if (*imon < 1) { *imon = *imon + 12; *iyr = *iyr - 1; } days = caldays (*iyr, *imon); *iday = *iday + days; } if (*imon < 1) { *imon = *imon + 12; *iyr = *iyr - 1; days = caldays (*iyr, *imon); if (*iday > days) { *iday = *iday - days; *imon = *imon + 1; } } if (*imon > 12) { *imon = *imon - 12; *iyr = *iyr + 1; } return; } /* Calculate days in month 1-12 given year (Gregorian calendar only) */ static int caldays (year, month) int year; /* 4-digit year */ int month; /* Month (1=January, 2=February, etc.) */ { if (month < 1) { month = month + 12; year = year + 1; } if (month > 12) { month = month - 12; year = year + 1; } switch (month) { case 1: return (31); case 2: if (year%400 == 0) return (29); else if (year%100 == 0) return (28); else if (year%4 == 0) return (29); else return (28); case 3: return (31); case 4: return (30); case 5: return (31); case 6: return (30); case 7: return (31); case 8: return (31); case 9: return (30); case 10: return (31); case 11: return (30); case 12: return (31); default: return (0); } } static double dint (dnum) double dnum; { double dn; if (dnum < 0.0) dn = -floor (-dnum); else dn = floor (dnum); return (dn); } static double dmod (dnum, dm) double dnum, dm; { double dnumx, dnumi, dnumf; if (dnum < 0.0) dnumx = -dnum; else dnumx = dnum; dnumi = dint (dnumx / dm); if (dnum < 0.0) dnumf = dnum + (dnumi * dm); else if (dnum > 0.0) dnumf = dnum - (dnumi * dm); else dnumf = 0.0; return (dnumf); } /* Jul 1 1999 New file, based on iolib/jcon.f and iolib/vcon.f and hgetdate() * Oct 21 1999 Fix declarations after lint * Oct 27 1999 Fix bug to return epoch if fractional year input * Dec 9 1999 Fix bug in ts2jd() found by Pete Ratzlaff (SAO) * Dec 17 1999 Add all unimplemented conversions * Dec 20 1999 Add isdate(); leave date, time strings unchanged in fd2i() * Dec 20 1999 Make all fd2*() subroutines deal with time alone * * Jan 3 2000 In old FITS format, year 100 is assumed to be 2000 * Jan 11 2000 Fix epoch to date conversion so .0 is 0:00, not 12:00 * Jan 21 2000 Add separate Besselian and Julian epoch computations * Jan 28 2000 Add Modified Julian Date conversions * Mar 2 2000 Implement decimal places for FITS date string * Mar 14 2000 Fix bug in dealing with 2000-02-29 in ts2i() * Mar 22 2000 Add lt2* and ut2* to get current time as local and UT * Mar 24 2000 Fix calloc() calls * Mar 24 2000 Add tsi2* and tsu2* to convert IRAF and Unix seconds * May 1 2000 In old FITS format, all years < 1000 get 1900 added to them * Aug 1 2000 Make ep2jd and jd2ep consistently starting at 1/1 0:00 * * Jan 11 2001 Print all messages to stderr * May 21 2001 Add day of year conversions * May 25 2001 Allow fraction of day in FITS date instead of time * * Apr 8 2002 Change all long declaration to time_t * May 13 2002 Fix bugs found by lint * Jul 5 2002 Fix bug in fixdate() so fractional seconds come out * Jul 8 2002 Fix rounding bug in t2i() * Jul 8 2002 Try Fliegel and Van Flandern's algorithm for JD to UT date * Jul 8 2002 If first character of string is -, check for other -'s in isdate * Sep 10 2002 Add ET/TDT/TT conversion from UT subroutines * Sep 10 2002 Add sidereal time conversions * * Jan 30 2003 Fix typo in ts2gst() * Mar 7 2003 Add conversions for heliocentric julian dates * May 20 2003 Declare nd in setdatedec() * Jul 18 2003 Add code to parse Las Campanas dates * * Mar 24 2004 If ndec > 0, add UT to FITS date even if it is 0:00:00 * * Oct 14 2005 Add tsd2fd() and tsd2dt() * * May 3 2006 Drop declaration of unused variables * Jun 20 2006 Initialized uninitialized variables * Aug 2 2006 Add local sidereal time * Sep 13 2006 Add more local sidereal time subroutines * Oct 2 2006 Add UT to old FITS date conversions * Oct 6 2006 Add eqeqnx() to compute equation of the equinoxes * * Jan 8 2007 Remove unused variables * * Sep 5 2008 Replace nutation with IAU 2006 model translated from SOFA * Sep 9 2008 Add ang2hr(), ang2deg(), hr2ang(), deg2ang() * Sep 10 2008 Add longitude to mean standard time (default = Greenwich) * Oct 8 2008 Clean up sidereal time computations * * Sep 24 2009 Add end to comment "Coefficients for fundamental arguments" * * Jan 11 2012 Add TAI, TT, GPS time * Oct 19 2012 Unused l0 dropped from jd2lst(); ts2ss from jd2mst() */ wcstools-3.9.5/libwcs/dateutil0.c0000664000016200001660000034266411750060473016017 0ustar minkoirsys/*** File libwcs/dateutil.c *** September 9, 2008 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1999-2008 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ /* Date and time conversion routines using the following conventions: ang = Angle in fractional degrees deg = Angle in degrees as dd:mm:ss.ss doy = 2 floating point numbers: year and day, including fraction, of year *** First day of year is 1, not zero. dt = 2 floating point numbers: yyyy.mmdd, hh.mmssssss ep = fractional year, often epoch of a position including proper motion epb = Besselian epoch = 365.242198781-day years based on 1900.0 epj = Julian epoch = 365.25-day years based on 2000.0 fd = FITS date string which may be any of the following: yyyy.ffff (fractional year) dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard FITS use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) hr = Sexigesimal hours as hh:mm:dd.ss jd = Julian Date lt = Local time mjd = modified Julian Date = JD - 2400000.5 ofd = FITS date string (dd/mm/yy before 2000, else no return) time = use fd2* with no date to convert time as hh:mm:ss.ss to sec, day, year ts = UT seconds since 1950-01-01T00:00 (used for ephemeris computations) tsi = local seconds since 1980-01-01T00:00 (used by IRAF as a time tag) tsu = UT seconds since 1970-01-01T00:00 (used as Unix system time) tsd = UT seconds of current day ut = Universal Time (UTC) et = Ephemeris Time (or TDB or TT) mst = Mean Greenwich Sidereal Time gst = Greenwich Sidereal Time (includes nutation) lst = Local Sidereal Time (includes nutation) (longitude must be set) hjd = Heliocentric Julian Date mhjd = modified Heliocentric Julian Date = HJD - 2400000.5 * ang2hr (angle) * Convert angle in decimal floating point degrees to hours as hh:mm:ss.ss * ang2deg (angle) * Convert angle in decimal floating point degrees to degrees as dd:mm:ss.ss * deg2ang (angle as dd:mm:ss.ss) * Convert angle in degrees as dd:mm:ss.ss to decimal floating point degrees * ang2hr (angle) * Convert angle in hours as hh:mm:ss.ss to decimal floating point degrees * * doy2dt (year, doy, date, time) * Convert year and day of year to date as yyyy.ddmm and time as hh.mmsss * doy2ep, doy2epb, doy2epj (date, time) * Convert year and day of year to fractional year * doy2fd (year, doy) * Convert year and day of year to FITS date string * doy2mjd (year, doy) * Convert year and day of year to modified Julian date * * dt2doy (date, time, year, doy) * Convert date as yyyy.ddmm and time as hh.mmsss to year and day of year * dt2ep, dt2epb, dt2epj (date, time) * Convert date as yyyy.ddmm and time as hh.mmsss to fractional year * dt2fd (date, time) * Convert date as yyyy.ddmm and time as hh.mmsss to FITS date string * dt2i (date,time,iyr,imon,iday,ihr,imn,sec, ndsec) * Convert yyyy.mmdd hh.mmssss to year month day hours minutes seconds * dt2jd (date,time) * Convert date as yyyy.ddmm and time as hh.mmsss to Julian date * dt2mjd (date,time) * Convert date as yyyy.ddmm and time as hh.mmsss to modified Julian date * dt2ts (date,time) * Convert date (yyyy.ddmm) and time (hh.mmsss) to seconds since 1950-01-01 * dt2tsi (date,time) * Convert date (yyyy.ddmm) and time (hh.mmsss) to seconds since 1980-01-01 * dt2tsu (date,time) * Convert date (yyyy.ddmm) and time (hh.mmsss) to seconds since 1970-01-01 * * ep2dt, epb2dt, epj2dt (epoch,date, time) * Convert fractional year to date as yyyy.ddmm and time as hh.mmsss * ep2fd, epb2fd, epj2fd (epoch) * Convert epoch to FITS ISO date string * ep2i, epb2i, epj2i (epoch,iyr,imon,iday,ihr,imn,sec, ndsec) * Convert fractional year to year month day hours minutes seconds * ep2jd, epb2jd, epj2jd (epoch) * Convert fractional year as used in epoch to Julian date * ep2mjd, epb2mjd, epj2mjd (epoch) * Convert fractional year as used in epoch to modified Julian date * ep2ts, epb2ts, epj2ts (epoch) * Convert fractional year to seconds since 1950.0 * * et2fd (string) * Convert from ET (or TDT or TT) in FITS format to UT in FITS format * fd2et (string) * Convert from UT in FITS format to ET (or TDT or TT) in FITS format * jd2jed (dj) * Convert from Julian Date to Julian Ephemeris Date * jed2jd (dj) * Convert from Julian Ephemeris Date to Julian Date * dt2et (date, time) * Convert date (yyyy.ddmm) and time (hh.mmsss) to ephemeris time * edt2dt (date, time) * Convert ephemeris date (yyyy.ddmm) and time (hh.mmsss) to UT * ts2ets (tsec) * Convert from UT in seconds since 1950-01-01 to ET in same format * ets2ts (tsec) * Convert from ET in seconds since 1950-01-01 to UT in same format * * fd2ep, fd2epb, fd2epj (string) * Convert FITS date string to fractional year * Convert time alone to fraction of Besselian year * fd2doy (string, year, doy) * Convert FITS standard date string to year and day of year * fd2dt (string, date, time) * Convert FITS date string to date as yyyy.ddmm and time as hh.mmsss * Convert time alone to hh.mmssss with date set to 0.0 * fd2i (string,iyr,imon,iday,ihr,imn,sec, ndsec) * Convert FITS standard date string to year month day hours min sec * Convert time alone to hours min sec, year month day are zero * fd2jd (string) * Convert FITS standard date string to Julian date * Convert time alone to fraction of day * fd2mjd (string) * Convert FITS standard date string to modified Julian date * fd2ts (string) * Convert FITS standard date string to seconds since 1950.0 * Convert time alone to seconds of day * fd2fd (string) * Convert FITS standard date string to ISO FITS date string * fd2of (string) * Convert FITS standard date string to old-format FITS date and time * fd2ofd (string) * Convert FITS standard date string to old-format FITS date string * fd2oft (string) * Convert time part of FITS standard date string to FITS date string * * jd2doy (dj, year, doy) * Convert Julian date to year and day of year * jd2dt (dj,date,time) * Convert Julian date to date as yyyy.mmdd and time as hh.mmssss * jd2ep, jd2epb, jd2epj (dj) * Convert Julian date to fractional year as used in epoch * jd2fd (dj) * Convert Julian date to FITS ISO date string * jd2i (dj,iyr,imon,iday,ihr,imn,sec, ndsec) * Convert Julian date to year month day hours min sec * jd2mjd (dj) * Convert Julian date to modified Julian date * jd2ts (dj) * Convert Julian day to seconds since 1950.0 * * lt2dt() * Return local time as yyyy.mmdd and time as hh.mmssss * lt2fd() * Return local time as FITS ISO date string * lt2tsi() * Return local time as IRAF seconds since 1980-01-01 00:00 * lt2tsu() * Return local time as Unix seconds since 1970-01-01 00:00 * lt2ts() * Return local time as Unix seconds since 1950-01-01 00:00 * * mjd2doy (dj,year,doy) * Convert modified Julian date to date as year and day of year * mjd2dt (dj,date,time) * Convert modified Julian date to date as yyyy.mmdd and time as hh.mmssss * mjd2ep, mjd2epb, mjd2epj (dj) * Convert modified Julian date to fractional year as used in epoch * mjd2fd (dj) * Convert modified Julian date to FITS ISO date string * mjd2i (dj,iyr,imon,iday,ihr,imn,sec, ndsec) * Convert modified Julian date to year month day hours min sec * mjd2jd (dj) * Convert modified Julian date to Julian date * mjd2ts (dj) * Convert modified Julian day to seconds since 1950.0 * * ts2dt (tsec,date,time) * Convert seconds since 1950.0 to date as yyyy.ddmm and time as hh.mmsss * ts2ep, ts2epb, ts2epj (tsec) * Convert seconds since 1950.0 to fractional year * ts2fd (tsec) * Convert seconds since 1950.0 to FITS standard date string * ts2i (tsec,iyr,imon,iday,ihr,imn,sec, ndsec) * Convert sec since 1950.0 to year month day hours minutes seconds * ts2jd (tsec) * Convert seconds since 1950.0 to Julian date * ts2mjd (tsec) * Convert seconds since 1950.0 to modified Julian date * tsi2fd (tsec) * Convert seconds since 1980-01-01 to FITS standard date string * tsi2dt (tsec,date,time) * Convert seconds since 1980-01-01 to date as yyyy.ddmm, time as hh.mmsss * tsu2fd (tsec) * Convert seconds since 1970-01-01 to FITS standard date string * tsu2tsi (tsec) * Convert UT seconds since 1970-01-01 to local seconds since 1980-01-01 * tsu2dt (tsec,date,time) * Convert seconds since 1970-01-01 to date as yyyy.ddmm, time as hh.mmsss * * tsd2fd (tsec) * Convert seconds since start of day to FITS time, hh:mm:ss.ss * tsd2dt (tsec) * Convert seconds since start of day to hh.mmssss * * fd2gst (string) * convert from FITS date Greenwich Sidereal Time * dt2gst (date, time) * convert from UT as yyyy.mmdd hh.mmssss to Greenwich Sidereal Time * ts2gst (tsec) * Calculate Greenwich Sidereal Time given Universal Time * in seconds since 1951-01-01T0:00:00 * fd2mst (string) * convert from FITS UT date to Mean Sidereal Time * dt2gmt (date, time) * convert from UT as yyyy.mmdd hh.mmssss to Mean Sidereal Time * ts2mst (tsec) * Calculate Mean Sidereal Time given Universal Time * in seconds since 1951-01-01T0:00:00 * jd2mst (string) * convert from Julian Date to Mean Sidereal Time * mst2fd (string) * convert to current UT in FITS format given Greenwich Mean Sidereal Time * mst2jd (dj) * convert to current UT as Julian Date given Greenwich Mean Sidereal Time * jd2lst (dj) * Calculate Local Sidereal Time from Julian Date * ts2lst (tsec) * Calculate Local Sidereal Time given UT in seconds since 1951-01-01T0:00 * fd2lst (string) * Calculate Local Sidereal Time given Universal Time as FITS ISO date * lst2jd (dj, lst) * Calculate Julian Date given current Julian date and Local Sidereal Time * lst2fd (string, lst) * Calculate Julian Date given current UT date and Local Sidereal Time * gst2fd (string) * Calculate current UT given UT date and Greenwich Sidereal Time * gst2jd (dj) * Calculate current UT given UT date and Greenwich Sidereal Time as JD * * compnut (dj, dpsi, deps, eps0) * Compute the longitude and obliquity components of nutation and * mean obliquity from the IAU 1980 theory * * utdt (dj) * Compute difference between UT and dynamical time (ET-UT) * ut2dt (year, doy) * Current Universal Time to year and day of year * ut2dt (date, time) * Current Universal Time to date (yyyy.mmdd) and time (hh.mmsss) * ut2ep(), ut2epb(), ut2epj() * Current Universal Time to fractional year, Besselian, Julian epoch * ut2fd() * Current Universal Time to FITS ISO date string * ut2jd() * Current Universal Time to Julian Date * ut2mjd() * Current Universal Time to Modified Julian Date * ut2tsi() * Current Universal Time to IRAF seconds since 1980-01-01T00:00 * ut2tsu() * Current Universal Time to Unix seconds since 1970-01-01T00:00 * ut2ts() * Current Universal Time to seconds since 1950-01-01T00:00 * isdate (string) * Return 1 if string is a FITS date (old or ISO) * * Internally-used subroutines * * fixdate (iyr, imon, iday, ihr, imn, sec, ndsec) * Round seconds and make sure date and time numbers are within limits * caldays (year, month) * Calculate days in month 1-12 given year (Gregorian calendar only * dint (dnum) * Return integer part of floating point number * dmod (dnum) * Return Mod of floating point number */ #include #include #include #include #include #include #include "wcs.h" #include "fitsfile.h" static double suntl(); static void fixdate(); static int caldays(); static double dint(); static double dmod(); static double longitude = 0.0; /* longitude of observatory in degrees (+=west) */ void setlongitude (longitude0) double longitude0; { longitude = longitude0; return; } static int ndec = 3; void setdatedec (nd) int nd; { ndec = nd; return; } /* ANG2HR -- Convert angle in fraction degrees to hours as hh:mm:ss.ss */ void ang2hr (angle, lstr, string) double angle; /* Angle in fractional degrees */ int lstr; /* Maximum number of characters in string */ char *string; /* Character string (hh:mm:ss.ss returned) */ { angle = angle / 15.0; dec2str (string, lstr, angle, ndec); return; } /* ANG2DEG -- Convert angle in fraction degrees to degrees as dd:mm:ss.ss */ void ang2deg (angle, lstr, string) double angle; /* Angle in fractional degrees */ int lstr; /* Maximum number of characters in string */ char *string; /* Character string (dd:mm:ss.ss returned) */ { dec2str (string, lstr, angle, ndec); return; } /* DEG2ANG -- Convert angle in degrees as dd:mm:ss.ss to fractional degrees */ double deg2ang (angle) char *angle; /* Angle as dd:mm:ss.ss */ { double deg; deg = str2dec (angle); return (deg); } /* HR2ANG -- Convert angle in hours as hh:mm:ss.ss to fractional degrees */ double hr2ang (angle) char *angle; /* Angle in sexigesimal hours (hh:mm:ss.sss) */ { double deg; deg = str2dec (angle); deg = deg * 15.0; return (deg); } /* DT2FD-- convert vigesimal date and time to FITS date, yyyy-mm-ddThh:mm:ss.ss */ char * dt2fd (date, time) double date; /* Date as yyyy.mmdd yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { int iyr,imon,iday,ihr,imn; double sec; int nf; char *string; char tstring[32], dstring[32]; char outform[64]; dt2i (date, time, &iyr,&imon,&iday,&ihr,&imn,&sec, ndec); /* Convert to ISO date format */ string = (char *) calloc (32, sizeof (char)); /* Make time string */ if (time != 0.0 || ndec > 0) { if (ndec == 0) nf = 2; else nf = 3 + ndec; if (ndec > 0) { sprintf (outform, "%%02d:%%02d:%%0%d.%df", nf, ndec); sprintf (tstring, outform, ihr, imn, sec); } else { sprintf (outform, "%%02d:%%02d:%%0%dd", nf); sprintf (tstring, outform, ihr, imn, (int)(sec+0.5)); } } /* Make date string */ if (date != 0.0) sprintf (dstring, "%4d-%02d-%02d", iyr, imon, iday); /* Make FITS (ISO) date string */ if (date == 0.0) strcpy (string, tstring); else if (time == 0.0 && ndec < 1) strcpy (string, dstring); else sprintf (string, "%sT%s", dstring, tstring); return (string); } /* DT2JD-- convert from date as yyyy.mmdd and time as hh.mmsss to Julian Date * Return fractional days if date is zero */ double dt2jd (date,time) double date; /* Date as yyyy.mmdd yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double dj; /* Julian date (returned) */ double tsec; /* seconds since 1950.0 */ tsec = dt2ts (date, time); if (date == 0.0) dj = tsec / 86400.0; else dj = ts2jd (tsec); return (dj); } /* DT2MJD-- convert from date yyyy.mmdd time hh.mmsss to modified Julian Date * Return fractional days if date is zero */ double dt2mjd (date,time) double date; /* Date as yyyy.mmdd yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double dj; /* Modified Julian date (returned) */ double tsec; /* seconds since 1950.0 */ tsec = dt2ts (date, time); if (date == 0.0) dj = tsec / 86400.0; else dj = ts2jd (tsec); return (dj - 2400000.5); } /* HJD2JD-- convert Heliocentric Julian Date to (geocentric) Julian date */ double hjd2jd (dj, ra, dec, sys) double dj; /* Heliocentric Julian date */ double ra; /* Right ascension (degrees) */ double dec; /* Declination (degrees) */ int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ { double lt; /* Light travel difference to the Sun (days) */ lt = suntl (dj, ra, dec, sys); /* Return Heliocentric Julian Date */ return (dj - lt); } /* JD2HJD-- convert (geocentric) Julian date to Heliocentric Julian Date */ double jd2hjd (dj, ra, dec, sys) double dj; /* Julian date (geocentric) */ double ra; /* Right ascension (degrees) */ double dec; /* Declination (degrees) */ int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ { double lt; /* Light travel difference to the Sun (days) */ lt = suntl (dj, ra, dec, sys); /* Return Heliocentric Julian Date */ return (dj + lt); } /* MHJD2MJD-- convert modified Heliocentric Julian Date to modified geocentric Julian date */ double mhjd2mjd (mhjd, ra, dec, sys) double mhjd; /* Modified Heliocentric Julian date */ double ra; /* Right ascension (degrees) */ double dec; /* Declination (degrees) */ int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ { double lt; /* Light travel difference to the Sun (days) */ double hjd; /* Heliocentric Julian date */ hjd = mjd2jd (mhjd); lt = suntl (hjd, ra, dec, sys); /* Return Heliocentric Julian Date */ return (jd2mjd (hjd - lt)); } /* MJD2MHJD-- convert modified geocentric Julian date tp modified Heliocentric Julian Date */ double mjd2mhjd (mjd, ra, dec, sys) double mjd; /* Julian date (geocentric) */ double ra; /* Right ascension (degrees) */ double dec; /* Declination (degrees) */ int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ { double lt; /* Light travel difference to the Sun (days) */ double dj; /* Julian date (geocentric) */ dj = mjd2jd (mjd); lt = suntl (dj, ra, dec, sys); /* Return Heliocentric Julian Date */ return (jd2mjd (dj + lt)); } /* SUNTL-- compute light travel time to heliocentric correction in days */ /* Translated into C from IRAF SPP noao.astutils.asttools.asthjd.x */ static double suntl (dj, ra, dec, sys) double dj; /* Julian date (geocentric) */ double ra; /* Right ascension (degrees) */ double dec; /* Declination (degrees) */ int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ { double t; /* Number of Julian centuries since J1900 */ double manom; /* Mean anomaly of the Earth's orbit (degrees) */ double lperi; /* Mean longitude of perihelion (degrees) */ double oblq; /* Mean obliquity of the ecliptic (degrees) */ double eccen; /* Eccentricity of the Earth's orbit (dimensionless) */ double eccen2, eccen3; double tanom; /* True anomaly (approximate formula) (radians) */ double slong; /* True longitude of the Sun from the Earth (radians) */ double rs; /* Distance to the sun (AU) */ double lt; /* Light travel difference to the Sun (days) */ double l; /* Longitude of star in orbital plane of Earth (radians) */ double b; /* Latitude of star in orbital plane of Earth (radians) */ double epoch; /* Epoch of obervation */ double rs1,rs2; t = (dj - 2415020.0) / 36525.0; /* Compute earth orbital parameters */ manom = 358.47583 + (t * (35999.04975 - t * (0.000150 + t * 0.000003))); lperi = 101.22083 + (t * (1.7191733 + t * (0.000453 + t * 0.000003))); oblq = 23.452294 - (t * (0.0130125 + t * (0.00000164 - t * 0.000000503))); eccen = 0.01675104 - (t * (0.00004180 + t * 0.000000126)); eccen2 = eccen * eccen; eccen3 = eccen * eccen2; /* Convert to principle angles */ manom = manom - (360.0 * (dint) (manom / 360.0)); lperi = lperi - (360.0 * (dint) (lperi / 360.0)); /* Convert to radians */ manom = degrad (manom); lperi = degrad (lperi); oblq = degrad (oblq); /* True anomaly */ tanom = manom + (2 * eccen - 0.25 * eccen3) * sin (manom) + 1.25 * eccen2 * sin (2 * manom) + 13./12. * eccen3 * sin (3 * manom); /* Distance to the Sun */ rs1 = 1.0 - eccen2; rs2 = 1.0 + (eccen * cos (tanom)); rs = rs1 / rs2; /* True longitude of the Sun seen from the Earth */ slong = lperi + tanom + PI; /* Longitude and latitude of star in orbital plane of the Earth */ epoch = jd2ep (dj); wcscon (sys, WCS_ECLIPTIC, 0.0, 0.0, &ra, &dec, epoch); l = degrad (ra); b = degrad (dec); /* Light travel difference to the Sun */ lt = -0.005770 * rs * cos (b) * cos (l - slong); /* Return light travel difference */ return (lt); } /* JD2DT-- convert Julian date to date as yyyy.mmdd and time as hh.mmssss */ void jd2dt (dj,date,time) double dj; /* Julian date */ double *date; /* Date as yyyy.mmdd (returned) */ double *time; /* Time as hh.mmssxxxx (returned) */ { int iyr,imon,iday,ihr,imn; double sec; /* Convert Julian Date to date and time */ jd2i (dj, &iyr, &imon, &iday, &ihr, &imn, &sec, 4); /* Convert date to yyyy.mmdd */ if (iyr < 0) { *date = (double) (-iyr) + 0.01 * (double) imon + 0.0001 * (double) iday; *date = -(*date); } else *date = (double) iyr + 0.01 * (double) imon + 0.0001 * (double) iday; /* Convert time to hh.mmssssss */ *time = (double) ihr + 0.01 * (double) imn + 0.0001 * sec; return; } /* JD2I-- convert Julian date to date as year, month, and day, and time hours, minutes, and seconds */ /* after Fliegel and Van Flander, CACM 11, 657 (1968) */ void jd2i (dj, iyr, imon, iday, ihr, imn, sec, ndsec) double dj; /* Julian date */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double tsec; double frac, dts, ts, sday; int jd, l, n, i, j; tsec = jd2ts (dj); /* ts2i (tsec, iyr, imon, iday, ihr, imn, sec, ndsec); */ /* Round seconds to 0 - 4 decimal places */ if (tsec < 0.0) dts = -0.5; else dts = 0.5; if (ndsec < 1) ts = dint (tsec + dts); else if (ndsec < 2) ts = dint (tsec * 10.0 + dts) / 10.0; else if (ndsec < 3) ts = dint (tsec * 100.0 + dts) / 100.0; else if (ndsec < 4) ts = dint (tsec * 1000.0 + dts) / 1000.0; else ts = dint (tsec * 10000.0 + dts) / 10000.0; /* Convert back to Julian Date */ dj = ts2jd (ts); /* Compute time from fraction of a day */ frac = dmod (dj, 1.0); if (frac < 0.5) { jd = (int) (dj - frac); sday = (frac + 0.5) * 86400.0; } else { jd = (int) (dj - frac) + 1; sday = (frac - 0.5) * 86400.0; } *ihr = (int) (sday / 3600.0); sday = sday - (double) (*ihr * 3600); *imn = (int) (sday / 60.0); *sec = sday - (double) (*imn * 60); /* Compute day, month, year */ l = jd + 68569; n = (4 * l) / 146097; l = l - (146097 * n + 3) / 4; i = (4000 * (l + 1)) / 1461001; l = l - (1461 * i) / 4 + 31; j = (80 * l) / 2447; *iday = l - (2447 * j) / 80; l = j / 11; *imon = j + 2 - (12 * l); *iyr = 100 * (n - 49) + i + l; return; } /* JD2MJD-- convert Julian Date to Modified Julian Date */ double jd2mjd (dj) double dj; /* Julian Date */ { return (dj - 2400000.5); } /* JD2EP-- convert Julian date to fractional year as used in epoch */ double jd2ep (dj) double dj; /* Julian date */ { double date, time; jd2dt (dj, &date, &time); return (dt2ep (date, time)); } /* JD2EPB-- convert Julian date to Besselian epoch */ double jd2epb (dj) double dj; /* Julian date */ { return (1900.0 + (dj - 2415020.31352) / 365.242198781); } /* JD2EPJ-- convert Julian date to Julian epoch */ double jd2epj (dj) double dj; /* Julian date */ { return (2000.0 + (dj - 2451545.0) / 365.25); } /* LT2DT-- Return local time as yyyy.mmdd and time as hh.mmssss */ void lt2dt(date, time) double *date; /* Date as yyyy.mmdd (returned) */ double *time; /* Time as hh.mmssxxxx (returned) */ { time_t tsec; struct timeval tp; struct timezone tzp; struct tm *ts; gettimeofday (&tp,&tzp); tsec = tp.tv_sec; ts = localtime (&tsec); if (ts->tm_year < 1000) *date = (double) (ts->tm_year + 1900); else *date = (double) ts->tm_year; *date = *date + (0.01 * (double) (ts->tm_mon + 1)); *date = *date + (0.0001 * (double) ts->tm_mday); *time = (double) ts->tm_hour; *time = *time + (0.01 * (double) ts->tm_min); *time = *time + (0.0001 * (double) ts->tm_sec); return; } /* LT2FD-- Return current local time as FITS ISO date string */ char * lt2fd() { time_t tsec; struct tm *ts; struct timeval tp; struct timezone tzp; int month, day, year, hour, minute, second; char *isotime; gettimeofday (&tp,&tzp); tsec = tp.tv_sec; ts = localtime (&tsec); year = ts->tm_year; if (year < 1000) year = year + 1900; month = ts->tm_mon + 1; day = ts->tm_mday; hour = ts->tm_hour; minute = ts->tm_min; second = ts->tm_sec; isotime = (char *) calloc (32, sizeof (char)); sprintf (isotime, "%04d-%02d-%02dT%02d:%02d:%02d", year, month, day, hour, minute, second); return (isotime); } /* LT2TSI-- Return local time as IRAF seconds since 1980-01-01 00:00 */ int lt2tsi() { return ((int)(lt2ts() - 946684800.0)); } /* LT2TSU-- Return local time as Unix seconds since 1970-01-01 00:00 */ time_t lt2tsu() { return ((time_t)(lt2ts() - 631152000.0)); } /* LT2TS-- Return local time as Unix seconds since 1950-01-01 00:00 */ double lt2ts() { double tsec; char *datestring; datestring = lt2fd(); tsec = fd2ts (datestring); free (datestring); return (tsec); } /* MJD2DT-- convert Modified Julian Date to date (yyyy.mmdd) time (hh.mmssss) */ void mjd2dt (dj,date,time) double dj; /* Modified Julian Date */ double *date; /* Date as yyyy.mmdd (returned) yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double *time; /* Time as hh.mmssxxxx (returned) *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double tsec; tsec = jd2ts (dj + 2400000.5); ts2dt (tsec, date, time); return; } /* MJD2I-- convert Modified Julian Date to date as year, month, day and time as hours, minutes, seconds */ void mjd2i (dj, iyr, imon, iday, ihr, imn, sec, ndsec) double dj; /* Modified Julian Date */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double tsec; tsec = jd2ts (dj + 2400000.5); ts2i (tsec, iyr, imon, iday, ihr, imn, sec, ndsec); return; } /* MJD2DOY-- convert Modified Julian Date to Year,Day-of-Year */ void mjd2doy (dj, year, doy) double dj; /* Modified Julian Date */ int *year; /* Year (returned) */ double *doy; /* Day of year with fraction (returned) */ { jd2doy (dj + 2400000.5, year, doy); return; } /* MJD2JD-- convert Modified Julian Date to Julian Date */ double mjd2jd (dj) double dj; /* Modified Julian Date */ { return (dj + 2400000.5); } /* MJD2EP-- convert Modified Julian Date to fractional year */ double mjd2ep (dj) double dj; /* Modified Julian Date */ { double date, time; jd2dt (dj + 2400000.5, &date, &time); return (dt2ep (date, time)); } /* MJD2EPB-- convert Modified Julian Date to Besselian epoch */ double mjd2epb (dj) double dj; /* Modified Julian Date */ { return (1900.0 + (dj - 15019.81352) / 365.242198781); } /* MJD2EPJ-- convert Modified Julian Date to Julian epoch */ double mjd2epj (dj) double dj; /* Modified Julian Date */ { return (2000.0 + (dj - 51544.5) / 365.25); } /* MJD2FD-- convert modified Julian date to FITS date, yyyy-mm-ddThh:mm:ss.ss */ char * mjd2fd (dj) double dj; /* Modified Julian date */ { return (jd2fd (dj + 2400000.5)); } /* MJD2TS-- convert modified Julian date to seconds since 1950.0 */ double mjd2ts (dj) double dj; /* Modified Julian date */ { return ((dj - 33282.0) * 86400.0); } /* EP2FD-- convert fractional year to FITS date, yyyy-mm-ddThh:mm:ss.ss */ char * ep2fd (epoch) double epoch; /* Date as fractional year */ { double tsec; /* seconds since 1950.0 (returned) */ tsec = ep2ts (epoch); return (ts2fd (tsec)); } /* EPB2FD-- convert Besselian epoch to FITS date, yyyy-mm-ddThh:mm:ss.ss */ char * epb2fd (epoch) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ { double dj; /* Julian Date */ dj = epb2jd (epoch); return (jd2fd (dj)); } /* EPJ2FD-- convert Julian epoch to FITS date, yyyy-mm-ddThh:mm:ss.ss */ char * epj2fd (epoch) double epoch; /* Julian epoch (fractional 365.25-day years) */ { double dj; /* Julian Date */ dj = epj2jd (epoch); return (jd2fd (dj)); } /* EP2TS-- convert fractional year to seconds since 1950.0 */ double ep2ts (epoch) double epoch; /* Date as fractional year */ { double dj; dj = ep2jd (epoch); return ((dj - 2433282.5) * 86400.0); } /* EPB2TS-- convert Besselian epoch to seconds since 1950.0 */ double epb2ts (epoch) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ { double dj; dj = epb2jd (epoch); return ((dj - 2433282.5) * 86400.0); } /* EPJ2TS-- convert Julian epoch to seconds since 1950.0 */ double epj2ts (epoch) double epoch; /* Julian epoch (fractional 365.25-day years) */ { double dj; dj = epj2jd (epoch); return ((dj - 2433282.5) * 86400.0); } /* EPB2EP-- convert Besselian epoch to fractional years */ double epb2ep (epoch) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ { double dj; dj = epb2jd (epoch); return (jd2ep (dj)); } /* EP2EPB-- convert fractional year to Besselian epoch */ double ep2epb (epoch) double epoch; /* Fractional year */ { double dj; dj = ep2jd (epoch); return (jd2epb (dj)); } /* EPJ2EP-- convert Julian epoch to fractional year */ double epj2ep (epoch) double epoch; /* Julian epoch (fractional 365.25-day years) */ { double dj; dj = epj2jd (epoch); return (jd2ep (dj)); } /* EP2EPJ-- convert fractional year to Julian epoch */ double ep2epj (epoch) double epoch; /* Fractional year */ { double dj; dj = ep2jd (epoch); return (jd2epj (dj)); } /* EP2I-- convert fractional year to year month day hours min sec */ void ep2i (epoch, iyr, imon, iday, ihr, imn, sec, ndsec) double epoch; /* Date as fractional year */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double date, time; ep2dt (epoch, &date, &time); dt2i (date, time, iyr,imon,iday,ihr,imn,sec, ndsec); return; } /* EPB2I-- convert Besselian epoch to year month day hours min sec */ void epb2i (epoch, iyr, imon, iday, ihr, imn, sec, ndsec) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double date, time; epb2dt (epoch, &date, &time); dt2i (date, time, iyr,imon,iday,ihr,imn,sec, ndsec); return; } /* EPJ2I-- convert Julian epoch to year month day hours min sec */ void epj2i (epoch, iyr, imon, iday, ihr, imn, sec, ndsec) double epoch; /* Julian epoch (fractional 365.25-day years) */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double date, time; epj2dt (epoch, &date, &time); dt2i (date, time, iyr,imon,iday,ihr,imn,sec, ndsec); return; } /* EP2JD-- convert fractional year as used in epoch to Julian date */ double ep2jd (epoch) double epoch; /* Date as fractional year */ { double dj; /* Julian date (returned)*/ double date, time; ep2dt (epoch, &date, &time); dj = dt2jd (date, time); return (dj); } /* EPB2JD-- convert Besselian epoch to Julian Date */ double epb2jd (epoch) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ { return (2415020.31352 + ((epoch - 1900.0) * 365.242198781)); } /* EPJ2JD-- convert Julian epoch to Julian Date */ double epj2jd (epoch) double epoch; /* Julian epoch (fractional 365.25-day years) */ { return (2451545.0 + ((epoch - 2000.0) * 365.25)); } /* EP2MJD-- convert fractional year as used in epoch to modified Julian date */ double ep2mjd (epoch) double epoch; /* Date as fractional year */ { double dj; /* Julian date (returned)*/ double date, time; ep2dt (epoch, &date, &time); dj = dt2jd (date, time); return (dj - 2400000.5); } /* EPB2MJD-- convert Besselian epoch to modified Julian Date */ double epb2mjd (epoch) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ { return (15019.81352 + ((epoch - 1900.0) * 365.242198781)); } /* EPJ2MJD-- convert Julian epoch to modified Julian Date */ double epj2mjd (epoch) double epoch; /* Julian epoch (fractional 365.25-day years) */ { return (51544.5 + ((epoch - 2000.0) * 365.25)); } /* EPB2EPJ-- convert Besselian epoch to Julian epoch */ double epb2epj (epoch) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ { double dj; /* Julian date */ dj = epb2jd (epoch); return (jd2epj (dj)); } /* EPJ2EPB-- convert Julian epoch to Besselian epoch */ double epj2epb (epoch) double epoch; /* Julian epoch (fractional 365.25-day years) */ { double dj; /* Julian date */ dj = epj2jd (epoch); return (jd2epb (dj)); } /* JD2FD-- convert Julian date to FITS date, yyyy-mm-ddThh:mm:ss.ss */ char * jd2fd (dj) double dj; /* Julian date */ { double tsec; /* seconds since 1950.0 (returned) */ tsec = (dj - 2433282.5) * 86400.0; return (ts2fd (tsec)); } /* JD2TS-- convert Julian date to seconds since 1950.0 */ double jd2ts (dj) double dj; /* Julian date */ { return ((dj - 2433282.5) * 86400.0); } /* JD2TSI-- convert Julian date to IRAF seconds since 1980-01-01T0:00 */ int jd2tsi (dj) double dj; /* Julian date */ { double ts; ts = (dj - 2444239.5) * 86400.0; return ((int) ts); } /* JD2TSU-- convert Julian date to Unix seconds since 1970-01-01T0:00 */ time_t jd2tsu (dj) double dj; /* Julian date */ { return ((time_t)((dj - 2440587.5) * 86400.0)); } /* DT2DOY-- convert yyyy.mmdd hh.mmss to year and day of year */ void dt2doy (date, time, year, doy) double date; /* Date as yyyy.mmdd */ double time; /* Time as hh.mmssxxxx */ int *year; /* Year (returned) */ double *doy; /* Day of year with fraction (returned) */ { double dj; /* Julian date */ double dj0; /* Julian date on January 1 0:00 */ double date0; /* January first of date's year */ double dyear; dyear = floor (date); date0 = dyear + 0.0101; dj0 = dt2jd (date0, 0.0); dj = dt2jd (date, time); *year = (int) (dyear + 0.00000001); *doy = dj - dj0 + 1.0; return; } /* DOY2DT-- convert year and day of year to yyyy.mmdd hh.mmss */ void doy2dt (year, doy, date, time) int year; /* Year */ double doy; /* Day of year with fraction */ double *date; /* Date as yyyy.mmdd (returned) */ double *time; /* Time as hh.mmssxxxx (returned) */ { double dj; /* Julian date */ double dj0; /* Julian date on January 1 0:00 */ double date0; /* January first of date's year */ date0 = year + 0.0101; dj0 = dt2jd (date0, 0.0); dj = dj0 + doy - 1.0; jd2dt (dj, date, time); return; } /* DOY2EP-- convert year and day of year to fractional year as used in epoch */ double doy2ep (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double date, time; doy2dt (year, doy, &date, &time); return (dt2ep (date, time)); } /* DOY2EPB-- convert year and day of year to Besellian epoch */ double doy2epb (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj; dj = doy2jd (year, doy); return (jd2epb (dj)); } /* DOY2EPJ-- convert year and day of year to Julian epoch */ double doy2epj (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj; dj = doy2jd (year, doy); return (jd2epj (dj)); } /* DOY2FD-- convert year and day of year to FITS date */ char * doy2fd (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj; /* Julian date */ dj = doy2jd (year, doy); return (jd2fd (dj)); } /* DOY2JD-- convert year and day of year to Julian date */ double doy2jd (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj0; /* Julian date */ double date; /* Date as yyyy.mmdd (returned) */ double time; /* Time as hh.mmssxxxx (returned) */ date = (double) year + 0.0101; time = 0.0; dj0 = dt2jd (date, time); return (dj0 + doy - 1.0); } /* DOY2MJD-- convert year and day of year to Julian date */ double doy2mjd (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj0; /* Julian date */ double date; /* Date as yyyy.mmdd (returned) */ double time; /* Time as hh.mmssxxxx (returned) */ date = (double) year + 0.0101; time = 0.0; dj0 = dt2jd (date, time); return (dj0 + doy - 1.0 - 2400000.5); } /* DOY2TSU-- convert from FITS date to Unix seconds since 1970-01-01T0:00 */ time_t doy2tsu (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj; dj = doy2jd (year, doy); return ((time_t)jd2ts (dj)); } /* DOY2TSI-- convert from FITS date to IRAF seconds since 1980-01-01T0:00 */ int doy2tsi (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj; dj = doy2jd (year, doy); return ((int)jd2tsi (dj)); } /* DOY2TS-- convert year, day of year to seconds since 1950 */ double doy2ts (year, doy) int year; /* Year */ double doy; /* Day of year with fraction */ { double dj; dj = doy2jd (year, doy); return (jd2ts (dj)); } /* FD2DOY-- convert FITS date to year and day of year */ void fd2doy (string, year, doy) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ int *year; /* Year (returned) */ double *doy; /* Day of year with fraction (returned) */ { double dj; /* Julian date */ dj = fd2jd (string); jd2doy (dj, year, doy); return; } /* JD2DOY-- convert Julian date to year and day of year */ void jd2doy (dj, year, doy) double dj; /* Julian date */ int *year; /* Year (returned) */ double *doy; /* Day of year with fraction (returned) */ { double date; /* Date as yyyy.mmdd (returned) */ double time; /* Time as hh.mmssxxxx (returned) */ double dj0; /* Julian date at 0:00 on 1/1 */ double dyear; jd2dt (dj, &date, &time); *year = (int) date; dyear = (double) *year; dj0 = dt2jd (dyear+0.0101, 0.0); *doy = dj - dj0 + 1.0; return; } /* TS2JD-- convert seconds since 1950.0 to Julian date */ double ts2jd (tsec) double tsec; /* seconds since 1950.0 */ { return (2433282.5 + (tsec / 86400.0)); } /* TS2MJD-- convert seconds since 1950.0 to modified Julian date */ double ts2mjd (tsec) double tsec; /* seconds since 1950.0 */ { return (33282.0 + (tsec / 86400.0)); } /* TS2EP-- convert seconds since 1950.0 to fractional year as used in epoch */ double ts2ep (tsec) double tsec; /* Seconds since 1950.0 */ { double date, time; ts2dt (tsec, &date, &time); return (dt2ep (date, time)); } /* TS2EPB-- convert seconds since 1950.0 to Besselian epoch */ double ts2epb (tsec) double tsec; /* Seconds since 1950.0 */ { double dj; /* Julian Date */ dj = ts2jd (tsec); return (jd2epb (dj)); } /* TS2EPB-- convert seconds since 1950.0 to Julian epoch */ double ts2epj (tsec) double tsec; /* Seconds since 1950.0 */ { double dj; /* Julian Date */ dj = ts2jd (tsec); return (jd2epj (dj)); } /* DT2EP-- convert from date, time as yyyy.mmdd hh.mmsss to fractional year */ double dt2ep (date, time) double date; /* Date as yyyy.mmdd yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double epoch; /* Date as fractional year (returned) */ double dj, dj0, dj1, date0, time0, date1; dj = dt2jd (date, time); if (date == 0.0) epoch = dj / 365.2422; else { time0 = 0.0; date0 = dint (date) + 0.0101; date1 = dint (date) + 1.0101; dj0 = dt2jd (date0, time0); dj1 = dt2jd (date1, time0); epoch = dint (date) + ((dj - dj0) / (dj1 - dj0)); } return (epoch); } /* DT2EPB-- convert from date, time as yyyy.mmdd hh.mmsss to Besselian epoch */ double dt2epb (date, time) double date; /* Date as yyyy.mmdd yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double dj; /* Julian date */ double epoch; /* Date as fractional year (returned) */ dj = dt2jd (date, time); if (date == 0.0) epoch = dj / 365.242198781; else epoch = jd2epb (dj); return (epoch); } /* DT2EPJ-- convert from date, time as yyyy.mmdd hh.mmsss to Julian epoch */ double dt2epj (date, time) double date; /* Date as yyyy.mmdd yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double dj; /* Julian date */ double epoch; /* Date as fractional year (returned) */ dj = dt2jd (date, time); if (date == 0.0) epoch = dj / 365.25; else epoch = jd2epj (dj); return (epoch); } /* EP2DT-- convert from fractional year to date, time as yyyy.mmdd hh.mmsss */ void ep2dt (epoch, date, time) double epoch; /* Date as fractional year */ double *date; /* Date as yyyy.mmdd (returned) yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double *time; /* Time as hh.mmssxxxx (returned) *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double dj, dj0, dj1, date0, time0, date1, epochi, epochf; time0 = 0.0; epochi = dint (epoch); epochf = epoch - epochi; date0 = epochi + 0.0101; date1 = epochi + 1.0101; dj0 = dt2jd (date0, time0); dj1 = dt2jd (date1, time0); dj = dj0 + epochf * (dj1 - dj0); jd2dt (dj, date, time); return; } /* EPB2DT-- convert from Besselian epoch to date, time as yyyy.mmdd hh.mmsss */ void epb2dt (epoch, date, time) double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ double *date; /* Date as yyyy.mmdd (returned) yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double *time; /* Time as hh.mmssxxxx (returned) *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double dj; /* Julian date */ dj = epb2jd (epoch); jd2dt (dj, date, time); } /* EPJ2DT-- convert from Julian epoch to date, time as yyyy.mmdd hh.mmsss */ void epj2dt (epoch, date, time) double epoch; /* Julian epoch (fractional 365.25-day years) */ double *date; /* Date as yyyy.mmdd (returned) yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double *time; /* Time as hh.mmssxxxx (returned) *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double dj; /* Julian date */ dj = epj2jd (epoch); jd2dt (dj, date, time); } /* FD2JD-- convert FITS standard date to Julian date */ double fd2jd (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double date, time; fd2dt (string, &date, &time); return (dt2jd (date, time)); } /* FD2MJD-- convert FITS standard date to modified Julian date */ double fd2mjd (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { return (fd2jd (string) - 2400000.5); } /* FD2TSU-- convert from FITS date to Unix seconds since 1970-01-01T0:00 */ time_t fd2tsu (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double date, time; fd2dt (string, &date, &time); return (dt2tsu (date, time)); } /* FD2TSI-- convert from FITS date to IRAF seconds since 1980-01-01T0:00 */ int fd2tsi (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double date, time; fd2dt (string, &date, &time); return (dt2tsi (date, time)); } /* FD2TS-- convert FITS standard date to seconds since 1950 */ double fd2ts (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double date, time; fd2dt (string, &date, &time); return (dt2ts (date, time)); } /* FD2FD-- convert any FITS standard date to ISO FITS standard date */ char * fd2fd (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double date, time; fd2dt (string, &date, &time); return (dt2fd (date, time)); } /* FD2OF-- convert any FITS standard date to old FITS standard date time */ char * fd2of (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { int iyr,imon,iday,ihr,imn; double sec; fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 3); /* Convert to old FITS date format */ string = (char *) calloc (32, sizeof (char)); if (iyr < 1900) sprintf (string, "*** date out of range ***"); else if (iyr < 2000) sprintf (string, "%02d/%02d/%02d %02d:%02d:%06.3f", iday, imon, iyr-1900, ihr, imn, sec); else if (iyr < 2900.0) sprintf (string, "%02d/%02d/%3d %02d:%02d:%6.3f", iday, imon, iyr-1900, ihr, imn, sec); else sprintf (string, "*** date out of range ***"); return (string); } /* TAI-UTC from the U.S. Naval Observatory */ /* ftp://maia.usno.navy.mil/ser7/tai-utc.dat */ static double taijd[23]={2441317.5, 2441499.5, 2441683.5, 2442048.5, 2442413.5, 2442778.5, 2443144.5, 2443509.5, 2443874.5, 2444239.5, 2444786.5, 2445151.5, 2445516.5, 2446247.5, 2447161.5, 2447892.5, 2448257.5, 2448804.5, 2449169.5, 2449534.5, 2450083.5, 2450630.5, 2451179.5}; static double taidt[23]={10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0, 20.0,21.0,22.0,23.0,24.0,25.0,26.0,27.0,28.0,29.0,30.0,31.0,32.0}; static double dttab[173]={13.7,13.4,13.1,12.9,12.7,12.6,12.5,12.5,12.5,12.5, 12.5,12.5,12.5,12.5,12.5,12.5,12.5,12.4,12.3,12.2,12.0,11.7,11.4, 11.1,10.6,10.2, 9.6, 9.1, 8.6, 8.0, 7.5, 7.0, 6.6, 6.3, 6.0, 5.8, 5.7, 5.6, 5.6, 5.6, 5.7, 5.8, 5.9, 6.1, 6.2, 6.3, 6.5, 6.6, 6.8, 6.9, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.7, 7.8, 7.8,7.88,7.82, 7.54, 6.97, 6.40, 6.02, 5.41, 4.10, 2.92, 1.82, 1.61, 0.10,-1.02, -1.28,-2.69,-3.24,-3.64,-4.54,-4.71,-5.11,-5.40,-5.42,-5.20,-5.46, -5.46,-5.79,-5.63,-5.64,-5.80,-5.66,-5.87,-6.01,-6.19,-6.64,-6.44, -6.47,-6.09,-5.76,-4.66,-3.74,-2.72,-1.54,-0.02, 1.24, 2.64, 3.86, 5.37, 6.14, 7.75, 9.13,10.46,11.53,13.36,14.65,16.01,17.20,18.24, 19.06,20.25,20.95,21.16,22.25,22.41,23.03,23.49,23.62,23.86,24.49, 24.34,24.08,24.02,24.00,23.87,23.95,23.86,23.93,23.73,23.92,23.96, 24.02,24.33,24.83,25.30,25.70,26.24,26.77,27.28,27.78,28.25,28.71, 29.15,29.57,29.97,30.36,30.72,31.07,31.35,31.68,32.18,32.68,33.15, 33.59,34.00,34.47,35.03,35.73,36.54,37.43,38.29,39.20,40.18,41.17, 42.23}; /* ET2FD-- convert from ET (or TDT or TT) in FITS format to UT in FITS format */ char * et2fd (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double dj0, dj, tsec, dt; dj0 = fd2jd (string); dt = utdt (dj0); dj = dj0 - (dt / 86400.0); dt = utdt (dj); tsec = fd2ts (string); tsec = tsec - dt; return (ts2fd (tsec)); } /* FD2ET-- convert from UT in FITS format to ET (or TDT or TT) in FITS format */ char * fd2et (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double dj, tsec, dt; dj = fd2jd (string); dt = utdt (dj); tsec = fd2ts (string); tsec = tsec + dt; return (ts2fd (tsec)); } /* DT2ET-- convert from UT as yyyy.mmdd hh.mmssss to ET in same format */ void dt2et (date, time) double *date; /* Date as yyyy.mmdd */ double *time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { double dj, dt, tsec; dj = dt2jd (*date, *time); dt = utdt (dj); tsec = dt2ts (*date, *time); tsec = tsec + dt; ts2dt (tsec, date, time); return; } /* EDT2DT-- convert from ET as yyyy.mmdd hh.mmssss to UT in same format */ void edt2dt (date, time) double *date; /* Date as yyyy.mmdd */ double *time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { double dj, dt, tsec, tsec0; dj = dt2jd (*date, *time); dt = utdt (dj); tsec0 = dt2ts (*date, *time); tsec = tsec0 + dt; dj = ts2jd (tsec); dt = utdt (dj); tsec = tsec0 + dt; ts2dt (tsec, date, time); return; } /* JD2JED-- convert from Julian Date to Julian Ephemeris Date */ double jd2jed (dj) double dj; /* Julian Date */ { double dt; dt = utdt (dj); return (dj + (dt / 86400.0)); } /* JED2JD-- convert from Julian Ephemeris Date to Julian Date */ double jed2jd (dj) double dj; /* Julian Ephemeris Date */ { double dj0, dt; dj0 = dj; dt = utdt (dj); dj = dj0 - (dt / 86400.0); dt = utdt (dj); return (dj - (dt / 86400.0)); } /* TS2ETS-- convert from UT in seconds since 1950-01-01 to ET in same format */ double ts2ets (tsec) double tsec; { double dj, dt; dj = ts2jd (tsec); dt = utdt (dj); return (tsec + dt); } /* ETS2TS-- convert from ET in seconds since 1950-01-01 to UT in same format */ double ets2ts (tsec) double tsec; { double dj, dj0, dt; dj0 = ts2jd (tsec); dt = utdt (dj0); dj = dj0 - (dt / 86400.0); dt = utdt (dj); return (tsec - dt); } /* UTDT-- Compute difference between UT and dynamical time (ET-UT) */ double utdt (dj) double dj; /* Julian Date (UT) */ { double dt, date, time, ts, ts1, ts0, date0, yfrac, diff, cj; int i, iyr, iyear; /* If after 1972-01-01, use tabulated TAI-UT */ if (dj >= 2441317.5) { dt = 0.0; for (i = 22; i > 0; i--) { if (dj >= taijd[i]) dt = taidt[i]; } dt = dt + 32.84; } /* For 1800-01-01 to 1972-01-01, use table of ET-UT from AE */ else if (dj >= 2378496.5) { jd2dt (dj, &date, &time); ts = jd2ts (dj); iyear = (int) date; iyr = iyear - 1800; date0 = (double) iyear + 0.0101; ts0 = dt2ts (date0, 0.0); date0 = (double) (iyear + 1) + 0.0101; ts1 = dt2ts (date0, 0.0); yfrac = (ts - ts0) / (ts1 - ts0); diff = dttab[iyr+1] - dttab[iyr]; dt = dttab[iyr] + (diff * yfrac); } /* Compute back to 1600 using formula from McCarthy and Babcock (1986) */ else if (dj >= 2305447.5) { cj = (dj - 2378496.5) / 36525.0; dt = 5.156 + 13.3066 * (cj - 0.19) * (cj - 0.19); } /* Compute back to 948 using formula from Stephenson and Morrison (1984) */ else if (dj >= 2067309.5) { cj = (dj - 2378496.5) / 36525.0; dt = 25.5 * cj * cj; } /*Compute back to 390 BC using formula from Stephenson and Morrison (1984)*/ else if (dj >= 0.0) { cj = (dj = 2378496.5) / 36525.0; dt = 1360.0 + (320.0 * cj) + (44.3 * cj * cj); } else dt = 0.0; return (dt); } /* FD2OFD-- convert any FITS standard date to old FITS standard date */ char * fd2ofd (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { int iyr,imon,iday,ihr,imn; double sec; fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 3); /* Convert to old FITS date format */ string = (char *) calloc (32, sizeof (char)); if (iyr < 1900) sprintf (string, "*** date out of range ***"); else if (iyr < 2000) sprintf (string, "%02d/%02d/%02d", iday, imon, iyr-1900); else if (iyr < 2900.0) sprintf (string, "%02d/%02d/%3d", iday, imon, iyr-1900); else sprintf (string, "*** date out of range ***"); return (string); } /* FD2OFT-- convert any FITS standard date to old FITS standard time */ char * fd2oft (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { int iyr,imon,iday,ihr,imn; double sec; fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 3); /* Convert to old FITS date format */ string = (char *) calloc (32, sizeof (char)); sprintf (string, "%02d:%02d:%06.3f", ihr, imn, sec); return (string); } /* FD2DT-- convert FITS standard date to date, time as yyyy.mmdd hh.mmsss */ void fd2dt (string, date, time) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ double *date; /* Date as yyyy.mmdd (returned) yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double *time; /* Time as hh.mmssxxxx (returned) *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { int iyr,imon,iday,ihr,imn; double sec; fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 4); /* Convert date to yyyy.mmdd */ if (iyr < 0) { *date = (double) (-iyr) + 0.01 * (double) imon + 0.0001 * (double) iday; *date = -(*date); } else *date = (double) iyr + 0.01 * (double) imon + 0.0001 * (double) iday; /* Convert time to hh.mmssssss */ *time = (double) ihr + 0.01 * (double) imn + 0.0001 * sec; return; } /* FD2EP-- convert from FITS standard date to fractional year */ double fd2ep (string) char *string; /* FITS date string, which may be: yyyy.ffff (fractional year) dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard FITS use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double dj; /* Julian date */ dj = fd2jd (string); if (dj < 1.0) return (dj / 365.2422); else return (jd2ep (dj)); } /* FD2EPB-- convert from FITS standard date to Besselian epoch */ double fd2epb (string) char *string; /* FITS date string, which may be: yyyy.ffff (fractional year) dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard FITS use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double dj; /* Julian date */ dj = fd2jd (string); if (dj < 1.0) return (dj / 365.242198781); else return (jd2epb (dj)); } /* FD2EPJ-- convert from FITS standard date to Julian epoch */ double fd2epj (string) char *string; /* FITS date string, which may be: yyyy.ffff (fractional year) dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard FITS use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double dj; /* Julian date */ dj = fd2jd (string); if (dj < 1.0) return (dj / 365.25); else return (jd2epj (dj)); } /* DT2TSU-- convert from date and time to Unix seconds since 1970-01-01T0:00 */ time_t dt2tsu (date,time) double date; /* Date as yyyy.mmdd */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { return ((time_t)(dt2ts (date, time) - 631152000.0)); } /* DT2TSI-- convert from date and time to IRAF seconds since 1980-01-01T0:00 */ int dt2tsi (date,time) double date; /* Date as yyyy.mmdd */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { return ((int)(dt2ts (date, time) - 946684800.0)); } /* DT2TS-- convert from date, time as yyyy.mmdd hh.mmsss to sec since 1950.0 */ double dt2ts (date,time) double date; /* Date as yyyy.mmdd yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { double tsec; /* Seconds past 1950.0 (returned) */ double dh,dm,dd; int iy,im,id; /* Calculate the number of full years, months, and days already * elapsed since 0h, March 1, -1 (up to most recent midnight). */ /* convert time of day to elapsed seconds */ /* If time is < 0, it is assumed to be a fractional day */ if (time < 0.0) tsec = time * -86400.0; else { dh = (int) (time + 0.0000000001); dm = (int) (((time - dh) * 100.0) + 0.0000000001); tsec = (time * 10000.0) - (dh * 10000.0) - (dm * 100.0); tsec = (int) (tsec * 100000.0 + 0.0001) / 100000.0; tsec = tsec + (dm * 60.0) + (dh * 3600.0); } /* Calculate the number of full months elapsed since * the current or most recent March */ if (date >= 0.0301) { iy = (int) (date + 0.0000000001); im = (int) (((date - (double) (iy)) * 10000.0) + 0.00000001); id = im % 100; im = (im / 100) + 9; if (im < 12) iy = iy - 1; im = im % 12; id = id - 1; /* starting with March as month 0 and ending with the following * February as month 11, the calculation of the number of days * per month reduces to a simple formula. the following statement * determines the number of whole days elapsed since 3/1/-1 and then * subtracts the 712163 days between then and 1/1/1950. it converts * the result to seconds and adds the accumulated seconds above. */ id = id + ((im+1+im/6+im/11)/2 * 31) + ((im-im/6-im/11)/2 * 30) + (iy / 4) - (iy / 100) + (iy / 400); dd = (double) id + (365.0 * (double) iy) - 712163.0; tsec = tsec + (dd * 86400.0); } return (tsec); } /* TS2DT-- convert seconds since 1950.0 to date, time as yyyy.mmdd hh.mmssss */ void ts2dt (tsec,date,time) double tsec; /* Seconds past 1950.0 */ double *date; /* Date as yyyy.mmdd (returned) yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double *time; /* Time as hh.mmssxxxx (returned) *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ { int iyr,imon,iday,ihr,imn; double sec; ts2i (tsec,&iyr,&imon,&iday,&ihr,&imn,&sec, 4); /* Convert date to yyyy.mmdd */ if (iyr < 0) { *date = (double) (-iyr) + 0.01 * (double) imon + 0.0001 * (double) iday; *date = -(*date); } else *date = (double) iyr + 0.01 * (double) imon + 0.0001 * (double) iday; /* Convert time to hh.mmssssss */ *time = (double) ihr + 0.01 * (double) imn + 0.0001 * sec; return; } /* TSI2DT-- Convert seconds since 1980-01-01 to date yyyy.ddmm, time hh.mmsss */ void tsi2dt (isec,date,time) int isec; /* Seconds past 1980-01-01 */ double *date; /* Date as yyyy.mmdd (returned) */ double *time; /* Time as hh.mmssxxxx (returned) */ { ts2dt (tsi2ts (isec), date, time); } /* TSI2FD-- Convert seconds since 1980-01-01 to FITS standard date string */ char * tsi2fd (isec) int isec; /* Seconds past 1980-01-01 */ { return (ts2fd (tsi2ts (isec))); } /* TSI2TS-- Convert seconds since 1980-01-01 to seconds since 1950-01-01 */ double tsi2ts (isec) int isec; /* Seconds past 1980-01-01 */ { return ((double) isec + 946684800.0); } /* TSU2FD-- Convert seconds since 1970-01-01 to FITS standard date string */ char * tsu2fd (isec) time_t isec; /* Seconds past 1970-01-01 */ { return (ts2fd (tsu2ts (isec))); } /* TSU2DT-- Convert seconds since 1970-01-01 to date yyyy.ddmm, time hh.mmsss */ void tsu2dt (isec,date,time) time_t isec; /* Seconds past 1970-01-01 */ double *date; /* Date as yyyy.mmdd (returned) */ double *time; /* Time as hh.mmssxxxx (returned) */ { ts2dt (tsu2ts (isec), date, time); } /* TSU2TS-- Convert seconds since 1970-01-01 to seconds since 1950-01-01 */ double tsu2ts (isec) time_t isec; /* Seconds past 1970-01-01 */ { return ((double) isec + 631152000.0); } /* TSU2TSI-- UT seconds since 1970-01-01 to local seconds since 1980-01-01 */ int tsu2tsi (isec) time_t isec; /* Seconds past 1970-01-01 */ { double date, time; struct tm *ts; /* Get local time from UT seconds */ ts = localtime (&isec); if (ts->tm_year < 1000) date = (double) (ts->tm_year + 1900); else date = (double) ts->tm_year; date = date + (0.01 * (double) (ts->tm_mon + 1)); date = date + (0.0001 * (double) ts->tm_mday); time = (double) ts->tm_hour; time = time + (0.01 * (double) ts->tm_min); time = time + (0.0001 * (double) ts->tm_sec); return ((int)(dt2ts (date, time) - 631152000.0)); } /* TS2FD-- convert seconds since 1950.0 to FITS date, yyyy-mm-ddThh:mm:ss.ss */ char * ts2fd (tsec) double tsec; /* Seconds past 1950.0 */ { double date, time; ts2dt (tsec, &date, &time); return (dt2fd (date, time)); } /* TSD2FD-- convert seconds since start of day to FITS time, hh:mm:ss.ss */ char * tsd2fd (tsec) double tsec; /* Seconds since start of day */ { double date, time; char *thms, *fdate; int lfd, nbc; ts2dt (tsec, &date, &time); fdate = dt2fd (date, time); thms = (char *) calloc (16, 1); lfd = strlen (fdate); nbc = lfd - 11; strncpy (thms, fdate+11, nbc); return (thms); } /* TSD2DT-- convert seconds since start of day to hh.mmssss */ double tsd2dt (tsec) double tsec; /* Seconds since start of day */ { double date, time; ts2dt (tsec, &date, &time); return (time); } /* DT2I-- convert vigesimal date and time to year month day hours min sec */ void dt2i (date, time, iyr, imon, iday, ihr, imn, sec, ndsec) double date; /* Date as yyyy.mmdd (returned) yyyy = calendar year (e.g. 1973) mm = calendar month (e.g. 04 = april) dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx (returned) *if time<0, it is time as -(fraction of a day) hh = hour of day (0 .le. hh .le. 23) nn = minutes (0 .le. nn .le. 59) ss = seconds (0 .le. ss .le. 59) xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double t,d; t = time; if (date < 0.0) d = -date; else d = date; /* Extract components of time */ *ihr = dint (t + 0.000000001); t = 100.0 * (t - (double) *ihr); *imn = dint (t + 0.0000001); *sec = 100.0 * (t - (double) *imn); /* Extract components of date */ *iyr = dint (d + 0.00001); d = 100.0 * (d - (double) *iyr); if (date < 0.0) *iyr = - *iyr; *imon = dint (d + 0.001); d = 100.0 * (d - (double) *imon); *iday = dint (d + 0.1); /* Make sure date and time are legal */ fixdate (iyr, imon, iday, ihr, imn, sec, ndsec); return; } /* FD2I-- convert from FITS standard date to year, mon, day, hours, min, sec */ void fd2i (string, iyr, imon, iday, ihr, imn, sec, ndsec) char *string; /* FITS date string, which may be: yyyy.ffff (fractional year) dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard FITS use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double tsec, fday, hr, mn; int i; char *sstr, *dstr, *tstr, *cstr, *nval, *fstr; /* Initialize all returned data to zero */ *iyr = 0; *imon = 0; *iday = 0; *ihr = 0; *imn = 0; *sec = 0.0; /* Return if no input string */ if (string == NULL) return; /* Check for various non-numeric characters */ sstr = strchr (string,'/'); dstr = strchr (string,'-'); if (dstr == string) dstr = strchr (string+1, '-'); fstr = strchr (string, '.'); tstr = strchr (string,'T'); if (tstr == NULL) tstr = strchr (string, 'Z'); if (tstr == NULL) tstr = strchr (string, 'S'); if (fstr != NULL && tstr != NULL && fstr > tstr) fstr = NULL; cstr = strchr (string,':'); /* Original FITS date format: dd/mm/yy */ if (sstr > string) { *sstr = '\0'; *iday = (int) atof (string); if (*iday > 31) { *iyr = *iday; if (*iyr >= 0 && *iyr <= 49) *iyr = *iyr + 2000; else if (*iyr < 1000) *iyr = *iyr + 1900; *sstr = '/'; nval = sstr + 1; sstr = strchr (nval,'/'); if (sstr > string) { *sstr = '\0'; *imon = (int) atof (nval); *sstr = '/'; nval = sstr + 1; *iday = (int) atof (nval); } } else { *sstr = '/'; nval = sstr + 1; sstr = strchr (nval,'/'); if (sstr == NULL) sstr = strchr (nval,'-'); if (sstr > string) { *sstr = '\0'; *imon = (int) atof (nval); *sstr = '/'; nval = sstr + 1; *iyr = (int) atof (nval); if (*iyr >= 0 && *iyr <= 49) *iyr = *iyr + 2000; else if (*iyr < 1000) *iyr = *iyr + 1900; } } tstr = strchr (string,'_'); if (tstr == NULL) return; } /* New FITS date format: yyyy-mm-ddThh:mm:ss[.sss] */ else if (dstr > string) { *dstr = '\0'; *iyr = (int) atof (string); *dstr = '-'; nval = dstr + 1; dstr = strchr (nval,'-'); *imon = 1; *iday = 1; /* Decode year, month, and day */ if (dstr > string) { *dstr = '\0'; *imon = (int) atof (nval); *dstr = '-'; nval = dstr + 1; if (tstr > string) *tstr = '\0'; *iday = (int) atof (nval); /* If fraction of a day is present, turn it into a time */ if (fstr != NULL) { fday = atof (fstr); hr = fday * 24.0; *ihr = (int) hr; mn = 60.0 * (hr - (double) *ihr); *imn = (int) mn; *sec = 60.0 * (mn - (double) *imn); } if (tstr > string) *tstr = 'T'; } /* If date is > 31, it is really year in old format */ if (*iday > 31) { i = *iyr; if (*iday < 100) *iyr = *iday + 1900; else *iyr = *iday; *iday = i; } } /* In rare cases, a FITS time is entered as an epoch */ else if (tstr == NULL && cstr == NULL && isnum (string)) { tsec = ep2ts (atof (string)); ts2i (tsec,iyr,imon,iday,ihr,imn,sec, ndsec); return; } /* Extract time, if it is present */ if (tstr > string || cstr > string) { if (tstr > string) nval = tstr + 1; else nval = string; cstr = strchr (nval,':'); if (cstr > string) { *cstr = '\0'; *ihr = (int) atof (nval); *cstr = ':'; nval = cstr + 1; cstr = strchr (nval,':'); if (cstr > string) { *cstr = '\0'; *imn = (int) atof (nval); *cstr = ':'; nval = cstr + 1; *sec = atof (nval); } else *imn = (int) atof (nval); } else *ihr = (int) atof (nval); } else ndsec = -1; /* Make sure date and time are legal */ fixdate (iyr, imon, iday, ihr, imn, sec, ndsec); return; } /* TS2I-- convert sec since 1950.0 to year month day hours minutes seconds */ void ts2i (tsec,iyr,imon,iday,ihr,imn,sec, ndsec) double tsec; /* seconds since 1/1/1950 0:00 */ int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double t,days, ts, dts; int nc,nc4,nly,ny,m,im; /* Round seconds to 0 - 4 decimal places */ ts = tsec + 61530883200.0; if (ts < 0.0) dts = -0.5; else dts = 0.5; if (ndsec < 1) t = dint (ts + dts) * 10000.0; else if (ndsec < 2) t = dint (ts * 10.0 + dts) * 1000.0; else if (ndsec < 3) t = dint (ts * 100.0 + dts) * 100.0; else if (ndsec < 4) t = dint (ts * 1000.0 + dts) * 10.0; else t = dint (ts * 10000.0 + dts); ts = t / 10000.0; /* Time of day (hours, minutes, seconds */ *ihr = (int) (dmod (ts/3600.0, 24.0)); *imn = (int) (dmod (ts/60.0, 60.0)); *sec = dmod (ts, 60.0); /* Number of days since 0 hr 0/0/0000 */ days = dint ((t / 864000000.0) + 0.000001); /* Number of leap centuries (400 years) */ nc4 = (int) ((days / 146097.0) + 0.00001); /* Number of centuries since last /400 */ days = days - (146097.0 * (double) (nc4)); nc = (int) ((days / 36524.0) + 0.000001); if (nc > 3) nc = 3; /* Number of leap years since last century */ days = days - (36524.0 * nc); nly = (int) ((days / 1461.0) + 0.0000000001); /* Number of years since last leap year */ days = days - (1461.0 * (double) nly); ny = (int) ((days / 365.0) + 0.00000001); if (ny > 3) ny = 3; /* Day of month */ days = days - (365.0 * (double) ny); if (days < 0) { m = 0; *iday = 29; } else { *iday = (int) (days + 0.00000001) + 1; for (m = 1; m <= 12; m++) { im = (m + ((m - 1) / 5)) % 2; /* fprintf (stderr,"%d %d %d %d\n", m, im, *iday, nc); */ if (*iday-1 < im+30) break; *iday = *iday - im - 30; } } /* Month */ *imon = ((m+1) % 12) + 1; /* Year */ *iyr = nc4*400 + nc*100 + nly*4 + ny + m/11; /* Make sure date and time are legal */ fixdate (iyr, imon, iday, ihr, imn, sec, ndsec); return; } /* UT2DOY-- Current Universal Time as year, day of year */ void ut2doy (year, doy) int *year; /* Year (returned) */ double *doy; /* Day of year (returned) */ { double date, time; ut2dt (&date, &time); dt2doy (date, time, year, doy); return; } /* UT2DT-- Current Universal Time as date (yyyy.mmdd) and time (hh.mmsss) */ void ut2dt(date, time) double *date; /* Date as yyyy.mmdd (returned) */ double *time; /* Time as hh.mmssxxxx (returned) */ { time_t tsec; struct timeval tp; struct timezone tzp; struct tm *ts; gettimeofday (&tp,&tzp); tsec = tp.tv_sec; ts = gmtime (&tsec); if (ts->tm_year < 1000) *date = (double) (ts->tm_year + 1900); else *date = (double) ts->tm_year; *date = *date + (0.01 * (double) (ts->tm_mon + 1)); *date = *date + (0.0001 * (double) ts->tm_mday); *time = (double) ts->tm_hour; *time = *time + (0.01 * (double) ts->tm_min); *time = *time + (0.0001 * (double) ts->tm_sec); return; } /* UT2EP-- Return current Universal Time as fractional year */ double ut2ep() { return (jd2ep (ut2jd())); } /* UT2EPB-- Return current Universal Time as Besselian epoch */ double ut2epb() { return (jd2epb (ut2jd())); } /* UT2EPJ-- Return current Universal Time as Julian epoch */ double ut2epj() { return (jd2epj (ut2jd())); } /* UT2FD-- Return current Universal Time as FITS ISO date string */ char * ut2fd() { int year, month, day, hour, minute, second; time_t tsec; struct timeval tp; struct timezone tzp; struct tm *ts; char *isotime; gettimeofday (&tp,&tzp); tsec = tp.tv_sec; ts = gmtime (&tsec); year = ts->tm_year; if (year < 1000) year = year + 1900; month = ts->tm_mon + 1; day = ts->tm_mday; hour = ts->tm_hour; minute = ts->tm_min; second = ts->tm_sec; isotime = (char *) calloc (32, sizeof (char)); sprintf (isotime, "%04d-%02d-%02dT%02d:%02d:%02d", year, month, day, hour, minute, second); return (isotime); } /* UT2JD-- Return current Universal Time as Julian Date */ double ut2jd() { return (fd2jd (ut2fd())); } /* UT2MJD-- convert current UT to Modified Julian Date */ double ut2mjd () { return (ut2jd() - 2400000.5); } /* UT2TS-- current Universal Time as IRAF seconds since 1950-01-01T00:00 */ double ut2ts() { double tsec; char *datestring; datestring = ut2fd(); tsec = fd2ts (datestring); free (datestring); return (tsec); } /* UT2TSI-- current Universal Time as IRAF seconds since 1980-01-01T00:00 */ int ut2tsi() { return ((int)(ut2ts() - 946684800.0)); } /* UT2TSU-- current Universal Time as IRAF seconds since 1970-01-01T00:00 */ time_t ut2tsu() { return ((time_t)(ut2ts () - 631152000.0)); } /* FD2GST-- convert from FITS date to Greenwich Sidereal Time */ char * fd2gst (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double dj, gsec, date, time; dj = fd2jd (string); gsec = jd2gst (dj); ts2dt (gsec, &date, &time); date = 0.0; return (dt2fd (date, time)); } /* DT2GST-- convert from UT as yyyy.mmdd hh.mmssss to Greenwich Sidereal Time*/ void dt2gst (date, time) double *date; /* Date as yyyy.mmdd */ double *time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { double dj, gsec; dj = dt2ts (*date, *time); gsec = jd2gst (dj); ts2dt (gsec, date, time); *date = 0.0; return; } /* JD2LST - Local Sidereal Time in seconds from Julian Date */ double jd2lst (dj) double dj; /* Julian Date */ { double gst, lst; /* Compute Greenwich Sidereal Time at this epoch */ gst = jd2gst (dj); /* Subtract longitude (in seconds of time) */ lst = gst - 3600.0 * (longitude / 15.0); if (lst < 0.0) lst = lst + 86400.0; else if (lst > 86400.0) lst = lst - 86400.0; return (lst); } /* FD2LST - Local Sidereal Time as hh:mm:ss.ss from Universal Time as FITS ISO date */ char * fd2lst (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) */ { double dj, date, time, lst; dj = fd2jd (string); lst = jd2lst (dj); ts2dt (lst, &date, &time); date = 0.0; return (dt2fd (date, time)); } /* DT2LST - Local Sidereal Time as hh.mmssss from Universal Time as yyyy.mmdd hh.mmssss */ void dt2lst (date, time) double *date; /* Date as yyyy.mmdd */ double *time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { double dj, lst, date0; dj = dt2jd (*date, *time); lst = jd2lst (dj); date0 = 0.0; ts2dt (lst, &date0, time); return; } /* TS2LST - Local Sidereal Time in seconds of day * from Universal Time in seconds since 1951-01-01T0:00:00 */ double ts2lst (tsec) double tsec; /* time since 1950.0 in UT seconds */ { double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ double lst; /* Local Sidereal Time in seconds since 0:00 */ double gsec, date; /* Greenwich Sidereal Time */ gsec = ts2gst (tsec); date = 0.0; ts2dt (gsec, &date, &gst); lst = gst - (longitude / 15.0); if (lst < 0.0) lst = lst + 86400.0; else if (lst > 86400.0) lst = lst - 86400.0; return (lst); } /* LST2FD - calculate current UT given Local Sidereal Time * plus date in FITS ISO format (yyyy-mm-dd) * Return UT date and time in FITS ISO format */ char * lst2fd (string) char *string; /* UT Date, LST as yyyy-mm-ddShh:mm:ss.ss */ { double sdj, dj; sdj = fd2jd (string); dj = lst2jd (sdj); return (jd2fd (dj)); } /* LST2JD - calculate current Julian Date given Local Sidereal Time * plus current Julian Date (0.5 at 0:00 UT) * Return UT date and time as Julian Date */ double lst2jd (sdj) double sdj; /* Julian Date of desired day at 0:00 UT + sidereal time */ { double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ double lsd; /* Local Sidereal Time in seconds since 0:00 */ double gst0, tsd, dj1, dj0, eqnx; int idj; /* Julian date at 0:00 UT */ idj = (int) sdj; dj0 = (double) idj + 0.5; if (dj0 > sdj) dj0 = dj0 - 1.0; /* Greenwich Sidereal Time at 0:00 UT in seconds */ gst0 = jd2gst (dj0); /* Sidereal seconds since 0:00 */ lsd = (sdj - dj0) * 86400.0; /* Remove longitude for current Greenwich Sidereal Time in seconds */ /* (convert longitude from degrees to seconds of time) */ gst = lsd + (longitude * 240.0); /* Time since 0:00 UT */ tsd = (gst - gst0) / 1.0027379093; /* Julian Date (UT) */ dj1 = dj0 + (tsd / 86400.0); /* Equation of the equinoxes converted to UT seconds */ eqnx = eqeqnx (dj1) / 1.002739093; /* Remove equation of equinoxes */ dj1 = dj1 - (eqnx / 86400.0); if (dj1 < dj0) dj1 = dj1 + 1.0; return (dj1); } /* MST2FD - calculate current UT given Greenwich Mean Sidereal Time * plus date in FITS ISO format (yyyy-mm-ddShh:mm:ss.ss) * Return UT date and time in FITS ISO format */ char * mst2fd (string) char *string; /* UT Date, MST as yyyy-mm-ddShh:mm:ss.ss */ { double sdj, dj; sdj = fd2jd (string); dj = mst2jd (sdj); return (jd2fd (dj)); } /* MST2JD - calculate current UT given Greenwich Mean Sidereal Time * plus date in Julian Date (0:00 UT + Mean Sidereal Time) * Return UT date and time as Julian Date */ double mst2jd (sdj) double sdj; /* UT Date, MST as Julian Date */ { double tsd, djd, st0, dj0, dj; dj0 = (double) ((int) sdj) + 0.5; /* Greenwich Mean Sidereal Time at 0:00 UT in seconds */ st0 = jd2mst (dj0); /* Mean Sidereal Time in seconds */ tsd = (sdj - dj0) * 86400.0; if (tsd < 0.0) tsd = tsd + 86400.0; /* Convert to fraction of a day since 0:00 UT */ djd = ((tsd - st0) / 1.0027379093) / 86400.0; /* Julian Date */ dj = dj0 + djd; if (dj < dj0) dj = dj + (1.0 / 1.0027379093); return (dj); } /* GST2FD - calculate current UT given Greenwich Sidereal Time * plus date in FITS ISO format (yyyy-mm-ddShh:mm:ss.ss) * Return UT date and time in FITS ISO format */ char * gst2fd (string) char *string; /* UT Date, GST as yyyy-mm-ddShh:mm:ss.ss */ { double sdj, dj; sdj = fd2jd (string); dj = gst2jd (sdj); return (jd2fd (dj)); } /* GST2JD - calculate current UT given Greenwich Sidereal Time * plus date as Julian Date (JD at 0:00 UT + sidereal time) * Return UT date and time as Julian Date */ double gst2jd (sdj) double sdj; /* UT Date, GST as Julian Date */ { double dj, tsd, djd, st0, dj0, eqnx; dj0 = (double) ((int) sdj) + 0.5; /* Greenwich Mean Sidereal Time at 0:00 UT in seconds */ st0 = jd2mst (dj0); /* Mean Sidereal Time in seconds */ tsd = (sdj - dj0) * 86400.0; if (tsd < 0.0) tsd = tsd + 86400.0; /* Convert to fraction of a day since 0:00 UT */ djd = ((tsd - st0) / 1.0027379093) / 86400.0; /* Julian Date */ dj = dj0 + djd; /* Equation of the equinoxes (converted to UT seconds) */ eqnx = eqeqnx (dj) / 1.002737909; dj = dj - eqnx / 86400.0; if (dj < dj0) dj = dj + 1.0; return (dj); } /* LST2DT - calculate current UT given Local Sidereal Time as hh.mmsss * plus date as yyyy.mmdd * Return UT time as hh.mmssss */ double lst2dt (date0, time0) double date0; /* UT date as yyyy.mmdd */ double time0; /* LST as hh.mmssss */ { double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ double lst; /* Local Sidereal Time in seconds since 0:00 */ double date1; /* UT date as yyyy.mmdd */ double time1; /* UT as hh.mmssss */ double tsec0, gst0, tsd, tsec; /* Greenwich Sidereal Time at 0:00 UT */ tsec0 = dt2ts (date0, 0.0); gst0 = ts2gst (tsec0); /* Current Greenwich Sidereal Time in seconds */ /* (convert longitude from degrees to seconds of time) */ lst = dt2ts (0.0, time0); gst = lst + (longitude * 240.0); /* Time since 0:00 UT */ tsd = (gst - gst0) / 1.0027379093; /* UT date and time */ tsec = tsec0 + tsd; ts2dt (tsec, &date1, &time1); return (time1); } /* TS2GST - calculate Greenwich Sidereal Time given Universal Time * in seconds since 1951-01-01T0:00:00 * Return sidereal time of day in seconds */ double ts2gst (tsec) double tsec; /* time since 1950.0 in UT seconds */ { double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ double tsd, eqnx, dj; int its; /* Elapsed time as of 0:00 UT */ if (tsec >= 0.0) { its = (int) (tsec + 0.5); tsd = (double) (its % 86400); } else { its = (int) (-tsec + 0.5); tsd = (double) (86400 - (its % 86400)); } /* Mean sidereal time */ gst = ts2mst (tsec); /* Equation of the equinoxes */ dj = ts2jd (tsec); eqnx = eqeqnx (dj); /* Apparent sidereal time at 0:00 ut */ gst = gst + eqnx; /* Current sidereal time */ gst = gst + (tsd * 1.0027379093); gst = dmod (gst,86400.0); return (gst); } /* FD2MST-- convert from FITS date Mean Sidereal Time */ char * fd2mst (string) char *string; /* FITS date string, which may be: fractional year dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { double gsec, date, time, dj; dj = fd2jd (string); gsec = jd2mst (dj); ts2dt (gsec, &date, &time); date = 0.0; return (dt2fd (date, time)); } /* DT2MST-- convert from UT as yyyy.mmdd hh.mmssss to Mean Sidereal Time in the same format */ void dt2mst (date, time) double *date; /* Date as yyyy.mmdd */ double *time; /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ { double date0, gsec, dj; date0 = *date; dj = dt2jd (*date, *time); gsec = jd2mst (dj); ts2dt (gsec, date, time); *date = date0; return; } /* TS2MST - calculate Greenwich Mean Sidereal Time given Universal Time * in seconds since 1951-01-01T0:00:00 */ double ts2mst (tsec) double tsec; /* time since 1950.0 in UT seconds */ { double dj; dj = ts2jd (tsec); return (jd2mst (dj)); } /* JD2MST - Julian Date to Greenwich Mean Sidereal Time using IAU 2000 * Return sideral time in seconds of time * (from USNO NOVAS package * http://aa.usno.navy.mil/software/novas/novas_info.html */ double jd2mst2 (dj) double dj; /* Julian Date */ { double dt, t, t2, t3, mst, st; dt = dj - 2451545.0; t = dt / 36525.0; t2 = t * t; t3 = t2 * t; /* Compute Greenwich Mean Sidereal Time in seconds */ st = (8640184.812866 * t) + (3155760000.0 * t) - (0.0000062 * t3) + (0.093104 * t2) + 67310.54841; mst = dmod (st, 86400.0); if (mst < 0.0) mst = mst + 86400.0; return (mst); } /* MJD2MST - Modified Julian Date to Greenwich Mean Sidereal Time using IAU 2000 * Return sideral time in seconds of time * (from USNO NOVAS package * http://aa.usno.navy.mil/software/novas/novas_info.html */ double mjd2mst (dj) double dj; /* Modified Julian Date */ { double dt, t, t2, t3, mst, st; dt = dj - 51544.5; t = dt / 36525.0; t2 = t * t; t3 = t2 * t; /* Compute Greenwich Mean Sidereal Time in seconds */ st = (8640184.812866 * t) + (3155760000.0 * t) - (0.0000062 * t3) + (0.093104 * t2) + 67310.54841; mst = dmod (st, 86400.0); if (mst < 0.0) mst = mst + 86400.0; return (mst); } /* JD2GST - Julian Date to Greenwich Sideral Time * Return sideral time in seconds of time * (Jean Meeus, Astronomical Algorithms, Willmann-Bell, 1991, pp 83-84) */ double jd2gst (dj) double dj; /* Julian Date */ { double dj0, gmt, gst, tsd, eqnx, ssd; double ts2ss = 1.00273790935; int ijd; /* Julian date at 0:00 UT */ ijd = (int) dj; dj0 = (double) ijd + 0.5; if (dj0 > dj) dj0 = dj0 - 1.0; /* Greenwich mean sidereal time at 0:00 UT in seconds */ gmt = jd2mst (dj0); /* Equation of the equinoxes */ eqnx = eqeqnx (dj); /* Apparent sidereal time at 0:00 ut */ gst = gmt + eqnx; /* UT seconds since 0:00 */ tsd = (dj - dj0) * 86400.0; ssd = tsd * ts2ss; /* Current sidereal time */ gst = gst + ssd; gst = dmod (gst, 86400.0); return (gst); } /* EQEQNX - Compute equation of the equinoxes for apparent sidereal time */ double eqeqnx (dj) double dj; /* Julian Date */ { double dt, edj, dpsi, deps, obl, eqnx; double rad2tsec = 13750.98708; /* Convert UT to Ephemeris Time (TDB or TT)*/ dt = utdt (dj); edj = dj + dt / 86400.0; /* Nutation and obliquity */ compnut (edj, &dpsi, &deps, &obl); /* Correct obliquity for nutation */ obl = obl + deps; /* Equation of the equinoxes in seconds */ eqnx = (dpsi * cos (obl)) * rad2tsec; return (eqnx); } /* JD2MST - Julian Date to Mean Sideral Time * Return sideral time in seconds of time * (Jean Meeus, Astronomical Algorithms, Willmann-Bell, 1991, pp 83-84) */ double jd2mst (dj) double dj; /* Julian Date */ { double dt, t, mst; dt = dj - 2451545.0; t = dt / 36525.0; /* Compute Greenwich mean sidereal time in degrees (Meeus, page 84) */ mst = 280.46061837 + (360.98564736629 * dt) + (0.000387933 * t * t) - (t * t * t / 38710000.0); /* Keep degrees between 0 and 360 */ while (mst > 360.0) mst = mst - 360.0; while (mst < 0.0) mst = mst + 360.0; /* Convert to time in seconds (3600 / 15) */ mst = mst * 240.0; /* Subtract longitude (in seconds of time) */ mst = mst - 3600.0 * (longitude / 15.0); if (mst < 0.0) mst = mst + 86400.0; else if (mst > 86400.0) mst = mst - 86400.0; return (mst); } /* COMPNUT - Compute nutation using the IAU 2000b model */ /* Translated from Pat Wallace's Fortran subroutine iau_nut00b (June 26 2007) into C by Jessica Mink on September 5, 2008 */ #define NLS 77 /* number of terms in the luni-solar nutation model */ void compnut (dj, dpsi, deps, eps0) double dj; /* Julian Date */ double *dpsi; /* Nutation in longitude in radians (returned) */ double *deps; /* Nutation in obliquity in radians (returned) */ double *eps0; /* Mean obliquity in radians (returned) */ /* This routine is translated from the International Astronomical Union's * Fortran SOFA (Standards Of Fundamental Astronomy) software collection. * * notes: * * 1) the nutation components in longitude and obliquity are in radians * and with respect to the equinox and ecliptic of date. the * obliquity at j2000 is assumed to be the lieske et al. (1977) value * of 84381.448 arcsec. (the errors that result from using this * routine with the iau 2006 value of 84381.406 arcsec can be * neglected.) * * the nutation model consists only of luni-solar terms, but includes * also a fixed offset which compensates for certain long-period * planetary terms (note 7). * * 2) this routine is an implementation of the iau 2000b abridged * nutation model formally adopted by the iau general assembly in * 2000. the routine computes the mhb_2000_short luni-solar nutation * series (luzum 2001), but without the associated corrections for * the precession rate adjustments and the offset between the gcrs * and j2000 mean poles. * * 3) the full IAU 2000a (mhb2000) nutation model contains nearly 1400 * terms. the IAU 2000b model (mccarthy & luzum 2003) contains only * 77 terms, plus additional simplifications, yet still delivers * results of 1 mas accuracy at present epochs. this combination of * accuracy and size makes the IAU 2000b abridged nutation model * suitable for most practical applications. * * the routine delivers a pole accurate to 1 mas from 1900 to 2100 * (usually better than 1 mas, very occasionally just outside 1 mas). * the full IAU 2000a model, which is implemented in the routine * iau_nut00a (q.v.), delivers considerably greater accuracy at * current epochs; however, to realize this improved accuracy, * corrections for the essentially unpredictable free-core-nutation * (fcn) must also be included. * * 4) the present routine provides classical nutation. the * mhb_2000_short algorithm, from which it is adapted, deals also * with (i) the offsets between the gcrs and mean poles and (ii) the * adjustments in longitude and obliquity due to the changed * precession rates. these additional functions, namely frame bias * and precession adjustments, are supported by the sofa routines * iau_bi00 and iau_pr00. * * 6) the mhb_2000_short algorithm also provides "total" nutations, * comprising the arithmetic sum of the frame bias, precession * adjustments, and nutation (luni-solar + planetary). these total * nutations can be used in combination with an existing IAU 1976 * precession implementation, such as iau_pmat76, to deliver gcrs-to- * true predictions of mas accuracy at current epochs. however, for * symmetry with the iau_nut00a routine (q.v. for the reasons), the * sofa routines do not generate the "total nutations" directly. * should they be required, they could of course easily be generated * by calling iau_bi00, iau_pr00 and the present routine and adding * the results. * * 7) the IAU 2000b model includes "planetary bias" terms that are fixed * in size but compensate for long-period nutations. the amplitudes * quoted in mccarthy & luzum (2003), namely dpsi = -1.5835 mas and * depsilon = +1.6339 mas, are optimized for the "total nutations" * method described in note 6. the luzum (2001) values used in this * sofa implementation, namely -0.135 mas and +0.388 mas, are * optimized for the "rigorous" method, where frame bias, precession * and nutation are applied separately and in that order. during the * interval 1995-2050, the sofa implementation delivers a maximum * error of 1.001 mas (not including fcn). * * References from original Fortran subroutines: * * Hilton, J. et al., 2006, Celest.Mech.Dyn.Astron. 94, 351 * * Lieske, J.H., Lederle, T., Fricke, W., Morando, B., "Expressions * for the precession quantities based upon the IAU 1976 system of * astronomical constants", Astron.Astrophys. 58, 1-2, 1-16. (1977) * * Luzum, B., private communication, 2001 (Fortran code * mhb_2000_short) * * McCarthy, D.D. & Luzum, B.J., "An abridged model of the * precession-nutation of the celestial pole", Cel.Mech.Dyn.Astron. * 85, 37-49 (2003) * * Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M., * Francou, G., Laskar, J., Astron.Astrophys. 282, 663-683 (1994) * */ { double as2r = 0.000004848136811095359935899141; /* arcseconds to radians */ double dmas2r = as2r / 1000.0; /* milliarcseconds to radians */ double as2pi = 1296000.0; /* arc seconds in a full circle */ double d2pi = 6.283185307179586476925287; /* 2pi */ double u2r = as2r / 10000000.0; /* units of 0.1 microarcsecond to radians */ double dj0 = 2451545.0; /* reference epoch (j2000), jd */ double djc = 36525.0; /* Days per julian century */ /* Miscellaneous */ double t, el, elp, f, d, om, arg, dp, de, sarg, carg; double dpsils, depsls, dpsipl, depspl; int i, j; int nls = NLS; /* number of terms in the luni-solar nutation model */ /* Fixed offset in lieu of planetary terms (radians) */ double dpplan = - 0.135 * dmas2r; double deplan = + 0.388 * dmas2r; /* Tables of argument and term coefficients */ /* Coefficients for fundamental arguments /* Luni-solar argument multipliers: */ /* l l' f d om */ static int nals[5*NLS]= {0, 0, 0, 0, 1, 0, 0, 2, -2, 2, 0, 0, 2, 0, 2, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 1, 2, -2, 2, 1, 0, 0, 0, 0, 0, 0, 2, 0, 1, 1, 0, 2, 0, 2, 0, -1, 2, -2, 2, 0, 0, 2, -2, 1, -1, 0, 2, 0, 2, -1, 0, 0, 2, 0, 1, 0, 0, 0, 1, -1, 0, 0, 0, 1, -1, 0, 2, 2, 2, 1, 0, 2, 0, 1, -2, 0, 2, 0, 1, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 0, -2, 2, -2, 2, -2, 0, 0, 2, 0, 2, 0, 2, 0, 2, 1, 0, 2, -2, 2, -1, 0, 2, 0, 1, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 2, 1, 0, 2, 2, -2, 2, 0, 0, -2, 2, 0, 1, 0, 0, -2, 1, 0, -1, 0, 0, 1, -1, 0, 2, 2, 1, 0, 2, 0, 0, 0, 1, 0, 2, 2, 2, -2, 0, 2, 0, 0, 0, 1, 2, 0, 2, 0, 0, 2, 2, 1, 0, -1, 2, 0, 2, 0, 0, 0, 2, 1, 1, 0, 2, -2, 1, 2, 0, 2, -2, 2, -2, 0, 0, 2, 1, 2, 0, 2, 0, 1, 0, -1, 2, -2, 1, 0, 0, 0, -2, 1, -1, -1, 0, 2, 0, 2, 0, 0, -2, 1, 1, 0, 0, 2, 0, 0, 1, 2, -2, 1, 1, -1, 0, 0, 0, -2, 0, 2, 0, 2, 3, 0, 2, 0, 2, 0, -1, 0, 2, 0, 1, -1, 2, 0, 2, 0, 0, 0, 1, 0, -1, -1, 2, 2, 2, -1, 0, 2, 0, 0, 0, -1, 2, 2, 2, -2, 0, 0, 0, 1, 1, 1, 2, 0, 2, 2, 0, 0, 0, 1, -1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 2, 0, 0, -1, 0, 2, -2, 1, 1, 0, 0, 0, 2, -1, 0, 0, 1, 0, 0, 0, 2, 1, 2, -1, 0, 2, 4, 2, -1, 1, 0, 1, 1, 0, -2, 2, -2, 1, 1, 0, 2, 2, 1, -2, 0, 2, 2, 2, -1, 0, 0, 0, 2, 1, 1, 2, -2, 2}; /* Luni-solar nutation coefficients, in 1e-7 arcsec */ /* longitude (sin, t*sin, cos), obliquity (cos, t*cos, sin) */ static double cls[6*NLS]= {-172064161.0, -174666.0, 33386.0, 92052331.0, 9086.0, 15377.0, -13170906.0, -1675.0, -13696.0, 5730336.0, -3015.0, -4587.0, -2276413.0, -234.0, 2796.0, 978459.0, -485.0, 1374.0, 2074554.0, 207.0, -698.0, -897492.0, 470.0, -291.0, 1475877.0, -3633.0, 11817.0, 73871.0, -184.0, -1924.0, -516821.0, 1226.0, -524.0, 224386.0, -677.0, -174.0, 711159.0, 73.0, -872.0, -6750.0, 0.0, 358.0, -387298.0, -367.0, 380.0, 200728.0, 18.0, 318.0, -301461.0, -36.0, 816.0, 129025.0, -63.0, 367.0, 215829.0, -494.0, 111.0, -95929.0, 299.0, 132.0, 128227.0, 137.0, 181.0, -68982.0, -9.0, 39.0, 123457.0, 11.0, 19.0, -53311.0, 32.0, -4.0, 156994.0, 10.0, -168.0, -1235.0, 0.0, 82.0, 63110.0, 63.0, 27.0, -33228.0, 0.0, -9.0, -57976.0, -63.0, -189.0, 31429.0, 0.0, -75.0, -59641.0, -11.0, 149.0, 25543.0, -11.0, 66.0, -51613.0, -42.0, 129.0, 26366.0, 0.0, 78.0, 45893.0, 50.0, 31.0, -24236.0, -10.0, 20.0, 63384.0, 11.0, -150.0, -1220.0, 0.0, 29.0, -38571.0, -1.0, 158.0, 16452.0, -11.0, 68.0, 32481.0, 0.0, 0.0, -13870.0, 0.0, 0.0, -47722.0, 0.0, -18.0, 477.0, 0.0, -25.0, -31046.0, -1.0, 131.0, 13238.0, -11.0, 59.0, 28593.0, 0.0, -1.0, -12338.0, 10.0, -3.0, 20441.0, 21.0, 10.0, -10758.0, 0.0, -3.0, 29243.0, 0.0, -74.0, -609.0, 0.0, 13.0, 25887.0, 0.0, -66.0, -550.0, 0.0, 11.0, -14053.0, -25.0, 79.0, 8551.0, -2.0, -45.0, 15164.0, 10.0, 11.0, -8001.0, 0.0, -1.0, -15794.0, 72.0, -16.0, 6850.0, -42.0, -5.0, 21783.0, 0.0, 13.0, -167.0, 0.0, 13.0, -12873.0, -10.0, -37.0, 6953.0, 0.0, -14.0, -12654.0, 11.0, 63.0, 6415.0, 0.0, 26.0, -10204.0, 0.0, 25.0, 5222.0, 0.0, 15.0, 16707.0, -85.0, -10.0, 168.0, -1.0, 10.0, -7691.0, 0.0, 44.0, 3268.0, 0.0, 19.0, -11024.0, 0.0, -14.0, 104.0, 0.0, 2.0, 7566.0, -21.0, -11.0, -3250.0, 0.0, -5.0, -6637.0, -11.0, 25.0, 3353.0, 0.0, 14.0, -7141.0, 21.0, 8.0, 3070.0, 0.0, 4.0, -6302.0, -11.0, 2.0, 3272.0, 0.0, 4.0, 5800.0, 10.0, 2.0, -3045.0, 0.0, -1.0, 6443.0, 0.0, -7.0, -2768.0, 0.0, -4.0, -5774.0, -11.0, -15.0, 3041.0, 0.0, -5.0, -5350.0, 0.0, 21.0, 2695.0, 0.0, 12.0, -4752.0, -11.0, -3.0, 2719.0, 0.0, -3.0, -4940.0, -11.0, -21.0, 2720.0, 0.0, -9.0, 7350.0, 0.0, -8.0, -51.0, 0.0, 4.0, 4065.0, 0.0, 6.0, -2206.0, 0.0, 1.0, 6579.0, 0.0, -24.0, -199.0, 0.0, 2.0, 3579.0, 0.0, 5.0, -1900.0, 0.0, 1.0, 4725.0, 0.0, -6.0, -41.0, 0.0, 3.0, -3075.0, 0.0, -2.0, 1313.0, 0.0, -1.0, -2904.0, 0.0, 15.0, 1233.0, 0.0, 7.0, 4348.0, 0.0, -10.0, -81.0, 0.0, 2.0, -2878.0, 0.0, 8.0, 1232.0, 0.0, 4.0, -4230.0, 0.0, 5.0, -20.0, 0.0, -2.0, -2819.0, 0.0, 7.0, 1207.0, 0.0, 3.0, -4056.0, 0.0, 5.0, 40.0, 0.0, -2.0, -2647.0, 0.0, 11.0, 1129.0, 0.0, 5.0, -2294.0, 0.0, -10.0, 1266.0, 0.0, -4.0, 2481.0, 0.0, -7.0, -1062.0, 0.0, -3.0, 2179.0, 0.0, -2.0, -1129.0, 0.0, -2.0, 3276.0, 0.0, 1.0, -9.0, 0.0, 0.0, -3389.0, 0.0, 5.0, 35.0, 0.0, -2.0, 3339.0, 0.0, -13.0, -107.0, 0.0, 1.0, -1987.0, 0.0, -6.0, 1073.0, 0.0, -2.0, -1981.0, 0.0, 0.0, 854.0, 0.0, 0.0, 4026.0, 0.0, -353.0, -553.0, 0.0, -139.0, 1660.0, 0.0, -5.0, -710.0, 0.0, -2.0, -1521.0, 0.0, 9.0, 647.0, 0.0, 4.0, 1314.0, 0.0, 0.0, -700.0, 0.0, 0.0, -1283.0, 0.0, 0.0, 672.0, 0.0, 0.0, -1331.0, 0.0, 8.0, 663.0, 0.0, 4.0, 1383.0, 0.0, -2.0, -594.0, 0.0, -2.0, 1405.0, 0.0, 4.0, -610.0, 0.0, 2.0, 1290.0, 0.0, 0.0, -556.0, 0.0, 0.0}; /* Interval between fundamental epoch J2000.0 and given date (JC) */ t = (dj - dj0) / djc; /* Luni-solar nutation */ /* Fundamental (delaunay) arguments from Simon et al. (1994) */ /* Mean anomaly of the moon */ el = fmod (485868.249036 + (1717915923.2178 * t), as2pi) * as2r; /* Mean anomaly of the sun */ elp = fmod (1287104.79305 + (129596581.0481 * t), as2pi) * as2r; /* Mean argument of the latitude of the moon */ f = fmod (335779.526232 + (1739527262.8478 * t), as2pi) * as2r; /* Mean elongation of the moon from the sun */ d = fmod (1072260.70369 + (1602961601.2090 * t), as2pi ) * as2r; /* Mean longitude of the ascending node of the moon */ om = fmod (450160.398036 - (6962890.5431 * t), as2pi ) * as2r; /* Initialize the nutation values */ dp = 0.0; de = 0.0; /* Summation of luni-solar nutation series (in reverse order) */ for (i = nls; i > 0; i=i-1) { j = i - 1; /* Argument and functions */ arg = fmod ( (double) (nals[5*j]) * el + (double) (nals[1+5*j]) * elp + (double) (nals[2+5*j]) * f + (double) (nals[3+5*j]) * d + (double) (nals[4+5*j]) * om, d2pi); sarg = sin (arg); carg = cos (arg); /* Terms */ dp = dp + (cls[6*j] + cls[1+6*j] * t) * sarg + cls[2+6*j] * carg; de = de + (cls[3+6*j] + cls[4+6*j] * t) * carg + cls[5+6*j] * sarg; } /* Convert from 0.1 microarcsec units to radians */ dpsils = dp * u2r; depsls = de * u2r; /* In lieu of planetary nutation */ /* Fixed offset to correct for missing terms in truncated series */ dpsipl = dpplan; depspl = deplan; /* Results */ /* Add luni-solar and planetary components */ *dpsi = dpsils + dpsipl; *deps = depsls + depspl; /* Mean Obliquity in radians (IAU 2006, Hilton, et al.) */ *eps0 = ( 84381.406 + ( -46.836769 + ( -0.0001831 + ( 0.00200340 + ( -0.000000576 + ( -0.0000000434 ) * t ) * t ) * t ) * t ) * t ) * as2r; } /* ISDATE - Return 1 if string is an old or ISO FITS standard date */ int isdate (string) char *string; /* Possible FITS date string, which may be: dd/mm/yy (FITS standard before 2000) dd-mm-yy (nonstandard FITS use before 2000) yyyy-mm-dd (FITS standard after 1999) yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ { int iyr = 0; /* year (returned) */ int imon = 0; /* month (returned) */ int iday = 0; /* day (returned) */ int i; char *sstr, *dstr, *tstr, *nval; /* Translate string from ASCII to binary */ if (string == NULL) return (0); sstr = strchr (string,'/'); dstr = strchr (string,'-'); if (dstr == string) dstr = strchr (string+1,'-'); tstr = strchr (string,'T'); /* Original FITS date format: dd/mm/yy */ if (sstr > string) { *sstr = '\0'; iday = (int) atof (string); *sstr = '/'; nval = sstr + 1; sstr = strchr (nval,'/'); if (sstr == NULL) sstr = strchr (nval,'-'); if (sstr > string) { *sstr = '\0'; imon = (int) atof (nval); *sstr = '/'; nval = sstr + 1; iyr = (int) atof (nval); if (iyr < 1000) iyr = iyr + 1900; } if (imon > 0 && iday > 0) return (1); else return (0); } /* New FITS date format: yyyy-mm-ddThh:mm:ss[.sss] */ else if (dstr > string) { *dstr = '\0'; iyr = (int) atof (string); nval = dstr + 1; *dstr = '-'; dstr = strchr (nval,'-'); imon = 0; iday = 0; /* Decode year, month, and day */ if (dstr > string) { *dstr = '\0'; imon = (int) atof (nval); *dstr = '-'; nval = dstr + 1; if (tstr > string) *tstr = '\0'; iday = (int) atof (nval); if (tstr > string) *tstr = 'T'; } /* If day is > 31, it is really year in old format */ if (iday > 31) { i = iyr; if (iday < 100) iyr = iday + 1900; else iyr = iday; iday = i; } if (imon > 0 && iday > 0) return (1); else return (0); } /* If FITS date is entered as an epoch, return 0 anyway */ else return (0); } /* Round seconds and make sure date and time numbers are within limits */ static void fixdate (iyr, imon, iday, ihr, imn, sec, ndsec) int *iyr; /* year (returned) */ int *imon; /* month (returned) */ int *iday; /* day (returned) */ int *ihr; /* hours (returned) */ int *imn; /* minutes (returned) */ double *sec; /* seconds (returned) */ int ndsec; /* Number of decimal places in seconds (0=int) */ { double days; /* Round seconds to 0 - 4 decimal places (no rounding if <0, >4) */ if (ndsec == 0) *sec = dint (*sec + 0.5); else if (ndsec < 2) *sec = dint (*sec * 10.0 + 0.5) / 10.0; else if (ndsec < 3) *sec = dint (*sec * 100.0 + 0.5) / 100.0; else if (ndsec < 4) *sec = dint (*sec * 1000.0 + 0.5) / 1000.0; else if (ndsec < 5) *sec = dint (*sec * 10000.0 + 0.5) / 10000.0; /* Adjust minutes and hours */ if (*sec > 60.0) { *sec = *sec - 60.0; *imn = *imn + 1; } if (*imn > 60) { *imn = *imn - 60; *ihr = *ihr + 1; } /* Return if no date */ if (*iyr == 0 && *imon == 0 && *iday == 0) return; /* Adjust date */ if (*ihr > 23) { *ihr = *ihr - 24; *iday = *iday + 1; } days = caldays (*iyr, *imon); if (*iday > days) { *iday = *iday - days; *imon = *imon + 1; } if (*iday < 1) { *imon = *imon - 1; if (*imon < 1) { *imon = *imon + 12; *iyr = *iyr - 1; } days = caldays (*iyr, *imon); *iday = *iday + days; } if (*imon < 1) { *imon = *imon + 12; *iyr = *iyr - 1; days = caldays (*iyr, *imon); if (*iday > days) { *iday = *iday - days; *imon = *imon + 1; } } if (*imon > 12) { *imon = *imon - 12; *iyr = *iyr + 1; } return; } /* Calculate days in month 1-12 given year (Gregorian calendar only) */ static int caldays (year, month) int year; /* 4-digit year */ int month; /* Month (1=January, 2=February, etc.) */ { if (month < 1) { month = month + 12; year = year + 1; } if (month > 12) { month = month - 12; year = year + 1; } switch (month) { case 1: return (31); case 2: if (year%400 == 0) return (29); else if (year%100 == 0) return (28); else if (year%4 == 0) return (29); else return (28); case 3: return (31); case 4: return (30); case 5: return (31); case 6: return (30); case 7: return (31); case 8: return (31); case 9: return (30); case 10: return (31); case 11: return (30); case 12: return (31); default: return (0); } } static double dint (dnum) double dnum; { double dn; if (dnum < 0.0) dn = -floor (-dnum); else dn = floor (dnum); return (dn); } static double dmod (dnum, dm) double dnum, dm; { double dnumx, dnumi, dnumf; if (dnum < 0.0) dnumx = -dnum; else dnumx = dnum; dnumi = dint (dnumx / dm); if (dnum < 0.0) dnumf = dnum + (dnumi * dm); else if (dnum > 0.0) dnumf = dnum - (dnumi * dm); else dnumf = 0.0; return (dnumf); } /* Jul 1 1999 New file, based on iolib/jcon.f and iolib/vcon.f and hgetdate() * Oct 21 1999 Fix declarations after lint * Oct 27 1999 Fix bug to return epoch if fractional year input * Dec 9 1999 Fix bug in ts2jd() found by Pete Ratzlaff (SAO) * Dec 17 1999 Add all unimplemented conversions * Dec 20 1999 Add isdate(); leave date, time strings unchanged in fd2i() * Dec 20 1999 Make all fd2*() subroutines deal with time alone * * Jan 3 2000 In old FITS format, year 100 is assumed to be 2000 * Jan 11 2000 Fix epoch to date conversion so .0 is 0:00, not 12:00 * Jan 21 2000 Add separate Besselian and Julian epoch computations * Jan 28 2000 Add Modified Julian Date conversions * Mar 2 2000 Implement decimal places for FITS date string * Mar 14 2000 Fix bug in dealing with 2000-02-29 in ts2i() * Mar 22 2000 Add lt2* and ut2* to get current time as local and UT * Mar 24 2000 Fix calloc() calls * Mar 24 2000 Add tsi2* and tsu2* to convert IRAF and Unix seconds * May 1 2000 In old FITS format, all years < 1000 get 1900 added to them * Aug 1 2000 Make ep2jd and jd2ep consistently starting at 1/1 0:00 * * Jan 11 2001 Print all messages to stderr * May 21 2001 Add day of year conversions * May 25 2001 Allow fraction of day in FITS date instead of time * * Apr 8 2002 Change all long declaration to time_t * May 13 2002 Fix bugs found by lint * Jul 5 2002 Fix bug in fixdate() so fractional seconds come out * Jul 8 2002 Fix rounding bug in t2i() * Jul 8 2002 Try Fliegel and Van Flandern's algorithm for JD to UT date * Jul 8 2002 If first character of string is -, check for other -'s in isdate * Sep 10 2002 Add ET/TDT/TT conversion from UT subroutines * Sep 10 2002 Add sidereal time conversions * * Jan 30 2003 Fix typo in ts2gst() * Mar 7 2003 Add conversions for heliocentric julian dates * May 20 2003 Declare nd in setdatedec() * Jul 18 2003 Add code to parse Las Campanas dates * * Mar 24 2004 If ndec > 0, add UT to FITS date even if it is 0:00:00 * * Oct 14 2005 Add tsd2fd() and tsd2dt() * * May 3 2006 Drop declaration of unused variables * Jun 20 2006 Initialized uninitialized variables * Aug 2 2006 Add local sidereal time * Sep 13 2006 Add more local sidereal time subroutines * Oct 2 2006 Add UT to old FITS date conversions * Oct 6 2006 Add eqeqnx() to compute equation of the equinoxes * * Jan 8 2007 Remove unused variables * * Sep 5 2008 Replace nutation with IAU 2006 model translated from SOFA * Sep 9 2008 Add ang2hr(), ang2deg(), hr2ang(), deg2ang() * Sep 10 2008 Add longitude to mean standard time (default = Greenwich) */ wcstools-3.9.5/libwcs/distort.c0000664000016200001660000002303011750060473015573 0ustar minkoirsys/*** File libwcs/distort.c *** January 4, 2007 *** By Jessica Mink, jmink@cfa.harvard.edu, *** Based on code written by Jing Li, IPAC *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 2004-2007 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: distort.c (World Coordinate Systems) * Purpose: Convert focal plane coordinates to pixels and vice versa: * Subroutine: distortinit (wcs, hstring) set distortion coefficients from FITS header * Subroutine: DelDistort (header, verbose) delete distortion coefficients in FITS header * Subroutine: pix2foc (wcs, x, y, u, v) pixel coordinates -> focal plane coordinates * Subroutine: foc2pix (wcs, u, v, x, y) focal plane coordinates -> pixel coordinates * Subroutine: setdistcode (wcs,ctype) sets distortion code from CTYPEi * Subroutine: getdistcode (wcs) returns distortion code string for CTYPEi */ #include #include #include #include #include "wcs.h" void distortinit (wcs, hstring) struct WorldCoor *wcs; /* World coordinate system structure */ const char *hstring; /* character string containing FITS header information in the format = [/ ] */ { int i, j, m; char keyword[12]; /* Read distortion coefficients, if present */ if (wcs->distcode == DISTORT_SIRTF) { if (wcs->wcsproj == WCS_OLD) { wcs->wcsproj = WCS_NEW; wcs->distort.a_order = 0; wcs->distort.b_order = 0; wcs->distort.ap_order = 0; wcs->distort.bp_order = 0; } else { if (!hgeti4 (hstring, "A_ORDER", &wcs->distort.a_order)) { setwcserr ("DISTINIT: Missing A_ORDER keyword for Spitzer distortion"); } else { m = wcs->distort.a_order; for (i = 0; i <= m; i++) { for (j = 0; j <= m; j++) { wcs->distort.a[i][j] = 0.0; } } for (i = 0; i <= m; i++) { for (j = 0; j <= m-i; j++) { sprintf (keyword, "A_%d_%d", i, j); hgetr8 (hstring, keyword, &wcs->distort.a[i][j]); } } } if (!hgeti4 (hstring, "B_ORDER", &wcs->distort.b_order)) { setwcserr ("DISTINIT: Missing B_ORDER keyword for Spitzer distortion"); } else { m = wcs->distort.b_order; for (i = 0; i <= m; i++) { for (j = 0; j <= m; j++) { wcs->distort.b[i][j] = 0.0; } } for (i = 0; i <= m; i++) { for (j = 0; j <= m-i; j++) { sprintf (keyword, "B_%d_%d", i, j); hgetr8 (hstring, keyword, &wcs->distort.b[i][j]); } } } if (!hgeti4 (hstring, "AP_ORDER", &wcs->distort.ap_order)) { setwcserr ("DISTINIT: Missing AP_ORDER keyword for Spitzer distortion"); } else { m = wcs->distort.ap_order; for (i = 0; i <= m; i++) { for (j = 0; j <= m; j++) { wcs->distort.ap[i][j] = 0.0; } } for (i = 0; i <= m; i++) { for (j = 0; j <= m-i; j++) { sprintf (keyword, "AP_%d_%d", i, j); hgetr8 (hstring, keyword, &wcs->distort.ap[i][j]); } } } if (!hgeti4 (hstring, "BP_ORDER", &wcs->distort.bp_order)) { setwcserr ("DISTINIT: Missing BP_ORDER keyword for Spitzer distortion"); } else { m = wcs->distort.bp_order; for (i = 0; i <= m; i++) { for (j = 0; j <= m; j++) { wcs->distort.bp[i][j] = 0.0; } } for (i = 0; i <= m; i++) { for (j = 0; j <= m-i; j++) { sprintf (keyword, "BP_%d_%d", i, j); hgetr8 (hstring, keyword, &wcs->distort.bp[i][j]); } } } } } return; } /* Delete all distortion-related fields. * return 0 if at least one such field is found, else -1. */ int DelDistort (header, verbose) char *header; int verbose; { char keyword[16]; char str[32]; int i, j, m; int lctype; int n; n = 0; if (hgeti4 (header, "A_ORDER", &m)) { for (i = 0; i <= m; i++) { for (j = 0; j <= m-i; j++) { sprintf (keyword, "A_%d_%d", i, j); hdel (header, keyword); n++; } } hdel (header, "A_ORDER"); n++; } if (hgeti4 (header, "AP_ORDER", &m)) { for (i = 0; i <= m; i++) { for (j = 0; j <= m-i; j++) { sprintf (keyword, "AP_%d_%d", i, j); hdel (header, keyword); n++; } } hdel (header, "AP_ORDER"); n++; } if (hgeti4 (header, "B_ORDER", &m)) { for (i = 0; i <= m; i++) { for (j = 0; j <= m-i; j++) { sprintf (keyword, "B_%d_%d", i, j); hdel (header, keyword); n++; } } hdel (header, "B_ORDER"); n++; } if (hgeti4 (header, "BP_ORDER", &m)) { for (i = 0; i <= m; i++) { for (j = 0; j <= m-i; j++) { sprintf (keyword, "BP_%d_%d", i, j); hdel (header, keyword); n++; } } hdel (header, "BP_ORDER"); n++; } if (n > 0 && verbose) fprintf (stderr,"%d keywords deleted\n", n); /* Remove WCS distortion code from CTYPEi in FITS header */ if (hgets (header, "CTYPE1", 31, str)) { lctype = strlen (str); if (lctype > 8) { str[8] = (char) 0; hputs (header, "CTYPE1", str); } } if (hgets (header, "CTYPE2", 31, str)) { lctype = strlen (str); if (lctype > 8) { str[8] = (char) 0; hputs (header, "CTYPE2", str); } } return (n); } void foc2pix (wcs, x, y, u, v) struct WorldCoor *wcs; /* World coordinate system structure */ double x, y; /* Focal plane coordinates */ double *u, *v; /* Image pixel coordinates (returned) */ { int m, n, i, j, k; double s[DISTMAX], sum; double temp_x, temp_y; /* Spitzer distortion */ if (wcs->distcode == DISTORT_SIRTF) { m = wcs->distort.ap_order; n = wcs->distort.bp_order; temp_x = x - wcs->xrefpix; temp_y = y - wcs->yrefpix; /* compute u */ for (j = 0; j <= m; j++) { s[j] = wcs->distort.ap[m-j][j]; for (k = j-1; k >= 0; k--) { s[j] = (temp_y * s[j]) + wcs->distort.ap[m-j][k]; } } sum = s[0]; for (i=m; i>=1; i--){ sum = (temp_x * sum) + s[m-i+1]; } *u = sum; /* compute v*/ for (j = 0; j <= n; j++) { s[j] = wcs->distort.bp[n-j][j]; for (k = j-1; k >= 0; k--) { s[j] = temp_y*s[j] + wcs->distort.bp[n-j][k]; } } sum = s[0]; for (i = n; i >= 1; i--) sum = temp_x * sum + s[n-i+1]; *v = sum; *u = x + *u; *v = y + *v; } /* If no distortion, return pixel positions unchanged */ else { *u = x; *v = y; } return; } void pix2foc (wcs, u, v, x, y) struct WorldCoor *wcs; /* World coordinate system structure */ double u, v; /* Image pixel coordinates */ double *x, *y; /* Focal plane coordinates (returned) */ { int m, n, i, j, k; double s[DISTMAX], sum; double temp_u, temp_v; /* Spitzer distortion */ if (wcs->distcode == DISTORT_SIRTF) { m = wcs->distort.a_order; n = wcs->distort.b_order; temp_u = u - wcs->xrefpix; temp_v = v - wcs->yrefpix; /* compute u */ for (j = 0; j <= m; j++) { s[j] = wcs->distort.a[m-j][j]; for (k = j-1; k >= 0; k--) { s[j] = (temp_v * s[j]) + wcs->distort.a[m-j][k]; } } sum = s[0]; for (i=m; i>=1; i--){ sum = temp_u*sum + s[m-i+1]; } *x = sum; /* compute v*/ for (j=0; j<=n; j++) { s[j] = wcs->distort.b[n-j][j]; for (k=j-1; k>=0; k--) { s[j] =temp_v*s[j] + wcs->distort.b[n-j][k]; } } sum = s[0]; for (i=n; i>=1; i--) sum = temp_u*sum + s[n-i+1]; *y = sum; *x = u + *x; *y = v + *y; /* *x = u + *x + coeff.crpix1; */ /* *y = v + *y + coeff.crpix2; */ } /* If no distortion, return pixel positions unchanged */ else { *x = u; *y = v; } return; } /* SETDISTCODE -- Set WCS distortion code from CTYPEi in FITS header */ void setdistcode (wcs, ctype) struct WorldCoor *wcs; /* World coordinate system structure */ char *ctype; /* Value of CTYPEi from FITS header */ { char *extension; int lctype; lctype = strlen (ctype); if (lctype < 9) wcs->distcode = DISTORT_NONE; else { extension = ctype + 8; if (!strncmp (extension, "-SIP", 4)) wcs->distcode = DISTORT_SIRTF; else wcs->distcode = DISTORT_NONE; } return; } /* GETDISTCODE -- Return NULL if no distortion or code from wcs.h */ char * getdistcode (wcs) struct WorldCoor *wcs; /* World coordinate system structure */ { char *dcode; /* Distortion string for CTYPEi */ if (wcs->distcode == DISTORT_SIRTF) { dcode = (char *) calloc (8, sizeof (char)); strcpy (dcode, "-SIP"); } else dcode = NULL; return (dcode); } /* Apr 2 2003 New subroutines * Nov 3 2003 Add getdistcode to return distortion code string * Nov 10 2003 Include unistd.h to get definition of NULL * Nov 18 2003 Include string.h to get strlen() * * Jan 9 2004 Add DelDistort() to delete distortion keywords * * Jan 4 2007 Declare header const char* * * Feb 25 2011 Change SIRTF to Spitzer (long overdue!) */ wcstools-3.9.5/libwcs/dsspos.c0000664000016200001660000002633411750060473015430 0ustar minkoirsys/*** File saoimage/wcslib/dsspos.c *** October 21, 1999 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1995-2002 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: dsspos.c (Plate solution WCS conversion) * Purpose: Compute WCS from Digital Sky Survey plate fit * Subroutine: dsspos() converts from pixel location to RA,Dec * Subroutine: dsspix() converts from RA,Dec to pixel location These functions are based on the astrmcal.c portion of GETIMAGE by J. Doggett and the documentation distributed with the Digital Sky Survey. */ #include #include #include #include "wcs.h" int dsspos (xpix, ypix, wcs, xpos, ypos) /* Routine to determine accurate position for pixel coordinates */ /* returns 0 if successful otherwise 1 = angle too large for projection; */ /* based on amdpos() from getimage */ /* Input: */ double xpix; /* x pixel number (RA or long without rotation) */ double ypix; /* y pixel number (dec or lat without rotation) */ struct WorldCoor *wcs; /* WCS parameter structure */ /* Output: */ double *xpos; /* Right ascension or longitude in degrees */ double *ypos; /* Declination or latitude in degrees */ { double x, y, xmm, ymm, xmm2, ymm2, xmm3, ymm3, x2y2; double xi, xir, eta, etar, raoff, ra, dec; double cond2r = 1.745329252e-2; double cons2r = 206264.8062470964; double twopi = 6.28318530717959; double ctan, ccos; /* Ignore magnitude and color terms double mag = 0.0; double color = 0.0; */ /* Convert from image pixels to plate pixels */ x = xpix + wcs->x_pixel_offset - 1.0 + 0.5; y = ypix + wcs->y_pixel_offset - 1.0 + 0.5; /* Convert from pixels to millimeters */ xmm = (wcs->ppo_coeff[2] - x * wcs->x_pixel_size) / 1000.0; ymm = (y * wcs->y_pixel_size - wcs->ppo_coeff[5]) / 1000.0; xmm2 = xmm * xmm; ymm2 = ymm * ymm; xmm3 = xmm * xmm2; ymm3 = ymm * ymm2; x2y2 = xmm2 + ymm2; /* Compute coordinates from x,y and plate model */ xi = wcs->x_coeff[ 0]*xmm + wcs->x_coeff[ 1]*ymm + wcs->x_coeff[ 2] + wcs->x_coeff[ 3]*xmm2 + wcs->x_coeff[ 4]*xmm*ymm + wcs->x_coeff[ 5]*ymm2 + wcs->x_coeff[ 6]*(x2y2) + wcs->x_coeff[ 7]*xmm3 + wcs->x_coeff[ 8]*xmm2*ymm + wcs->x_coeff[ 9]*xmm*ymm2 + wcs->x_coeff[10]*ymm3 + wcs->x_coeff[11]*xmm*(x2y2) + wcs->x_coeff[12]*xmm*x2y2*x2y2; /* Ignore magnitude and color terms + wcs->x_coeff[13]*mag + wcs->x_coeff[14]*mag*mag + wcs->x_coeff[15]*mag*mag*mag + wcs->x_coeff[16]*mag*xmm + wcs->x_coeff[17]*mag*x2y2 + wcs->x_coeff[18]*mag*xmm*x2y2 + wcs->x_coeff[19]*color; */ eta = wcs->y_coeff[ 0]*ymm + wcs->y_coeff[ 1]*xmm + wcs->y_coeff[ 2] + wcs->y_coeff[ 3]*ymm2 + wcs->y_coeff[ 4]*xmm*ymm + wcs->y_coeff[ 5]*xmm2 + wcs->y_coeff[ 6]*(x2y2) + wcs->y_coeff[ 7]*ymm3 + wcs->y_coeff[ 8]*ymm2*xmm + wcs->y_coeff[ 9]*ymm*xmm2 + wcs->y_coeff[10]*xmm3 + wcs->y_coeff[11]*ymm*(x2y2) + wcs->y_coeff[12]*ymm*x2y2*x2y2; /* Ignore magnitude and color terms + wcs->y_coeff[13]*mag + wcs->y_coeff[14]*mag*mag + wcs->y_coeff[15]*mag*mag*mag + wcs->y_coeff[16]*mag*ymm + wcs->y_coeff[17]*mag*x2y2) + wcs->y_coeff[18]*mag*ymm*x2y2 + wcs->y_coeff[19]*color; */ /* Convert to radians */ xir = xi / cons2r; etar = eta / cons2r; /* Convert to RA and Dec */ ctan = tan (wcs->plate_dec); ccos = cos (wcs->plate_dec); raoff = atan2 (xir / ccos, 1.0 - etar * ctan); ra = raoff + wcs->plate_ra; if (ra < 0.0) ra = ra + twopi; *xpos = ra / cond2r; dec = atan (cos (raoff) * ((etar + ctan) / (1.0 - (etar * ctan)))); *ypos = dec / cond2r; return 0; } int dsspix (xpos, ypos, wcs, xpix, ypix) /* Routine to determine pixel coordinates for sky position */ /* returns 0 if successful otherwise 1 = angle too large for projection; */ /* based on amdinv() from getimage */ /* Input: */ double xpos; /* Right ascension or longitude in degrees */ double ypos; /* Declination or latitude in degrees */ struct WorldCoor *wcs; /* WCS parameter structure */ /* Output: */ double *xpix; /* x pixel number (RA or long without rotation) */ double *ypix; /* y pixel number (dec or lat without rotation) */ { double div,xi,eta,x,y,xy,x2,y2,x2y,y2x,x3,y3,x4,y4,x2y2,cjunk,dx,dy; double sypos,cypos,syplate,cyplate,sxdiff,cxdiff; double f,fx,fy,g,gx,gy, xmm, ymm; double conr2s = 206264.8062470964; double tolerance = 0.0000005; int max_iterations = 50; int i; double xr, yr; /* position in radians */ *xpix = 0.0; *ypix = 0.0; /* Convert RA and Dec in radians to standard coordinates on a plate */ xr = degrad (xpos); yr = degrad (ypos); sypos = sin (yr); cypos = cos (yr); if (wcs->plate_dec == 0.0) wcs->plate_dec = degrad (wcs->yref); syplate = sin (wcs->plate_dec); cyplate = cos (wcs->plate_dec); if (wcs->plate_ra == 0.0) wcs->plate_ra = degrad (wcs->yref); sxdiff = sin (xr - wcs->plate_ra); cxdiff = cos (xr - wcs->plate_ra); div = (sypos * syplate) + (cypos * cyplate * cxdiff); if (div == 0.0) return (1); xi = cypos * sxdiff * conr2s / div; eta = ((sypos * cyplate) - (cypos * syplate * cxdiff)) * conr2s / div; /* Set initial value for x,y */ if (wcs->plate_scale == 0.0) return (1); xmm = xi / wcs->plate_scale; ymm = eta / wcs->plate_scale; /* Iterate by Newton's method */ for (i = 0; i < max_iterations; i++) { /* X plate model */ xy = xmm * ymm; x2 = xmm * xmm; y2 = ymm * ymm; x2y = x2 * ymm; y2x = y2 * xmm; x2y2 = x2 + y2; cjunk = x2y2 * x2y2; x3 = x2 * xmm; y3 = y2 * ymm; x4 = x2 * x2; y4 = y2 * y2; f = wcs->x_coeff[0]*xmm + wcs->x_coeff[1]*ymm + wcs->x_coeff[2] + wcs->x_coeff[3]*x2 + wcs->x_coeff[4]*xy + wcs->x_coeff[5]*y2 + wcs->x_coeff[6]*x2y2 + wcs->x_coeff[7]*x3 + wcs->x_coeff[8]*x2y + wcs->x_coeff[9]*y2x + wcs->x_coeff[10]*y3 + wcs->x_coeff[11]*xmm*x2y2 + wcs->x_coeff[12]*xmm*cjunk; /* magnitude and color terms ignored + wcs->x_coeff[13]*mag + wcs->x_coeff[14]*mag*mag + wcs->x_coeff[15]*mag*mag*mag + wcs->x_coeff[16]*mag*xmm + wcs->x_coeff[17]*mag*(x2+y2) + wcs->x_coeff[18]*mag*xmm*(x2+y2) + wcs->x_coeff[19]*color; */ /* Derivative of X model wrt x */ fx = wcs->x_coeff[0] + wcs->x_coeff[3]*2.0*xmm + wcs->x_coeff[4]*ymm + wcs->x_coeff[6]*2.0*xmm + wcs->x_coeff[7]*3.0*x2 + wcs->x_coeff[8]*2.0*xy + wcs->x_coeff[9]*y2 + wcs->x_coeff[11]*(3.0*x2+y2) + wcs->x_coeff[12]*(5.0*x4 +6.0*x2*y2+y4); /* magnitude and color terms ignored wcs->x_coeff[16]*mag + wcs->x_coeff[17]*mag*2.0*xmm + wcs->x_coeff[18]*mag*(3.0*x2+y2); */ /* Derivative of X model wrt y */ fy = wcs->x_coeff[1] + wcs->x_coeff[4]*xmm + wcs->x_coeff[5]*2.0*ymm + wcs->x_coeff[6]*2.0*ymm + wcs->x_coeff[8]*x2 + wcs->x_coeff[9]*2.0*xy + wcs->x_coeff[10]*3.0*y2 + wcs->x_coeff[11]*2.0*xy + wcs->x_coeff[12]*4.0*xy*x2y2; /* magnitude and color terms ignored wcs->x_coeff[17]*mag*2.0*ymm + wcs->x_coeff[18]*mag*2.0*xy; */ /* Y plate model */ g = wcs->y_coeff[0]*ymm + wcs->y_coeff[1]*xmm + wcs->y_coeff[2] + wcs->y_coeff[3]*y2 + wcs->y_coeff[4]*xy + wcs->y_coeff[5]*x2 + wcs->y_coeff[6]*x2y2 + wcs->y_coeff[7]*y3 + wcs->y_coeff[8]*y2x + wcs->y_coeff[9]*x2y + wcs->y_coeff[10]*x3 + wcs->y_coeff[11]*ymm*x2y2 + wcs->y_coeff[12]*ymm*cjunk; /* magnitude and color terms ignored wcs->y_coeff[13]*mag + wcs->y_coeff[14]*mag*mag + wcs->y_coeff[15]*mag*mag*mag + wcs->y_coeff[16]*mag*ymm + wcs->y_coeff[17]*mag*x2y2 + wcs->y_coeff[18]*mag*ymm*x2y2 + wcs->y_coeff[19]*color; */ /* Derivative of Y model wrt x */ gx = wcs->y_coeff[1] + wcs->y_coeff[4]*ymm + wcs->y_coeff[5]*2.0*xmm + wcs->y_coeff[6]*2.0*xmm + wcs->y_coeff[8]*y2 + wcs->y_coeff[9]*2.0*xy + wcs->y_coeff[10]*3.0*x2 + wcs->y_coeff[11]*2.0*xy + wcs->y_coeff[12]*4.0*xy*x2y2; /* magnitude and color terms ignored wcs->y_coeff[17]*mag*2.0*xmm + wcs->y_coeff[18]*mag*ymm*2.0*xmm; */ /* Derivative of Y model wrt y */ gy = wcs->y_coeff[0] + wcs->y_coeff[3]*2.0*ymm + wcs->y_coeff[4]*xmm + wcs->y_coeff[6]*2.0*ymm + wcs->y_coeff[7]*3.0*y2 + wcs->y_coeff[8]*2.0*xy + wcs->y_coeff[9]*x2 + wcs->y_coeff[11]*(x2+3.0*y2) + wcs->y_coeff[12]*(5.0*y4 + 6.0*x2*y2 + x4); /* magnitude and color terms ignored wcs->y_coeff[16]*mag + wcs->y_coeff[17]*mag*2.0*ymm + wcs->y_coeff[18]*mag*(x2+3.0*y2); */ f = f - xi; g = g - eta; dx = ((-f * gy) + (g * fy)) / ((fx * gy) - (fy * gx)); dy = ((-g * fx) + (f * gx)) / ((fx * gy) - (fy * gx)); xmm = xmm + dx; ymm = ymm + dy; if ((fabs(dx) < tolerance) && (fabs(dy) < tolerance)) break; } /* Convert mm from plate center to plate pixels */ if (wcs->x_pixel_size == 0.0 || wcs->y_pixel_size == 0.0) return (1); x = (wcs->ppo_coeff[2] - xmm*1000.0) / wcs->x_pixel_size; y = (wcs->ppo_coeff[5] + ymm*1000.0) / wcs->y_pixel_size; /* Convert from plate pixels to image pixels */ *xpix = x - wcs->x_pixel_offset + 1.0 - 0.5; *ypix = y - wcs->y_pixel_offset + 1.0 - 0.5; /* If position is off of the image, return offscale code */ if (*xpix < 0.5 || *xpix > wcs->nxpix+0.5) return -1; if (*ypix < 0.5 || *ypix > wcs->nypix+0.5) return -1; return 0; } /* Mar 6 1995 Original version of this code * May 4 1995 Fix eta cross terms which were all in y * Jun 21 1995 Add inverse routine * Oct 17 1995 Fix inverse routine (degrees -> radians) * Nov 7 1995 Add half pixel to image coordinates to get astrometric * plate coordinates * Feb 26 1996 Fix plate to image pixel conversion error * * Mar 23 1998 Change names from plate*() to dss*() * Apr 7 1998 Change amd_i_coeff to i_coeff * Sep 4 1998 Fix possible divide by zero in dsspos() from Allen Harris, SAO * Sep 10 1998 Fix possible divide by zero in dsspix() from Allen Harris, SAO * * Oct 21 1999 Drop declaration of cond2r in dsspix() */ wcstools-3.9.5/libwcs/fileutil.c0000664000016200001660000005223312377700365015736 0ustar minkoirsys/*** File libwcs/fileutil.c *** August 28, 2014 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1999-2014 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: fileutil.c (ASCII file utilities) * Purpose: Find out things about ASCII files * Subroutine: getfilelines (filename) * Return number of lines in an ASCII file * Subroutine: getfilebuff (filename) * Return entire file contents in a character string * Subroutine: getfilesize (filename) * Return size of a binary or ASCII file * Subroutine: isimlist (filename) * Return 1 if file is list of FITS or IRAF image files, else 0 * Subroutine: isimlistd (filename, rootdir) * Return 1 if file is list of FITS or IRAF image files, else 0 * Subroutine: isfilelist (filename, rootdir) * Return 1 if file is list of readable files, else 0 * Subroutine: isfile (filename) * Return 1 if file is a readable file, else 0 * Subroutine: first_token (diskfile, ncmax, token) * Return the first token from the next line of an ASCII file * Subroutine: next_line (diskfile, ncmax, line) * Read the next line of an ASCII file and return its length * Subroutine: stc2s (spchar, string) * Replace character in string with space * Subroutine: sts2c (spchar, string) * Replace spaces in string with character * Subroutine: istiff (filename) * Return 1 if file is a readable TIFF graphics file, else 0 * Subroutine: isjpeg (filename) * Return 1 if file is a readable JPEG graphics file, else 0 * int setoken (tokens, string, cwhite) * Tokenize a string for easy decoding * int nextoken (tokens, token, maxchars) * Get next token from tokenized string * int getoken (tokens, itok, token, maxchars) * Get specified token from tokenized string */ #include #ifndef VMS #include #endif #include #include #include #include #include #include "fitsfile.h" #include #include /* GETFILELINES -- return number of lines in one file */ int getfilelines (filename) char *filename; /* Name of file for which to find number of lines */ { char *buffer, *bufline; int nlines = 0; char newline = 10; /* Read file */ buffer = getfilebuff (filename); /* Count lines in file */ if (buffer != NULL) { bufline = buffer; nlines = 0; while ((bufline = strchr (bufline, newline)) != NULL) { bufline = bufline + 1; nlines++; } free (buffer); return (nlines); } else { return (0); } } /* GETFILEBUFF -- return entire file contents in one character string */ char * getfilebuff (filename) char *filename; /* Name of file for which to find number of lines */ { FILE *diskfile; int lfile, nr, lbuff, ipt, ibuff; char *buffer, *newbuff, *nextbuff; /* Treat stdin differently */ if (!strcmp (filename, "stdin")) { lbuff = 5000; lfile = lbuff; buffer = NULL; ipt = 0; for (ibuff = 0; ibuff < 10; ibuff++) { if ((newbuff = realloc (buffer, lfile+1)) != NULL) { buffer = newbuff; nextbuff = buffer + ipt; nr = fread (nextbuff, 1, lbuff, stdin); if (nr == lbuff) break; else { ipt = ipt + lbuff; lfile = lfile + lbuff; } } else { fprintf (stderr,"GETFILEBUFF: No room for %d-byte buffer\n", lfile); break; } } return (buffer); } /* Open file */ if ((diskfile = fopen (filename, "rb")) == NULL) return (NULL); /* Find length of file */ if (fseek (diskfile, 0, 2) == 0) lfile = ftell (diskfile); else lfile = 0; if (lfile < 1) { fprintf (stderr,"GETFILEBUFF: File %s is empty\n", filename); fclose (diskfile); return (NULL); } /* Allocate buffer to hold entire file and read it */ if ((buffer = calloc (1, lfile+1)) != NULL) { fseek (diskfile, 0, 0); nr = fread (buffer, 1, lfile, diskfile); if (nr < lfile) { fprintf (stderr,"GETFILEBUFF: File %s: read %d / %d bytes\n", filename, nr, lfile); free (buffer); fclose (diskfile); return (NULL); } buffer[lfile] = (char) 0; fclose (diskfile); return (buffer); } else { fprintf (stderr,"GETFILEBUFF: File %s: no room for %d-byte buffer\n", filename, lfile); fclose (diskfile); return (NULL); } } /* GETFILESIZE -- return size of one file in bytes */ int getfilesize (filename) char *filename; /* Name of file for which to find size */ { struct stat statbuff; if (stat (filename, &statbuff)) return (0); else return ((int) statbuff.st_size); } int getfilesize0 (filename) char *filename; /* Name of file for which to find size */ { FILE *diskfile; long filesize; /* Open file */ if ((diskfile = fopen (filename, "rb")) == NULL) return (-1); /* Move to end of the file */ if (fseek (diskfile, 0, 2) == 0) /* Position is the size of the file */ filesize = ftell (diskfile); else filesize = -1; fclose (diskfile); return ((int) filesize); } /* ISIMLIST -- Return 1 if list of FITS or IRAF files, else 0 */ int isimlist (filename) char *filename; /* Name of possible list file */ { FILE *diskfile; char token[256]; int ncmax = 254; if ((diskfile = fopen (filename, "r")) == NULL) return (0); else { first_token (diskfile, ncmax, token); fclose (diskfile); if (isfits (token) | isiraf (token)) return (1); else return (0); } } /* ISIMLISTD -- Return 1 if list of FITS or IRAF files, else 0 */ int isimlistd (filename, rootdir) char *filename; /* Name of possible list file */ char *rootdir; /* Name of root directory for files in list */ { FILE *diskfile; char token[256]; char filepath[256]; int ncmax = 254; if ((diskfile = fopen (filename, "r")) == NULL) return (0); else { first_token (diskfile, ncmax, token); fclose (diskfile); if (rootdir != NULL) { strcpy (filepath, rootdir); strcat (filepath, "/"); strcat (filepath, token); } else strcpy (filepath, token); if (isfits (filepath) | isiraf (filepath)) return (1); else return (0); } } /* ISFILELIST -- Return 1 if list of readable files, else 0 */ int isfilelist (filename, rootdir) char *filename; /* Name of possible list file */ char *rootdir; /* Name of root directory for files in list */ { FILE *diskfile; char token[256]; char filepath[256]; int ncmax = 254; if ((diskfile = fopen (filename, "r")) == NULL) return (0); else { first_token (diskfile, ncmax, token); fclose (diskfile); if (rootdir != NULL) { strcpy (filepath, rootdir); strcat (filepath, "/"); strcat (filepath, token); } else strcpy (filepath, token); if (isfile (filepath)) return (1); else return (0); } } /* ISFILE -- Return 1 if file is a readable file, else 0 */ int isfile (filename) char *filename; /* Name of file to check */ { struct stat statbuff; if (!strcasecmp (filename, "stdin")) return (1); else if (access (filename, R_OK)) return (0); else if (stat (filename, &statbuff)) return (0); else { if (S_ISDIR(statbuff.st_mode) && S_IFDIR) return (2); else return (1); } } /* NEXT_LINE -- Read the next line of an ASCII file, returning length */ /* Lines beginning with # are ignored*/ int next_line (diskfile, ncmax, line) FILE *diskfile; /* File descriptor for ASCII file */ int ncmax; /* Maximum number of characters returned */ char *line; /* Next line (returned) */ { char *lastchar; /* If line can be read, add null at the end of the first token */ if (fgets (line, ncmax, diskfile) != NULL) { while (line[0] == '#') { (void) fgets (line, ncmax, diskfile); } /* If only character is a control character, return a NULL string */ if ((strlen(line)==1) && (line[0]<32)){ line[0] = (char)0; return (1); } lastchar = line + strlen (line) - 1; /* Remove trailing spaces or control characters */ while (*lastchar <= 32) *lastchar-- = 0; return (strlen (line)); } else return (0); } /* FIRST_TOKEN -- Return first token from the next line of an ASCII file */ /* Lines beginning with # are ignored */ int first_token (diskfile, ncmax, token) FILE *diskfile; /* File descriptor for ASCII file */ int ncmax; /* Maximum number of characters returned */ char *token; /* First token on next line (returned) */ { char *lastchar, *lspace; /* If line can be read, add null at the end of the first token */ if (fgets (token, ncmax, diskfile) != NULL) { while (token[0] == '#') { (void) fgets (token, ncmax, diskfile); } /* If only character is a control character, return a NULL */ if ((strlen(token)==1) && (token[0]<32)){ token[0]=0; return (1); } lastchar = token + strlen (token) - 1; /* Remove trailing spaces or control characters */ while (*lastchar <= 32) *lastchar-- = 0; if ((lspace = strchr (token, ' ')) != NULL) { *lspace = (char) 0; } return (1); } else return (0); } /* Replace character in string with space */ int stc2s (spchar, string) char *spchar; /* Character to replace with spaces */ char *string; { int i, lstr, n; lstr = strlen (string); n = 0; for (i = 0; i < lstr; i++) { if (string[i] == spchar[0]) { n++; string[i] = ' '; } } return (n); } /* Replace spaces in string with character */ int sts2c (spchar, string) char *spchar; /* Character with which to replace spaces */ char *string; { int i, lstr, n; lstr = strlen (string); n = 0; for (i = 0; i < lstr; i++) { if (string[i] == ' ') { n++; string[i] = spchar[0]; } } return (n); } /* ISTIFF -- Return 1 if TIFF file, else 0 */ int istiff (filename) char *filename; /* Name of file to check */ { int diskfile; char keyword[16]; int nbr; /* First check to see if this is an assignment */ if (strchr (filename, '=')) return (0); /* Check file extension */ if (strsrch (filename, ".tif") || strsrch (filename, ".tiff") || strsrch (filename, ".TIFF") || strsrch (filename, ".TIF")) return (1); /* If no TIFF file suffix, try opening the file */ else { if ((diskfile = open (filename, O_RDONLY)) < 0) return (0); else { nbr = read (diskfile, keyword, 4); close (diskfile); if (nbr < 4) return (0); else if (!strncmp (keyword, "II", 2)) return (1); else if (!strncmp (keyword, "MM", 2)) return (1); else return (0); } } } /* ISJPEG -- Return 1 if JPEG file, else 0 */ int isjpeg (filename) char *filename; /* Name of file to check */ { int diskfile; char keyword[16]; int nbr; /* First check to see if this is an assignment */ if (strchr (filename, '=')) return (0); /* Check file extension */ if (strsrch (filename, ".jpg") || strsrch (filename, ".jpeg") || strsrch (filename, ".JPEG") || strsrch (filename, ".jfif") || strsrch (filename, ".jfi") || strsrch (filename, ".JFIF") || strsrch (filename, ".JFI") || strsrch (filename, ".JPG")) return (1); /* If no JPEG file suffix, try opening the file */ else { if ((diskfile = open (filename, O_RDONLY)) < 0) return (0); else { nbr = read (diskfile, keyword, 2); close (diskfile); if (nbr < 4) return (0); else if (keyword[0] == (char) 0xFF && keyword[1] == (char) 0xD8) return (1); else return (0); } } } /* ISGIF -- Return 1 if GIF file, else 0 */ int isgif (filename) char *filename; /* Name of file to check */ { int diskfile; char keyword[16]; int nbr; /* First check to see if this is an assignment */ if (strchr (filename, '=')) return (0); /* Check file extension */ if (strsrch (filename, ".gif") || strsrch (filename, ".GIF")) return (1); /* If no GIF file suffix, try opening the file */ else { if ((diskfile = open (filename, O_RDONLY)) < 0) return (0); else { nbr = read (diskfile, keyword, 6); close (diskfile); if (nbr < 4) return (0); else if (!strncmp (keyword, "GIF", 3)) return (1); else return (0); } } } static int maxtokens = MAXTOKENS; /* Set maximum number of tokens from wcscat.h*/ /* -- SETOKEN -- tokenize a string for easy decoding */ int setoken (tokens, string, cwhite) struct Tokens *tokens; /* Token structure returned */ char *string; /* character string to tokenize */ char *cwhite; /* additional whitespace characters * if = tab, disallow spaces and commas */ { char squote, dquote, jch, newline; char *iq, *stri, *wtype, *str0, *inew; int i,j,naddw, ltok; newline = (char) 10; squote = (char) 39; dquote = (char) 34; if (string == NULL) return (0); /* Line is terminated by newline or NULL */ inew = strchr (string, newline); if (inew != NULL) tokens->lline = inew - string - 1; else tokens->lline = strlen (string); /* Save current line in structure */ tokens->line = string; /* Add extra whitespace characters */ if (cwhite == NULL) naddw = 0; else naddw = strlen (cwhite); /* if character is tab, allow only tabs and nulls as separators */ if (naddw > 0 && !strncmp (cwhite, "tab", 3)) { tokens->white[0] = (char) 9; /* Tab */ tokens->white[1] = (char) 0; /* NULL (end of string) */ tokens->nwhite = 2; } /* if character is bar, allow only bars and nulls as separators */ else if (naddw > 0 && !strncmp (cwhite, "bar", 3)) { tokens->white[0] = '|'; /* Bar */ tokens->white[1] = (char) 0; /* NULL (end of string) */ tokens->nwhite = 2; } /* otherwise, allow spaces, tabs, commas, nulls, and cwhite */ else { tokens->nwhite = 4 + naddw;; tokens->white[0] = ' '; /* Space */ tokens->white[1] = (char) 9; /* Tab */ tokens->white[2] = ','; /* Comma */ tokens->white[3] = (char) 124; /* Vertical bar */ tokens->white[4] = (char) 0; /* Null (end of string) */ if (tokens->nwhite > 20) tokens->nwhite = 20; if (naddw > 0) { i = 0; for (j = 4; j < tokens->nwhite; j++) { tokens->white[j] = cwhite[i]; i++; } } } tokens->white[tokens->nwhite] = (char) 0; tokens->ntok = 0; tokens->itok = 0; iq = string - 1; for (i = 0; i < maxtokens; i++) { tokens->tok1[i] = NULL; tokens->ltok[i] = 0; } /* Process string one character at a time */ stri = string; str0 = string; while (stri < string+tokens->lline) { /* Keep stuff between quotes in one token */ if (stri <= iq) continue; jch = *stri; /* Handle quoted strings */ if (jch == squote) iq = strchr (stri+1, squote); else if (jch == dquote) iq = strchr (stri+1, dquote); else iq = stri; if (iq > stri) { tokens->ntok = tokens->ntok + 1; if (tokens->ntok > maxtokens) return (maxtokens); tokens->tok1[tokens->ntok] = stri + 1; tokens->ltok[tokens->ntok] = (iq - stri) - 1; stri = iq + 1; str0 = iq + 1; continue; } /* Search for unquoted tokens */ wtype = strchr (tokens->white, jch); /* If this is one of the additional whitespace characters, * pass as a separate token */ if (wtype > tokens->white + 3) { /* Terminate token before whitespace */ if (stri > str0) { tokens->ntok = tokens->ntok + 1; if (tokens->ntok > maxtokens) return (maxtokens); tokens->tok1[tokens->ntok] = str0; tokens->ltok[tokens->ntok] = stri - str0; } /* Make whitespace character next token; start new one */ tokens->ntok = tokens->ntok + 1; if (tokens->ntok > maxtokens) return (maxtokens); tokens->tok1[tokens->ntok] = stri; tokens->ltok[tokens->ntok] = 1; stri++; str0 = stri; } /* Pass previous token if regular whitespace or NULL */ else if (wtype != NULL || jch == (char) 0) { /* Ignore leading whitespace */ if (stri == str0) { stri++; str0 = stri; } /* terminate token before whitespace; start new one */ else { tokens->ntok = tokens->ntok + 1; if (tokens->ntok > maxtokens) return (maxtokens); tokens->tok1[tokens->ntok] = str0; tokens->ltok[tokens->ntok] = stri - str0; stri++; str0 = stri; } } /* Keep going if not whitespace */ else stri++; } /* Add token terminated by end of line */ if (str0 < stri) { tokens->ntok = tokens->ntok + 1; if (tokens->ntok > maxtokens) return (maxtokens); tokens->tok1[tokens->ntok] = str0; ltok = stri - str0 + 1; tokens->ltok[tokens->ntok] = ltok; /* Deal with white space just before end of line */ jch = str0[ltok-1]; if (strchr (tokens->white, jch)) { ltok = ltok - 1; tokens->ltok[tokens->ntok] = ltok; tokens->ntok = tokens->ntok + 1; tokens->tok1[tokens->ntok] = str0 + ltok; tokens->ltok[tokens->ntok] = 0; } } tokens->itok = 0; return (tokens->ntok); } /* NEXTOKEN -- get next token from tokenized string */ int nextoken (tokens, token, maxchars) struct Tokens *tokens; /* Token structure returned */ char *token; /* token (returned) */ int maxchars; /* Maximum length of token */ { int ltok; /* length of token string (returned) */ int it, i; int maxc = maxchars - 1; tokens->itok = tokens->itok + 1; it = tokens->itok; if (it > tokens->ntok) it = tokens->ntok; else if (it < 1) it = 1; ltok = tokens->ltok[it]; if (ltok > maxc) ltok = maxc; strncpy (token, tokens->tok1[it], ltok); for (i = ltok; i < maxc; i++) token[i] = (char) 0; return (ltok); } /* GETOKEN -- get specified token from tokenized string */ int getoken (tokens, itok, token, maxchars) struct Tokens *tokens; /* Token structure returned */ int itok; /* token sequence number of token * if <0, get whole string after token -itok * if =0, get whole string */ char *token; /* token (returned) */ int maxchars; /* Maximum length of token */ { int ltok; /* length of token string (returned) */ int it, i; int maxc = maxchars - 1; it = itok; if (it > 0 ) { if (it > tokens->ntok) it = tokens->ntok; ltok = tokens->ltok[it]; if (ltok > maxc) ltok = maxc; strncpy (token, tokens->tok1[it], ltok); } else if (it < 0) { if (it < -tokens->ntok) it = -tokens->ntok; ltok = tokens->line + tokens->lline - tokens->tok1[-it]; if (ltok > maxc) ltok = maxc; strncpy (token, tokens->tok1[-it], ltok); } else { ltok = tokens->lline; if (ltok > maxc) ltok = maxc; strncpy (token, tokens->tok1[1], ltok); } for (i = ltok; i < maxc; i++) token[i] = (char) 0; return (ltok); } /* * Jul 14 1999 New subroutines * Jul 15 1999 Add getfilebuff() * Oct 15 1999 Fix format eror in error message * Oct 21 1999 Fix declarations after lint * Dec 9 1999 Add next_token(); set pointer to next token in first_token * * Sep 25 2001 Add isfilelist(); move isfile() from catutil.c * * Jan 4 2002 Allow getfilebuffer() to read from stdin * Jan 8 2002 Add sts2c() and stc2s() for space-replaced strings * Mar 22 2002 Clean up isfilelist() * Aug 1 2002 Return 1 if file is stdin in isfile() * * Feb 4 2003 Open catalog file rb instead of r (Martin Ploner, Bern) * Mar 5 2003 Add isimlistd() to check image lists with root directory * May 27 2003 Use file stat call in getfilesize() instead of opening file * Jul 17 2003 Add root directory argument to isfilelist() * * Sep 29 2004 Drop next_token() to avoid conflict with subroutine in catutil.c * * Sep 26 2005 In first_token, return NULL if token is only control character * * Feb 23 2006 Add istiff(), isjpeg(), isgif() to check TIFF, JPEG, GIF files * Jun 20 2006 Cast call to fgets() void * * Jan 5 2007 Change stc2s() and sts2c() to pass single character as pointer * Jan 11 2007 Move token access subroutines from catutil.c * * Aug 28 2014 Return length from next_line(): 0=unsuccessful */ wcstools-3.9.5/libwcs/findstar.c0000664000016200001660000006735112733276641015743 0ustar minkoirsys/*** File libwcs/findstar.c *** June 24, 2016 *** By Jessica Mink, after Elwood Downey *** Copyright (C) 1996-2016 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include #include "fitsfile.h" #include "wcs.h" #include "wcscat.h" #include "lwcs.h" #define ABS(a) ((a) < 0 ? (-(a)) : (a)) static int HotPixel(); static int starRadius(); static void starCentroid(); static int BrightWalk (); static double FindFlux (); static void mean2d(); static void mean1d(); static void rotstars(); extern void setminmatch(); extern void setnitmax(); extern void setminstars(); extern void setminpmqual(); extern void setminid(); extern void setnxydec(); /* Set input catalog for image stars */ static char imcatname[256] = ""; void setimcat (cat) char *cat; {strcpy (imcatname, cat); return; } /* Get input catalog for image stars */ char *getimcat () {return (imcatname); } static int nspix = NSTATPIX; /* Stats are computed for +- this many pixels */ void setnspix (nsp) int nsp; { nspix = nsp; return; } static int ispix = ISTATPIX; /* Stats are computed every this many pixels */ void setispix (isp) int isp; { ispix = isp; return; } static int maxw = MAXWALK; /* Farthest distance to walk from seed */ void setmaxwalk (wmax) int wmax; { maxw = wmax; return; } static double burnedout = BURNEDOUT; /* Clamp pixels brighter than this */ void setburnedout (bmax) double bmax; { burnedout = bmax; return; } static int niterate = NITERATE; /* Number of iterations for sigma clipping */ void setniterate (nit) int nit; { niterate = nit; return;} /* Stars must be at least this many standard deviations above the mean */ static double starsig = STARSIGMA; void setstarsig (sig) double sig; { starsig = sig; return; } static int fsborder = BORDER; /* Ignore this much of the edge */ void setborder (brd) int brd; { fsborder = brd; return; } static int rnoise = RNOISE; /* Mean noise is from center +- this many pixels */ void setrnoise (rn) int rn; { rnoise = rn; return; } static int maxrad = MAXRAD; /* Maximum radius for a star */ void setmaxrad (rmax) int rmax; { maxrad = rmax; return; } static int minrad = MINRAD; /* Minimum radius for a star */ void setminrad (rmin) int rmin; { minrad = rmin; return; } static double bmin = MINPEAK; /* Minimum peak for a star */ void setbmin (min) double min; { bmin = min; return; } static int minsep = MINSEP; /* Minimum separation for stars */ void setminsep (smin) int smin; { minsep = smin; return; } static int mirror = 0; void setmirror (mirror1) int mirror1; { mirror = mirror1; return;} static int rotate = 0; void setrotate (rotate1) int rotate1; { rotate = rotate1; return;} /* Find the location and brightest pixel of stars in the given image. * Return malloced arrays of x and y and b. * N.B. Caller must free *xa and *ya and *ba even if 0 stars are returned. * N.B. Pixels outside fsborder are ignored. * N.B. Isolated hot pixels are ignored. * return number of stars (might well be 0 :-), or -1 if trouble. */ int FindStars (header, image, xa, ya, ba, pa, verbose, zap) char *header; /* FITS header */ char *image; /* image pixels */ double **xa, **ya; /* X and Y coordinates of stars, array returned */ double **ba; /* Fluxes of stars in counts, array returned */ int **pa; /* Peak counts of stars in counts, array returned */ int verbose; /* 1 to print each star's position */ int zap; /* If 1, set star to background after reading */ { double noise, nsigma; int nstars; double minll; int bitpix; int w, h, ilp, irp, i, idx, idy; int x, y, x1, x2, y1, y2; double xai, yai, bai; double minsig, sigma; double *svec, *svb, *sv, *sv1, *sv2, *svlim; double rmax; double bz, bs; /* Pixel value scaling */ int *ixa, *iya; int lwidth; int nextline; int xborder1, xborder2, yborder1, yborder2; char trimsec[32]; int nstarmax = 100; extern void setscale(); hgeti4 (header,"NAXIS1", &w); hgeti4 (header,"NAXIS2", &h); hgeti4 (header,"BITPIX", &bitpix); bz = 0.0; hgetr8 (header,"BZERO", &bz); bs = 1.0; hgetr8 (header,"BSCALE", &bs); if (bz == 0.0 && bs == 1.0) setscale (0); /* Allocate the position, flux, and peak intensity arrays * it's ok to do now because we claim caller should always free these. */ *xa = (double *) calloc (nstarmax, sizeof(double)); *ya = (double *) calloc (nstarmax, sizeof(double)); *ba = (double *) calloc (nstarmax, sizeof(double)); *pa = (int *) calloc (nstarmax, sizeof(int)); ixa = (int *) calloc (nstarmax, sizeof (int)); iya = (int *) calloc (nstarmax, sizeof (int)); /* Read star list from file */ if (imcatname[0] != 0) { int nlog = 0; if (verbose) nlog = 10; if (istab (imcatname)) nstars = tabxyread (imcatname, xa, ya, ba, pa, nlog); else nstars = daoread (imcatname, xa, ya, ba, pa, nlog); if (rotate != 0 || mirror) rotstars (nstars, *xa, *ya, w, h); return (nstars); } /* Set trim section for star searching */ if (hgets (header, "TRIMSEC", 32, trimsec)) { char *tx1, *tx2, *tx3, *tx4, *tx5; tx1 = trimsec + 1; tx2 = strchr (trimsec, ':'); *tx2 = (char) 0; xborder1 = atoi (tx1); tx2 = tx2 + 1; tx3 = strchr (tx2, ','); *tx3 = (char) 0; xborder2 = w - atoi (tx2); tx3 = tx3 + 1; tx4 = strchr (tx3, ':'); *tx4 = (char) 0; yborder1 = atoi (tx3); tx4= tx4 + 1; tx5 = strchr (tx4, ']'); *tx5 = (char) 0; yborder2 = atoi (tx4) - h; } else { xborder1 = fsborder; xborder2 = fsborder; yborder1 = fsborder; yborder2 = fsborder; } /* Allocate a buffer to hold one image line */ svec = (double *) malloc (w * sizeof (double)); /* Compute image noise from a central swath */ x1 = (w / 2) - rnoise; if (x1 < 1) x1 = 1; x2 = (w / 2) + rnoise; if (x2 > w) x2 = w; y1 = (h / 2) - rnoise; if (y1 < 1) y1 = 1; y2 = (h / 2) + rnoise; if (y2 > h) y2 = h; mean2d (image,bitpix,w,h,bz,bs, x1, x2, y1, y2, &noise, &nsigma); if (verbose) fprintf (stderr, "FindStar mean is %.2f, sigma is %.2f\n", noise, nsigma); /* Fill in borders of the image line buffer with noise */ svlim = svec + w; svb = svec + xborder1; for (sv = svec; sv < svb; sv++) *sv = noise; for (sv = svlim - xborder2; sv < svlim; sv++) *sv = noise; if (verbose) { fprintf (stderr, "FindStar x=1-%d, %d-%d set to noise\n", xborder1, w-xborder2+1, w); fprintf (stderr, "FindStar y=1-%d, %d-%d set to noise\n", yborder1, h-yborder2+1, h); } if (bmin > 0) minll = noise + bmin; else minll = noise + (starsig * nsigma); sigma = sqrt (minll); if (nsigma < sigma) minsig = sigma; else minsig = nsigma; /* Scan for stars based on surrounding local noise figure */ nstars = 0; lwidth = w - xborder2 - xborder1 + 1; for (y = yborder1; y < h-yborder1; y++) { int ipix = 0; /* Get one line of the image minus the noise-filled borders */ nextline = (w * (y-1)) + xborder1 - 1; getvec (image, bitpix, bz, bs, nextline, lwidth, svb); if (verbose) fprintf (stderr, "Row %5d Col 0:\r", y+1); /* Search row for bright pixels */ for (x = xborder1; x < w-xborder2; x++) { if (verbose && x%100 == 0) fprintf (stderr, "Row %5d Col %5d:\r", y+1, x+1); /* Redo stats once for every several pixels */ if (ispix > 0 && nspix > 0 && ipix++ % ispix == 0) { /* Find stats to the left */ ilp = x - (nspix / 2); if (ilp < 0) ilp = 0; sv1 = svec + ilp; irp = ilp + nspix; if (irp < w) sv2 = svec + irp; else sv2 = svlim; minsig = 0.0; if (sv2 > sv1+1) mean1d (sv1, sv2, &noise, &minsig); sigma = sqrt (noise); if (minsig < sigma) minsig = sigma; minll = noise + (starsig * minsig); } /* Pixel is a candidate if above the noise */ if (svec[x] > minll) { int sx, sy, r, rf; double b; int i; /* Ignore faint stars */ if (svec[x] < bmin) continue; /* Ignore hot pixels */ if (!HotPixel (image,bitpix,w,h,bz,bs, x, y, minll)) continue; /* Walkabout to find brightest pixel in neighborhood */ if (BrightWalk (image,bitpix,w,h,bz,bs,x,y,maxw,&sx,&sy,&b) < 0) continue; /* Ignore really bright stars */ if (burnedout > 0 && b >= burnedout) continue; /* Skip star if already in list */ for (i = 0; i < nstars; i++) { idy = iya[i] - sy; if (idy < 0) idy = -idy; if (idy <= minsep) { idx = ixa[i] - sx; if (idx < 0) idx = -idx; if (idx <= minsep) break; } } if (i < nstars) continue; /* Keep it if it is within the size range for stars */ rmax = maxrad; r = starRadius (image,bitpix,w,h,bz,bs, sx, sy, rmax, minsig, noise); if (r > minrad && r <= maxrad) { /* Centroid star */ nstars++; if (nstars > nstarmax) { nstarmax = nstarmax * 2; *xa= (double *) realloc(*xa, nstarmax*sizeof(double)); *ya= (double *) realloc(*ya, nstarmax*sizeof(double)); ixa= (int *) realloc(ixa, nstarmax*sizeof(int)); iya= (int *) realloc(iya, nstarmax*sizeof(int)); *ba= (double *) realloc(*ba, nstarmax*sizeof(double)); *pa= (int *) realloc(*pa, nstarmax*sizeof(int)); } starCentroid (image,bitpix,w,h,bz,bs, sx, sy, &xai, &yai); (*xa)[nstars-1] = xai; (*ya)[nstars-1] = yai; ixa[nstars-1] = (int) (xai + 0.5); iya[nstars-1] = (int) (yai + 0.5); (*pa)[nstars-1] = (int) b; /* Find radius of star for photometry */ /* Outermost 1-pixel radial band is one sigma above background */ sx = (int) (xai + 0.5); sy = (int) (yai + 0.5); rmax = 2.0 * (double) maxrad; rf = starRadius (image,bitpix,w,h,bz,bs, sx, sy, rmax, minsig, noise); /* Find flux from star */ bai = FindFlux (image,bitpix,w,h,bz,bs,sx,sy,rf,noise,zap); (*ba)[nstars-1] = bai; if (verbose) { fprintf (stderr, "Row %5d Col %5d: ", y+1, x+1); fprintf (stderr," %d: (%d %d) -> (%7.3f %7.3f)", nstars, sx, sy, xai, yai); fprintf (stderr," %8.1f -> %10.1f %d -> %d ", b, bai, r, rf); (void)putc (13,stderr); } } /* else { fprintf (stderr," %d: (%d %d) %d > %d\n", nstars, sx, sy, r, maxrad); } */ } } } /* Turn fluxes into instrument magnitudes */ (void) FluxSortStars (*xa, *ya, *ba, *pa, nstars); if (nstars > 0) { double *flux; for (i = 0; i < nstars; i++) { flux = (*ba)+i; *flux = -2.5 * log10 (*flux); } } free ((char *)svec); return (nstars); } /* Check pixel at x/y for being "hot", ie, a pixel surrounded by noise. * If any are greater than pixel at x/y then return -1. * Else set the pixel at x/y to llimit and return 0. */ static int HotPixel (image, bitpix, w, h, bz, bs, x, y, llimit) char *image; /* Image array origin pointer */ int bitpix; /* Bits per pixel, negative for floating point or unsigned int */ int w; /* Image width in pixels */ int h; /* Image height in pixels */ double bz; /* Zero point for pixel scaling */ double bs; /* Scale factor for pixel scaling */ int x, y; double llimit; { double pix1, pix2, pix3; /* Check for hot row */ pix1 = getpix (image,bitpix,w,h,bz,bs,x-1,y-1); pix2 = getpix (image,bitpix,w,h,bz,bs,x,y-1); pix3 = getpix (image,bitpix,w,h,bz,bs,x+1,y-1); if (pix1 > llimit || pix2 > llimit || pix3 > llimit) return (-1); pix1 = getpix (image,bitpix,w,h,bz,bs,x-1,y+1); pix2 = getpix (image,bitpix,w,h,bz,bs,x,y+1); pix3 = getpix (image,bitpix,w,h,bz,bs,x+1,y+1); if (pix1 > llimit || pix2 > llimit || pix3 > llimit) return (-1); /* Check for hot column */ pix1 = getpix (image,bitpix,w,h,bz,bs,x-1,y-1); pix2 = getpix (image,bitpix,w,h,bz,bs,x-1,y); pix3 = getpix (image,bitpix,w,h,bz,bs,x-1,y+1); if (pix1 > llimit || pix2 > llimit || pix3 > llimit) return (-1); pix1 = getpix (image,bitpix,w,h,bz,bs,x+1,y-1); pix2 = getpix (image,bitpix,w,h,bz,bs,x+1,y); pix3 = getpix (image,bitpix,w,h,bz,bs,x+1,y+1); if (pix1 > llimit || pix2 > llimit || pix3 > llimit) return (-1); /* Check for hot pixel */ pix1 = getpix (image,bitpix,w,h,bz,bs,x-1,y); pix3 = getpix (image,bitpix,w,h,bz,bs,x+1,y); if (pix1 > llimit || pix3 > llimit) return (-1); pix1 = getpix (image,bitpix,w,h,bz,bs,x,y-1); pix3 = getpix (image,bitpix,w,h,bz,bs,x,y+1); if (pix1 > llimit || pix3 > llimit) return (-1); putpix (image, bitpix, w, h, bz, bs, x, y, llimit); return (0); } /* Compute and return the radius of the star centered at x0, y0. * A guard band is assumed to exist on the image. * Calling program is assumed to reject object if r > rmax. */ static int starRadius (imp, bitpix, w, h, bz, bs, x0, y0, rmax, minsig, background) char *imp; /* Image array origin pointer */ int bitpix; /* Bits per pixel, negative for floating point or unsigned int */ int w; /* Image width in pixels */ int h; /* Image height in pixels */ double bz; /* Zero point for pixel scaling */ double bs; /* Scale factor for pixel scaling */ int x0, y0; /* Coordinates of center pixel of star */ double rmax; /* Maximum allowable radius of star */ double minsig; /* Minimum level for signal */ double background; /* Mean background level */ { int r, irmax; double dp, sum, mean; int xyrr, yrr, np; int inrr, outrr; int x, y; irmax = (int) rmax; /* Compute star's radius. * Scan in ever-greater circles until find one such that the mean at * that radius is less than one sigma above the background level. */ for (r = 2; r <= irmax; r++) { inrr = r*r; outrr = (r+1)*(r+1); np = 0; sum = 0.0; for (y = -r; y <= r; y++) { yrr = y*y; for (x = -r; x <= r; x++) { xyrr = x*x + yrr; if (xyrr >= inrr && xyrr < outrr) { dp = getpix (imp,bitpix,w,h,bz,bs,x0+x,y0+y); sum += dp; np++; } } } mean = (sum / np) - background; if (mean < minsig) break; } return (r); } /* Compute the fine location of the star peaking at [x0,y0] */ static void starCentroid (imp, bitpix, w, h, bz, bs, x0, y0, xp, yp) char *imp; int bitpix; int w; int h; double bz; /* Zero point for pixel scaling */ double bs; /* Scale factor for pixel scaling */ int x0, y0; double *xp, *yp; { double p1, p2, p22, p3, d; /* Find maximum of best-fit parabola in each direction. * see Bevington, page 210 */ p1 = getpix (imp,bitpix,w,h,bz,bs,x0-1,y0); p2 = getpix (imp,bitpix,w,h,bz,bs,x0,y0); p22 = 2*p2; p3 = getpix (imp,bitpix,w,h,bz,bs,x0+1,y0); d = p3 - p22 + p1; *xp = (d == 0) ? x0 : x0 + 0.5 - (p3 - p2)/d; *xp = *xp + 1.0; p1 = getpix (imp,bitpix,w,h,bz,bs,x0,y0-1); p3 = getpix (imp,bitpix,w,h,bz,bs,x0,y0+1); d = p3 - p22 + p1; *yp = (d == 0) ? y0 : y0 + 0.5 - (p3 - p2)/d; *yp = *yp + 1.0; } /* Given an image and a starting point, walk the gradient to the brightest * pixel and return its location, never going more than maxrad away. * Return 0 if brightest pixel found within maxsteps, else -1 */ static int dx[8]={1,0,-1,1,-1,1,0,-1}; static int dy[8]={1,1,1,0,0,-1,-1,-1}; static int BrightWalk (image, bitpix, w, h, bz, bs, x0, y0, maxr, xp, yp, bp) char *image; int bitpix; int w; int h; double bz; /* Zero point for pixel scaling */ double bs; /* Scale factor for pixel scaling */ int x0; int y0; int maxr; int *xp; int *yp; double *bp; { double b, tmpb, newb; int x, y, x1, y1, i, xa, ya; /* start by assuming seed point is brightest */ b = getpix (image,bitpix,w,h,bz,bs, x0,y0); x = x0; y = y0; xa = x0; ya = y0; /* walk towards any brighter pixel */ for (;;) { int newx = 0; int newy = 0; /* Find brightest pixel in 3x3 region */ newb = b; for (i = 0; i < 8; i++) { x1 = x + dx[i]; y1 = y + dy[i]; tmpb = getpix (image,bitpix,w,h,bz,bs, x1, y1); if (tmpb >= newb) { if (x1 == xa && y1 == ya) break; xa = x; ya = y; newx = x1; newy = y1; newb = tmpb; } } /* If brightest pixel is one in center of region, quit */ if (newb == b) break; /* Otherwise, set brightest pixel to new center */ x = newx; y = newy; b = newb; if (abs(x-x0) > maxr || abs(y-y0) > maxr) return (-1); } *xp = x; *yp = y; *bp = b; return (0); } /* Compute stats in the give region of the image of width w pixels. * Bounds are not checked. */ static void mean2d (image, bitpix, w, h, bz, bs, x1, x2, y1, y2, mean, sigma) char *image; int bitpix; int w; int h; double bz; /* Zero point for pixel scaling */ double bs; /* Scale factor for pixel scaling */ int x1,x2; int y1, y2; double *mean; double *sigma; { double p, pmin, pmax; double pmean = 0.0; double sd = 0.0; int x, y; int i; double sum; double dnpix; int npix; pmin = -1.0e20; pmax = 1.0e20; for (i = 0; i < niterate; i++ ) { sum = 0.0; npix = 0; /* Compute mean */ if (i == 0) { for (y = y1; y < y2; y++) { for (x = x1; x < x2; x++) { p = getpix (image,bitpix,w,h,bz,bs, x, y); sum += p; npix++; } } } else { for (y = y1; y < y2; y++) { for (x = x1; x < x2; x++) { p = getpix (image,bitpix,w,h,bz,bs, x, y); if (p > pmin && p < pmax) { sum += p; npix++; } } } } dnpix = (double) npix; pmean = sum / dnpix; /* Compute average deviation */ npix = 0; sum = 0.0; for (y = y1; y < y2; y++) { for (x = x1; x < x2; x++) { p = getpix (image,bitpix,w,h,bz,bs, x, y); if (p > pmin && p < pmax) { sum += fabs (p - pmean); npix++; } } } dnpix = (double) npix; if (npix > 0) sd = sum / dnpix; else sd = 0.0; pmin = pmean - sd * starsig; pmax = pmean + sd * starsig; } *mean = pmean; *sigma = sd; return; } static void mean1d (sv1, sv2, mean, sigma) double *sv1, *sv2; /* starting and ending pixels for statistics */ double *mean; /* Mean value of pixels (returned) */ double *sigma; /* Average deviation of pixels (returned) */ { double *sv; double p, pmin, pmax; double pmean = 0.0; double sd = 0.0; int i; int npix; double dnpix; double sum; pmin = -1.0e20; pmax = 1.0e20; /* Iterate with sigma-clipping */ for (i = 0; i < niterate; i++ ) { npix = 0; sum = 0.0; /* Compute mean */ for (sv = sv1; sv < sv2; sv++) { p = *sv; if (p > pmin && p < pmax) { sum += p; npix++; } } if (npix > 0) { dnpix = (double) npix; pmean = sum / dnpix; } else pmean = 0.0; /* Compute average deviation */ npix = 0; sum = 0.0; for (sv = sv1; sv < sv2; sv++) { p = *sv; if (p > pmin && p < pmax) { sum += fabs (p - pmean); npix++; } } if (npix > 0) sd = sum / dnpix; else sd = 0.0; pmin = pmean - (sd * starsig); pmax = pmean + (sd * starsig); } *mean = pmean; *sigma = sd; return; } /* Find total flux within a circular region minus a mean background level */ static double FindFlux (image, bitpix, w, h, bz, bs, x0, y0, r, background, zap) char *image; int bitpix; int w; int h; double bz; /* Zero point for pixel scaling */ double bs; /* Scale factor for pixel scaling */ int x0; int y0; int r; double background; /* Background level (subtracted for flux) */ int zap; /* If 1, set star to background after reading */ { double sum = 0.0; int x, y, x1, x2, y1, y2, yy, xxyy, xi, yi; int rr = r * r; double dp; /* Keep X within image */ x1 = -r; if (x0-r < 0) x1 = 0; x2 = r; if (x0+r > 0) x2 = w; /* Keep Y within image */ y1 = -r; if (y0-r < 0) y1 = 0; y2 = r; if (y0+r > 0) y2 = h; /* Integrate circular region around a star */ for (y = y1; y <= y2; y++) { yy = y*y; for (x = x1; x <= x2; x++) { xxyy = x*x + yy; if (xxyy <= rr) { xi = x0 + x; yi = y0 + x; dp = getpix (image, bitpix, w,h,bz,bs, xi, yi); if (dp > background) { sum += dp - background; if (zap) putpix (image, bitpix, w,h,bz,bs, xi, yi,background); } } } } return (sum); } /* Reset parameter values from the command line */ void setparm (parstring) char *parstring; { char *parname; char *parvalue; parname = parstring; if ((parvalue = strchr (parname,'=')) == NULL) return; *parvalue = (char) 0; parvalue++; if (!strcmp (parname, "nstatpix") || !strcmp (parname, "nspix")) setnspix (atoi (parvalue)); else if (!strcmp (parname, "istatpix") || !strcmp (parname, "ispix")) setispix (atoi (parvalue)); else if (!strcmp (parname, "niterate") || !strcmp (parname, "niter")) setniterate (atoi (parvalue)); else if (!strcmp (parname, "border")) setborder (atoi (parvalue)); else if (!strcmp (parname, "maxrad")) setmaxrad (atoi (parvalue)); else if (!strcmp (parname, "minrad")) setminrad (atoi (parvalue)); else if (!strcmp (parname, "starsig")) setstarsig (atof (parvalue)); else if (!strcmp (parname, "maxwalk")) setmaxwalk (atoi (parvalue)); else if (!strcmp (parname, "minsep")) setminsep (atoi (parvalue)); else if (!strcmp (parname, "minpeak")) setbmin (atof (parvalue)); else if (!strcmp (parname, "minmatch")) setminmatch ((int) atof (parvalue)); else if (!strcmp (parname, "nmax")) setnitmax ((int) atof (parvalue)); else if (!strcmp (parname, "nitmax")) setnitmax ((int) atof (parvalue)); else if (!strcmp (parname, "minstars")) setminstars ((int) atof (parvalue)); else if (!strcmp (parname, "minpmqual")) setminpmqual ((int) atof (parvalue)); else if (!strcmp (parname, "minid")) setminid ((int) atof (parvalue)); else if (!strcmp (parname, "nxydec")) setnxydec ((int) atof (parvalue)); else if (!strcmp (parname, "rnoise")) setrnoise ((int) atof (parvalue)); return; } static void rotstars (nstars, xa, ya, w, h) int nstars; /* Number of stars found in image */ double *xa; /* X coordinates of stars */ double *ya; /* Y coordinates of stars */ int w; /* Original width of image */ int h; /* Original height of image */ { int istar; void rotstar(); if (rotate == 1) rotate = 90; else if (rotate == 2) rotate = 180; else if (rotate == 3) rotate = 270; else if (rotate < 0) rotate = rotate + 360; else if (rotate > 360) rotate = rotate - 360; /* Rotate star postions one at a time */ for (istar = 0; istar < nstars; istar++) rotstar (&xa[istar], &ya[istar], w, h); return; } void rotstar (x, y, w, h) double *x; /* X coordinates of stars */ double *y; /* Y coordinates of stars */ int w; /* Original width of image */ int h; /* Original height of image */ { double x1, y1, x2, y2; double xn = (double) w; double yn = (double) h; int reflect=mirror; /* 1 if image is reflected, else 0 */ x1 = *x; y1 = *y; x2 = x1; y2 = y1; /* Rotate star postions one at a time */ /* Mirror coordinates without rotation */ if (rotate < 45.0 && rotate > -45.0) { if (reflect == 1) x2 = xn - x1 - 1.0; else if (reflect == 2) y2 = yn - y1 - 1.0; } /* Rotate by 90 degrees */ else if (rotate >= 45 && rotate < 135) { if (reflect == 1) { x2 = yn - y1 - 1.0; y2 = xn - x1 - 1.0; } else if (reflect == 2) { x2 = y1; y2 = x1; } else { x2 = yn - y1 - 1.0; y2 = x1; } } /* Rotate by 180 degrees */ else if (rotate >= 135 && rotate < 225) { if (reflect == 1) y2 = yn - y1 - 1.0; else if (reflect == 2) x2 = xn - x1 - 1.0; else { x2 = xn - x1 - 1.0; y2 = yn - y1 - 1.0; } } /* Rotate by 270 degrees */ else if (rotate >= 225 && rotate < 315) { if (reflect == 1) { x2 = y1; y2 = x1; } else if (reflect == 2) { x2 = yn - y1 - 1.0; y2 = xn - x1 - 1.0; } else { x2 = y1; y2 = xn - x1 - 1.0; } } /* If rotating by more than 315 degrees, flip across both axes */ else if (rotate >= 315 && mirror) { x2 = y1; y2 = x1; } *x = x2; *y = y2; return; } /* May 21 1996 Return peak flux in counts * May 22 1996 Add arguments so GETPIX and PUTPIX can check coordinates * Jun 6 1996 Change name from findStars to FindStars * Jun 12 1996 Remove unused variables after using lint * Jun 13 1996 Removed leftover free of image * Aug 6 1996 Fixed small defects after lint * Aug 26 1996 Drop unused variables NH and NW * Aug 30 1996 Modify sigma computation; allow border to be set * Sep 1 1996 Set constants in lwcs.h * Oct 15 1996 Drop unused variables * Dec 10 1996 Check for hot columns as well as hot rows * Dec 10 1996 Add option to read image stars from DAOFIND file * * Mar 20 1997 Declare external subroutine DAOREAD * Nov 6 1997 Add subroutine to return image catalog filename * Dec 15 1997 Change calls to ABS to FABS when doubles are involved * * May 27 1998 Include imio.h * Jul 30 1998 Deal with too-small sigmas * * Feb 4 1999 Keep overexposed (pixel value > BURNEDOUT) stars * Apr 26 1999 Fix Bright Walk() to slide along bleeding rows or columns * Apr 28 1999 Add scaling to getpix and getvec * Jun 11 1999 Add parameter setting subroutine * Oct 21 1999 Drop unused variables and fix sigma usage after lint * Oct 25 1999 Fix mean loop to avoid bad pointer creation * Oct 29 1999 Read image star positions from tab table or DAOPHOT table * Nov 23 1999 Lengthen imcatname from 32 to 256 for long pathnames * * Mar 27 2000 Drop unused variable imtab * * Jan 18 2001 Use trim section from image header, if not trimmed * Jul 25 2001 Return plate magnitudes instead of fluxes * Oct 31 2001 Add minmatch from matchstar.c to setparm() options * Nov 6 2001 Add setnitmax() to setparm() * Nov 7 2001 Add setminstars() to setparm() * Dec 19 2001 Add setmirror() and setrotate() to rotate input catalog * * Jan 23 2002 If zap, set pixels in star to background after adding up flux * Jan 23 2002 Skip recomputation of noise if istat is zero * Jan 23 2002 Set scale flag if BSCALE and BZERO not used * May 13 2002 Fix bugs found by lint * * Jan 23 2003 Add setminpmqual() to setparm() for USNO-B1.0 * Jan 29 2003 Add setminid() to setparm() for USNO-B1.0 * Apr 3 2003 Fix bug setting minll if bmin is less than 0 * Jun 2 2003 Fix bug to setcale(0) if bscale == 1, not 0 (J-B Marquette) * * Aug 3 2004 Move single star image position rotation into rotstar() * Aug 3 2004 Move daoread() declaration to wcscat.h * Sep 24 2004 Fix rotstar() to separate output values from input values * * Mar 30 2006 Add nxydec=num. decimal places in image coordinates to setparm() * Apr 25 2006 Change MINPEAK to mean counts above noise background * Suggested by Hill & Biddick for high background situations * Jun 19 2006 Initialized uninitialized variables * Oct 24 2006 Add reflection across horizontal as well as vertical axis * * Jan 8 2007 Include fitsfile.h instead of fitshead.h and imio.h * Jan 8 2007 Drop unused variables * Jan 10 2007 Include wcs.h * Oct 19 2007 Fix pointers in trim section processing * * Jun 24 2016 Fixed bug in TRIMSEC parsing found by Ole Streicher */ wcstools-3.9.5/libwcs/fitsfile.c0000664000016200001660000017310412733277111015721 0ustar minkoirsys/*** File libwcs/fitsfile.c *** June 24, 2016 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2016 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: fitsfile.c (FITS file reading and writing) * Purpose: Read and write FITS image and table files * fitsropen (inpath) * Open a FITS file for reading, returning a FILE pointer * fitsrhead (filename, lhead, nbhead) * Read FITS header and return it * fitsrtail (filename, lhead, nbhead) * Read appended FITS header and return it * fitsrsect (filename, nbhead, header, fd, x0, y0, nx, ny) * Read section of a FITS image, having already read the header * fitsrimage (filename, nbhead, header) * Read FITS image, having already ready the header * fitsrfull (filename, nbhead, header) * Read a FITS image of any dimension * fitsrtopen (inpath, nk, kw, nrows, nchar, nbhead) * Open a FITS table file for reading; return header information * fitsrthead (header, nk, kw, nrows, nchar, nbhead) * Extract FITS table information from a FITS header * fitsrtline (fd, nbhead, lbuff, tbuff, irow, nbline, line) * Read next line of FITS table file * ftgetr8 (entry, kw) * Extract column from FITS table line as double * ftgetr4 (entry, kw) * Extract column from FITS table line as float * ftgeti4 (entry, kw) * Extract column from FITS table line as int * ftgeti2 (entry, kw) * Extract column from FITS table line as short * ftgetc (entry, kw, string, maxchar) * Extract column from FITS table line as a character string * fitswimage (filename, header, image) * Write FITS header and image * fitswext (filename, header, image) * Write FITS header and image as extension to existing FITS file * fitswhdu (fd, filename, header, image) * Write FITS header and image as extension to file descriptor * fitscimage (filename, header, filename0) * Write FITS header and copy FITS image * fitswhead (filename, header) * Write FITS header and keep file open for further writing * fitswexhead (filename, header) * Write FITS header only to FITS extension without writing data * isfits (filename) * Return 1 if file is a FITS file, else 0 * fitsheadsize (header) * Return size of FITS header in bytes */ #include #ifndef VMS #include #endif #include #include #include #include #include #include "fitsfile.h" static int verbose=0; /* Print diagnostics */ static char fitserrmsg[80]; static int fitsinherit = 1; /* Append primary header to extension header */ void setfitsinherit (inh) int inh; {fitsinherit = inh; return;} static off_t ibhead = 0; /* Number of bytes read before header starts */ off_t getfitsskip() {return (ibhead);} /* FITSRHEAD -- Read a FITS header */ char * fitsrhead (filename, lhead, nbhead) char *filename; /* Name of FITS image file */ int *lhead; /* Allocated length of FITS header in bytes (returned) */ int *nbhead; /* Number of bytes before start of data (returned) */ /* This includes all skipped image extensions */ { int fd; char *header; /* FITS image header (filled) */ int extend; int nbytes,naxis, i; int ntry,nbr,irec,nrec, nbh, ipos, npos, nbprim, lprim, lext; int nax1, nax2, nax3, nax4, nbpix, ibpix, nblock, nbskip; char fitsbuf[2884]; char *headend; /* Pointer to last line of header */ char *headnext; /* Pointer to next line of header to be added */ int hdu; /* header/data unit counter */ int extnum; /* desired header data number (0=primary -1=first with data -2=use EXTNAME) */ char extname[32]; /* FITS extension name */ char extnam[32]; /* Desired FITS extension name */ char *ext; /* FITS extension name or number in header, if any */ char *pheader; /* Primary header (naxis is 0) */ char cext = 0; char *rbrac; /* Pointer to right bracket if present in file name */ char *mwcs; /* Pointer to WCS name separated by % */ char *newhead; /* New larger header */ int nbh0; /* Length of old too small header */ char *pheadend; int inherit = 1; /* Value of INHERIT keyword in FITS extension header */ int extfound = 0; /* Set to one if desired FITS extension is found */ int npcount; pheader = NULL; lprim = 0; header = NULL; /* Check for FITS WCS specification and ignore for file opening */ mwcs = strchr (filename, '%'); if (mwcs != NULL) *mwcs = (char) 0; /* Check for FITS extension and ignore for file opening */ rbrac = NULL; ext = strchr (filename, ','); if (ext == NULL) { ext = strchr (filename, '['); if (ext != NULL) { rbrac = strchr (filename, ']'); if (rbrac != NULL) *rbrac = (char) 0; } } if (ext != NULL) { cext = *ext; *ext = (char) 0; } /* Open the image file and read the header */ if (strncasecmp (filename,"stdin",5)) { fd = -1; fd = fitsropen (filename); } #ifndef VMS else { fd = STDIN_FILENO; extnum = -1; } #endif if (ext != NULL) { if (isnum (ext+1) == 1) extnum = atoi (ext+1); else { extnum = -2; strcpy (extnam, ext+1); } } else extnum = -1; /* Repair the damage done to the file-name string during parsing */ if (ext != NULL) *ext = cext; if (rbrac != NULL) *rbrac = ']'; if (mwcs != NULL) *mwcs = '%'; if (fd < 0) { fprintf (stderr,"FITSRHEAD: cannot read file %s\n", filename); return (NULL); } nbytes = FITSBLOCK; *nbhead = 0; headend = NULL; nbh = FITSBLOCK * 20 + 4; header = (char *) calloc ((unsigned int) nbh, 1); (void) hlength (header, nbh); headnext = header; nrec = 1; hdu = 0; ibhead = 0; /* Read FITS header from input file one FITS block at a time */ irec = 0; ibhead = 0; while (irec < 500) { nbytes = FITSBLOCK; for (ntry = 0; ntry < 10; ntry++) { for (i = 0; i < 2884; i++) fitsbuf[i] = 0; nbr = read (fd, fitsbuf, nbytes); if (verbose) fprintf (stderr,"FITSRHEAD: %d header bytes read\n",nbr); /* Short records allowed only if they have the last header line */ if (nbr < nbytes) { headend = ksearch (fitsbuf,"END"); if (headend == NULL) { if (ntry < 9) { if (verbose) fprintf (stderr,"FITSRHEAD: %d / %d bytes read %d\n", nbr,nbytes,ntry); } else { snprintf(fitserrmsg,79,"FITSRHEAD: '%d / %d bytes of header read from %s\n" ,nbr,nbytes,filename); #ifndef VMS if (fd != STDIN_FILENO) #endif (void)close (fd); free (header); /* if (pheader != NULL) return (pheader); */ if (extnum != -1 && !extfound) { *ext = (char) 0; if (extnum < 0) { snprintf (fitserrmsg,79, "FITSRHEAD: Extension %s not found in file %s", extnam, filename); } else { snprintf (fitserrmsg,79, "FITSRHEAD: Extension %d not found in file %s", extnum, filename); } *ext = cext; } else if (hdu > 0) { snprintf (fitserrmsg,79, "FITSRHEAD: No extensions found in file %s", filename); hdu = 0; if (pheader != NULL) { *lhead = nbprim; *nbhead = nbprim; return (pheader); } break; } else { snprintf (fitserrmsg,79, "FITSRHEAD: No header found in file %s", filename); } return (NULL); } } else break; } else break; } /* Replace control characters and nulls with spaces */ for (i = 0; i < 2880; i++) if (fitsbuf[i] < 32 || i > nbr) fitsbuf[i] = 32; if (nbr < 2880) nbr = 2880; /* Move current FITS record into header string */ strncpy (headnext, fitsbuf, nbr); *nbhead = *nbhead + nbr; nrec = nrec + 1; *(headnext+nbr+1) = 0; ibhead = ibhead + 2880; if (verbose) fprintf (stderr,"FITSRHEAD: %d bytes in header\n",ibhead); /* Check to see if this is the final record in this header */ headend = ksearch (fitsbuf,"END"); if (headend == NULL) { /* Double size of header buffer if too small */ if (nrec * FITSBLOCK > nbh) { nbh0 = nbh - 4; nbh = (nrec * 2 * FITSBLOCK) + 4; newhead = (char *) calloc (1,(unsigned int) nbh); if (newhead) { for (i = 0; i < nbh0; i++) newhead[i] = header[i]; free (header); newhead[nbh-3] = (char) 0; header = newhead; (void) hlength (header, nbh); headnext = header + ((nrec-1) * FITSBLOCK); } else { fprintf (stderr,"FITSRHEAD: %d bytes cannot be allocated for header\n",nbh); exit (1); } } else headnext = headnext + FITSBLOCK; } else { naxis = 0; hgeti4 (header,"NAXIS",&naxis); /* If header has no data, save it for appending to desired header */ if (naxis < 1) { nbprim = nrec * FITSBLOCK; headend = ksearch (header,"END"); lprim = headend + 80 - header; pheader = (char *) calloc ((unsigned int) (nbprim + 1), 1); for (i = 0; i < lprim; i++) pheader[i] = header[i]; for (i = lprim; i < nbprim; i++) pheader[i] = ' '; } /* If header has no data, start with the next record */ if (naxis < 1 && extnum == -1) { extend = 0; hgetl (header,"EXTEND",&extend); if (naxis == 0 && extend) { headnext = header; *headend = ' '; headend = NULL; nrec = 1; hdu = hdu + 1; } else { break; } } /* If this is the desired header data unit, keep it */ else if (extnum != -1) { if (extnum > -1 && hdu == extnum) { extfound = 1; break; } else if (extnum < 0) { extname[0] = 0; hgets (header, "EXTNAME", 32, extname); if (!strcmp (extnam,extname)) { extfound = 1; break; } } /* If this is not desired header data unit, skip over data */ hdu = hdu + 1; nblock = 0; ibhead = 0; if (naxis > 0) { ibpix = 0; hgeti4 (header,"BITPIX",&ibpix); if (ibpix < 0) { nbpix = -ibpix / 8; } else { nbpix = ibpix / 8; } nax1 = 1; hgeti4 (header,"NAXIS1",&nax1); nax2 = 1; if (naxis > 1) { hgeti4 (header,"NAXIS2",&nax2); } nax3 = 1; if (naxis > 2) { hgeti4 (header,"NAXIS3",&nax3); } nax4 = 1; if (naxis > 3) { hgeti4 (header,"NAXIS4",&nax4); } nbskip = nax1 * nax2 * nax3 * nax4 * nbpix; nblock = nbskip / 2880; if (nblock*2880 < nbskip) { nblock = nblock + 1; } npcount = 0; hgeti4 (header,"PCOUNT", &npcount); if (npcount > 0) { nbskip = nbskip + npcount; nblock = nbskip / 2880; if (nblock*2880 < nbskip) nblock = nblock + 1; } } else { nblock = 0; } *nbhead = *nbhead + (nblock * 2880); /* Set file pointer to beginning of next header/data unit */ if (nblock > 0) { #ifndef VMS if (fd != STDIN_FILENO) { ipos = lseek (fd, *nbhead, SEEK_SET); npos = *nbhead; } else { #else { #endif ipos = 0; for (i = 0; i < nblock; i++) { nbytes = FITSBLOCK; nbr = read (fd, fitsbuf, nbytes); if (nbr < nbytes) { ipos = ipos + nbr; break; } else { ipos = ipos + nbytes; } } npos = nblock * 2880; } if (ipos < npos) { snprintf (fitserrmsg,79,"FITSRHEAD: %d / %d bytes skipped\n", ipos,npos); extfound = 0; break; } } headnext = header; headend = NULL; nrec = 1; } else { break; } } } #ifndef VMS if (fd != STDIN_FILENO) (void)close (fd); #endif /* Print error message and return null if extension not found */ if (extnum != -1 && !extfound) { if (extnum < 0) fprintf (stderr, "FITSRHEAD: Extension %s not found in file %s\n",extnam, filename); else fprintf (stderr, "FITSRHEAD: Extension %d not found in file %s\n",extnum, filename); if (pheader != NULL) { free (pheader); pheader = NULL; } return (NULL); } /* Allocate an extra block for good measure */ *lhead = (nrec + 1) * FITSBLOCK; if (*lhead > nbh) { newhead = (char *) calloc (1,(unsigned int) *lhead); for (i = 0; i < nbh; i++) newhead[i] = header[i]; free (header); header = newhead; (void) hlength (header, *lhead); } else *lhead = nbh; /* If INHERIT keyword is FALSE, never append primary header */ if (hgetl (header, "INHERIT", &inherit)) { if (!inherit && fitsinherit) fitsinherit = 0; } /* Append primary data header to extension header */ if (pheader != NULL && extnum != 0 && fitsinherit && hdu > 0) { extname[0] = 0; hgets (header, "XTENSION", 32, extname); if (!strcmp (extname,"IMAGE")) { strncpy (header, "SIMPLE ", 8); hputl (header, "SIMPLE", 1); } headend = blsearch (header,"END"); if (headend == NULL) headend = ksearch (header, "END"); lext = headend - header; /* Update primary header for inclusion at end of extension header */ hchange (pheader, "SIMPLE", "ROOTHEAD"); hchange (pheader, "NEXTEND", "NUMEXT"); hdel (pheader, "BITPIX"); hdel (pheader, "NAXIS"); hdel (pheader, "EXTEND"); hputl (pheader, "ROOTEND",1); pheadend = ksearch (pheader,"END"); lprim = pheadend + 320 - pheader; if (lext + lprim > nbh) { nrec = (lext + lprim) / FITSBLOCK; if (FITSBLOCK*nrec < lext+lprim) nrec = nrec + 1; *lhead = (nrec+1) * FITSBLOCK; newhead = (char *) calloc (1,(unsigned int) *lhead); for (i = 0; i < nbh; i++) newhead[i] = header[i]; free (header); header = newhead; headend = header + lext; (void) hlength (header, *lhead); } hputs (header,"COMMENT","-------------------------------------------"); hputs (header,"COMMENT","Information from Primary Header"); hputs (header,"COMMENT","-------------------------------------------"); headend = blsearch (header,"END"); if (headend == NULL) headend = ksearch (header, "END"); pheader[lprim] = 0; strncpy (headend, pheader, lprim); if (pheader != NULL) { free (pheader); pheader = NULL; } } ibhead = *nbhead - ibhead; return (header); } /* FITSRTAIL -- Read FITS header appended to graphics file */ char * fitsrtail (filename, lhead, nbhead) char *filename; /* Name of image file */ int *lhead; /* Allocated length of FITS header in bytes (returned) */ int *nbhead; /* Number of bytes before start of data (returned) */ /* This includes all skipped image extensions */ { int fd; char *header; /* FITS image header (filled) */ int nbytes, i, ndiff; int nbr, irec; off_t offset; char *mwcs; /* Pointer to WCS name separated by % */ char *headstart; char *newhead; header = NULL; /* Check for FITS WCS specification and ignore for file opening */ mwcs = strchr (filename, '%'); if (mwcs != NULL) *mwcs = (char) 0; /* Open the image file and read the header */ if (strncasecmp (filename,"stdin",5)) { fd = -1; fd = fitsropen (filename); } #ifndef VMS else { fd = STDIN_FILENO; } #endif /* Repair the damage done to the file-name string during parsing */ if (mwcs != NULL) *mwcs = '%'; if (fd < 0) { fprintf (stderr,"FITSRTAIL: cannot read file %s\n", filename); return (NULL); } nbytes = FITSBLOCK; *nbhead = 0; *lhead = 0; /* Read FITS header from end of input file one FITS block at a time */ irec = 0; while (irec < 100) { nbytes = FITSBLOCK * (irec + 2); header = (char *) calloc ((unsigned int) nbytes, 1); offset = lseek (fd, -nbytes, SEEK_END); if (offset < 0) { free (header); header = NULL; nbytes = 0; break; } for (i = 0; i < nbytes; i++) header[i] = 0; nbr = read (fd, header, nbytes); /* Check for SIMPLE at start of header */ for (i = 0; i < nbr; i++) if (header[i] < 32) header[i] = 32; if ((headstart = ksearch (header,"SIMPLE"))) { if (headstart != header) { ndiff = headstart - header; newhead = (char *) calloc ((unsigned int) nbytes, 1); for (i = 0; i < nbytes-ndiff; i++) newhead[i] = headstart[i]; free (header); header = newhead; } *lhead = nbytes; *nbhead = nbytes; break; } free (header); } (void) hlength (header, nbytes); #ifndef VMS if (fd != STDIN_FILENO) (void)close (fd); #endif return (header); } /* FITSRSECT -- Read a piece of a FITS image, having already read the header */ char * fitsrsect (filename, header, nbhead, x0, y0, nx, ny, nlog) char *filename; /* Name of FITS image file */ char *header; /* FITS header for image (previously read) */ int nbhead; /* Actual length of image header(s) in bytes */ int x0, y0; /* FITS image coordinate of first pixel */ int nx; /* Number of columns to read (less than NAXIS1) */ int ny; /* Number of rows to read (less than NAXIS2) */ int nlog; /* Note progress mod this rows */ { int fd; /* File descriptor */ int nbimage, naxis1, naxis2, bytepix, nbread; int bitpix, naxis, nblocks, nbytes, nbr; int x1, y1, nbline, nyleft; off_t impos, nblin; char *image, *imline, *imlast; int ilog = 0; int row; /* Open the image file and read the header */ if (strncasecmp (filename,"stdin", 5)) { fd = -1; fd = fitsropen (filename); if (fd < 0) { snprintf (fitserrmsg,79, "FITSRSECT: cannot read file %s\n", filename); return (NULL); } /* Skip over FITS header and whatever else needs to be skipped */ if (lseek (fd, nbhead, SEEK_SET) < 0) { (void)close (fd); snprintf (fitserrmsg,79, "FITSRSECT: cannot skip header of file %s\n", filename); return (NULL); } } #ifndef VMS else fd = STDIN_FILENO; #endif /* Compute size of image in bytes using relevant header parameters */ naxis = 1; hgeti4 (header,"NAXIS",&naxis); naxis1 = 1; hgeti4 (header,"NAXIS1",&naxis1); naxis2 = 1; hgeti4 (header,"NAXIS2",&naxis2); bitpix = 0; hgeti4 (header,"BITPIX",&bitpix); if (bitpix == 0) { /* snprintf (fitserrmsg,79, "FITSRSECT: BITPIX is 0; image not read\n"); */ (void)close (fd); return (NULL); } bytepix = bitpix / 8; if (bytepix < 0) bytepix = -bytepix; /* Keep X coordinates within image limits */ if (x0 < 1) x0 = 1; else if (x0 > naxis1) x0 = naxis1; x1 = x0 + nx - 1; if (x1 < 1) x1 = 1; else if (x1 > naxis1) x1 = naxis1; nx = x1 - x0 + 1; /* Keep Y coordinates within image limits */ if (y0 < 1) y0 = 1; else if (y0 > naxis2) y0 = naxis2; y1 = y0 + ny - 1; if (y1 < 1) y1 = 1; else if (y1 > naxis2) y1 = naxis2; ny = y1 - y0 + 1; /* Number of bytes in output image */ nbline = nx * bytepix; nbimage = nbline * ny; /* Set number of bytes to integral number of 2880-byte blocks */ nblocks = nbimage / FITSBLOCK; if (nblocks * FITSBLOCK < nbimage) nblocks = nblocks + 1; nbytes = nblocks * FITSBLOCK; /* Allocate image section to be read */ image = (char *) malloc (nbytes); nyleft = ny; imline = image; nbr = 0; /* Computer pointer to first byte of input image to read */ nblin = naxis1 * bytepix; impos = ((y0 - 1) * nblin) + ((x0 - 1) * bytepix); row = y0 - 1; /* Read image section one line at a time */ while (nyleft-- > 0) { if (lseek (fd, impos, SEEK_CUR) >= 0) { nbread = read (fd, imline, nbline); nbr = nbr + nbread; impos = nblin - nbread; imline = imline + nbline; row++; if (++ilog == nlog) { ilog = 0; fprintf (stderr, "Row %5d extracted ", row); (void) putc (13,stderr); } } } if (nlog) fprintf (stderr, "\n"); /* Fill rest of image with zeroes */ imline = image + nbimage; imlast = image + nbytes; while (imline++ < imlast) *imline = (char) 0; /* Byte-reverse image, if necessary */ if (imswapped ()) imswap (bitpix, image, nbytes); return (image); } /* FITSRIMAGE -- Read a FITS image */ char * fitsrimage (filename, nbhead, header) char *filename; /* Name of FITS image file */ int nbhead; /* Actual length of image header(s) in bytes */ char *header; /* FITS header for image (previously read) */ { int fd; int nbimage, naxis1, naxis2, bytepix, nbread; int bitpix, naxis, nblocks, nbytes, nbleft, nbr; int simple; char *image, *imleft; /* Open the image file and read the header */ if (strncasecmp (filename,"stdin", 5)) { fd = -1; fd = fitsropen (filename); if (fd < 0) { snprintf (fitserrmsg,79, "FITSRIMAGE: cannot read file %s\n", filename); return (NULL); } /* Skip over FITS header and whatever else needs to be skipped */ if (lseek (fd, nbhead, SEEK_SET) < 0) { (void)close (fd); snprintf (fitserrmsg,79, "FITSRIMAGE: cannot skip header of file %s\n", filename); return (NULL); } } #ifndef VMS else fd = STDIN_FILENO; #endif /* If SIMPLE=F in header, simply put post-header part of file in buffer */ hgetl (header, "SIMPLE", &simple); if (!simple) { nbytes = getfilesize (filename) - nbhead; if ((image = (char *) malloc (nbytes + 1)) == NULL) { /* snprintf (fitserrmsg,79, "FITSRIMAGE: %d-byte image buffer cannot be allocated\n"); */ (void)close (fd); return (NULL); } hputi4 (header, "NBDATA", nbytes); nbread = read (fd, image, nbytes); return (image); } /* Compute size of image in bytes using relevant header parameters */ naxis = 1; hgeti4 (header,"NAXIS",&naxis); naxis1 = 1; hgeti4 (header,"NAXIS1",&naxis1); naxis2 = 1; hgeti4 (header,"NAXIS2",&naxis2); bitpix = 0; hgeti4 (header,"BITPIX",&bitpix); if (bitpix == 0) { /* snprintf (fitserrmsg,79, "FITSRIMAGE: BITPIX is 0; image not read\n"); */ (void)close (fd); return (NULL); } bytepix = bitpix / 8; if (bytepix < 0) bytepix = -bytepix; /* If either dimension is one and image is 3-D, read all three dimensions */ if (naxis == 3 && (naxis1 ==1 || naxis2 == 1)) { int naxis3; hgeti4 (header,"NAXIS3",&naxis3); nbimage = naxis1 * naxis2 * naxis3 * bytepix; } else nbimage = naxis1 * naxis2 * bytepix; /* Set number of bytes to integral number of 2880-byte blocks */ nblocks = nbimage / FITSBLOCK; if (nblocks * FITSBLOCK < nbimage) nblocks = nblocks + 1; nbytes = nblocks * FITSBLOCK; /* Allocate and read image */ image = (char *) malloc (nbytes); nbleft = nbytes; imleft = image; nbr = 0; while (nbleft > 0) { nbread = read (fd, imleft, nbleft); nbr = nbr + nbread; #ifndef VMS if (fd == STDIN_FILENO && nbread < nbleft && nbread > 0) { nbleft = nbleft - nbread; imleft = imleft + nbread; } else #endif nbleft = 0; } #ifndef VMS if (fd != STDIN_FILENO) (void)close (fd); #endif if (nbr < nbimage) { snprintf (fitserrmsg,79, "FITSRIMAGE: %d of %d bytes read from file %s\n", nbr, nbimage, filename); return (NULL); } /* Byte-reverse image, if necessary */ if (imswapped ()) imswap (bitpix, image, nbytes); return (image); } /* FITSRFULL -- Read a FITS image of any dimension */ char * fitsrfull (filename, nbhead, header) char *filename; /* Name of FITS image file */ int nbhead; /* Actual length of image header(s) in bytes */ char *header; /* FITS header for image (previously read) */ { int fd; int nbimage, naxisi, iaxis, bytepix, nbread; int bitpix, naxis, nblocks, nbytes, nbleft, nbr, simple; char keyword[16]; char *image, *imleft; /* Open the image file and read the header */ if (strncasecmp (filename,"stdin", 5)) { fd = -1; fd = fitsropen (filename); if (fd < 0) { snprintf (fitserrmsg,79, "FITSRFULL: cannot read file %s\n", filename); return (NULL); } /* Skip over FITS header and whatever else needs to be skipped */ if (lseek (fd, nbhead, SEEK_SET) < 0) { (void)close (fd); snprintf (fitserrmsg,79, "FITSRFULL: cannot skip header of file %s\n", filename); return (NULL); } } #ifndef VMS else fd = STDIN_FILENO; #endif /* If SIMPLE=F in header, simply put post-header part of file in buffer */ hgetl (header, "SIMPLE", &simple); if (!simple) { nbytes = getfilesize (filename) - nbhead; if ((image = (char *) malloc (nbytes + 1)) == NULL) { snprintf (fitserrmsg,79, "FITSRFULL: %d-byte image buffer cannot be allocated\n",nbytes+1); (void)close (fd); return (NULL); } hputi4 (header, "NBDATA", nbytes); nbread = read (fd, image, nbytes); return (image); } /* Find number of bytes per pixel */ bitpix = 0; hgeti4 (header,"BITPIX",&bitpix); if (bitpix == 0) { snprintf (fitserrmsg,79, "FITSRFULL: BITPIX is 0; image not read\n"); (void)close (fd); return (NULL); } bytepix = bitpix / 8; if (bytepix < 0) bytepix = -bytepix; nbimage = bytepix; /* Compute size of image in bytes using relevant header parameters */ naxis = 1; hgeti4 (header,"NAXIS",&naxis); for (iaxis = 1; iaxis <= naxis; iaxis++) { sprintf (keyword, "NAXIS%d", iaxis); naxisi = 1; hgeti4 (header,keyword,&naxisi); nbimage = nbimage * naxisi; } /* Set number of bytes to integral number of 2880-byte blocks */ nblocks = nbimage / FITSBLOCK; if (nblocks * FITSBLOCK < nbimage) nblocks = nblocks + 1; nbytes = nblocks * FITSBLOCK; /* Allocate and read image */ image = (char *) malloc (nbytes); nbleft = nbytes; imleft = image; nbr = 0; while (nbleft > 0) { nbread = read (fd, imleft, nbleft); nbr = nbr + nbread; #ifndef VMS if (fd == STDIN_FILENO && nbread < nbleft && nbread > 0) { nbleft = nbleft - nbread; imleft = imleft + nbread; } else #endif nbleft = 0; } #ifndef VMS if (fd != STDIN_FILENO) (void)close (fd); #endif if (nbr < nbimage) { snprintf (fitserrmsg,79, "FITSRFULL: %d of %d image bytes read from file %s\n", nbr, nbimage, filename); return (NULL); } /* Byte-reverse image, if necessary */ if (imswapped ()) imswap (bitpix, image, nbytes); return (image); } /* FITSROPEN -- Open a FITS file, returning the file descriptor */ int fitsropen (inpath) char *inpath; /* Pathname for FITS tables file to read */ { int ntry; int fd; /* file descriptor for FITS tables file (returned) */ char *ext; /* extension name or number */ char cext = 0; char *rbrac; char *mwcs; /* Pointer to WCS name separated by % */ /* Check for FITS WCS specification and ignore for file opening */ mwcs = strchr (inpath, '%'); /* Check for FITS extension and ignore for file opening */ ext = strchr (inpath, ','); rbrac = NULL; if (ext == NULL) { ext = strchr (inpath, '['); if (ext != NULL) { rbrac = strchr (inpath, ']'); } } /* Open input file */ for (ntry = 0; ntry < 3; ntry++) { if (ext != NULL) { cext = *ext; *ext = 0; } if (rbrac != NULL) *rbrac = (char) 0; if (mwcs != NULL) *mwcs = (char) 0; fd = open (inpath, O_RDONLY); if (ext != NULL) *ext = cext; if (rbrac != NULL) *rbrac = ']'; if (mwcs != NULL) *mwcs = '%'; if (fd >= 0) break; else if (ntry == 2) { snprintf (fitserrmsg,79, "FITSROPEN: cannot read file %s\n", inpath); return (-1); } } if (verbose) fprintf (stderr,"FITSROPEN: input file %s opened\n",inpath); return (fd); } static int offset1=0; static int offset2=0; /* FITSRTOPEN -- Open FITS table file and fill structure with * pointers to selected keywords * Return file descriptor (-1 if unsuccessful) */ int fitsrtopen (inpath, nk, kw, nrows, nchar, nbhead) char *inpath; /* Pathname for FITS tables file to read */ int *nk; /* Number of keywords to use */ struct Keyword **kw; /* Structure for desired entries */ int *nrows; /* Number of rows in table (returned) */ int *nchar; /* Number of characters in one table row (returned) */ int *nbhead; /* Number of characters before table starts */ { char temp[16]; int fd; int lhead; /* Maximum length in bytes of FITS header */ char *header; /* Header for FITS tables file to read */ /* Read FITS header from input file */ header = fitsrhead (inpath, &lhead, nbhead); if (!header) { snprintf (fitserrmsg,79,"FITSRTOPEN: %s is not a FITS file\n",inpath); return (0); } /* Make sure this file is really a FITS table file */ temp[0] = 0; (void) hgets (header,"XTENSION",16,temp); if (strlen (temp) == 0) { snprintf (fitserrmsg,79, "FITSRTOPEN: %s is not a FITS table file\n",inpath); free ((void *) header); return (0); } /* If it is a FITS file, get table information from the header */ else if (!strcmp (temp, "TABLE") || !strcmp (temp, "BINTABLE")) { if (fitsrthead (header, nk, kw, nrows, nchar)) { snprintf (fitserrmsg,79, "FITSRTOPEN: Cannot read FITS table from %s\n",inpath); free ((void *) header); return (-1); } else { fd = fitsropen (inpath); offset1 = 0; offset2 = 0; free ((void *) header); return (fd); } } /* If it is another FITS extension note it and return */ else { snprintf (fitserrmsg,79, "FITSRTOPEN: %s is a %s extension, not table\n", inpath, temp); free ((void *) header); return (0); } } static struct Keyword *pw; /* Structure for all entries */ static int *lpnam; /* length of name for each field */ static int bfields = 0; /* FITSRTHEAD -- From FITS table header, read pointers to selected keywords */ int fitsrthead (header, nk, kw, nrows, nchar) char *header; /* Header for FITS tables file to read */ int *nk; /* Number of keywords to use */ struct Keyword **kw; /* Structure for desired entries */ int *nrows; /* Number of rows in table (returned) */ int *nchar; /* Number of characters in one table row (returned) */ { struct Keyword *rw; /* Structure for desired entries */ int nfields; int ifield, ik, i, ikf, ltform, kl; char *h0, *h1, *tf1, *tf2; char tname[12]; char temp[16]; char tform[16]; int tverb; int bintable = 0; h0 = header; /* Make sure this is really a FITS table file header */ temp[0] = 0; hgets (header,"XTENSION",16,temp); if (strlen (temp) == 0) { snprintf (fitserrmsg,79, "FITSRTHEAD: Not a FITS table header\n"); return (-1); } else if (!strcmp (temp, "BINTABLE")) { bintable = 1; } else if (strcmp (temp, "TABLE")) { snprintf (fitserrmsg,79, "FITSRTHEAD: %s extension, not TABLE\n",temp); return (-1); } /* Get table size from FITS header */ *nchar = 0; hgeti4 (header,"NAXIS1",nchar); *nrows = 0; hgeti4 (header,"NAXIS2", nrows); if (*nrows <= 0 || *nchar <= 0) { snprintf (fitserrmsg,79, "FITSRTHEAD: cannot read %d x %d table\n", *nrows,*nchar); return (-1); } /* Set up table for access to individual fields */ nfields = 0; hgeti4 (header,"TFIELDS",&nfields); if (verbose) fprintf (stderr, "FITSRTHEAD: %d fields per table entry\n", nfields); if (nfields > bfields) { if (bfields > 0) free ((void *)pw); pw = (struct Keyword *) calloc (nfields, sizeof(struct Keyword)); if (pw == NULL) { snprintf (fitserrmsg,79,"FITSRTHEAD: cannot allocate table structure\n"); return (-1); } if (bfields > 0) free ((void *)lpnam); lpnam = (int *) calloc (nfields, sizeof(int)); if (lpnam == NULL) { snprintf (fitserrmsg,79,"FITSRTHEAD: cannot allocate length structure\n"); return (-1); } bfields = nfields; } tverb = verbose; verbose = 0; ikf = 0; for (ifield = 0; ifield < nfields; ifield++) { /* Name of field */ for (i = 0; i < 12; i++) tname[i] = 0; sprintf (tname, "TTYPE%d", ifield+1);; temp[0] = 0; h1 = ksearch (h0,tname); h0 = h1; hgets (h0,tname,16,temp); strcpy (pw[ifield].kname,temp); pw[ifield].lname = strlen (pw[ifield].kname); /* Sequence of field on line */ pw[ifield].kn = ifield + 1; /* First column of field */ if (bintable) pw[ifield].kf = ikf; else { for (i = 0; i < 12; i++) tname[i] = 0; sprintf (tname, "TBCOL%d", ifield+1); pw[ifield].kf = 0; hgeti4 (h0,tname, &pw[ifield].kf); } /* Length of field */ for (i = 0; i < 12; i++) tname[i] = 0; sprintf (tname, "TFORM%d", ifield+1);; tform[0] = 0; hgets (h0,tname,16,tform); strcpy (pw[ifield].kform, tform); ltform = strlen (tform); if (tform[ltform-1] == 'A') { pw[ifield].kform[0] = 'A'; for (i = 0; i < ltform-1; i++) pw[ifield].kform[i+1] = tform[i]; pw[ifield].kform[ltform] = (char) 0; tf1 = pw[ifield].kform + 1; kl = atof (tf1); } else if (!strcmp (tform,"I")) kl = 2; else if (!strcmp (tform, "J")) kl = 4; else if (!strcmp (tform, "E")) kl = 4; else if (!strcmp (tform, "D")) kl = 8; else { tf1 = tform + 1; tf2 = strchr (tform,'.'); if (tf2 != NULL) *tf2 = ' '; kl = atoi (tf1); } pw[ifield].kl = kl; ikf = ikf + kl; } /* Set up table for access to desired fields */ verbose = tverb; if (verbose) fprintf (stderr, "FITSRTHEAD: %d keywords read\n", *nk); /* If nk = 0, allocate and return structures for all table fields */ if (*nk <= 0) { *kw = pw; *nk = nfields; return (0); } else rw = *kw; /* Find each desired keyword in the header */ for (ik = 0; ik < *nk; ik++) { if (rw[ik].kn <= 0) { for (ifield = 0; ifield < nfields; ifield++) { if (rw[ik].lname != pw[ifield].lname) continue; if (strcmp (pw[ifield].kname, rw[ik].kname) == 0) { break; } } } else ifield = rw[ik].kn - 1; /* Set pointer, lentth, and name in returned array of structures */ rw[ik].kn = ifield + 1; rw[ik].kf = pw[ifield].kf - 1; rw[ik].kl = pw[ifield].kl; strcpy (rw[ik].kform, pw[ifield].kform); strcpy (rw[ik].kname, pw[ifield].kname); } return (0); } int fitsrtline (fd, nbhead, lbuff, tbuff, irow, nbline, line) int fd; /* File descriptor for FITS file */ int nbhead; /* Number of bytes in FITS header */ int lbuff; /* Number of bytes in table buffer */ char *tbuff; /* FITS table buffer */ int irow; /* Number of table row to read */ int nbline; /* Number of bytes to read for this line */ char *line; /* One line of FITS table (returned) */ { int nbuff, nlbuff; int nbr = 0; int offset, offend, ntry, ioff; char *tbuff1; offset = nbhead + (nbline * irow); offend = offset + nbline - 1; /* Read a new buffer of the FITS table into memory if needed */ if (offset < offset1 || offend > offset2) { nlbuff = lbuff / nbline; nbuff = nlbuff * nbline; for (ntry = 0; ntry < 3; ntry++) { ioff = lseek (fd, offset, SEEK_SET); if (ioff < offset) { if (ntry == 2) return (0); else continue; } nbr = read (fd, tbuff, nbuff); if (nbr < nbline) { if (verbose) fprintf (stderr, "FITSRTLINE: %d / %d bytes read %d\n", nbr,nbuff,ntry); if (ntry == 2) return (nbr); } else break; } offset1 = offset; offset2 = offset + nbr - 1; strncpy (line, tbuff, nbline); return (nbline); } else { tbuff1 = tbuff + (offset - offset1); strncpy (line, tbuff1, nbline); return (nbline); } } void fitsrtlset () { offset1 = 0; offset2 = 0; return; } /* FTGETI2 -- Extract n'th column from FITS table line as short */ short ftgeti2 (entry, kw) char *entry; /* Row or entry from table */ struct Keyword *kw; /* Table column information from FITS header */ { char temp[30]; short i; int j; float r; double d; if (ftgetc (entry, kw, temp, 30)) { if (!strcmp (kw->kform, "I")) moveb (temp, (char *) &i, 2, 0, 0); else if (!strcmp (kw->kform, "J")) { moveb (temp, (char *) &j, 4, 0, 0); i = (short) j; } else if (!strcmp (kw->kform, "E")) { moveb (temp, (char *) &r, 4, 0, 0); i = (short) r; } else if (!strcmp (kw->kform, "D")) { moveb (temp, (char *) &d, 8, 0, 0); i = (short) d; } else i = (short) atof (temp); return (i); } else return ((short) 0); } /* FTGETI4 -- Extract n'th column from FITS table line as int */ int ftgeti4 (entry, kw) char *entry; /* Row or entry from table */ struct Keyword *kw; /* Table column information from FITS header */ { char temp[30]; short i; int j; float r; double d; if (ftgetc (entry, kw, temp, 30)) { if (!strcmp (kw->kform, "I")) { moveb (temp, (char *) &i, 2, 0, 0); j = (int) i; } else if (!strcmp (kw->kform, "J")) moveb (temp, (char *) &j, 4, 0, 0); else if (!strcmp (kw->kform, "E")) { moveb (temp, (char *) &r, 4, 0, 0); j = (int) r; } else if (!strcmp (kw->kform, "D")) { moveb (temp, (char *) &d, 8, 0, 0); j = (int) d; } else j = (int) atof (temp); return (j); } else return (0); } /* FTGETR4 -- Extract n'th column from FITS table line as float */ float ftgetr4 (entry, kw) char *entry; /* Row or entry from table */ struct Keyword *kw; /* Table column information from FITS header */ { char temp[30]; short i; int j; float r; double d; if (ftgetc (entry, kw, temp, 30)) { if (!strcmp (kw->kform, "I")) { moveb (temp, (char *) &i, 2, 0, 0); r = (float) i; } else if (!strcmp (kw->kform, "J")) { moveb (temp, (char *) &j, 4, 0, 0); r = (float) j; } else if (!strcmp (kw->kform, "E")) moveb (temp, (char *) &r, 4, 0, 0); else if (!strcmp (kw->kform, "D")) { moveb (temp, (char *) &d, 8, 0, 0); r = (float) d; } else r = (float) atof (temp); return (r); } else return ((float) 0.0); } /* FTGETR8 -- Extract n'th column from FITS table line as double */ double ftgetr8 (entry, kw) char *entry; /* Row or entry from table */ struct Keyword *kw; /* Table column information from FITS header */ { char temp[30]; short i; int j; float r; double d; if (ftgetc (entry, kw, temp, 30)) { if (!strcmp (kw->kform, "I")) { moveb (temp, (char *) &i, 2, 0, 0); d = (double) i; } else if (!strcmp (kw->kform, "J")) { moveb (temp, (char *) &j, 4, 0, 0); d = (double) j; } else if (!strcmp (kw->kform, "E")) { moveb (temp, (char *) &r, 4, 0, 0); d = (double) r; } else if (!strcmp (kw->kform, "D")) moveb (temp, (char *) &d, 8, 0, 0); else d = atof (temp); return (d); } else return ((double) 0.0); } /* FTGETC -- Extract n'th column from FITS table line as character string */ int ftgetc (entry, kw, string, maxchar) char *entry; /* Row or entry from table */ struct Keyword *kw; /* Table column information from FITS header */ char *string; /* Returned string */ int maxchar; /* Maximum number of characters in returned string */ { int length = maxchar; if (kw->kl < length) length = kw->kl; if (length > 0) { strncpy (string, entry+kw->kf, length); string[length] = 0; return ( 1 ); } else return ( 0 ); } extern int errno; /*FITSWIMAGE -- Write FITS header and image */ int fitswimage (filename, header, image) char *filename; /* Name of FITS image file */ char *header; /* FITS image header */ char *image; /* FITS image pixels */ { int fd; /* Open the output file */ if (strcasecmp (filename,"stdout") ) { if (!access (filename, 0)) { fd = open (filename, O_WRONLY); if (fd < 3) { snprintf (fitserrmsg,79, "FITSWIMAGE: file %s not writeable\n", filename); return (0); } } else { fd = open (filename, O_RDWR+O_CREAT, 0666); if (fd < 3) { snprintf (fitserrmsg,79, "FITSWIMAGE: cannot create file %s\n", filename); return (0); } } } #ifndef VMS else fd = STDOUT_FILENO; #endif return (fitswhdu (fd, filename, header, image)); } /*FITSWEXT -- Write FITS header and image as extension to a file */ int fitswext (filename, header, image) char *filename; /* Name of IFTS image file */ char *header; /* FITS image header */ char *image; /* FITS image pixels */ { int fd; /* Open the output file */ if (strcasecmp (filename,"stdout") ) { if (!access (filename, 0)) { fd = open (filename, O_WRONLY); if (fd < 3) { snprintf (fitserrmsg,79, "FITSWEXT: file %s not writeable\n", filename); return (0); } } else { fd = open (filename, O_APPEND, 0666); if (fd < 3) { snprintf (fitserrmsg,79, "FITSWEXT: cannot append to file %s\n", filename); return (0); } } } #ifndef VMS else fd = STDOUT_FILENO; #endif return (fitswhdu (fd, filename, header, image)); } /* FITSWHDU -- Write FITS head and image as extension */ int fitswhdu (fd, filename, header, image) int fd; /* File descriptor */ char *filename; /* Name of IFTS image file */ char *header; /* FITS image header */ char *image; /* FITS image pixels */ { int nbhead, nbimage, nblocks, bytepix, i, nbhw; int bitpix, naxis, iaxis, naxisi, nbytes, nbw, nbpad, nbwp, simple; char *endhead, *padding; double bzero, bscale; char keyword[32]; /* Change BITPIX=-16 files to BITPIX=16 with BZERO and BSCALE */ bitpix = 0; hgeti4 (header,"BITPIX",&bitpix); if (bitpix == -16) { if (!hgetr8 (header, "BZERO", &bzero) && !hgetr8 (header, "BSCALE", &bscale)) { bitpix = 16; hputi4 (header, "BITPIX", bitpix); hputr8 (header, "BZERO", 32768.0); hputr8 (header, "BSCALE", 1.0); } } /* Write header to file */ endhead = ksearch (header,"END") + 80; nbhead = endhead - header; nbhw = write (fd, header, nbhead); if (nbhw < nbhead) { snprintf (fitserrmsg,79, "FITSWHDU: wrote %d / %d bytes of header to file %s\n", nbhw, nbhead, filename); (void)close (fd); return (0); } /* Write extra spaces to make an integral number of 2880-byte blocks */ nblocks = nbhead / FITSBLOCK; if (nblocks * FITSBLOCK < nbhead) nblocks = nblocks + 1; nbytes = nblocks * FITSBLOCK; nbpad = nbytes - nbhead; padding = (char *)calloc (1, nbpad); for (i = 0; i < nbpad; i++) padding[i] = ' '; nbwp = write (fd, padding, nbpad); if (nbwp < nbpad) { snprintf (fitserrmsg,79, "FITSWHDU: wrote %d / %d bytes of header padding to file %s\n", nbwp, nbpad, filename); (void)close (fd); return (0); } nbhw = nbhw + nbwp; free (padding); /* Return if file has no data */ if (bitpix == 0 || image == NULL) { /* snprintf (fitserrmsg,79, "FITSWHDU: BITPIX is 0; image not written\n"); */ (void)close (fd); return (0); } /* If SIMPLE=F in header, just write whatever is in the buffer */ hgetl (header, "SIMPLE", &simple); if (!simple) { hgeti4 (header, "NBDATA", &nbytes); nbimage = nbytes; } else { /* Compute size of pixel in bytes */ bytepix = bitpix / 8; if (bytepix < 0) bytepix = -bytepix; nbimage = bytepix; /* Compute size of image in bytes using relevant header parameters */ naxis = 1; hgeti4 (header,"NAXIS",&naxis); for (iaxis = 1; iaxis <= naxis; iaxis++) { sprintf (keyword, "NAXIS%d", iaxis); naxisi = 1; hgeti4 (header,keyword,&naxisi); nbimage = nbimage * naxisi; } /* Number of bytes to write is an integral number of FITS blocks */ nblocks = nbimage / FITSBLOCK; if (nblocks * FITSBLOCK < nbimage) nblocks = nblocks + 1; nbytes = nblocks * FITSBLOCK; /* Byte-reverse image before writing, if necessary */ if (imswapped ()) imswap (bitpix, image, nbimage); } /* Write image to file */ nbw = write (fd, image, nbimage); if (nbw < nbimage) { snprintf (fitserrmsg,79, "FITSWHDU: wrote %d / %d bytes of image to file %s\n", nbw, nbimage, filename); return (0); } /* Write extra zeroes to make an integral number of 2880-byte blocks */ nbpad = nbytes - nbimage; if (nbpad > 0) { padding = (char *)calloc (1, nbpad); nbwp = write (fd, padding, nbpad); if (nbwp < nbpad) { snprintf (fitserrmsg,79, "FITSWHDU: wrote %d / %d bytes of image padding to file %s\n", nbwp, nbpad, filename); (void)close (fd); return (0); } free (padding); } else nbwp = 0; (void)close (fd); /* Byte-reverse image after writing, if necessary */ if (imswapped ()) imswap (bitpix, image, nbimage); nbw = nbw + nbwp + nbhw; return (nbw); } /*FITSCIMAGE -- Write FITS header and copy FITS image Return number of bytes in output image, 0 if failure */ int fitscimage (filename, header, filename0) char *filename; /* Name of output FITS image file */ char *header; /* FITS image header */ char *filename0; /* Name of input FITS image file */ { int fdout, fdin; int nbhead, nbimage, nblocks, bytepix; int bitpix, naxis, naxis1, naxis2, nbytes, nbw, nbpad, nbwp; char *endhead, *lasthead, *padding; char *image; /* FITS image pixels */ char *oldhead; /* Input file image header */ int nbhead0; /* Length of input file image header */ int lhead0; int nbbuff, nbuff, ibuff, nbr, nbdata; /* Compute size of image in bytes using relevant header parameters */ naxis = 1; hgeti4 (header, "NAXIS", &naxis); naxis1 = 1; hgeti4 (header, "NAXIS1", &naxis1); naxis2 = 1; hgeti4 (header, "NAXIS2", &naxis2); hgeti4 (header, "BITPIX", &bitpix); bytepix = bitpix / 8; if (bytepix < 0) bytepix = -bytepix; /* If either dimension is one and image is 3-D, read all three dimensions */ if (naxis == 3 && (naxis1 ==1 || naxis2 == 1)) { int naxis3; hgeti4 (header,"NAXIS3",&naxis3); nbimage = naxis1 * naxis2 * naxis3 * bytepix; } else nbimage = naxis1 * naxis2 * bytepix; nblocks = nbimage / FITSBLOCK; if (nblocks * FITSBLOCK < nbimage) nblocks = nblocks + 1; nbytes = nblocks * FITSBLOCK; /* Allocate image buffer */ nbbuff = FITSBLOCK * 100; if (nbytes < nbbuff) nbbuff = nbytes; image = (char *) calloc (1, nbbuff); nbuff = nbytes / nbbuff; if (nbytes > nbuff * nbbuff) nbuff = nbuff + 1; /* Read input file header */ if ((oldhead = fitsrhead (filename0, &lhead0, &nbhead0)) == NULL) { snprintf (fitserrmsg, 79,"FITSCIMAGE: header of input file %s cannot be read\n", filename0); return (0); } /* Find size of output header */ nbhead = fitsheadsize (header); /* If overwriting, be more careful if new header is longer than old */ if (!strcmp (filename, filename0) && nbhead > nbhead0) { if ((image = fitsrimage (filename0, nbhead0, oldhead)) == NULL) { snprintf (fitserrmsg,79, "FITSCIMAGE: cannot read image from file %s\n", filename0); free (oldhead); return (0); } return (fitswimage (filename, header, image)); } free (oldhead); /* Open the input file and skip over the header */ if (strcasecmp (filename0,"stdin")) { fdin = -1; fdin = fitsropen (filename0); if (fdin < 0) { snprintf (fitserrmsg, 79,"FITSCIMAGE: cannot read file %s\n", filename0); return (0); } /* Skip over FITS header */ if (lseek (fdin, nbhead0, SEEK_SET) < 0) { (void)close (fdin); snprintf (fitserrmsg,79, "FITSCIMAGE: cannot skip header of file %s\n", filename0); return (0); } } #ifndef VMS else fdin = STDIN_FILENO; #endif /* Open the output file */ if (!access (filename, 0)) { fdout = open (filename, O_WRONLY); if (fdout < 3) { snprintf (fitserrmsg,79, "FITSCIMAGE: file %s not writeable\n", filename); return (0); } } else { fdout = open (filename, O_RDWR+O_CREAT, 0666); if (fdout < 3) { snprintf (fitserrmsg,79, "FITSCHEAD: cannot create file %s\n", filename); return (0); } } /* Pad header with spaces */ endhead = ksearch (header,"END") + 80; lasthead = header + nbhead; while (endhead < lasthead) *(endhead++) = ' '; /* Write header to file */ nbw = write (fdout, header, nbhead); if (nbw < nbhead) { snprintf (fitserrmsg, 79,"FITSCIMAGE: wrote %d / %d bytes of header to file %s\n", nbw, nbytes, filename); (void)close (fdout); (void)close (fdin); return (0); } /* Return if no data */ if (bitpix == 0) { (void)close (fdout); (void)close (fdin); return (nbhead); } nbdata = 0; for (ibuff = 0; ibuff < nbuff; ibuff++) { nbr = read (fdin, image, nbbuff); if (nbr > 0) { nbw = write (fdout, image, nbr); nbdata = nbdata + nbw; } } /* Write extra to make integral number of 2880-byte blocks */ nblocks = nbdata / FITSBLOCK; if (nblocks * FITSBLOCK < nbdata) nblocks = nblocks + 1; nbytes = nblocks * FITSBLOCK; nbpad = nbytes - nbdata; padding = (char *)calloc (1,nbpad); nbwp = write (fdout, padding, nbpad); nbw = nbdata + nbwp; free (padding); (void)close (fdout); (void)close (fdin); if (nbw < nbimage) { snprintf (fitserrmsg, 79, "FITSWIMAGE: wrote %d / %d bytes of image to file %s\n", nbw, nbimage, filename); return (0); } else return (nbw); } /* FITSWHEAD -- Write FITS header and keep file open for further writing */ int fitswhead (filename, header) char *filename; /* Name of IFTS image file */ char *header; /* FITS image header */ { int fd; int nbhead, nblocks; int nbytes, nbw; char *endhead, *lasthead; /* Open the output file */ if (!access (filename, 0)) { fd = open (filename, O_WRONLY); if (fd < 3) { snprintf (fitserrmsg, 79, "FITSWHEAD: file %s not writeable\n", filename); return (0); } } else { fd = open (filename, O_RDWR+O_CREAT, 0666); if (fd < 3) { snprintf (fitserrmsg, 79, "FITSWHEAD: cannot create file %s\n", filename); return (0); } } /* Write header to file */ endhead = ksearch (header,"END") + 80; nbhead = endhead - header; nblocks = nbhead / FITSBLOCK; if (nblocks * FITSBLOCK < nbhead) nblocks = nblocks + 1; nbytes = nblocks * FITSBLOCK; /* Pad header with spaces */ lasthead = header + nbytes; while (endhead < lasthead) *(endhead++) = ' '; nbw = write (fd, header, nbytes); if (nbw < nbytes) { fprintf (stderr, "FITSWHEAD: wrote %d / %d bytes of header to file %s\n", nbw, nbytes, filename); (void)close (fd); return (0); } return (fd); } /* FITSWEXHEAD -- Write FITS header in place */ int fitswexhead (filename, header) char *filename; /* Name of FITS image file with ,extension */ char *header; /* FITS image header */ { int fd; int nbhead, lhead; int nbw, nbnew, nbold; char *endhead, *lasthead, *oldheader; char *ext, cext; /* Compare size of existing header to size of new header */ fitsinherit = 0; oldheader = fitsrhead (filename, &lhead, &nbhead); if (oldheader == NULL) { snprintf (fitserrmsg, 79, "FITSWEXHEAD: file %s cannot be read\n", filename); return (-1); } nbold = fitsheadsize (oldheader); nbnew = fitsheadsize (header); /* Return if the new header is bigger than the old header */ if (nbnew > nbold) { snprintf (fitserrmsg, 79, "FITSWEXHEAD: old header %d bytes, new header %d bytes\n", nbold,nbnew); free (oldheader); oldheader = NULL; return (-1); } /* Add blank lines if new header is smaller than the old header */ else if (nbnew < nbold) { strcpy (oldheader, header); endhead = ksearch (oldheader,"END"); lasthead = oldheader + nbold; while (endhead < lasthead) *(endhead++) = ' '; strncpy (lasthead-80, "END", 3); } /* Pad header with spaces */ else { endhead = ksearch (header,"END") + 80; lasthead = header + nbnew; while (endhead < lasthead) *(endhead++) = ' '; strncpy (oldheader, header, nbnew); } /* Check for FITS extension and ignore for file opening */ ext = strchr (filename, ','); if (ext == NULL) ext = strchr (filename, '['); if (ext != NULL) { cext = *ext; *ext = (char) 0; } /* Open the output file */ fd = open (filename, O_WRONLY); if (ext != NULL) *ext = cext; if (fd < 3) { snprintf (fitserrmsg, 79, "FITSWEXHEAD: file %s not writeable\n", filename); return (-1); } /* Skip to appropriate place in file */ (void) lseek (fd, ibhead, SEEK_SET); /* Write header to file */ nbw = write (fd, oldheader, nbold); (void)close (fd); free (oldheader); oldheader = NULL; if (nbw < nbold) { fprintf (stderr, "FITSWHEAD: wrote %d / %d bytes of header to file %s\n", nbw, nbold, filename); return (-1); } return (0); } /* ISFITS -- Return 1 if FITS file, else 0 */ int isfits (filename) char *filename; /* Name of file for which to find size */ { int diskfile; char keyword[16]; char *comma; int nbr; /* First check to see if this is an assignment */ if (strchr (filename, '=')) return (0); /* Check for stdin (input from pipe) */ else if (!strcasecmp (filename,"stdin")) return (1); /* Then check file extension else if (strsrch (filename, ".fit") || strsrch (filename, ".fits") || strsrch (filename, ".fts")) return (1); */ /* If no FITS file extension, try opening the file */ else { if ((comma = strchr (filename,','))) *comma = (char) 0; if ((diskfile = open (filename, O_RDONLY)) < 0) { if (comma) *comma = ','; return (0); } else { nbr = read (diskfile, keyword, 8); if (comma) *comma = ','; close (diskfile); if (nbr < 8) return (0); else if (!strncmp (keyword, "SIMPLE", 6)) return (1); else return (0); } } } /* FITSHEADSIZE -- Find size of FITS header */ int fitsheadsize (header) char *header; /* FITS header */ { char *endhead; int nbhead, nblocks; endhead = ksearch (header,"END") + 80; nbhead = endhead - header; nblocks = nbhead / FITSBLOCK; if (nblocks * FITSBLOCK < nbhead) nblocks = nblocks + 1; return (nblocks * FITSBLOCK); } /* Print error message */ void fitserr () { fprintf (stderr, "%s\n",fitserrmsg); return; } /* MOVEB -- Copy nbytes bytes from source+offs to dest+offd (any data type) */ void moveb (source, dest, nbytes, offs, offd) char *source; /* Pointer to source */ char *dest; /* Pointer to destination */ int nbytes; /* Number of bytes to move */ int offs; /* Offset in bytes in source from which to start copying */ int offd; /* Offset in bytes in destination to which to start copying */ { char *from, *last, *to; from = source + offs; to = dest + offd; last = from + nbytes; while (from < last) *(to++) = *(from++); return; } /* * Feb 8 1996 New subroutines * Apr 10 1996 Add subroutine list at start of file * Apr 17 1996 Print error message to stderr * May 2 1996 Write using stream IO * May 14 1996 If FITSRTOPEN NK is zero, return all keywords in header * May 17 1996 Make header internal to FITSRTOPEN * Jun 3 1996 Use stream I/O for input as well as output * Jun 10 1996 Remove unused variables after running lint * Jun 12 1996 Deal with byte-swapped images * Jul 11 1996 Rewrite code to separate header and data reading * Aug 6 1996 Fixed small defects after lint * Aug 6 1996 Drop unused NBHEAD argument from FITSRTHEAD * Aug 13 1996 If filename is stdin, read from standard input instead of file * Aug 30 1996 Use write for output, not fwrite * Sep 4 1996 Fix mode when file is created * Oct 15 1996 Drop column argument from FGET* subroutines * Oct 15 1996 Drop unused variable * Dec 17 1996 Add option to skip bytes in file before reading the header * Dec 27 1996 Turn nonprinting header characters into spaces * * Oct 9 1997 Add FITS extension support as filename,extension * Dec 15 1997 Fix minor bugs after lint * * Feb 23 1998 Do not append primary header if getting header for ext. 0 * Feb 23 1998 Accept either bracketed or comma extension * Feb 24 1998 Add SIMPLE keyword to start of extracted extension * Apr 30 1998 Fix error return if not table file after Allan Brighton * May 4 1998 Fix error in argument sequence in HGETS call * May 27 1998 Include fitsio.h and imio.h * Jun 1 1998 Add VMS fixes from Harry Payne at STScI * Jun 3 1998 Fix bug reading EXTNAME * Jun 11 1998 Initialize all header parameters before reading them * Jul 13 1998 Clarify argument definitions * Aug 6 1998 Rename fitsio.c to fitsfile.c to avoid conflict with CFITSIO * Aug 13 1998 Add FITSWHEAD to write only header * Sep 25 1998 Allow STDIN or stdin for standard input reading * Oct 5 1998 Add isfits() to decide whether a file is FITS * Oct 9 1998 Assume stdin and STDIN to be FITS files in isfits() * Nov 30 1998 Fix bug found by Andreas Wicenec when reading large headers * Dec 8 1998 Fix bug introduced by previous bug fix * * Jan 4 1999 Do not print error message if BITPIX is 0 * Jan 27 1999 Read and write all of 3D images if one dimension is 1 * Jan 27 1999 Pad out data to integral number of 2880-byte blocks * Apr 29 1999 Write BITPIX=-16 files as BITPIX=16 with BSCALE and BZERO * Apr 30 1999 Add % as alternative to , to denote sub-images * May 25 1999 Set buffer offsets to 0 when FITS table file is opened * Jul 14 1999 Do not try to write image data if BITPIX is 0 * Sep 27 1999 Add STDOUT as output filename option in fitswimage() * Oct 6 1999 Set header length global variable hget.lhead0 in fitsrhead() * Oct 14 1999 Update header length as it is changed in fitsrhead() * Oct 20 1999 Change | in if statements to || * Oct 25 1999 Change most malloc() calls to calloc() * Nov 24 1999 Add fitscimage() * * Feb 23 2000 Fix problem with some error returns in fitscimage() * Mar 17 2000 Drop unused variables after lint * Jul 20 2000 Drop BITPIX and NAXIS from primary header if extension printerd * Jul 20 2000 Start primary part of header with ROOTHEAD keyword * Jul 28 2000 Add loop to deal with buffered stdin * * Jan 11 2001 Print all messages to stderr * Jan 12 2001 Add extension back onto filename after fitsropen() (Guy Rixon) * Jan 18 2001 Drop EXTEND keyword when extracting an extension * Jan 18 2001 Add fitswext() to append HDU and fitswhdu() to do actual writing * Jan 22 2001 Ignore WCS name or letter following a : in file name in fitsrhead() * Jan 30 2001 Fix FITSCIMAGE so it doesn't overwrite data when overwriting a file * Feb 20 2001 Ignore WCS name or letter following a : in file name in fitsropen() * Feb 23 2001 Initialize rbrac in fitsropen() * Mar 8 2001 Use % instead of : for WCS specification in file name * Mar 9 2001 Fix bug so primary header is always appended to secondary header * Mar 9 2001 Change NEXTEND to NUMEXT in appended primary header * Mar 20 2001 Declare fitsheadsize() in fitschead() * Apr 24 2001 When matching column names, use longest length * Jun 27 2001 In fitsrthead(), allocate pw and lpnam only if more space needed * Aug 24 2001 In isfits(), return 0 if argument contains an equal sign * * Jan 28 2002 In fitsrhead(), allow stdin to include extension and/or WCS selection * Jun 18 2002 Save error messages as fitserrmsg and use fitserr() to print them * Oct 21 2002 Add fitsrsect() to read a section of an image * * Feb 4 2003 Open catalog file rb instead of r (Martin Ploner, Bern) * Apr 2 2003 Drop unused variable in fitsrsect() * Jul 11 2003 Use strcasecmp() to check for stdout and stdin * Aug 1 2003 If no other header, return root header from fitsrhead() * Aug 20 2003 Add fitsrfull() to read n-dimensional FITS images * Aug 21 2003 Modify fitswimage() to always write n-dimensional FITS images * Nov 18 2003 Fix minor bug in fitswhdu() * Dec 3 2003 Remove unused variable lasthead in fitswhdu() * * May 3 2004 Do not always append primary header to extension header * May 3 2004 Add ibhead as position of header read in file * May 19 2004 Do not reset ext if NULL in fitswexhead() * Jul 1 2004 Initialize INHERIT to 1 * Aug 30 2004 Move fitsheadsize() declaration to fitsfile.h * Aug 31 2004 If SIMPLE=F, put whatever is in file after header in image * * Mar 17 2005 Use unbuffered I/O in isfits() for robustness * Jun 27 2005 Drop unused variable nblocks in fitswexhead() * Aug 8 2005 Fix space-padding bug in fitswexhead() found by Armin Rest * Sep 30 2005 Fix fitsrsect() to position relatively, not absolutely * Oct 28 2005 Add error message if desired FITS extension is not found * Oct 28 2005 Fix initialization problem found by Sergey Koposov * * Feb 23 2006 Add fitsrtail() to read appended FITS headers * Feb 27 2006 Add file name to header-reading error messages * May 3 2006 Remove declarations of unused variables * Jun 20 2006 Initialize uninitialized variables * Nov 2 2006 Change all realloc() calls to calloc() * * Jan 5 2007 In fitsrtail(), change control characters in header to spaces * Apr 30 2007 Improve error reporting in FITSRFULL * Nov 28 2007 Add support to BINTABLE in ftget*() and fitsrthead() * Dec 20 2007 Add data heap numerated by PCOUNT when skipping HDU in fitsrhead() * Dec 20 2007 Return NULL pointer if fitsrhead() cannot find requested HDU * * Apr 7 2008 Drop comma from name when reading file in isfits() * Jun 27 2008 Do not append primary data header if it is the only header * Nov 21 2008 In fitswhead(), print message if too few bytes written * * Sep 18 2009 In fitswexhead() write to error string instead of stderr * Sep 22 2009 In fitsrthead(), fix lengths for ASCII numeric table entries * Sep 25 2009 Add subroutine moveb() and fix calls to it * Sep 25 2009 Fix several small errors found by Jessicalas Burke * * Mar 29 2010 In fitswhead(), always pad blocks to 2880 bytes with spaces * Mar 31 2010 In fitsrhead(), fix bug reading long primary headers * * Sep 15 2011 In fitsrsect() declare impos and nblin off_t * Sep 15 2011 In fitsrtail() declare offset off_t * Sep 15 2011 Declare global variable ibhead off_t * * Jul 25 2014 Fix bug when reallocating buffer for long headers * * Jun 9 2016 Fix isnum() tests for added coloned times and dashed dates * Jun 24 2016 Add 1 to allocation of pheader for trailing null, fix by Ole Streicher */ wcstools-3.9.5/libwcs/hget.c0000664000016200001660000014301012726336102015032 0ustar minkoirsys/*** File libwcs/hget.c *** November 6, 2015 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1994-2015 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: hget.c (Get FITS Header parameter values) * Purpose: Extract values for variables from FITS header string * Subroutine: hgeti2 (hstring,keyword,ival) returns short integer * Subroutine: hgeti4c (hstring,keyword,wchar,ival) returns long integer * Subroutine: hgeti4 (hstring,keyword,ival) returns long integer * Subroutine: hgetr4 (hstring,keyword,rval) returns real * Subroutine: hgetra (hstring,keyword,ra) returns double RA in degrees * Subroutine: hgetdec (hstring,keyword,dec) returns double Dec in degrees * Subroutine: hgetr8c (hstring,keyword,wchar,dval) returns double * Subroutine: hgetr8 (hstring,keyword,dval) returns double * Subroutine: hgetl (hstring,keyword,lval) returns logical int (0=F, 1=T) * Subroutine: hgetsc (hstring,keyword,wchar,lstr,str) returns character string * Subroutine: hgets (hstring,keyword, lstr, str) returns character string * Subroutine: hgetm (hstring,keyword, lstr, str) returns multi-keyword string * Subroutine: hgetdate (hstring,keyword,date) returns date as fractional year * Subroutine: hgetndec (hstring, keyword, ndec) returns number of dec. places * Subroutine: hgetc (hstring,keyword) returns character string * Subroutine: blsearch (hstring,keyword) returns pointer to blank lines before keyword * Subroutine: ksearch (hstring,keyword) returns pointer to header string entry * Subroutine: str2ra (in) converts string to right ascension in degrees * Subroutine: str2dec (in) converts string to declination in degrees * Subroutine: strsrch (s1, s2) finds string s2 in null-terminated string s1 * Subroutine: strnsrch (s1, s2, ls1) finds string s2 in ls1-byte string s1 * Subroutine: hlength (header,lhead) sets length of FITS header for searching * Subroutine: isnum (string) returns 1 if integer, 2 if fp number, * 3 if hh:mm:dd.ss time, 4 if yyyy-mm-dd date, else 0 * Subroutine: notnum (string) returns 0 if number, else 1 * Subroutine: numdec (string) returns number of decimal places in numeric string * Subroutine: strfix (string,blankfill,zerodrop) removes extraneous characters */ #include /* NULL, strlen, strstr, strcpy */ #include #include "fitshead.h" /* FITS header extraction subroutines */ #include #ifndef VMS #include #else #define INT_MAX 2147483647 /* Biggest number that can fit in long */ #define SHRT_MAX 32767 #endif #define VLENGTH 81 #ifdef USE_SAOLIB static int use_saolib=0; #endif char *hgetc (); static char val[VLENGTH+1]; static int multiline = 0; static int lhead0 = 0; /* Length of header string */ /* Set the length of the header string, if not terminated by NULL */ int hlength (header, lhead) const char *header; /* FITS header */ int lhead; /* Maximum length of FITS header */ { char *hend; if (lhead > 0) lhead0 = lhead; else { lhead0 = 0; hend = ksearch (header,"END"); lhead0 = hend + 80 - header; } return (lhead0); } /* Return the length of the header string, computing it if lhead0 not set */ int gethlength (header) char *header; /* FITS header */ { if (lhead0 > 0) return (lhead0); else return (hlength (header, 0)); } /* Extract Integer*4 value for variable from FITS header string */ int hgeti4c (hstring,keyword,wchar,ival) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ const char *wchar; /* Character of multiple WCS header; =0 if unused */ int *ival; /* Keyword value returned */ { char keyword1[16]; int lkey; if (wchar[0] < (char) 64) return (hgeti4 (hstring, keyword, ival)); else { strcpy (keyword1, keyword); lkey = strlen (keyword); keyword1[lkey] = wchar[0]; keyword1[lkey+1] = (char) 0; return (hgeti4 (hstring, keyword1, ival)); } } /* Extract long value for variable from FITS header string */ int hgeti4 (hstring,keyword,ival) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ int *ival; { char *value; double dval; int minint; int lval; char *dchar; /* Get value and comment from header string */ value = hgetc (hstring,keyword); /* Translate value from ASCII to binary */ if (value != NULL) { if (value[0] == '#') value++; minint = -INT_MAX - 1; lval = strlen (value); if (lval > VLENGTH) { strncpy (val, value, VLENGTH); val[VLENGTH] = (char) 0; } else strcpy (val, value); if (isnum (val) == 2) { if ((dchar = strchr (val, 'D'))) *dchar = 'e'; if ((dchar = strchr (val, 'd'))) *dchar = 'e'; if ((dchar = strchr (val, 'E'))) *dchar = 'e'; } dval = atof (val); if (dval+0.001 > INT_MAX) *ival = INT_MAX; else if (dval >= 0) *ival = (int) (dval + 0.001); else if (dval-0.001 < minint) *ival = minint; else *ival = (int) (dval - 0.001); return (1); } else { return (0); } } /* Extract integer*2 value for variable from fits header string */ int hgeti2 (hstring,keyword,ival) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ short *ival; { char *value; double dval; int minshort; int lval; char *dchar; /* Get value and comment from header string */ value = hgetc (hstring,keyword); /* Translate value from ASCII to binary */ if (value != NULL) { if (value[0] == '#') value++; lval = strlen (value); if (lval > VLENGTH) { strncpy (val, value, VLENGTH); val[VLENGTH] = (char) 0; } else strcpy (val, value); if (isnum (val) == 2) { if ((dchar = strchr (val, 'D'))) *dchar = 'e'; if ((dchar = strchr (val, 'd'))) *dchar = 'e'; if ((dchar = strchr (val, 'E'))) *dchar = 'e'; } dval = atof (val); minshort = -SHRT_MAX - 1; if (dval+0.001 > SHRT_MAX) *ival = SHRT_MAX; else if (dval >= 0) *ival = (short) (dval + 0.001); else if (dval-0.001 < minshort) *ival = minshort; else *ival = (short) (dval - 0.001); return (1); } else { return (0); } } /* Extract real value for variable from FITS header string */ int hgetr4 (hstring,keyword,rval) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ float *rval; { char *value; int lval; char *dchar; /* Get value and comment from header string */ value = hgetc (hstring,keyword); /* translate value from ASCII to binary */ if (value != NULL) { if (value[0] == '#') value++; lval = strlen (value); if (lval > VLENGTH) { strncpy (val, value, VLENGTH); val[VLENGTH] = (char) 0; } else strcpy (val, value); if (isnum (val) == 2) { if ((dchar = strchr (val, 'D'))) *dchar = 'e'; if ((dchar = strchr (val, 'd'))) *dchar = 'e'; if ((dchar = strchr (val, 'E'))) *dchar = 'e'; } *rval = (float) atof (val); return (1); } else { return (0); } } /* Extract real*8 right ascension in degrees from FITS header string */ int hgetra (hstring,keyword,dval) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ double *dval; /* Right ascension in degrees (returned) */ { char *value; /* Get value from header string */ value = hgetc (hstring,keyword); /* Translate value from ASCII colon-delimited string to binary */ if (value != NULL) { *dval = str2ra (value); return (1); } else return (0); } /* Extract real*8 declination in degrees from FITS header string */ int hgetdec (hstring,keyword,dval) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ double *dval; /* Right ascension in degrees (returned) */ { char *value; /* Get value from header string */ value = hgetc (hstring,keyword); /* Translate value from ASCII colon-delimited string to binary */ if (value != NULL) { *dval = str2dec (value); return (1); } else return (0); } /* Extract real*8 value for variable from FITS header string */ int hgetr8c (hstring,keyword,wchar,dval) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ const char *wchar; /* Character of multiple WCS header; =0 if unused */ double *dval; /* Keyword value returned */ { char keyword1[16]; int lkey; if (wchar[0] < (char) 64) return (hgetr8 (hstring, keyword, dval)); else { strcpy (keyword1, keyword); lkey = strlen (keyword); keyword1[lkey] = wchar[0]; keyword1[lkey+1] = (char) 0; return (hgetr8 (hstring, keyword1, dval)); } } /* Extract real*8 value for variable from FITS header string */ int hgetr8 (hstring,keyword,dval) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ double *dval; { char *value; int lval; char *dchar; /* Get value and comment from header string */ value = hgetc (hstring,keyword); /* Translate value from ASCII to binary */ if (value != NULL) { if (value[0] == '#') value++; lval = strlen (value); if (lval > VLENGTH) { strncpy (val, value, VLENGTH); val[VLENGTH] = (char) 0; } else strcpy (val, value); if (isnum (val) == 2) { if ((dchar = strchr (val, 'D'))) *dchar = 'e'; if ((dchar = strchr (val, 'd'))) *dchar = 'e'; if ((dchar = strchr (val, 'E'))) *dchar = 'e'; } *dval = atof (val); return (1); } else { return (0); } } /* Extract logical value for variable from FITS header string */ int hgetl (hstring,keyword,ival) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ int *ival; { char *value; char newval; int lval; /* Get value and comment from header string */ value = hgetc (hstring,keyword); /* Translate value from ASCII to binary */ if (value != NULL) { lval = strlen (value); if (lval > VLENGTH) { strncpy (val, value, VLENGTH); val[VLENGTH] = (char) 0; } else strcpy (val, value); newval = val[0]; if (newval == 't' || newval == 'T') *ival = 1; else *ival = 0; return (1); } else { return (0); } } /* Extract real*8 date from FITS header string (dd/mm/yy or dd-mm-yy) */ int hgetdate (hstring,keyword,dval) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ double *dval; { double yeardays, seconds, fday; char *value,*sstr, *dstr, *tstr, *cstr, *nval; int year, month, day, yday, i, hours, minutes; static int mday[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; /* Get value and comment from header string */ value = hgetc (hstring,keyword); /* Translate value from ASCII to binary */ if (value != NULL) { sstr = strchr (value,'/'); dstr = strchr (value,'-'); /* Original FITS date format: dd/mm/yy */ if (sstr > value) { *sstr = '\0'; day = (int) atof (value); *sstr = '/'; nval = sstr + 1; sstr = strchr (nval,'/'); if (sstr == NULL) sstr = strchr (nval,'-'); if (sstr > value) { *sstr = '\0'; month = (int) atof (nval); *sstr = '/'; nval = sstr + 1; year = (int) atof (nval); if (day > 31) { yday = year; year = day; day = yday; } if (year >= 0 && year <= 49) year = year + 2000; else if (year < 100) year = year + 1900; if ((year % 4) == 0) mday[1] = 29; else mday[1] = 28; if ((year % 100) == 0 && (year % 400) != 0) mday[1] = 28; if (day > mday[month-1]) day = mday[month-1]; else if (day < 1) day = 1; if (mday[1] == 28) yeardays = 365.0; else yeardays = 366.0; yday = day - 1; for (i = 0; i < month-1; i++) yday = yday + mday[i]; *dval = (double) year + ((double)yday / yeardays); return (1); } else return (0); } /* New FITS date format: yyyy-mm-ddThh:mm:ss[.sss] */ else if (dstr > value) { *dstr = '\0'; year = (int) atof (value); *dstr = '-'; nval = dstr + 1; dstr = strchr (nval,'-'); month = 1; day = 1; tstr = NULL; if (dstr > value) { *dstr = '\0'; month = (int) atof (nval); *dstr = '-'; nval = dstr + 1; tstr = strchr (nval,'T'); if (tstr > value) *tstr = '\0'; day = (int) atof (nval); if (tstr > value) *tstr = 'T'; } /* If year is < 32, it is really day of month in old format */ if (year < 32) { i = year; year = day + 1900; day = i; } if ((year % 4) == 0) mday[1] = 29; else mday[1] = 28; if ((year % 100) == 0 && (year % 400) != 0) mday[1] = 28; if (day > mday[month-1]) day = mday[month-1]; else if (day < 1) day = 1; if (mday[1] == 28) yeardays = 365.0; else yeardays = 366.0; yday = day - 1; for (i = 0; i < month-1; i++) yday = yday + mday[i]; *dval = (double) year + ((double)yday / yeardays); /* Extract time, if it is present */ if (tstr > value) { nval = tstr + 1; hours = 0.0; minutes = 0.0; seconds = 0.0; cstr = strchr (nval,':'); if (cstr > value) { *cstr = '\0'; hours = (int) atof (nval); *cstr = ':'; nval = cstr + 1; cstr = strchr (nval,':'); if (cstr > value) { *cstr = '\0'; minutes = (int) atof (nval); *cstr = ':'; nval = cstr + 1; seconds = atof (nval); } else { minutes = (int) atof (nval); seconds = 0.0; } } fday = ((3.6e3 * (double)hours) + (6.e1 * (double)minutes) + seconds) / 8.64e4; *dval = *dval + (fday / yeardays); } return (1); } else return (0); } else return (0); } /* Extract IRAF multiple-keyword string value from FITS header string */ int hgetm (hstring, keyword, lstr, str) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the root name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ const int lstr; /* Size of str in characters */ char *str; /* String (returned) */ { char *value; char *stri; char keywordi[16]; int lval, lstri, ikey; char keyform[8]; stri = str; lstri = lstr; sprintf (keywordi, "%s_1", keyword); if (ksearch (hstring, keywordi)) strcpy (keyform, "%s_%d"); else { sprintf (keywordi, "%s_01", keyword); if (ksearch (hstring, keywordi)) strcpy (keyform, "%s_%02d"); else { sprintf (keywordi, "%s_001", keyword); if (ksearch (hstring, keywordi)) strcpy (keyform, "%s_%03d"); else if (ksearch (hstring, keywordi)) strcpy (keyform, "%s_%03d"); else return (0); } } /* Loop through sequentially-named keywords */ multiline = 1; for (ikey = 1; ikey < 500; ikey++) { sprintf (keywordi, keyform, keyword, ikey); /* Get value for this keyword */ value = hgetc (hstring, keywordi); if (value != NULL) { lval = strlen (value); if (lval < lstri) strcpy (stri, value); else if (lstri > 1) { strncpy (stri, value, lstri-1); stri[lstri] = (char) 0; break; } else { str[0] = value[0]; break; } } else break; stri = stri + lval; lstri = lstri - lval; } multiline = 0; /* Return 1 if any keyword found, else 0 */ if (ikey > 1) return (1); else return (0); } /* Extract string value for variable from FITS header string */ int hgetsc (hstring,keyword,wchar,lstr,str) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ const char *wchar; /* Character of multiple WCS header; =0 if unused */ const int lstr; /* Size of str in characters */ char *str; /* String (returned) */ { char keyword1[16]; int lkey; if (wchar[0] < (char) 64) return (hgets (hstring, keyword, lstr, str)); else { strcpy (keyword1, keyword); lkey = strlen (keyword); keyword1[lkey] = wchar[0]; keyword1[lkey+1] = (char) 0; return (hgets (hstring, keyword1, lstr, str)); } } /* Extract string value for variable from FITS header string */ int hgets (hstring, keyword, lstr, str) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ const int lstr; /* Size of str in characters */ char *str; /* String (returned) */ { char *value; int lval; /* Get value and comment from header string */ value = hgetc (hstring,keyword); if (value != NULL) { lval = strlen (value); if (lval < lstr) strcpy (str, value); else if (lstr > 1) strncpy (str, value, lstr-1); else str[0] = value[0]; return (1); } else return (0); } /* Extract number of decimal places for value in FITS header string */ int hgetndec (hstring, keyword, ndec) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ int *ndec; /* Number of decimal places in keyword value */ { char *value; int i, nchar; /* Get value and comment from header string */ value = hgetc (hstring,keyword); /* Find end of string and count backward to decimal point */ *ndec = 0; if (value != NULL) { nchar = strlen (value); for (i = nchar-1; i >= 0; i--) { if (value[i] == '.') return (1); *ndec = *ndec + 1; } return (1); } else return (0); } /* Extract character value for variable from FITS header string */ char * hgetc (hstring,keyword0) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword0; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ { static char cval[80]; char *value; char cwhite[2]; char squot[2], dquot[2], lbracket[2], rbracket[2], slash[2], comma[2]; char space; char keyword[81]; /* large for ESO hierarchical keywords */ char line[100]; char *vpos, *cpar; char *q1, *q2, *v1, *v2, *c1, *brack1, *brack2; int ipar, i, lkey; #ifdef USE_SAOLIB int iel=1, ip=1, nel, np, ier; char *get_fits_head_str(); if( !use_saolib ){ #endif squot[0] = (char) 39; squot[1] = (char) 0; dquot[0] = (char) 34; dquot[1] = (char) 0; lbracket[0] = (char) 91; lbracket[1] = (char) 0; comma[0] = (char) 44; comma[1] = (char) 0; rbracket[0] = (char) 93; rbracket[1] = (char) 0; slash[0] = (char) 47; slash[1] = (char) 0; space = (char) 32; /* Find length of variable name */ strncpy (keyword,keyword0, sizeof(keyword)-1); brack1 = strsrch (keyword,lbracket); if (brack1 == NULL) brack1 = strsrch (keyword,comma); if (brack1 != NULL) { *brack1 = '\0'; brack1++; } /* Search header string for variable name */ vpos = ksearch (hstring,keyword); /* Exit if not found */ if (vpos == NULL) return (NULL); /* Initialize line to nulls */ for (i = 0; i < 100; i++) line[i] = 0; /* In standard FITS, data lasts until 80th character */ /* Extract entry for this variable from the header */ strncpy (line,vpos,80); /* Check for quoted value */ q1 = strsrch (line,squot); c1 = strsrch (line,slash); if (q1 != NULL) { if (c1 != NULL && q1 < c1) { q2 = strsrch (q1+1,squot); if (q2 == NULL) { q2 = c1 - 1; while (*q2 == space) q2--; q2++; } else if (c1 < q2) c1 = strsrch (q2,slash); } else if (c1 == NULL) { q2 = strsrch (q1+1,squot); if (q2 == NULL) { q2 = line + 79; while (*q2 == space) q2--; q2++; } } else q1 = NULL; } else { q1 = strsrch (line,dquot); if (q1 != NULL) { if (c1 != NULL && q1 < c1) { q2 = strsrch (q1+1,dquot); if (q2 == NULL) { q2 = c1 - 1; while (*q2 == space) q2--; q2++; } else if (c1 < q2) c1 = strsrch (q2,slash); } else if (c1 == NULL) { q2 = strsrch (q1+1,dquot); if (q2 == NULL) { q2 = line + 79; while (*q2 == space) q2--; q2++; } } else q1 = NULL; } else { q1 = NULL; q2 = line + 10; } } /* Extract value and remove excess spaces */ if (q1 != NULL) { v1 = q1 + 1; v2 = q2; } else { v1 = strsrch (line,"="); if (v1 == NULL) v1 = line + 9; else v1 = v1 + 1; c1 = strsrch (line,"/"); if (c1 != NULL) v2 = c1; else v2 = line + 79; } /* Ignore leading spaces if not multiline */ if (!multiline) { while (*v1 == ' ' && v1 < v2) { v1++; } } /* Drop trailing spaces */ *v2 = '\0'; if (!multiline) { v2--; while ((*v2 == ' ' || *v2 == (char) 13) && v2 > v1) { *v2 = '\0'; v2--; } } /* Convert -zero to just plain 0 */ if (!strcmp (v1, "-0")) v1++; strcpy (cval,v1); value = cval; /* If keyword has brackets, extract appropriate token from value */ if (brack1 != NULL) { brack2 = strsrch (brack1,rbracket); if (brack2 != NULL) *brack2 = '\0'; if (isnum (brack1) == 1) { ipar = atoi (brack1); cwhite[0] = ' '; cwhite[1] = '\0'; if (ipar > 0) { for (i = 1; i <= ipar; i++) { cpar = strtok (v1,cwhite); v1 = NULL; } if (cpar != NULL) { strcpy (cval,cpar); value = cval; } else value = NULL; } /* If token counter is negative, include rest of value */ else if (ipar < 0) { for (i = 1; i < -ipar; i++) { v1 = strchr (v1, ' '); if (v1 == NULL) break; else v1 = v1 + 1; } if (v1 != NULL) { strcpy (cval, v1); value = cval; } else value = NULL; } } else { lkey = strlen (brack1); for (i = 0; i < lkey; i++) { if (brack1[i] > 64 && brack1[i] < 91) brack1[i] = brack1[i] + 32; } v1 = igetc (cval, brack1); if (v1) { strcpy (cval,v1); value = cval; } else value = NULL; } } return (value); #ifdef USE_SAOLIB } else { return(get_fits_head_str(keyword0, iel, ip, &nel, &np, &ier, hstring)); } #endif } /* Find beginning of fillable blank line before FITS header keyword line */ char * blsearch (hstring,keyword) /* Find entry for keyword keyword in FITS header string hstring. (the keyword may have a maximum of eight letters) NULL is returned if the keyword is not found */ const char *hstring; /* character string containing fits-style header information in the format = {/ } the default is that each entry is 80 characters long; however, lines may be of arbitrary length terminated by nulls, carriage returns or linefeeds, if packed is true. */ const char *keyword; /* character string containing the name of the variable to be returned. ksearch searches for a line beginning with this string. The string may be a character literal or a character variable terminated by a null or '$'. it is truncated to 8 characters. */ { const char *headlast; char *loc, *headnext, *pval, *lc, *line; char *bval; int icol, nextchar, lkey, nleft, lhstr; pval = 0; /* Search header string for variable name */ if (lhead0) lhstr = lhead0; else { lhstr = 0; while (lhstr < 256000 && hstring[lhstr] != 0) lhstr++; } headlast = hstring + lhstr; headnext = (char *) hstring; pval = NULL; while (headnext < headlast) { nleft = headlast - headnext; loc = strncsrch (headnext, keyword, nleft); /* Exit if keyword is not found */ if (loc == NULL) { break; } icol = (loc - hstring) % 80; lkey = strlen (keyword); nextchar = (int) *(loc + lkey); /* If this is not in the first 8 characters of a line, keep searching */ if (icol > 7) headnext = loc + 1; /* If parameter name in header is longer, keep searching */ else if (nextchar != 61 && nextchar > 32 && nextchar < 127) headnext = loc + 1; /* If preceeding characters in line are not blanks, keep searching */ else { line = loc - icol; for (lc = line; lc < loc; lc++) { if (*lc != ' ') headnext = loc + 1; } /* Return pointer to start of line if match */ if (loc >= headnext) { pval = line; break; } } } /* Return NULL to calling program if keyword is not found */ if (pval == NULL) return (pval); /* Return NULL if keyword is found at start of FITS header string */ if (pval == hstring) return (NULL); /* Find last nonblank in FITS header string line before requested keyword */ bval = pval - 80; while (!strncmp (bval," ",8) && bval >= hstring) bval = bval - 80; bval = bval + 80; /* Return pointer to calling program if blank lines found */ if (bval < pval && bval >= hstring) return (bval); else return (NULL); } /* Find FITS header line containing specified keyword */ char * ksearch (hstring,keyword) /* Find entry for keyword keyword in FITS header string hstring. (the keyword may have a maximum of eight letters) NULL is returned if the keyword is not found */ const char *hstring; /* character string containing fits-style header information in the format = {/ } the default is that each entry is 80 characters long; however, lines may be of arbitrary length terminated by nulls, carriage returns or linefeeds, if packed is true. */ const char *keyword; /* character string containing the name of the variable to be returned. ksearch searches for a line beginning with this string. The string may be a character literal or a character variable terminated by a null or '$'. it is truncated to 8 characters. */ { const char *headlast; char *loc, *headnext, *pval, *lc, *line; int icol, nextchar, lkey, nleft, lhead, lmax; #ifdef USE_SAOLIB int iel=1, ip=1, nel, np, ier; char *get_fits_head_str(); if( !use_saolib ){ #endif pval = 0; /* Find current length of header string */ if (lhead0) lmax = lhead0; else lmax = 256000; for (lhead = 0; lhead < lmax; lhead++) { if (hstring[lhead] <= (char) 0) break; } /* Search header string for variable name */ headlast = hstring + lhead; headnext = (char *) hstring; pval = NULL; while (headnext < headlast) { nleft = headlast - headnext; loc = strncsrch (headnext, keyword, nleft); /* Exit if keyword is not found */ if (loc == NULL) { break; } icol = (loc - hstring) % 80; lkey = strlen (keyword); nextchar = (int) *(loc + lkey); /* If this is not in the first 8 characters of a line, keep searching */ if (icol > 7) headnext = loc + 1; /* If parameter name in header is longer, keep searching */ else if (nextchar != 61 && nextchar > 32 && nextchar < 127) headnext = loc + 1; /* If preceeding characters in line are not blanks, keep searching */ else { line = loc - icol; for (lc = line; lc < loc; lc++) { if (*lc != ' ') headnext = loc + 1; } /* Return pointer to start of line if match */ if (loc >= headnext) { pval = line; break; } } } /* Return pointer to calling program */ return (pval); #ifdef USE_SAOLIB } else { if (get_fits_head_str(keyword,iel,ip,&nel,&np,&ier,hstring) != NULL) return(hstring); else return(NULL); } #endif } /* Return the right ascension in degrees from sexagesimal hours or decimal degrees */ double str2ra (in) const char *in; /* Character string of sexigesimal hours or decimal degrees */ { double ra; /* Right ascension in degrees (returned) */ ra = str2dec (in); if (strsrch (in,":")) ra = ra * 15.0; return (ra); } /* Return the declination in degrees from sexagesimal or decimal degrees */ double str2dec (in) const char *in; /* Character string of sexigesimal or decimal degrees */ { double dec; /* Declination in degrees (returned) */ double deg, min, sec, sign; char *value, *c1, *c2; int lval; char *dchar; dec = 0.0; /* Return 0.0 if string is null */ if (in == NULL) return (dec); /* Translate value from ASCII colon-delimited string to binary */ if (in[0]) { value = (char *) in; /* Remove leading spaces */ while (*value == ' ') value++; /* Save sign */ if (*value == '-') { sign = -1.0; value++; } else if (*value == '+') { sign = 1.0; value++; } else sign = 1.0; /* Turn comma into space */ if ((c1 = strsrch (value,",")) != NULL) *c1 = ' '; /* Remove trailing spaces */ lval = strlen (value); while (value[lval-1] == ' ') lval--; if ((c1 = strsrch (value,":")) == NULL) c1 = strnsrch (value," ",lval); if (c1 != NULL) { *c1 = 0; deg = (double) atoi (value); *c1 = ':'; value = c1 + 1; if ((c2 = strsrch (value,":")) == NULL) c2 = strsrch (value," "); if (c2 != NULL) { *c2 = 0; min = (double) atoi (value); *c2 = ':'; value = c2 + 1; sec = atof (value); } else { sec = 0.0; if ((c1 = strsrch (value,".")) != NULL) min = atof (value); if (strlen (value) > 0) min = (double) atoi (value); } dec = sign * (deg + (min / 60.0) + (sec / 3600.0)); } else if (isnum (value) == 2) { if ((dchar = strchr (value, 'D'))) *dchar = 'e'; if ((dchar = strchr (value, 'd'))) *dchar = 'e'; if ((dchar = strchr (value, 'E'))) *dchar = 'e'; dec = sign * atof (value); } else dec = sign * (double) atoi (value); } return (dec); } /* Find string s2 within null-terminated string s1 */ char * strsrch (s1, s2) const char *s1; /* String to search */ const char *s2; /* String to look for */ { int ls1; ls1 = strlen (s1); return (strnsrch (s1, s2, ls1)); } /* Find string s2 within string s1 */ char * strnsrch (s1, s2, ls1) const char *s1; /* String to search */ const char *s2; /* String to look for */ const int ls1; /* Length of string being searched */ { char *s,*s1e; char cfirst,clast; int i,ls2; /* Return null string if either pointer is NULL */ if (s1 == NULL || s2 == NULL) return (NULL); /* A zero-length pattern is found in any string */ ls2 = strlen (s2); if (ls2 ==0) return ((char *) s1); /* Only a zero-length string can be found in a zero-length string */ if (ls1 ==0) return (NULL); cfirst = (char) s2[0]; clast = (char) s2[ls2-1]; s1e = (char *) s1 + (int) ls1 - ls2 + 1; s = (char *) s1; while (s < s1e) { /* Search for first character in pattern string */ if (*s == cfirst) { /* If single character search, return */ if (ls2 == 1) return (s); /* Search for last character in pattern string if first found */ if (s[ls2-1] == clast) { /* If two-character search, return */ if (ls2 == 2) return (s); /* If 3 or more characters, check for rest of search string */ i = 1; while (i < ls2 && s[i] == s2[i]) i++; /* If entire string matches, return */ if (i >= ls2) return (s); } } s++; } return (NULL); } /* Find string s2 within null-terminated string s1 (case-free search) */ char * strcsrch (s1, s2) const char *s1; /* String to search */ const char *s2; /* String to look for */ { int ls1; ls1 = strlen ((char *) s1); return (strncsrch (s1, s2, ls1)); } /* Find string s2 within string s1 (case-free search) */ char * strncsrch (s1, s2, ls1) const char *s1; /* String to search */ const char *s2; /* String to look for */ const int ls1; /* Length of string being searched */ { char *s,*s1e, sl, *os2; char cfirst,ocfirst; char clast = ' '; char oclast = ' '; int i,ls2; /* Return null string if either pointer is NULL */ if (s1 == NULL || s2 == NULL) return (NULL); /* A zero-length pattern is found in any string */ ls2 = strlen (s2); if (ls2 ==0) return ((char *) s1); /* Only a zero-length string can be found in a zero-length string */ os2 = NULL; if (ls1 ==0) return (NULL); /* For one or two characters, set opposite case first and last letters */ if (ls2 < 3) { cfirst = (char) s2[0]; if (cfirst > 96 && cfirst < 123) ocfirst = cfirst - 32; else if (cfirst > 64 && cfirst < 91) ocfirst = cfirst + 32; else ocfirst = cfirst; if (ls2 > 1) { clast = s2[1]; if (clast > 96 && clast < 123) oclast = clast - 32; else if (clast > 64 && clast < 91) oclast = clast + 32; else oclast = clast; } } /* Else duplicate string with opposite case letters for comparison */ else { os2 = (char *) calloc (ls2, 1); for (i = 0; i < ls2; i++) { if (s2[i] > 96 && s2[i] < 123) os2[i] = s2[i] - 32; else if (s2[i] > 64 && s2[i] < 91) os2[i] = s2[i] + 32; else os2[i] = s2[i]; } cfirst = s2[0]; ocfirst = os2[0]; clast = s2[ls2-1]; oclast = os2[ls2-1]; } /* Loop through input string, character by character */ s = (char *) s1; s1e = s + (int) ls1 - ls2 + 1; while (s < s1e) { /* Search for first character in pattern string */ if (*s == cfirst || *s == ocfirst) { /* If single character search, return */ if (ls2 == 1) { if (os2 != NULL) free (os2); return (s); } /* Search for last character in pattern string if first found */ sl = s[ls2-1]; if (sl == clast || sl == oclast) { /* If two-character search, return */ if (ls2 == 2) { if (os2 != NULL) free (os2); return (s); } /* If 3 or more characters, check for rest of search string */ i = 1; while (i < ls2 && (s[i] == (char) s2[i] || s[i] == os2[i])) i++; /* If entire string matches, return */ if (i >= ls2) { if (os2 != NULL) free (os2); return (s); } } } s++; } if (os2 != NULL) free (os2); return (NULL); } int notnum (string) const char *string; /* Character string */ { if (isnum (string)) return (0); else return (1); } /* ISNUM-- Return 1 if string is an integer number, 2 if floating point, 3 if sexigesimal, with or without decimal point 4 if yyyy-mm-dd date else 0 */ int isnum (string) const char *string; /* Character string */ { int lstr, i, nd, cl; char cstr, cstr1, cstr2; int fpcode; /* Return 0 if string is NULL */ if (string == NULL) return (0); lstr = strlen (string); nd = 0; cl = 0; fpcode = 1; /* Return 0 if string starts with a D or E */ cstr = string[0]; if (cstr == 'D' || cstr == 'd' || cstr == 'E' || cstr == 'e') { return (0); } /* Remove trailing spaces */ while (string[lstr-1] == ' ') lstr--; /* Numeric strings contain 0123456789-+ and d or e for exponents */ for (i = 0; i < lstr; i++) { cstr = string[i]; if (cstr == '\n') break; /* Ignore leading spaces */ if (cstr == ' ' && nd == 0) continue; if ((cstr < 48 || cstr > 57) && cstr != '+' && cstr != '-' && cstr != 'D' && cstr != 'd' && cstr != 'E' && cstr != 'e' && cstr != ':' && cstr != '.') return (0); else if (cstr == '+' || cstr == '-') { if (string[i+1] == '-' || string[i+1] == '+') return (0); else if (i > 0) { cstr1 = string[i-1]; cstr2 = string[i+1]; if (cstr == '-' && cstr1 > 47 && cstr1 < 58 && cstr2 > 47 && cstr2 < 58) return (4); else if (cstr1 != 'D' && cstr1 != 'd' && cstr1 != 'E' && cstr1 != 'e' && cstr1 != ':' && cstr1 != ' ') return (0); } } else if (cstr >= 47 && cstr <= 57) nd++; /* Check for colon */ else if (cstr == 58) cl++; if (cstr=='.' || cstr=='d' || cstr=='e' || cstr=='d' || cstr=='e') fpcode = 2; } if (nd > 0) { if (cl) fpcode = 3; return (fpcode); } else return (0); } /* NUMDEC -- Return number of decimal places in numeric string (-1 if not number) */ int numdec (string) const char *string; /* Numeric string */ { char *cdot; int lstr; if (notnum (string) && !strchr (string, ':')) return (-1); else { lstr = strlen (string); if ((cdot = strchr (string, '.')) == NULL) return (0); else return (lstr - (cdot - string) - 1); } } #ifdef USE_SAOLIB int set_saolib(hstring) void *hstring; { if( *((int *)hstring) == 142857 ) use_saolib = 1; else use_saolib = 0; } #endif /* Remove exponent, leading #, surrounding parentheses, and/or trailing zeroes, if reasonable */ void strfix (string, fillblank, dropzero) char *string; /* String to modify */ int fillblank; /* If nonzero, fill blanks with underscores */ int dropzero; /* If nonzero, drop trailing zeroes */ { char *sdot, *s, *strend, *str, ctemp, *slast; int ndek, lstr, i; /* If number, ignore leading # and remove trailing non-numeric character */ if (string[0] == '#') { strend = string + strlen (string); str = string + 1; strend = str + strlen (str) - 1; ctemp = *strend; if (!isnum (strend)) *strend = (char) 0; if (isnum (str)) { strend = string + strlen (string); for (str = string; str < strend; str++) *str = *(str + 1); } else *strend = ctemp; } /* Remove parentheses if they enclose the string */ if (string[0] == '(') { lstr = strlen (string); if (string[lstr-1] == ')') { string[lstr-1] = (char) 0; strend = string + lstr - 1; for (str = string; str < strend; str++) *str = *(str+1); string[lstr-2] = (char) 0; } } /* Remove positive exponent if there are enough digits given */ if (isnum (string) > 1 && strsrch (string, "E+") != NULL) { lstr = strlen (string); ndek = (int) (string[lstr-1] - 48); ndek = ndek + (10 * ((int) (string[lstr-2] - 48))); if (ndek < lstr - 7) { lstr = lstr - 4; string[lstr] = (char) 0; string[lstr+1] = (char) 0; string[lstr+2] = (char) 0; string[lstr+3] = (char) 0; sdot = strchr (string, '.'); if (ndek > 0 && sdot != NULL) { for (i = 1; i <= ndek; i++) { *sdot = *(sdot+1); sdot++; *sdot = '.'; } } } } /* Remove trailing zeroes if they are not significant */ if (dropzero) { if (isnum (string) > 1 && strchr (string, '.') != NULL && strsrch (string, "E-") == NULL && strsrch (string, "E+") == NULL && strsrch (string, "e-") == NULL && strsrch (string, "e+") == NULL) { lstr = strlen (string); s = string + lstr - 1; while (*s == '0' && lstr > 1) { if (*(s - 1) != '.') { *s = (char) 0; lstr --; } s--; } } } /* Remove trailing decimal point */ lstr = strlen (string); s = string + lstr - 1; if (*s == '.') *s = (char) 0; /* Replace embedded blanks with underscores, if requested to */ if (fillblank) { lstr = strlen (string); slast = string + lstr; for (s = string; s < slast; s++) { if (*s == ' ') *s = '_'; } } return; } /* Oct 28 1994 New program * * Mar 1 1995 Search for / after second quote, not first one * May 2 1995 Initialize line in HGETC; deal with logicals in HGETL better * May 4 1995 Declare STRSRCH in KSEARCH * Aug 7 1995 Fix line initialization in HGETC * Dec 22 1995 Add HGETRA and HGETDEC to get degrees from xx:xx:xx.xxx string * * Jan 26 1996 Fix HGETL to not crash when parameter is not present * Feb 1 1996 Fix HGETC to deal with quotes correctly * Feb 1 1996 Fix HGETDEG to deal with sign correctly * Feb 6 1996 Add HGETS to update character strings * Feb 8 1996 Fix STRSRCH to find final characters in string * Feb 23 1996 Add string to degree conversions * Apr 26 1996 Add HGETDATE to get fractional year from date string * May 22 1996 Fix documentation; return double from STR2RA and STR2DEC * May 28 1996 Fix string translation of RA and Dec when no seconds * Jun 10 1996 Remove unused variables after running lint * Jun 17 1996 Fix bug which failed to return single character strings * Jul 1 1996 Skip sign when reading declination after testing for it * Jul 19 1996 Do not divide by 15 if RA header value is already in degrees * Aug 5 1996 Add STRNSRCH to search strings which are not null-terminated * Aug 6 1996 Make minor changes after lint * Aug 8 1996 Fix ksearch bug which finds wrong keywords * Aug 13 1996 Fix sign bug in STR2DEC for degrees * Aug 26 1996 Drop unused variables ICOL0, NLINE, PREVCHAR from KSEARCH * Sep 10 1996 Fix header length setting code * Oct 15 1996 Clean up loops and fix ICOL assignment * Nov 13 1996 Handle integer degrees correctly in STR2DEC * Nov 21 1996 Make changes for Linux thanks to Sidik Isani * Dec 12 1996 Add ISNUM to check to see whether strings are numbers * * Jan 22 1997 Add ifdefs for Eric Mandel (SAOtng) * Jan 27 1997 Convert to integer through ATOF so exponents are recognized * Jul 25 1997 Implement FITS version of ISO date format * * Feb 24 1998 Implement code to return IRAF multiple-keyword strings * Mar 12 1998 Add subroutine NOTNUM * Mar 27 1998 Add changes to match SKYCAT version * Apr 30 1998 Add BLSEARCH() to find blank lines before END * May 27 1998 Add HGETNDEC() to get number of decimal places in entry * Jun 1 1998 Add VMS patch from Harry Payne at StSci * Jun 18 1998 Fix code which extracts tokens from string values * Jul 21 1998 Drop minus sign for values of -0 * Sep 29 1998 Treat hyphen-separated date as old format if 2-digit year * Oct 7 1998 Clean up search for last blank line * * Apr 5 1999 Check lengths of strings before copying them * May 5 1999 values.h -> POSIX limits.h: MAXINT->INT_MAX, MAXSHORT->SHRT_MAX * Jul 15 1999 Add hgetm() options of 1- or 2-digit keyword extensions * Oct 6 1999 Add gethlength() to return header length * Oct 14 1999 In ksearch(), search only to null not to end of buffer * Oct 15 1999 Return 1 from hgetndec() if successful * Oct 20 1999 Drop unused variable after lint (val in hgetndec) * Dec 3 1999 Fix isnum() to reject strings starting with a d or e * Dec 20 1999 Update hgetdate() to get minutes and seconds right * * Feb 10 2000 Parse RA and Dec with spaces as well as colons as separators * Feb 11 2000 Add null at end of multi-line keyword value character string * Feb 25 2000 Change max search string length from 57600 to 256000 * Mar 15 2000 Deal with missing second quotes in string values * Mar 17 2000 Return 2 from isnum() if number is floating point (.de) * Mar 17 2000 Ignore leading # for numeric values in header * Mar 21 2000 Implement -n to get string value starting with nth token * Apr 5 2000 Reject +- in isnum() * Jun 9 2000 Read keyword values even if no equal sign is present * Sep 20 2000 Ignore linefeed at end of number in isnum() * Oct 23 2000 Fix handling of embedded + or - in isnum() * * Jan 19 2000 Return 0 from isnum(), str2ra(), and str2dec() if string is null * Mar 30 2001 Fix header length finding algorithm in ksearch() * Jul 13 2001 Make val[] static int instead of int; drop unused variables * Sep 12 2001 Read yyyy/mm/dd dates as well as dd/mm/yyyy * Sep 20 2001 Ignore leading spaces in str2dec() * Sep 20 2001 Ignore trailing spaces in isnum() * * Apr 3 2002 Add hgetr8c(), hgeti4c(), and hgetsc() for multiple WCS handling * Apr 26 2002 Fix bug in hgetsc(), hgeti4c(), and hgetr8c() found by Bill Joye * Jun 26 2002 Do not drop leading or trailing spaces in multi-line values * Aug 6 2002 Add strcsrch() and strncsrch() for case-insensitive searches * Aug 30 2002 Fix bug so strcsrch() really is case-insensitive * Oct 20 2003 Add numdec() to return number of decimal places in a string * Dec 9 2003 Fix numdec() to return 0 if no digits after decimal point * * Feb 26 2004 Extract value from keyword=value strings within a keyword value * Apr 9 2004 Use strncsrch() in ksearch() to find differently-cased keywords * Apr 28 2004 Free os2 in strncsrch() only if it is allocated * Jul 13 2004 Accept D, d, E, or e as exponent delimiter in floating points * Aug 30 2004 Change numdec() to accept sexigesimal numbers (:'s) * * Jun 27 2005 Drop unused variables * Aug 30 2005 Adjust code in hlength() * * Jun 20 2006 Initialize uninitialized variables in strnsrch() * Jun 29 2006 Add new subroutine strfix() to clean strings for other uses * Jul 13 2006 Increase maximum number of multiline keywords from 20 to 500 * * Jan 4 2007 Declare header, keyword to be const * Jan 4 2007 Change WCS letter from char to char* * Feb 28 2007 If header length is not set in hlength, set it to 0 * May 31 2007 Add return value of 3 to isnum() if string has colon(s) * Aug 22 2007 If closing quote not found, make one up * * Nov 12 2009 In strfix(), if drop enclosing parantheses * * Apr 19 2011 In str2dec(), change comma to space * May 19 2011 In strncsrch() always free allocated memory before returning * * Nov 6 2015 In isnum(), add return of 4 for yyyy-mm-dd dates * * Jun 9 2016 Fix isnum() tests for added coloned times and dashed dates */ wcstools-3.9.5/libwcs/fitswcs.c0000664000016200001660000004525511750060473015602 0ustar minkoirsys/*** File libwcs/fitswcs.c *** March 14, 2011 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2011 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: fitswcs.c (FITS file WCS reading and deleting) * Purpose: Read and delete FITS image world coordinate system keywords * * Subroutine: GetWCSFITS (filename, verbose) * Open a FITS or IRAF image file and returns its WCS structure * Subroutine: GetFITShead (filename, verbose) * Open a FITS or IRAF image file and returns a FITS header * Subroutine: DelWCSFITS (header, verbose) * Delete all standard WCS keywords from a FITS header * Subroutine: PrintWCS (header, verbose) * Check the WCS fields and print any that are found if verbose. * Subroutine: SetFITSWCS (header, wcs) * Set FITS WCS keywords from WCS data structure */ #include #include #include #include "fitsfile.h" #include "wcs.h" struct WorldCoor * GetWCSFITS (filename, verbose) char *filename; /* FITS or IRAF file filename */ int verbose; /* Print extra information if nonzero */ { char *header; /* FITS header */ struct WorldCoor *wcs; /* World coordinate system structure */ char *GetFITShead(); char *cwcs; /* Multiple wcs string (name or character) */ /* Read the FITS or IRAF image file header */ header = GetFITShead (filename, verbose); if (header == NULL) return (NULL); /* Set the world coordinate system from the image header */ cwcs = strchr (filename, '%'); if (cwcs != NULL) cwcs++; wcs = wcsinitn (header, cwcs); if (wcs == NULL) { setwcsfile (filename); if (verbose) wcserr (); } free (header); return (wcs); } char * GetFITShead (filename, verbose) char *filename; /* FITS or IRAF file filename */ int verbose; /* Print error messages if nonzero */ { char *header; /* FITS header */ int lhead; /* Maximum number of bytes in FITS header */ char *irafheader; /* IRAF image header */ int nbiraf, nbfits; /* Open IRAF image if .imh extension is present */ if (isiraf (filename)) { if ((irafheader = irafrhead (filename, &nbiraf)) != NULL) { if ((header = iraf2fits (filename, irafheader, nbiraf, &lhead)) == NULL) { if (verbose) fprintf (stderr, "Cannot translate IRAF header %s\n",filename); free (irafheader); irafheader = NULL; return (NULL); } free (irafheader); irafheader = NULL; } else { if (verbose) fprintf (stderr, "Cannot read IRAF header file %s\n", filename); return (NULL); } } else if (istiff (filename) || isgif (filename) || isjpeg (filename)) { if ((header = fitsrtail (filename, &lhead, &nbfits)) == NULL) { if (verbose) fprintf (stderr, "TIFF file %s has no appended header\n", filename); return (NULL); } } /* Open FITS file if .imh extension is not present */ else { if ((header = fitsrhead (filename, &lhead, &nbfits)) == NULL) { if (verbose) /* fprintf (stderr, "Cannot read FITS file %s\n", filename); */ fitserr (); return (NULL); } } return (header); } /* delete all the C* fields. * return 0 if at least one such field is found, else -1. */ int DelWCSFITS (header, verbose) char *header; int verbose; { static char flds[19][8]; char keyword[8]; int i; int n, nfields; double eq; char rastr[32],decstr[32]; n = 0; /* Delete standard WCS fields */ nfields = 19; strcpy (flds[0], "CTYPE1"); strcpy (flds[1], "CTYPE2"); strcpy (flds[2], "CRVAL1"); strcpy (flds[3], "CRVAL2"); strcpy (flds[4], "CDELT1"); strcpy (flds[5], "CDELT2"); strcpy (flds[6], "CRPIX1"); strcpy (flds[7], "CRPIX2"); strcpy (flds[8], "CROTA1"); strcpy (flds[9], "CROTA2"); strcpy (flds[10], "IMWCS"); strcpy (flds[11], "CD1_1"); strcpy (flds[12], "CD1_2"); strcpy (flds[13], "CD2_1"); strcpy (flds[14], "CD2_2"); strcpy (flds[15], "PC1_1"); strcpy (flds[16], "PC1_2"); strcpy (flds[17], "PC2_1"); strcpy (flds[18], "PC2_2"); for (i = 0; i < nfields; i++) { if (hdel (header, flds[i])) { n++; if (verbose) fprintf (stderr,"%s: deleted\n", flds[i]); } } /* Delete projection parameters */ for (i = 0; i < MAXPV; i++) { sprintf (keyword, "PV1_%d", i); if (hdel (header, keyword)) { n++; if (verbose) fprintf (stderr,"%s: deleted\n", keyword); } sprintf (keyword, "PV2_%d", i); if (hdel (header, keyword)) { n++; if (verbose) fprintf (stderr,"%s: deleted\n", keyword); } } /* Delete rotation matrix, if present */ if (ksearch (header, "PC001001")) { int i, j; char keyword[16]; for (i = 1; i < 6; i++) { for (j = 1; j < 6; j++) { sprintf (keyword,"PC%03d%03d", i, j); if (hdel (header, keyword)) { if (verbose) fprintf (stderr,"%s deleted\n", keyword); n++; } } } } if (verbose && n == 0) fprintf (stderr,"DelWCSFITS: No WCS in header\n"); /* Delete RA DEC EPOCH, replacing with saved values, if present */ if (ksearch (header,"WRA")) { hdel (header, "RA"); n++; hchange (header, "WRA","RA"); if (ksearch (header,"WDEC")) { hdel (header, "DEC"); n++; hchange (header, "WDEC", "DEC"); } eq = 0.0; if (!hgetr8 (header, "WEQUINOX", &eq)) { if (!hgetr8 (header, "WEPOCH", &eq)) { if (!hgetr8 (header, "EQUINOX", &eq)) { hgetr8 (header, "EPOCH", &eq); } } } if (ksearch (header,"WEQUINOX")) { hdel (header, "EPOCH"); n++; hchange (header, "WEQUINOX", "EPOCH"); } else if (ksearch (header,"WEPOCH")) { hdel (header, "EPOCH"); n++; hchange (header, "WEPOCH", "EPOCH"); } else if (eq > 0.0) { hputr8 (header, "EPOCH", eq); } if (ksearch (header, "EQUINOX")) { hdel (header, "EQUINOX"); n++; if (verbose) fprintf (stderr,"EQUINOX deleted\n"); } if (hdel (header, "RADECSYS")) { if (verbose) fprintf (stderr,"RADECSYS deleted\n"); n++; } if (hdel (header, "SECPIX1")) { if (verbose) fprintf (stderr,"SECPIX1 deleted\n"); n++; } if (hdel (header, "SECPIX2")) { if (verbose) fprintf (stderr,"SECPIX2 deleted\n"); n++; } if (verbose) { hgets (header,"RA", 31, rastr); hgets (header,"DEC", 31, decstr); eq = 0.0; hgetr8 (header,"EPOCH",&eq); if (eq == 0.0) hgetr8 (header,"EQUINOX",&eq); fprintf (stderr,"DelWCS: Center reset to %s %s %.1f\n", rastr,decstr, eq); } } else if (ksearch (header, "EPOCH") && !ksearch (header, "PLTRAH")) { if (hdel (header,"EQUINOX")) { if (verbose) fprintf (stderr,"EQUINOX: deleted\n"); n++; } else if (verbose) fprintf (stderr,"DelWCS: EPOCH, but not EQUINOX found\n"); } /* Delete IMWCS result keywords, if present */ if (ksearch (header, "WCSMATCH")) { hdel (header, "WCSMATCH"); hdel (header, "WCSRFCAT"); hdel (header, "WCSIMCAT"); hdel (header, "WCSNREF"); hdel (header, "WCSTOL"); hdel (header, "WCSSEP"); } /* Delete SAO polynomial, if present */ if (ksearch (header, "CO1_1")) { int i; char keyword[16]; for (i = 1; i < 13; i++) { sprintf (keyword,"CO1_%d", i); if (hdel (header, keyword)) { if (verbose) fprintf (stderr,"%s deleted\n", keyword); n++; } } for (i = 1; i < 13; i++) { sprintf (keyword,"CO2_%d", i); if (hdel (header, keyword)) { if (verbose) fprintf (stderr,"%s deleted\n", keyword); n++; } } } if (n > 0 && verbose) fprintf (stderr,"%d keywords deleted\n", n); return (n); } /* check the WCS fields and print any that are found if verbose. * return 0 if all are found, else -1. */ int PrintWCS (header, verbose) char *header; /* FITS header */ int verbose; /* 1 to print WCS header keyword values */ { char str[80]; double v; int n, i; char keyword[16]; n = 0; if (hgets (header,"IMWCS",80,str)) { if (verbose) fprintf (stderr,"IMWCS = %s\n", str); n++; } if (hgets (header,"CTYPE1",16,str)) { if (verbose) fprintf (stderr,"CTYPE1 = %s\n", str); n++; } if (hgetr8 (header, "CRVAL1", &v)) { if (verbose) fprintf (stderr,"CRVAL1 = %.8f\n", v); n++; } if (hgetr8 (header, "CRPIX1", &v)) { if (verbose) fprintf (stderr,"CRPIX1 = %.8f\n", v); n++; } if (hgets (header,"CTYPE2",16,str)) { if (verbose) fprintf (stderr,"CTYPE2 = %s\n", str); n++; } if (hgetr8 (header, "CRVAL2", &v)) { if (verbose) fprintf (stderr,"CRVAL2 = %.8f\n", v); n++; } if (hgetr8 (header, "CRPIX2", &v)) { if (verbose) fprintf (stderr,"CRPIX2 = %.8f\n", v); n++; } /* Polynomial plate fit */ if (hgetr8 (header, "CO1_1", &v)) { if (verbose) fprintf (stderr,"CO1_1 = %.8g\n", v); for (i = 1; i < 20; i++) { sprintf (keyword,"CO1_%d",i+1); if (hgetr8 (header, keyword, &v)) { if (verbose) fprintf (stderr,"%s = %.8g\n", keyword, v); n++; } } } if (hgetr8 (header, "CO2_1", &v)) { if (verbose) fprintf (stderr,"CO2_1 = %.8g\n", v); for (i = 1; i < 20; i++) { sprintf (keyword,"CO2_%d",i+1); if (hgetr8 (header, keyword, &v)) { if (verbose) fprintf (stderr,"%s = %.8g\n", keyword, v); n++; } } } /* Plate scale and rotation from CD matrix */ if (hgetr8 (header, "CD1_1", &v)) { if (verbose) fprintf (stderr,"CD1_1 = %.8g\n", v); n++; if (hgetr8 (header, "CD1_2", &v)) { if (verbose) fprintf (stderr,"CD1_2 = %.8g\n", v); n++; } if (hgetr8 (header, "CD2_1", &v)) { if (verbose) fprintf (stderr,"CD2_1 = %.8g\n", v); n++; } if (hgetr8 (header, "CD2_2", &v)) { if (verbose) fprintf (stderr,"CD2_2 = %.8g\n", v); n++; } } /* Plate scale and rotation from CDELTn and CROTAn */ else { if (hgetr8 (header, "CDELT1", &v)) { if (verbose) fprintf (stderr,"CDELT1 = %.8f\n", v); n++; } if (hgetr8 (header, "CROTA1", &v)) { if (verbose) fprintf (stderr,"CROTA1 = %.3f\n", v); n++; } if (hgetr8 (header, "CDELT2", &v)) { if (verbose) fprintf (stderr,"CDELT2 = %.8f\n", v); n++; } if (hgetr8 (header, "CROTA2", &v)) { if (verbose) fprintf (stderr,"CROTA2 = %.3f\n", v); n++; } } return (n > 8 ? 0 : -1); } static char wcsproj[8]="TAN"; /* WCS projection name */ void setwcsproj (type) char *type; { strcpy (wcsproj, type); return; } /* Set FITS C* fields, assuming RA/DEC refers to the reference pixel, CRPIX1/CRPIX2 */ void SetFITSWCS (header, wcs) char *header; /* Image FITS header */ struct WorldCoor *wcs; /* WCS structure */ { double ep; char wcstemp[16]; char *wcsdist; /* Rename old center coordinates */ if (!ksearch (header,"WRA") && ksearch (header,"RA")) hchange (header,"RA","WRA"); if (!ksearch (header,"WDEC") && ksearch (header,"DEC")) hchange (header,"DEC","WDEC"); if (!ksearch (header,"WEQUINOX") && ksearch (header,"EQUINOX")) hchange (header, "EQUINOX", "WEQUINOX"); /* Only change EPOCH if it is used instead of EQUINOX */ else if (!ksearch (header,"WEPOCH") && ksearch (header,"EPOCH")) hchange (header, "EPOCH", "WEPOCH"); /* Set new center coordinates */ if (wcs->xref < 0) wcs->xref = 360.0 + wcs->xref; hputra (header,"RA",wcs->xref); hputdec (header,"DEC",wcs->yref); hputr8 (header, "EQUINOX", wcs->equinox); if (hgetr8 (header, "WEPOCH", &ep)) hputr8 (header, "EPOCH", wcs->equinox); else if (!hgetr8 (header, "EPOCH", &ep)) hputr8 (header, "EPOCH", wcs->equinox); if (wcs->radecsys[0] == 'B' || wcs->radecsys[0] == 'b') hputs (header, "RADECSYS", "FK4"); else if (wcs->radecsys[0] == 'I' || wcs->radecsys[0] == 'i') hputs (header, "RADECSYS", "IRCS"); else if (wcs->radecsys[0] == 'J' || wcs->radecsys[0] == 'j') hputs (header, "RADECSYS", "FK5"); else hputs (header, "RADECSYS", wcs->radecsys); /* Set standard FITS WCS keywords */ wcsdist = getdistcode (wcs); /* FITS WCS distortion code */ strcpy (wcstemp, "RA---"); strcat (wcstemp, wcsproj); if (wcsdist != NULL) strcat (wcstemp, wcsdist); hputs (header, "CTYPE1", wcstemp); strcpy (wcstemp, "DEC--"); strcat (wcstemp, wcsproj); if (wcsdist != NULL) strcat (wcstemp, wcsdist); hputs (header, "CTYPE2", wcstemp); /* Reference pixel in WCS and image coordinates */ hputnr8 (header, "CRVAL1", 9, wcs->xref); hputnr8 (header, "CRVAL2", 9, wcs->yref); hputnr8 (header, "CRPIX1", 4, wcs->xrefpix); hputnr8 (header, "CRPIX2", 4, wcs->yrefpix); /* CD matrix (proposed FITS standard) */ if (wcs->rotmat) { hputnr8 (header, "CD1_1", 12, wcs->cd[0]); hputnr8 (header, "CD1_2", 12, wcs->cd[1]); hputnr8 (header, "CD2_1", 12, wcs->cd[2]); hputnr8 (header, "CD2_2", 12, wcs->cd[3]); hdel (header, "CDELT1"); hdel (header, "CDELT2"); hdel (header, "CROTA1"); hdel (header, "CROTA2"); } /* Scale and rotation (old FITS standard) */ else { hputnr8 (header, "CDELT1", 12, wcs->xinc); hputnr8 (header, "CDELT2", 12, wcs->yinc); hputnr8 (header, "CROTA1", 6, wcs->rot); hputnr8 (header, "CROTA2", 6, wcs->rot); hputnr8 (header, "CD1_1", 12, wcs->cd[0]); hputnr8 (header, "CD1_2", 12, wcs->cd[1]); hputnr8 (header, "CD2_1", 12, wcs->cd[2]); hputnr8 (header, "CD2_2", 12, wcs->cd[3]); /* hdel (header, "CD1_1"); hdel (header, "CD1_2"); hdel (header, "CD2_1"); hdel (header, "CD2_2"); */ } /* Plate scale at reference pixel */ if (-wcs->xinc != wcs->yinc) { if (ksearch (header,"SECPIX")) hdel (header,"SECPIX"); hputnr8 (header, "SECPIX1", 4, -wcs->xinc*3600.0); hputnr8 (header, "SECPIX2", 4, wcs->yinc*3600.0); } else { if (ksearch (header,"SECPIX1")) hdel (header,"SECPIX1"); if (ksearch (header,"SECPIX2")) hdel (header,"SECPIX2"); hputnr8 (header, "SECPIX", 6, wcs->yinc*3600.0); } /* Plate fit coefficients, if present */ if (wcs->ncoeff1 > 0) { char keyword[16]; int i; for (i = 0; i < wcs->ncoeff1; i++) { sprintf (keyword, "CO1_%d",i+1); hputr8 (header, keyword, wcs->x_coeff[i]); } } if (wcs->ncoeff2 > 0) { char keyword[16]; int i; for (i = 0; i < wcs->ncoeff2; i++) { sprintf (keyword, "CO2_%d",i+1); hputr8 (header, keyword, wcs->y_coeff[i]); } } return; } /* May 29 1996 Change name from delWCSFITS to DelWCSFITS * May 31 1996 Print single message if no WCS is found in header * May 31 1996 Use stream I/O instead of standard I/O * Jun 10 1996 Combine imgetwcs.c and imdelwcs.c into fitswcs.c * Jun 17 1996 Delete IMWCS record, too * Jul 16 1996 Update arguments for header-reading subroutines * Aug 6 1996 Fixed small defects after lint * Aug 8 1996 Restore old image center after deleting WCS * Aug 26 1996 Fix subroutine arguments after lint * * Feb 21 1997 Check pointers against NULL explicitly for Linux * Feb 21 1997 Add GetFITShead() subroutine and use it * Mar 20 1997 Remove unused variables * Nov 6 1997 Add PrintWCS() from IMWCS * * Jan 7 1998 Return NULL WCS structure if no FITS header can be read * Feb 18 1998 Move SetFITSWCS() here from imsetwcs.c * Feb 24 1998 Delete CD matrix in DelWCS() * Mar 20 1998 Write CD matrix in SetFITSWCS() * Mar 27 1998 Add plate constants in SetFITSWCS() * Mar 27 1998 Delete plate constants in DelFITSWCS() * Apr 6 1998 Change coefficient keywords from PLTij to COi_j * Apr 7 1998 Change amd_i_coeff to i_coeff * Apr 10 1998 Write out polynomial coefficients correctly * Apr 13 1998 Print polynomial coefficients, if in header * Apr 16 1998 Drop NCOEFF header parameter * Apr 17 1998 Do not write W* keywords if they are already there * May 27 1998 Include fitsio.h instead of fitshead.h * Jun 1 1998 Print error message if WCS cannot be initialized * Jun 11 1998 Change WCSTYPE to WCSPROJ to avoid conflict * Jul 23 1998 In DelWCS, delete specific number of fields * Jul 24 1998 Make irafheader char instead of int * Jul 27 1998 Set irafheader pointer to NULL after use * Aug 6 1998 Change fitsio.h to fitsfile.h * Oct 5 1998 Use isiraf() to determine file type * Oct 28 1998 Delete EQUINOX, RADECSYS, SECPIX1, SECPIX2 from imwcs * * Apr 7 1999 Add file name to error message if WCS error * Jul 8 1999 Write RADECSYS as FK5 or FK4 instead of J2000 or B1950 * Jul 21 1999 Add SECPIX plate scale output to SetFITSWCS() * Oct 21 1999 Fix declarations after lint * * Mar 23 2000 Fix bug in IRAF header error message * * Jan 11 2001 Print all messages to stderr * Jan 31 2001 Add code to extract WCS name or character from filename * Mar 8 2001 Change WCS character separator from : to % in FITS filenames * Jul 11 2001 Add PC matrix to keywords deleted by DelWCS() * * Apr 23 2002 Always write CD matrix in SetFITSWCS() * Jun 19 2002 Add verbose argument to GetWCSFITS() and GetFITShead() * * Feb 10 2003 Print 12 decimal places instead of 9 for CD matrix and CDELT * Oct 23 2003 Add PCi_j to DelWCSFITS() * Nov 3 2003 In SetFITSWCS(), add distortion code if in WCS * Dec 5 2003 Fix bug, delete projection parameters in DelWCSFITS() * * Jul 19 2004 Print error message in verbose mode only * Sep 16 2004 Add 360.0 to negative right ascensions in SetFITSWCS() * Nov 1 2005 Set RADECSYS to ICRS if appropriate * * Feb 23 2006 Add code to read FITS header appended to TIFF file * Jun 1 2006 Fix bug so CD matrix is deleted by DelWCSFITS() * Sep 26 2006 Increase length of rastr and destr from 16 to 32 * * Apr 2 2007 Fix DelWCSFITS() argument description at top of file * Apr 18 2007 Delete WCS result keywords with DelWCSFITS() * Dec 20 2007 Print error message set by fitsrhead() * * Apr 22 2010 Fix parameter deletion errors found by Paul Liptack * Apr 22 2010 Only print deletion confirmation if deletion occurred * Apr 29 2010 Fx loop index test bug i -> j in PC matrix deletion * * Mar 14 2011 Delete up to j=MAXPV PVi_j parameters (for SCAMP from Ed Los) */ wcstools-3.9.5/libwcs/fortcat.c0000664000016200001660000001431311750060473015551 0ustar minkoirsys/*** File libwcs/fortcat.c *** April 3, 2003 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 2001-2003 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ /* Fortran wrappers for subroutines which read astronomical catalogs * * Catalogs supported include: USNO-A2.0, USNO_SA2.0, ACT, Tycho 2, SAO * TDC binary format (SAO, PPM, Yale Bright Star, IRAS Point Source Catalogs) * SAO TDC ASCII format, and Starbase tab-delimited format * * For shell-level searches, use WCSTools scat, documented at * http://tdc-www.harvard.edu/software/wcstools/scat/ * * int catread_() Read catalog stars in specified region of the sky * int catrnum_() Read catalog stars with specified numbers */ #include #include #include #include #include #include #include "wcs.h" #include "wcscat.h" /* default pathname for catalog, used if catalog file not found in current working directory, but overridden by WCS_CATDIR environment variable */ char catdir[64]="/data/catalogs"; static struct StarCat **starcat; /* Catalog data structure */ /* CATREAD -- Read ASCII stars in specified region using ctgread() */ void catread_ (catfile, distsort, cra, cdec, dra, ddec, drad, csysout, eqout, epout, mag1, mag2, nsmax, nlog, nstars, xnum, xra, xdec, xpra, xpdec, xmag, xmagb) char *catfile; /* Name of reference star catalog file */ int distsort; /* 1 to sort stars by distance from center */ double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ char *csysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int nsmax; /* Maximum number of stars to be returned */ int nlog; /* Logging frequency */ int *nstars; /* Number of catalog stars found (returned) */ double *xnum; /* Array of ID numbers (returned) */ double *xra; /* Array of right ascensions (returned) */ double *xdec; /* Array of declinations (returned) */ double *xpra; /* Array of right ascension proper motions (returned) */ double *xpdec; /* Array of declination proper motions (returned) */ double *xmag; /* Array of magnitudes (returned) */ double *xmagb; /* Array of second magnitudes (returned) */ { int refcat; /* Catalog code from wcscat.h */ char **tobj; /* Array of object names (ignored) */ int *tc; /* Array of fluxes (ignored) */ int nread; /* Number of stars read from catalog */ int sysout; /* Search coordinate system */ tc = NULL; tobj = NULL; refcat = CatCode (catfile); sysout = wcscsys (csysout); nread = ctgread (catfile, refcat, distsort, cra, cdec, dra, ddec, drad, sysout, eqout, epout, mag1, mag2, nsmax, starcat, xnum, xra, xdec, xpra, xpdec, xmag, xmagb, tc, tobj, nlog); /* Return number of stars read or maximum, which ever is lower */ if (nread < nsmax) *nstars = nread; else *nstars = nsmax; return; } /* CATRNUM -- Read ASCII stars with specified numbers using ctgrnum() */ void catrnum_ (catfile, nnum, csysout, eqout, epout, match, nlog, nstars, xnum, xra, xdec, xpra, xpdec, xmag, xmagb) char *catfile; /* Name of reference star catalog file */ int nnum; /* Number of stars to look for */ char *csysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ int match; /* 1 to match star number exactly, else sequence num.*/ int nlog; /* Logging frequency */ int *nstars; /* Number of catalog stars found (returned) */ double *xnum; /* Array of star numbers to look for */ double *xra; /* Array of right ascensions (returned) */ double *xdec; /* Array of declinations (returned) */ double *xpra; /* Array of right ascension proper motions (returned) */ double *xpdec; /* Array of declination proper motions (returned) */ double *xmag; /* Array of magnitudes (returned) */ double *xmagb; /* Array of second magnitudes (returned) */ { int refcat; /* Catalog code from wcscat.h */ int *tc; /* Array of fluxes (ignore) */ char **tobj; /* Array of object names (ignored) */ int sysout; /* Search coordinate system */ int nread; /* Number of stars read from catalog */ tc = NULL; tobj = NULL; sysout = wcscsys (csysout); refcat = CatCode (catfile); nread = ctgrnum (catfile,refcat, nnum,sysout,eqout,epout,match,starcat, xnum,xra,xdec,xpra,xpdec,xmag,xmagb,tc,tobj,nlog); *nstars = nread; return; } /* * Feb 16 2001 New subroutines * Sep 19 2001 Drop fitshead.h; it is in wcs.h * * Apr 3 2003 Use CatCode() instead of RefCat(); add nstars to catrnum_() */ wcstools-3.9.5/libwcs/fortwcs.c0000664000016200001660000003636711750060473015613 0ustar minkoirsys/*** File wcstools/libwcs/fortwcs.c *** April 7, 2003 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2003 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: wcsfort.c (World Coordinate Systems) * Purpose: Fortran interface to C WCS subroutines in wcsinit.c and wcs.c * Subroutine: wcsinit_ (hstring, wcs) sets WCS structure from an image header * Subroutine: wcsxinit_ (cra,cdec,secpix,xrpix,yrpix,nxpix,nypix,rotate, equinox,epoch,proj) sets WCS structure from arguments * Subroutine: wcskinit_ (nxpix,nypix,ctype1,ctype2,crpix1,crpix2,crval1, * crval2, cd,cdelt1,cdelt2,crota,equinox,epoch) * sets a WCS structure from keyword-based arguments * Subroutine: wcsclose_ (iwcs) closes and frees the specified WCS structure * Subroutine: wcssize_ (wcs, cra, cdec, dra, ddec) * returns the image center and size in WCS units * Subroutine: wcsdist_ (x1,y1,x2,y2,diff) * compute angular distance between ra/dec or lat/long * Subroutine: wcsoutinit (wcs,coor) sets up the output coordinate system * Subroutine: getwcsout_ (iwcs, coorsys) * Return WCS output coordinate system used by pix2wcs * Subroutine: wcsininit (wcs,coor) sets up the input coordinate system * Subroutine: getwcsin_ (iwcs, coorsys) * Return WCS output coordinate system used by pix2wcs * Subroutine: getwcsim_ (iwcs, coorsys) Return WCS coordinate system of image * Subroutine: setwcslin_ (iwcs, mode) * Set output string mode for LINEAR coordinates * Subroutine: setwcsdeg_ (iwcs, mode) * Set output string mode as decimal degrees if not zero * Subroutine: pix2wcs_ (wcs,xpix,ypix,xpos,ypos) * pixel coordinates -> sky coordinates * Subroutine: pix2wcst_ (wcs,xpix,ypix,wcstring,lstr) * pixels -> sky coordinate string * Subroutine: wcs2pix_ (wcs,xpos,ypos,xpix,ypix) * sky coordinates -> pixel coordinates * Copyright: 2000-2003 Smithsonian Astrophysical Observatory * You may do anything you like with this file except remove * this copyright. The Smithsonian Astrophysical Observatory * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. */ #include /* strstr, NULL */ #include /* stderr */ #include /* stderr */ #include "wcs.h" #ifndef VMS #include #endif static struct WorldCoor **pwcs; static int nwcs = 0; /* set up a WCS structure from a FITS or IRAF image header */ /* Call WCSINIT (HSTRING, IWCS) * where HSTRING is a Character string and IWCS is a returned integer * identifying the data structure which is created */ void wcsinit_ (hstring, iwcs, nc) char *hstring; /* Character string containing FITS header information in the format = {/ } */ int *iwcs; /* Pointer to wcs structure (returned) */ int nc; /* Number of characters in hstring (supplied by Fortran */ { int id; struct WorldCoor *twcs, *wcsinit(); twcs = wcsinit (hstring); /* Set index to -1 if no WCS is found in header */ if (twcs == NULL) *iwcs = -1; /* Otherwise, use first available index into vector of pointers */ else if (nwcs == 0) { pwcs = (struct WorldCoor **) calloc (10, sizeof (void *)); nwcs = 10; *iwcs = 0; pwcs[0] = twcs; } else { for (id = 0; id < nwcs; id++) { if (pwcs[id] == NULL) { *iwcs = id; pwcs[id] = twcs; break; } } } return; } /* set up a WCS structure from subroutine arguments*/ void wcsxinit_ (iwcs,cra,cdec,secpix,xrpix,yrpix,nxpix,nypix,rotate,equinox, epoch,proj,np) int *iwcs; /* Pointer to wcs structure (returned) */ double *cra; /* Center right ascension in degrees */ double *cdec; /* Center declination in degrees */ double *secpix; /* Number of arcseconds per pixel */ double *xrpix; /* Reference pixel X coordinate */ double *yrpix; /* Reference pixel X coordinate */ int *nxpix; /* Number of pixels along x-axis */ int *nypix; /* Number of pixels along y-axis */ double *rotate; /* Rotation angle (clockwise positive) in degrees */ int *equinox; /* Equinox of coordinates, 1950 and 2000 supported */ double *epoch; /* Epoch of coordinates, used for FK4/FK5 conversion * no effect if 0 */ char *proj; /* Projection */ int np; /* Length of projection (supplied by Fortran) */ { int id; struct WorldCoor *twcs; twcs = wcsxinit (*cra,*cdec,*secpix,*xrpix,*yrpix,*nxpix,*nypix, *rotate,*equinox,*epoch,proj); /* Set index to -1 if no WCS is found in header */ if (twcs == NULL) *iwcs = -1; /* Otherwise, use first available index into vector of pointers */ else if (nwcs == 0) { pwcs = (struct WorldCoor **) calloc (10, sizeof (void *)); nwcs = 10; *iwcs = 0; pwcs[0] = twcs; } else { for (id = 0; id < 10; id++) { if (pwcs[id] == NULL) { *iwcs = id; pwcs[id] = twcs; break; } } } return; } /* set up a WCS structure from subroutine arguments matching FITS keywords*/ void wcskinit_ (iwcs,naxis1,naxis2,ctype1,ctype2,crpix1,crpix2,crval1,crval2,cd, cdelt1,cdelt2,crota,equinox,epoch, nc1,nc2) int *iwcs; /* Pointer to wcs structure (returned) */ int *naxis1; /* Number of pixels along x-axis */ int *naxis2; /* Number of pixels along y-axis */ char *ctype1; /* FITS WCS projection for axis 1 */ char *ctype2; /* FITS WCS projection for axis 2 */ double *crpix1, *crpix2; /* Reference pixel coordinates */ double *crval1, *crval2; /* Coordinates at reference pixel in degrees */ double *cd; /* Rotation matrix, used if all 4 elements nonzero */ double *cdelt1, *cdelt2; /* scale in degrees/pixel, ignored if cd is not NULL */ double *crota; /* Rotation angle in degrees, ignored if cd is set */ int *equinox; /* Equinox of coordinates, 1950 and 2000 supported */ double *epoch; /* Epoch of coordinates, used for FK4/FK5 conversion * no effect if 0 */ int nc1, nc2; /* Lengths of CTYPEs (supplied by Fortran) */ { int id; struct WorldCoor *twcs; twcs = wcskinit (*naxis1,*naxis2,ctype1,ctype2,*crpix1,*crpix2,*crval1, *crval2, cd, *cdelt1, *cdelt2, *crota, *equinox, *epoch); /* Set index to -1 if no WCS is found in header */ if (twcs == NULL) *iwcs = -1; /* Otherwise, use first available index into vector of pointers */ else if (nwcs == 0) { pwcs = (struct WorldCoor **) calloc (10, sizeof (void *)); nwcs = 10; *iwcs = 0; pwcs[0] = twcs; } else { for (id = 0; id < nwcs; id++) { if (pwcs[id] == NULL) { *iwcs = id; pwcs[id] = twcs; break; } } } return; } void wcsclose_ (iwcs) int *iwcs; /* Index to WCS pointer array */ { struct WorldCoor *wcs; /* World coordinate system structure */ if (*iwcs >= 0 && *iwcs < nwcs) wcs = pwcs[*iwcs]; else wcs = pwcs[0]; if (wcs != NULL) { wcsfree (wcs); pwcs[*iwcs] = NULL; } return; } /* Return RA and Dec of image center, plus size in RA and Dec */ void wcssize_ (iwcs, cra, cdec, dra, ddec, radecsys) int *iwcs; /* Index to WCS pointer array */ double *cra; /* Right ascension of image center (rad) (returned) */ double *cdec; /* Declination of image center radg) (returned) */ double *dra; /* Half-width in radians (returned) */ double *ddec; /* Half-height in radians (returned) */ char *radecsys; /* Equinox (returned) */ { struct WorldCoor *wcs; /* World coordinate system structure */ double width, height; if (*iwcs >= 0 && *iwcs < nwcs) wcs = pwcs[*iwcs]; else wcs = pwcs[0]; /* If there is no WCS defined, return all zeroes */ if (wcs == NULL) { (void)fprintf (stderr,"No WCS info available\n"); *cra = 0.0; *cdec = 0.0; *dra = 0.0; *ddec = 0.0; } else { wcsfull (wcs, cra, cdec, &width, &height); *dra = 0.5 * width; *ddec = 0.5 * height; /* Get coordinate system from structure */ strcpy (radecsys, wcs->radecsys); } return; } /* Compute distance in degrees between two sky coordinates */ void wcsdist_ (x1,y1,x2,y2,diff) double *x1,*y1; /* (RA,Dec) or (Long,Lat) in degrees */ double *x2,*y2; /* (RA,Dec) or (Long,Lat) in degrees */ double *diff; /* Distance in degrees */ { double xr1, xr2, yr1, yr2; double pos1[3], pos2[3], w, cosb; int i; /* Convert two vectors to direction cosines */ xr1 = degrad (*x1); yr1 = degrad (*y1); cosb = cos (yr1); pos1[0] = cos (xr1) * cosb; pos1[1] = sin (xr1) * cosb; pos1[2] = sin (yr1); xr2 = degrad (*x2); yr2 = degrad (*y2); cosb = cos (yr2); pos2[0] = cos (xr2) * cosb; pos2[1] = sin (xr2) * cosb; pos2[2] = sin (yr2); /* Modulus squared of half the difference vector */ w = 0.0; for (i = 0; i < 3; i++) { w = w + (pos1[i] - pos2[i]) * (pos1[i] - pos2[i]); } w = w / 4.0; if (w > 1.0) w = 1.0; /* Angle beween the vectors */ *diff = 2.0 * atan2 (sqrt (w), sqrt (1.0 - w)); *diff = raddeg (*diff); return; } /* Initialize WCS output coordinate system used by pix2wcs */ void wcsoutinit_ (iwcs, coorsys, nc) int *iwcs; /* Index to WCS structure */ char *coorsys; /* Output coordinate system */ int nc; /* Length of coorsys (set by Fortran) */ { struct WorldCoor *wcs; /* World coordinate system structure */ if (*iwcs >= 0 && *iwcs < nwcs) wcs = pwcs[*iwcs]; else wcs = pwcs[0]; if (wcs != NULL) wcsoutinit (wcs, coorsys); return; } /* Return WCS output coordinate system used by pix2wcs */ void getwcsout_ (iwcs, coorsys, nc) int *iwcs; /* Index to WCS structure */ char *coorsys; /* Output coordinate system (returned) */ int nc; /* Length of coorsys (set by Fortran) */ { struct WorldCoor *wcs; /* World coordinate system structure */ if (*iwcs >= 0 && *iwcs < nwcs) wcs = pwcs[*iwcs]; else wcs = pwcs[0]; if (wcs != NULL) strncpy (coorsys, getwcsout (wcs), nc); return; } /* Initialize WCS input coordinate system used by wcs2pix */ void wcsininit_ (iwcs, coorsys, nc) int *iwcs; /* Index to WCS structure */ char *coorsys; /* Input coordinate system */ int nc; /* Length of coorsys (Set by Fortran) */ { struct WorldCoor *wcs; /* World coordinate system structure */ if (*iwcs >= 0 && *iwcs < nwcs) wcs = pwcs[*iwcs]; else wcs = pwcs[0]; if (wcs != NULL) wcsininit (wcs, coorsys); return; } /* Return WCS input coordinate system used by wcs2pix */ void getwcsin_ (iwcs, coorsys, nc) int *iwcs; /* Index to WCS structure */ char *coorsys; /* Input coordinate system (returned) */ int nc; /* Length of coorsys (Set by Fortran) */ { struct WorldCoor *wcs; /* World coordinate system structure */ if (*iwcs >= 0 && *iwcs < nwcs) wcs = pwcs[*iwcs]; else wcs = pwcs[0]; if (wcs != NULL) strncpy (coorsys, getwcsin (wcs), nc); return; } /* Return WCS coordinate system of image */ void getwcsim_ (iwcs, coorsys, nc) int *iwcs; /* Index to WCS structure */ char *coorsys; /* Image coordinate system (returned) */ int nc; /* Length of coorsys (Set by Fortran) */ { struct WorldCoor *wcs; /* World coordinate system structure */ if (*iwcs >= 0 && *iwcs < nwcs) wcs = pwcs[*iwcs]; else wcs = pwcs[0]; if (wcs != NULL) strncpy (coorsys, getradecsys (wcs), nc); return; } /* Set WCS output in degrees or hh:mm:ss dd:mm:ss */ void setwcsdeg_ (iwcs, mode) int *iwcs; /* Index to WCS structure */ int *mode; /* mode = 0: h:m:s d:m:s mode = 1: fractional degrees */ { struct WorldCoor *wcs; /* World coordinate system structure */ if (*iwcs >= 0 && *iwcs < nwcs) wcs = pwcs[*iwcs]; else wcs = pwcs[0]; if (wcs != NULL) wcs->degout = *mode; return; } /* Set output string mode for LINEAR coordinates */ void setwcslin_ (iwcs, mode) int *iwcs; /* World coordinate system structure */ int *mode; /* mode = 0: x y linear mode = 1: x units x units mode = 2: x y linear units */ { struct WorldCoor *wcs; /* World coordinate system structure */ if (*iwcs >= 0 && *iwcs < nwcs) wcs = pwcs[*iwcs]; else wcs = pwcs[0]; if (wcs != NULL) wcs->linmode = *mode; return; } /* Convert pixels to sky coordinate string */ void pix2wcst_ (iwcs,xpix,ypix,wcstring,lstr) int *iwcs; /* World coordinate system structure */ double *xpix, *ypix; /* x and y image coordinates in pixels */ char *wcstring; /* World coordinate string (returned) */ int lstr; /* Length of world coordinate string (set by Fortran) */ { struct WorldCoor *wcs; /* World coordinate system structure */ if (*iwcs >= 0 && *iwcs < nwcs) wcs = pwcs[*iwcs]; else wcs = pwcs[0]; if (wcs != NULL) pix2wcst (wcs, *xpix, *ypix, wcstring, lstr); return; } /* Convert pixel coordinates to World Coordinates */ void pix2wcs_ (iwcs, xpix, ypix, xpos, ypos) int *iwcs; /* World coordinate system structure */ double *xpix, *ypix; /* x and y image coordinates in pixels */ double *xpos, *ypos; /* RA and Dec in radians (returned) */ { struct WorldCoor *wcs; /* World coordinate system structure */ if (*iwcs >= 0 && *iwcs < nwcs) wcs = pwcs[*iwcs]; else wcs = pwcs[0]; if (wcs != NULL) pix2wcs (wcs, *xpix, *ypix, xpos, ypos); return; } /* Convert World Coordinates to pixel coordinates */ void wcs2pix_ (iwcs, xpos, ypos, xpix, ypix, offscl) int *iwcs; /* World coordinate system structure */ double *xpos, *ypos; /* World coordinates in degrees */ double *xpix, *ypix; /* Image coordinates in pixels */ int *offscl; { struct WorldCoor *wcs; /* World coordinate system structure */ if (*iwcs >= 0 && *iwcs < nwcs) wcs = pwcs[*iwcs]; else wcs = pwcs[0]; if (wcs != NULL) wcs2pix (wcs, *xpos, *ypos, xpix, ypix, offscl); return; } /* Jan 4 1996 new program * Jan 12 1996 Add WCSSET to set WCS without an image * * Jun 15 1998 rename wcsf77.c to wcsfort.c and move to libwcs * Jun 15 1998 rename WCSSET WCSXINIT and update arguments * Jul 7 1998 Change setlinmode to setwcslin_; add setwcsdeg_ * * Oct 15 1999 Free wcs using wcsfree() * Oct 21 1999 Add pix2wcst_(); drop unused variables after lint * Dec 10 1999 Add error handling for iwcs; document all subroutines * * Jun 2 2000 Fix WCS structure pointers * * Feb 16 2001 Change name of file from wcsfort.c to fortwcs.c * * Apr 7 2003 Add wcsclose_() to list at top of file * Apr 7 2003 Fix all init_() subroutines to work correctly on first call */ wcstools-3.9.5/libwcs/gsc2read.c0000664000016200001660000002633412504334360015604 0ustar minkoirsys/*** File libwcs/gsc2read.c *** March 24, 2015 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 2001-2015 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include #include #include #include "fitsfile.h" #include "wcs.h" #include "wcscat.h" static void parsex(); #define ABS(a) ((a) < 0 ? (-(a)) : (a)) #define LINE 1024 /* URL for GSC II search engine at STScI Catalogs and Surveys Branch */ char gsc23url[64]="http://gsss.stsci.edu/webservices/vo/CatalogSearch.aspx"; /* GSC2READ -- Read GSC II catalog stars over the web */ int gsc2read (refcatname,cra,cdec,dra,ddec,drad,dradi,distsort,sysout,eqout,epout, mag1,mag2,sortmag,nstarmax,gnum,gobj,gra,gdec,gpra,gpdec,gmag,gtype,nlog) char *refcatname; /* Name of catalog (GSC2 for 2.2; GSC2.3 for 2.3) */ double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ double dradi; /* Inner edge of annulus in degrees (ignore if 0) */ int distsort; /* 1 to sort stars by distance from center */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 to nmag) */ int nstarmax; /* Maximum number of stars to be returned */ double *gnum; /* Array of Guide Star numbers (returned) */ char **gobj; /* Array of object IDs (mixed characters and numbers) */ double *gra; /* Array of right ascensions (returned) */ double *gdec; /* Array of declinations (returned) */ double *gpra; /* Array of right ascension proper motions (returned) */ double *gpdec; /* Array of declination proper motions (returned) */ double **gmag; /* 2-D array of magnitudes (returned) */ int *gtype; /* Array of object classes (returned) */ int nlog; /* 1 for diagnostics */ { char srchurl[LINE]; char temp[64]; struct TabTable *tabtable; double dr; struct StarCat *starcat; int nstar, i; int rah, ram, dd, dm; double ras, ds; char sr[4], sd[4]; double ra, dec, mag, ddra; char *gsc2url; /* Set URL for search command */ gsc2url = gsc23url; if (nstarmax < 1) nlog = -1; /* make mag1 always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } /* Set up query for STScI GSC II server */ ra = cra; dec = cdec; if (sysout != WCS_J2000) wcscon (sysout, WCS_J2000, eqout, 2000.0, &ra, &dec, epout); sprintf (srchurl, "?RA=%.6f&DEC=%.6f&", ra, dec); if (drad != 0.0) { dr = drad; } else { ddra = dra * cos (degrad (cdec)); dr = sqrt (ddra*ddra + ddec*ddec); } sprintf (temp, "EQ=2000&SR=%.3f&FORMAT=tsv&CAT=gsc23&", dr); strcat (srchurl, temp); if (nlog > 0) fprintf (stderr,"%s%s\n", gsc2url, srchurl); /* Run search across the web */ if ((tabtable = webopen (gsc2url, srchurl, nlog)) == NULL) { if (nlog > 0) fprintf (stderr, "WEBREAD: %s failed\n", srchurl); return (0); } /* Return if no data */ if (tabtable->tabdata == NULL || strlen (tabtable->tabdata) == 0 || !strncasecmp (tabtable->tabdata, "[EOD]", 5)) { if (nlog > 0) fprintf (stderr, "WEBRNUM: No data returned\n"); return (0); } /* Dump returned file and stop */ if (nlog < 0) { (void) fwrite (tabtable->tabbuff, tabtable->lbuff, 1, stdout); exit (0); } /* Open returned Starbase table as a catalog */ if ((starcat = tabcatopen (gsc2url, tabtable,0)) == NULL) { if (nlog > 0) fprintf (stderr, "WEBREAD: Could not open Starbase table as catalog\n"); return (0); } /* Set reference frame, epoch, and equinox of catalog */ /* starcat->rpmunit = PM_MASYR; starcat->dpmunit = PM_MASYR; */ starcat->rpmunit = 0; starcat->dpmunit = 0; starcat->coorsys = WCS_J2000; starcat->epoch = 2000.0; starcat->equinox = 2000.0; /* Extract desired sources from catalog and return them */ nstar = tabread (gsc2url,distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nstarmax,&starcat, gnum,gra,gdec,gpra,gpdec,gmag,gtype,gobj,nlog); tabcatclose (starcat); /* Zero out any proper motions for GSC 3.3 and earlier */ if (!strchr (refcatname, '4')) { for (i = 0; i < nstar; i++) { if (i < nstarmax) { gpra[i] = 0.0; gpdec[i] = 0.0; } } } starcat = NULL; return (nstar); } static void parsex (str, ss, d, m, s) char *str; char *ss; int *d; int *m; double *s; { char *c0, *cstr; c0 = str; *ss = (char) 0; *d = 0; *m = 0; *s = 0.0; /* Skip over blanks at start of number */ while (*c0 == ' ') c0++; if (*c0 == '+' || *c0 == '-') { ss[0] = *c0; ss[1] = (char) 0; c0++; } else { ss[0] = '+'; ss[1] = (char) 0; } cstr = strchr (c0,':'); if (cstr > c0) { *cstr = (char) 0; *d = (int) atof (c0); *cstr = ':'; c0 = cstr + 1; cstr = strchr (c0,':'); if (cstr > c0) { *cstr = '\0'; *m = (int) atof (c0); *cstr = ':'; c0 = cstr + 1; *s = atof (c0); } else *m = (int) atof (c0); } else *d = (int) atof (c0); } char * gsc2c2t (csvbuff) char *csvbuff; /* Input comma-separated table */ { char *tabbuff; /* Output tab-separated table */ char *databuff; char *lastbuff; char *oldbuff; char *colhead, *colsep; int lhead, lbuff, i, j; char ctab = (char) 9; char ccom = ','; char clf = '\n'; char ccr = '\r'; char csp = ' '; /* First line of buffer is header */ databuff = strchr (csvbuff, clf) + 1; lhead = (int) (databuff - csvbuff); /* Allocate buffer for tab-separated table with header */ lbuff = strlen (databuff) + (2 * lhead); tabbuff = (char *) calloc (lbuff, 1); /* Copy header into new buffer with tabs instead of commas */ oldbuff = csvbuff; i = 0; while (oldbuff < databuff) { if (*oldbuff == ccom) tabbuff[i++] = ctab; else if (*oldbuff != csp && *oldbuff != ccr && *oldbuff != clf) tabbuff[i++] = *oldbuff; oldbuff++; } tabbuff[i++] = clf; /* Make separating line from first line of input file */ oldbuff = csvbuff; while (oldbuff < databuff) { if (*oldbuff == ccom) tabbuff[i++] = ctab; else if (*oldbuff != csp && *oldbuff != ccr && *oldbuff != clf) tabbuff[i++] = '-'; oldbuff++; } tabbuff[i++] = clf; /* Drop extraneous data after last linefeed */ lbuff = strlen (databuff); if (lbuff > 0) { lastbuff = strrchr (databuff, '\n'); if (lastbuff - databuff < lbuff) *(lastbuff+1) = (char) 0; /* Convert commas in data table to tabs and drop spaces */ for (j = 0; j < lbuff; j++) { if (databuff[j] == ccom) tabbuff[i++] = ctab; else if (databuff[j] != csp && databuff[j] != ccr) tabbuff[i++] = databuff[j]; } } return (tabbuff); } char * gsc2t2t (tsvbuff) char *tsvbuff; /* Input tab-separated table */ { char *tabbuff; /* Output tab-separated table */ int lbuff, i, ih, j, k, kfirst; char tsvbi, tsvbj; char ctab = (char) 9; char clf = '\n'; char ccr = '\r'; char csp = ' '; char cdash = '-'; char colon = ':'; /* Allocate buffer for tab-separated table with header */ lbuff = strlen (tsvbuff); tabbuff = (char *) calloc (2*lbuff, 1); /* Copy input into new buffer dropping first line and extra carriage returns */ /* Add a line of dashes after the header line */ i = 0; ih = 0; for (j = 0; j < lbuff; j++) { tsvbj = tsvbuff[j]; if (tsvbj == clf) { ih++; if (ih == 1) kfirst = j + 1; if (ih == 2) { tabbuff[i++] = clf; for (k = kfirst; k < j; k++) { if (tsvbuff[k] == ctab) tabbuff[i++] = ctab; else tabbuff[i++] = cdash; } } } if (ih > 0 && tsvbj != csp && tsvbj != ccr) { if (tsvbi == ctab && tsvbj == ctab) tabbuff[i++] = '0'; tabbuff[i++] = tsvbj; tsvbi = tsvbj; } } tabbuff[i++] = (char) 0; return (tabbuff); } /* Jun 22 2001 New program * Jun 28 2001 Set proper motion to milliarcseconds/year * Jun 29 2001 Always set maximum magnitude to 99.9 to get Tycho-2 stars, too * Sep 13 2001 Pass array of magnitudes, not vector * Sep 14 2001 Add option to print entire returned file if nlog < 0 * Sep 20 2001 Make argument starcat, not *starcat in tabcatclose() * * Apr 8 2002 Fix bugs in null subroutine gsc2rnum() * Oct 3 2002 If nstarmax is less than 1, print everything returned * * Feb 6 2003 Reset nmag to 4 because there is an epoch column * Mar 11 2003 Fix URL for search * Apr 3 2003 Drop unused variables after lint; drop gsc2rnum() * Apr 24 2003 Set nmag to 5 to include epoch, which is not printed * Aug 22 2003 Add radi argument for inner edge of search annulus * Nov 22 2003 Return object class (c column) as gtype * Dec 3 2003 Add option to access GSC 2.3 over the Web * Dec 4 2003 Add proper motions for GSC 2.3 * Dec 11 2003 Search to corners of rectangle, not to longest edge * Dec 12 2003 Fix call to tabcatopen() * * Oct 18 2004 Divide RA by cos(Dec) when computing radius for rect. input * * Jun 20 2006 Cast fwrite to void * Sep 8 2006 Fix comment which mentioned wrong catalog * Mar 12 2007 Read from copy in STScI MAST GALEX archive * Mar 12 2007 Add parsex \() to separate sexigesimal number into components * Mar 13 2007 Add gsc2c2v() to convert comma-separated input to tab-separated * Apr 11 2007 Return null data buffer from gsc2c2t() if no data * * Oct 24 2008 Reset to read from new CASB server and drop GALEX server * Oct 24 2008 Add gsc2t2t to drop extra characters from returned table * * Aug 17 2009 Set proper motion to 0.0 for all versions * * Aug 29 2014 Update to read GSC2.3.3 * Aug 29 2014 Add line of dashes after header to returned table * * Mar 24 2015 Drop concatenation of "empty" string to search URL */ wcstools-3.9.5/libwcs/gscread.c0000664000016200001660000012645011750060473015525 0ustar minkoirsys/*** File libwcs/gscread.c *** September 22, 2009 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2009 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include #include #include "fitsfile.h" #include "wcs.h" #include "wcscat.h" /* Pathname of northern hemisphere GSC CDROM or search engine URL */ static char cdn[64]="/data/astrocat/gsc1"; /* Uncomment following line to use ESO GSC server for GSC static char cdn[64]="http://archive.eso.org/skycat/servers/gsc-server"; */ /* Pathname of southern hemisphere GSC CDROM */ static char cds[64]="/data/astrocat/gsc2"; /* Pathname of northern hemisphere GSC-ACT CDROM or search engine URL */ static char cdna[64]="/data/astrocat/gscact1"; /* Pathname of southern hemisphere GSC-ACT CDROM */ static char cdsa[64]="/data/astrocat/gscact2"; static void gscpath(); static int gscreg(); static char *table = NULL; /* FITS table buffer */ static int ltab = 0; /* Length of FITS table buffer */ static double *gdist = NULL; /* Array of distances to stars */ static int ndist = 0; void gscfree() { free ((void *)table); ltab = 0; free ((void *)gdist); ndist = 0; return; } static int classd = -1; /* Desired object class (-2=all objects, -1=all, 0=stars, 3=nonstars) */ void setgsclass (class) int class; { classd = class; return; } /* GSCREAD -- Read HST Guide Star Catalog stars from CDROM */ int gscread (refcat,cra,cdec,dra,ddec,drad,dradi,distsort,sysout,eqout,epout, mag1,mag2,nstarmax,gnum,gra,gdec,gmag,gtype,nlog) int refcat; /* Catalog code (GSC or GSCACT) */ double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ double dradi; /* Inner separation in degrees for annulus (ignore if 0) */ int distsort; /* 1 to sort stars by distance from center */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int nstarmax; /* Maximum number of stars to be returned */ double *gnum; /* Array of Guide Star numbers (returned) */ double *gra; /* Array of right ascensions (returned) */ double *gdec; /* Array of declinations (returned) */ double **gmag; /* Array of magnitudes (returned) */ int *gtype; /* Array of object types (returned) */ int nlog; /* 1 for diagnostics */ { double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ double dist = 0.0; /* Distance from search center in degrees */ double faintmag=0.0; /* Faintest magnitude */ double maxdist=0.0; /* Largest distance */ int faintstar=0; /* Faintest star */ int farstar=0; /* Most distant star */ int magsort=0; int nreg; /* Number of input FITS tables files */ double xnum; /* Guide Star number */ int rlist[100]; /* List of input FITS tables files */ char inpath[64]; /* Pathname for input FITS table file */ char entry[100]; /* Buffer for FITS table row */ int class; /* Object class (0>star, 3>other) */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ struct Keyword kw[8]; /* Keyword structure */ struct Keyword *kwn; int verbose; int pass; int rnum, num0, num, itot,ireg; int ik,nk,itable,ntable,jstar; int nbline,npos,nbhead; int nbr,nrmax,nstar,i; int ift; int wrap; double ra,rasum,dec,decsum,perr,perr2,perrsum,msum; double mag,merr,merr2,merrsum; int band0 = 0; int band = 0; int class0 = 0; double merr0 = 0.0; double mag0 = 0.0; double perr0 = 0.0; double ra0 = 0.0; double dec0 = 0.0; double rra1, rra2, rdec1, rdec2; double rdist, ddist; char *str; char *url; char *title; char cstr[32], numstr[32], rastr[32], decstr[32], catid[16]; itot = 0; if (nlog == 1) verbose = 1; else verbose = 0; verbose = nlog; /* If root pathname is a URL, search and return */ url = cdn; if (refcat == GSC) { url = cdn; if ((str = getenv("GSC_NORTH")) == NULL) str = getenv ("GSC_PATH"); if (str != NULL) url = str; } if (refcat == GSCACT) { url = cdna; if ((str = getenv("GSCACT_NORTH")) == NULL) str = getenv ("GSCACT_PATH"); if (str != NULL) url = str; } if (!strncmp (url, "http:",5)) return (webread (url,"gsc",distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,magsort,nstarmax, gnum,gra,gdec,NULL,NULL,gmag,gtype,nlog)); /* Allocate FITS table buffer which is saved between calls */ if (ltab < 1) { ltab = 10000; table = (char *)calloc (ltab, sizeof (char)); if (table == NULL) { fprintf (stderr, "GSCREAD: cannot allocate FITS table buffer\n"); return (0); } } for (i = 0; i < 100; i++) entry[i] = 0; /* Set path to Guide Star Catalog */ if (refcat == GSCACT) { if ((str = getenv("GSCACT_NORTH")) != NULL ) strcpy (cdna,str); if ((str = getenv("GSCACT_SOUTH")) != NULL ) strcpy (cdsa,str); } else { if ((str = getenv("GSC_NORTH")) != NULL ) strcpy (cdn,str); if ((str = getenv("GSC_SOUTH")) != NULL ) strcpy (cds,str); } wcscstr (cstr, sysout, eqout, epout); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* Make mag1 always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } /* Find Guide Star Catalog regions in which to search */ nrmax = 100; rra1 = ra1; rra2 = ra2; rdec1 = dec1; rdec2 = dec2; RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref,0.0, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); nreg = gscreg (refcat,rra1,rra2,rdec1,rdec2,table,nrmax,rlist,verbose); if (nreg <= 0) { fprintf (stderr,"GSCREAD: no Guide Star regions found\n"); return (0); } /* Allocate array for distances from search center */ if (nstarmax > ndist) { if (ndist > 0) free ((void *)gdist); gdist = (double *) malloc (nstarmax * sizeof (double)); if (gdist == NULL) { fprintf (stderr,"GSCREAD: cannot allocate separation array\n"); return (0); } ndist = nstarmax; } /* Set keyword list */ nk = 8; strcpy (kw[0].kname,"GSC_ID"); strcpy (kw[1].kname,"RA_DEG"); strcpy (kw[2].kname,"DEC_DEG"); strcpy (kw[3].kname,"POS_ERR"); strcpy (kw[4].kname,"MAG"); strcpy (kw[5].kname,"MAG_ERR"); strcpy (kw[6].kname,"MAG_BAND"); strcpy (kw[7].kname,"CLASS"); for (ik = 0; ik < nk; ik++) { kw[ik].lname = (int) strlen (kw[ik].kname); kw[ik].kn = 0; kw[ik].kf = 0; kw[ik].kl = 0; } nstar = 0; /* Write header if printing star entries as found */ if (nstarmax < 1) { char *revmessage; revmessage = getrevmsg(); title = CatName (refcat, NULL); printf ("catalog %s\n", title); free (title); ra2str (rastr, 31, cra, 3); printf ("ra %s\n", rastr); dec2str (decstr, 31, cdec, 2); printf ("dec %s\n", decstr); if (drad != 0.0) { printf ("radmin %.1f\n", drad*60.0); if (dradi > 0) printf ("radimin %.1f\n", dradi*60.0); } else { printf ("dramin %.1f\n", dra*60.0* cosdeg (cdec)); printf ("ddecmin %.1f\n", ddec*60.0); } printf ("radecsys %s\n", cstr); printf ("equinox %.3f\n", eqout); printf ("epoch %.3f\n", epout); printf ("program scat %s\n", revmessage); CatID (catid, refcat); printf ("%s ra dec ", catid); printf ("magv class band n arcmin\n"); printf ("--------- ------------ ------------ "); printf ("----- ----- ---- - ------\n"); } /* Loop through region list */ for (ireg = 0; ireg < nreg; ireg++) { gscpath (refcat, rlist[ireg], inpath); /* Read size and keyword info from FITS table header */ kwn = kw; ift = fitsrtopen (inpath,&nk,&kwn,&ntable,&nbline,&nbhead); rnum = rlist[ireg]; num0 = 0; rasum = 0.0; decsum = 0.0; msum = 0.0; perrsum = 0.0; merrsum = 0.0; npos = 0; num = 0; fitsrtlset(); jstar = 0; class = 0; /* Loop through FITS table for this region */ for (itable = 0; itable <= ntable; itable++) { if (itable < ntable) { nbr = fitsrtline (ift,nbhead,ltab,table,itable,nbline,entry); if (nbr < nbline) { fprintf (stderr,"GSCREAD: %d / %d bytes read, line %d / %d, region %d\n", nbr,nbline,itable,ntable,rnum); break; } /* Extract selected fields */ /* Star number within region */ num0 = ftgeti4 (entry, &kw[0]); /* Right ascension in degrees */ ra0 = ftgetr8 (entry, &kw[1]); /* Declination in degrees */ dec0 = ftgetr8 (entry, &kw[2]); /* Position error */ perr0 = ftgetr8 (entry, &kw[3]); /* Magnitude */ mag0 = ftgetr8 (entry, &kw[4]); /* Magnitude error */ merr0 = ftgetr8 (entry, &kw[5]); /* Bandpass code */ band0 = ftgeti4 (entry, &kw[6]); /* Object class code */ class0 = ftgeti4 (entry, &kw[7]); } else num0 = 0; /* Compute mean position and magnitude for object */ if (itable > 0 && npos > 0 && ((classd < -1 && band != band0) || (classd < -1 && class != class0) || num != num0)) { pass = 1; if (perrsum == 0.0 || merrsum == 0) pass = 0; else { ra = rasum / perrsum; dec = decsum / perrsum; mag = msum / merrsum; } if (pass > 0 && classd > -1 && class != classd) pass = 0; /* Check magnitude and position limits */ if (pass > 0 && mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; if (pass) { wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); /* Compute distance from search center */ if (drad > 0 || distsort) dist = wcsdist (cra,cdec,ra,dec); else dist = 0.0; /* Check position limits */ if (drad > 0) { if (dist > drad) pass = 0; if (dradi > 0.0 && dist < dradi) pass = 0; } else { ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } } if (pass) { class = class + (band * 100) + (npos * 10000); xnum = (double)rnum + (0.0001 * (double) num); /* Write star position and magnitudes to stdout */ if (nstarmax < 1) { CatNum (refcat, -9, 0, xnum, numstr); ra2str (rastr, 31, ra, 3); dec2str (decstr, 31, dec, 2); dist = wcsdist (cra,cdec,ra,dec) * 60.0; printf ("%s %s %s", numstr,rastr,decstr); printf (" %.2f %d %d %d %.2f\n", mag, class-(band*100)-(npos*10000), band, npos, dist); } /* Save star position in table */ else if (nstar < nstarmax) { gnum[nstar] = xnum; gra[nstar] = ra; gdec[nstar] = dec; gmag[0][nstar] = mag; gtype[nstar] = class; gdist[nstar] = dist; if (dist > maxdist) { maxdist = dist; farstar = nstar; } if (mag > faintmag) { faintmag = mag; faintstar = nstar; } } /* If too many stars and distance sorting, replace furthest star */ else if (distsort) { if (dist < maxdist) { gnum[farstar] = xnum; gra[farstar] = ra; gdec[farstar] = dec; gmag[0][farstar] = mag; gtype[farstar] = class; gdist[farstar] = dist; maxdist = 0.0; /* Find new farthest star */ for (i = 0; i < nstarmax; i++) { if (gdist[i] > maxdist) { maxdist = gdist[i]; farstar = i; } } } } /* If too many stars, replace faintest star */ else if (mag < faintmag) { gnum[faintstar] = xnum; gra[faintstar] = ra; gdec[faintstar] = dec; gmag[0][faintstar] = mag; gtype[faintstar] = class; gdist[faintstar] = dist; faintmag = 0.0; /* Find new faintest star */ for (i = 0; i < nstarmax; i++) { if (gmag[0][i] > faintmag) { faintmag = gmag[0][i]; faintstar = i; } } } nstar++; jstar++; if (nlog == 1) fprintf (stderr,"GSCREAD: %04d.%04d: %9.5f %9.5f %s %5.2f %d %d\n", rnum,num,ra,dec,cstr,mag,class,npos); } /* Reset star position for averaging */ rasum = 0.0; decsum = 0.0; msum = 0.0; perrsum = 0.0; merrsum = 0.0; npos = 0; } /* Add information from current line to current object */ /* Check object class */ if ((classd > -1 && class0 == classd) || classd < -2 || (classd < 0 && class0 != 5)) { perr = perr0; perr2 = perr * perr; if (perr2 <= 0.0) perr2 = 0.01; rasum = rasum + (ra0 / perr2); decsum = decsum + (dec0 / perr2); perrsum = perrsum + (1.0 / perr2); if (merr0 <= 0.0) merr0 = 0.01; merr = merr0; merr2 = merr * merr; msum = msum + (mag0 / merr2); merrsum = merrsum + (1.0 / merr2); num = num0; class = class0; band = band0; npos++; } /* Log operation */ if (nlog > 0 && itable%nlog == 0) fprintf (stderr,"GSCREAD: %4d / %4d: %5d / %5d / %5d sources, region %4d.%04d\r", ireg,nreg,jstar,itable,ntable,rlist[ireg],num0); /* End of region */ } /* Close region input file */ (void) close (ift); itot = itot + itable; if (nlog > 0) fprintf (stderr,"GSCREAD: %4d / %4d: %5d / %5d / %5d sources from region %4d \n", ireg+1,nreg,jstar,itable,ntable,rlist[ireg]); } /* Close output file and summarize transfer */ if (nlog > 0) { if (nreg > 1) fprintf (stderr,"GSCREAD: %d regions: %d / %d found\n",nreg,nstar,itot); else fprintf (stderr,"GSCREAD: 1 region: %d / %d found\n",nstar,itable); if (nstar > nstarmax ) fprintf (stderr,"GSCREAD: %d stars found; only %d returned\n", nstar,nstarmax); } return (nstar); } /* GSCRNUM -- Read HST Guide Star Catalog stars from CDROM */ int gscrnum (refcat, nstars, sysout, eqout, epout, gnum,gra,gdec,gmag,gtype,nlog) int refcat; /* Catalog code (GSC or GSCACT) */ int nstars; /* Number of stars to find */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double *gnum; /* Array of Guide Star numbers (returned) */ double *gra; /* Array of right ascensions (returned) */ double *gdec; /* Array of declinations (returned) */ double **gmag; /* Array of magnitudes (returned) */ int *gtype; /* Array of object types (returned) */ int nlog; /* 1 for diagnostics */ { char *table; /* FITS table */ char inpath[64]; /* Pathname for input FITS table file */ char entry[100]; /* Buffer for FITS table row */ int class; /* Object class (0>star, 3>other) */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ struct Keyword kw[8]; /* Keyword structure */ struct Keyword *kwn; int rnum, num0, num, itot; int ik,nk,itable,ntable,jstar; int nbline,npos,nbhead; int nbr,nstar,i, snum; int ift; double dnum; double ra,rasum,dec,decsum,perr,perr2,perrsum,msum; double mag,merr,merr2,merrsum; int band0 = 0; int band = 0; int class0 = 0; double merr0 = 0.0; double mag0 = 0.0; double perr0 = 0.0; double ra0 = 0.0; double dec0 = 0.0; char *str; char *url; itot = 0; /* If root pathname is a URL, search and return */ url = cdn; if (refcat == GSC) { url = cdn; if ((str = getenv("GSC_NORTH")) == NULL) str = getenv ("GSC_PATH"); if (str != NULL) url = str; if (!strncmp (url, "http:",5)) return (webrnum (str,"gsc",nstars,sysout,eqout,epout,1, gnum,gra,gdec,NULL,NULL,gmag,gtype,nlog)); } if (refcat == GSCACT) { url = cdna; if ((str = getenv("GSCACT_NORTH")) == NULL) str = getenv ("GSCACT_PATH"); if (str != NULL) url = str; } if (!strncmp (url, "http:",5)) return (webrnum (str,"gsc",nstars,sysout,eqout,epout,1, gnum,gra,gdec,NULL,NULL,gmag,gtype,nlog)); if (ltab < 1) { ltab = 10000; table = (char *)calloc (ltab, sizeof (char)); } for (i = 0; i < 100; i++) entry[i] = 0; /* Set path to Guide Star Catalog */ if ((str = getenv("GSC_NORTH")) != NULL ) strcpy (cdn,str); if ((str = getenv("GSC_SOUTH")) != NULL ) strcpy (cds,str); /* Set keyword list */ nk = 8; strcpy (kw[0].kname,"GSC_ID"); strcpy (kw[1].kname,"RA_DEG"); strcpy (kw[2].kname,"DEC_DEG"); strcpy (kw[3].kname,"POS_ERR"); strcpy (kw[4].kname,"MAG"); strcpy (kw[5].kname,"MAG_ERR"); strcpy (kw[6].kname,"MAG_BAND"); strcpy (kw[7].kname,"CLASS"); for (ik = 0; ik < nk; ik++) { kw[ik].lname = (int) strlen (kw[ik].kname); kw[ik].kn = 0; kw[ik].kf = 0; kw[ik].kl = 0; } nstar = 0; /* Loop through star list */ for (jstar = 0; jstar < nstars; jstar++) { rnum = (int) gnum[jstar]; gscpath (refcat, rnum, inpath); dnum = (gnum[jstar] - (double)rnum) * 10000.0; snum = (int) (dnum + 0.5); /* Read size and keyword info from FITS table header */ kwn = kw; ift = fitsrtopen (inpath,&nk,&kwn,&ntable,&nbline,&nbhead); if (ift < 0) { fprintf (stderr,"GSCRNUM: File %s not found\n",inpath); return (0); } num0 = 0; rasum = 0.0; decsum = 0.0; msum = 0.0; perrsum = 0.0; merrsum = 0.0; npos = 0; num = 0; fitsrtlset(); class = 0; /* Loop through FITS table for this region */ for (itable = 0; itable <= ntable; itable++) { if (itable < ntable) { nbr = fitsrtline (ift,nbhead,ltab,table,itable,nbline,entry); if (nbr < nbline) { fprintf (stderr,"GSCRNUM: %d / %d bytes read, line %d / %d, region %d\n", nbr,nbline,itable,ntable,rnum); break; } /* Extract selected fields */ /* Star number within region */ num0 = ftgeti4 (entry, &kw[0]); if (num0 < snum) continue; else if (num == 0) num = num0; /* Right ascension in degrees */ ra0 = ftgetr8 (entry, &kw[1]); /* Declination in degrees */ dec0 = ftgetr8 (entry, &kw[2]); /* Position error */ perr0 = ftgetr8 (entry, &kw[3]); /* Magnitude */ mag0 = ftgetr8 (entry, &kw[4]); /* Magnitude error */ merr0 = ftgetr8 (entry, &kw[5]); /* Bandpass code */ band0 = ftgeti4 (entry, &kw[6]); /* Object class code */ class0 = ftgeti4 (entry, &kw[7]); } else num0 = 0; /* Compute mean position and magnitude for object */ if (num != num0 && itable > 0 && npos > 0) { ra = rasum / perrsum; dec = decsum / perrsum; wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); mag = msum / merrsum; class = class + (band * 100) + (npos * 10000); /* Save star position in table */ gra[nstar] = ra; gdec[nstar] = dec; gmag[0][nstar] = mag; gtype[nstar] = class; nstar++; if (nlog == 1) fprintf (stderr,"GSCRNUM: %04d.%04d: %9.5f %9.5f %5.2f %d %d\n", rnum,num,ra,dec,mag,class,npos); /* Reset star position for averaging */ rasum = 0.0; decsum = 0.0; msum = 0.0; perrsum = 0.0; merrsum = 0.0; npos = 0; break; } /* Add information from current line to current object */ perr = perr0; perr2 = perr * perr; if (perr2 <= 0.0) perr2 = 0.01; rasum = rasum + (ra0 / perr2); decsum = decsum + (dec0 / perr2); perrsum = perrsum + (1.0 / perr2); if (merr0 <= 0.0) merr0 = 0.01; merr = merr0; merr2 = merr * merr; msum = msum + (mag0 / merr2); merrsum = merrsum + (1.0 / merr2); num = num0; class = class0; band = band0; npos = npos + 1; /* Log operation */ if (nlog > 0 && itable%nlog == 0) fprintf (stderr,"GSCRNUM: %4d / %4d: %5d / %5d sources, region %4d.%04d\r", jstar+1,nstars,itable,ntable,rnum,snum); /* End of region */ } /* Close region input file */ (void) close (ift); itot = itot + itable; if (nlog > 0) fprintf (stderr,"GSCRNUM: %4d / %4d: %5d / %5d sources, region %4d.%04d\n", jstar+1,nstars,itable,ntable,rnum,snum); } return (nstars); } /* GSCBIN -- Fill FITS WCS image with HST Guide Star Catalog objects */ int gscbin (refcat, wcs, header, image, mag1, mag2, magscale, nlog) int refcat; /* Catalog code (GSC or GSCACT) */ struct WorldCoor *wcs; /* World coordinate system for image */ char *header; /* FITS header for output image */ char *image; /* Output FITS image */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ double magscale; /* Scaling factor for magnitude to pixel flux * (number of catalog objects per bin if 0) */ int nlog; /* 1 for diagnostics */ { double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ int sysout = wcs->syswcs; /* Image coordinate system */ double eqout = wcs->equinox; /* Image coordinate equinox */ double epout = wcs->epoch; /* Image epoch */ double ra1,ra2; /* Limiting right ascensions of image in degrees */ double dec1,dec2; /* Limiting declinations of image in degrees */ int nreg; /* Number of input FITS tables files */ double xnum; /* Guide Star number */ int rlist[100]; /* List of input FITS tables files */ char inpath[64]; /* Pathname for input FITS table file */ char entry[100]; /* Buffer for FITS table row */ int class, class0; /* Object class (0>star, 3>other) */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ struct Keyword kw[8]; /* Keyword structure */ struct Keyword *kwn; int verbose; int pass; int wrap; int rnum, num0, num, itot,ireg; int ik,nk,itable,ntable,jstar; int nbline,npos,nbhead; int nbr,nrmax,nstar,i; int ift, band0, band; double ra,ra0,rasum,dec,dec0,decsum,perr,perr0,perr2,perrsum,msum; double mag,mag0,merr,merr0,merr2,merrsum; double rra1, rra2, rdec1, rdec2; double rdist, ddist; char *str; char cstr[32]; int bitpix, w, h; /* Image bits/pixel and pixel width and height */ double logt = log(10.0); double xpix, ypix, flux; int ix, iy; int offscl; itot = 0; if (nlog == 1) verbose = 1; else verbose = 0; verbose = nlog; /* Set image parameters */ bitpix = 0; (void)hgeti4 (header, "BITPIX", &bitpix); w = 0; (void)hgeti4 (header, "NAXIS1", &w); h = 0; (void)hgeti4 (header, "NAXIS2", &h); if (refcat == GSCACT) { if ((str = getenv("GSCACT_NORTH")) == NULL) str = getenv ("GSCACT_PATH"); } /* Allocate FITS table buffer which is saved between calls */ if (ltab < 1) { ltab = 10000; table = (char *)calloc (ltab, sizeof (char)); if (table == NULL) { fprintf (stderr, "GSCBIN: cannot allocate FITS table buffer\n"); return (0); } } for (i = 0; i < 100; i++) entry[i] = 0; /* Set path to Guide Star Catalog */ if (refcat == GSCACT) { if ((str = getenv("GSCACT_NORTH")) != NULL ) strcpy (cdna,str); if ((str = getenv("GSCACT_SOUTH")) != NULL ) strcpy (cdsa,str); } else { if ((str = getenv("GSC_NORTH")) != NULL ) strcpy (cdn,str); if ((str = getenv("GSC_SOUTH")) != NULL ) strcpy (cds,str); } wcscstr (cstr, sysout, eqout, epout); wcssize (wcs, &cra, &cdec, &dra, &ddec); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* Make mag1 always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } /* Find Guide Star Catalog regions in which to search */ nrmax = 100; rra1 = ra1; rra2 = ra2; rdec1 = dec1; rdec2 = dec2; RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epout,0.0, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); nreg = gscreg (refcat,rra1,rra2,rdec1,rdec2,table,nrmax,rlist,verbose); if (nreg <= 0) { fprintf (stderr,"GSCBIN: no Guide Star regions found\n"); return (0); } /* Set keyword list */ nk = 8; strcpy (kw[0].kname,"GSC_ID"); strcpy (kw[1].kname,"RA_DEG"); strcpy (kw[2].kname,"DEC_DEG"); strcpy (kw[3].kname,"POS_ERR"); strcpy (kw[4].kname,"MAG"); strcpy (kw[5].kname,"MAG_ERR"); strcpy (kw[6].kname,"MAG_BAND"); strcpy (kw[7].kname,"CLASS"); for (ik = 0; ik < nk; ik++) { kw[ik].lname = (int) strlen (kw[ik].kname); kw[ik].kn = 0; kw[ik].kf = 0; kw[ik].kl = 0; } nstar = 0; /* Loop through region list */ for (ireg = 0; ireg < nreg; ireg++) { gscpath (refcat, rlist[ireg], inpath); /* Read size and keyword info from FITS table header */ kwn = kw; ift = fitsrtopen (inpath,&nk,&kwn,&ntable,&nbline,&nbhead); rnum = rlist[ireg]; num0 = 0; rasum = 0.0; decsum = 0.0; msum = 0.0; perrsum = 0.0; merrsum = 0.0; npos = 0; num = 0; fitsrtlset(); jstar = 0; class = 0; /* Loop through FITS table for this region */ for (itable = 0; itable <= ntable; itable++) { if (itable < ntable) { nbr = fitsrtline (ift,nbhead,ltab,table,itable,nbline,entry); if (nbr < nbline) { fprintf (stderr,"GSCBIN: %d / %d bytes read, line %d / %d, region %d\n", nbr,nbline,itable,ntable,rnum); break; } /* Extract selected fields */ /* Star number within region */ num0 = ftgeti4 (entry, &kw[0]); /* Right ascension in degrees */ ra0 = ftgetr8 (entry, &kw[1]); /* Declination in degrees */ dec0 = ftgetr8 (entry, &kw[2]); /* Position error */ perr0 = ftgetr8 (entry, &kw[3]); /* Magnitude */ mag0 = ftgetr8 (entry, &kw[4]); /* Magnitude error */ merr0 = ftgetr8 (entry, &kw[5]); /* Bandpass code */ band0 = ftgeti4 (entry, &kw[6]); /* Object class code */ class0 = ftgeti4 (entry, &kw[7]); } else num0 = 0; /* Compute mean position and magnitude for object */ if (itable > 0 && npos > 0 && ((classd < -1 && band != band0) || (classd < -1 && class != class0) || num != num0)) { pass = 1; if (perrsum == 0.0 || merrsum == 0) pass = 0; else { ra = rasum / perrsum; dec = decsum / perrsum; mag = msum / merrsum; } if (pass > 0 && classd > -1 && class != classd) pass = 0; /* Check magnitude and position limits */ if (pass > 0 && mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; if (pass) { wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); /* Check position limits */ ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } /* Save star in FITS image */ if (pass) { class = class + (band * 100) + (npos * 10000); xnum = (double)rnum + (0.0001 * (double) num); wcs2pix (wcs, ra, dec, &xpix, &ypix, &offscl); if (!offscl) { if (magscale > 0.0) flux = magscale * exp (logt * (-mag / 2.5)); else flux = 1.0; ix = (int) (xpix + 0.5); iy = (int) (ypix + 0.5); addpix1 (image, bitpix, w,h, 0.0,1.0, xpix,ypix, flux); nstar++; jstar++; } else { ix = 0; iy = 0; } if (nlog == 1) { fprintf (stderr,"GSCBIN: %04d.%04d: %9.5f %9.5f %s %d %d", rnum, num, ra, dec, cstr, class, npos); if (magscale > 0.0) fprintf (stderr, " %5.2f", mag); if (!offscl) flux = getpix1 (image, bitpix, w, h, 0.0, 1.0, ix, iy); else flux = 0.0; fprintf (stderr," (%d,%d): %f\n", ix, iy, flux); } } /* Reset star position for averaging */ rasum = 0.0; decsum = 0.0; msum = 0.0; perrsum = 0.0; merrsum = 0.0; npos = 0; } /* Add information from current line to current object */ /* Check object class */ if ((classd > -1 && class0 == classd) || classd < -2 || (classd < 0 && class0 != 5)) { perr = perr0; perr2 = perr * perr; if (perr2 <= 0.0) perr2 = 0.01; rasum = rasum + (ra0 / perr2); decsum = decsum + (dec0 / perr2); perrsum = perrsum + (1.0 / perr2); if (merr0 <= 0.0) merr0 = 0.01; merr = merr0; merr2 = merr * merr; msum = msum + (mag0 / merr2); merrsum = merrsum + (1.0 / merr2); num = num0; class = class0; band = band0; npos++; } /* Log operation */ if (nlog > 0 && itable%nlog == 0) fprintf (stderr,"GSCBIN: %4d / %4d: %5d / %5d / %5d sources, region %4d.%04d\r", ireg,nreg,jstar,itable,ntable,rlist[ireg],num0); /* End of region */ } /* Close region input file */ (void) close (ift); itot = itot + itable; if (nlog > 0) fprintf (stderr,"GSCBIN: %4d / %4d: %5d / %5d / %5d sources from region %4d \n", ireg+1,nreg,jstar,itable,ntable,rlist[ireg]); } /* Close output file and summarize transfer */ if (nlog > 0) { if (nreg > 1) fprintf (stderr,"GSCBIN: %d regions: %d / %d found\n",nreg,nstar,itot); else fprintf (stderr,"GSCBIN: 1 region: %d / %d found\n",nstar,itable); } return (nstar); } /* First region in each declination zone */ int zreg1[24]={1,594,1178,1729,2259,2781,3246,3652,4014,4294, 4492,4615, 4663,5260,5838,6412,6989,7523,8022,8464,8840,9134,9346,9490}; /* Last region in each declination zone */ int zreg2[24]={593,1177,1728,2258,2780,3245,3651,4013,4293,4491,4614,4662, 5259,5837,6411,6988,7522,8021,8463,8839,9133,9345,9489,9537}; /* Directory for each declination zone */ char zdir[24][8]={"n0000","n0730","n1500","n2230","n3000","n3730","n4500", "n5230","n6000","n6730","n7500","n8230","s0000","s0730", "s1500","s2230","s3000","s3730","s4500","s5230","s6000", "s6730","s7500","s8230"}; static struct Keyword rkw[15]; static int nrkw = 13; /* GSCREG -- search the HST Guide Star Catalog index table for fields * in the specified range of coordinates and magnitudes. Build a * list containing the pathnames of the files on the cd-rom. */ static int gscreg (refcat, ra1, ra2, dec1, dec2, table, nrmax, rgns, verbose) int refcat; /* Catalog code (GSC or GSCACT) */ double ra1, ra2; /* Right ascension limits in degrees */ double dec1, dec2; /* Declination limits in degrees */ char *table; /* Table data buffer */ int nrmax; /* Maximum number of regions to find */ int *rgns; /* Region numbers (returned)*/ int verbose; /* 1 for diagnostics */ { int nrgn; /* Number of regions found (returned) */ char tabpath[64]; /* Pathname for regions table */ int nrows; /* Number of entries in table */ int nchar; /* Number of characters per line in table */ int nwrap; /* 1 if 0h included in RA span*/ int iwrap; struct Keyword *kwn; double gscra(), gscdec(); int gsczone(); char fitsline[120]; int irow,iz1,iz2,ir1,ir2,jr1,jr2,i; int nsrch,nsrch1,nbhead,nbr; int ift; double ralow, rahi; double declow, dechi, decmin, decmax; int regnum; /* Set up keyword list for table entries to extract */ strcpy (rkw[0].kname,"REG_NO"); strcpy (rkw[1].kname,"RA_H_LOW"); strcpy (rkw[2].kname,"RA_M_LOW"); strcpy (rkw[3].kname,"RA_S_LOW"); strcpy (rkw[4].kname,"RA_H_HI"); strcpy (rkw[5].kname,"RA_M_HI"); strcpy (rkw[6].kname,"RA_S_HI"); strcpy (rkw[7].kname,"DECSI_LO"); strcpy (rkw[8].kname,"DEC_D_LO"); strcpy (rkw[9].kname,"DEC_M_LO"); strcpy (rkw[10].kname,"DECSI_HI"); strcpy (rkw[11].kname,"DEC_D_HI"); strcpy (rkw[12].kname,"DEC_M_HI"); rkw[13].kname[0] = 0; /* Add lengths of keywords to keyword structures */ for (i = 0; i < 13; i++) rkw[i].lname = strlen (rkw[i].kname); /* Initialize region list to zeroes */ for (i = 0; i < nrmax; i++) rgns[i] = 0; /* Initialize FITS table line buffer to zeroes */ for (i = 0; i < 120; i++) fitsline[i] = (char) 0; nrgn = 0; /* Set pathnames to Guide Star Catalog CDROM */ if (refcat == GSCACT) strcpy (tabpath,cdna); else strcpy (tabpath,cdn); /* Set pathname for region table file */ strcat (tabpath,"/tables/regions.tbl"); /* Open the index table */ kwn = rkw; ift = fitsrtopen (tabpath,&nrkw,&kwn, &nrows, &nchar, &nbhead); /* If the northern hemisphere CDROM cannot be read, try the southern */ if (ift < 0) { if (refcat == GSCACT) strcpy (tabpath,cdsa); else strcpy (tabpath,cds); strcat (tabpath,"/tables/regions.tbl"); ift = fitsrtopen (tabpath,&nrkw,&kwn,&nchar,&nrows,&nbhead); if (ift < 0) { fprintf (stderr,"GSCREG: error reading region table %s\n",tabpath); return (0); } } /* Find region range to search based on declination */ iz1 = gsczone (dec1); iz2 = gsczone (dec2); jr1 = 0; jr2 = 0; nwrap = 1; /* Search region northern hemisphere or only one region */ if (iz2 >= iz1) { ir1 = zreg1[iz1]; ir2 = zreg2[iz2]; } /* Search region in southern hemisphere with multiple regions */ else if (dec1 < 0 && dec2 < 0) { ir1 = zreg1[iz2]; ir2 = zreg2[iz1]; } /* Search region spans equator */ else if (dec1 < 0 && dec2 >= 0) { ir1 = zreg1[12]; ir2 = zreg2[iz1]; jr1 = zreg1[0]; jr2 = zreg2[iz2]; nwrap = 2; } else { ir1 = 1; ir2 = 0; } nsrch = ir2 - ir1 + 1; if (verbose) fprintf (stderr,"GSCREG: searching %d regions: %d - %d\n",nsrch,ir1,ir2); if (jr1 > 0) { nsrch1 = jr2 - jr1 + 1; if (verbose) fprintf (stderr,"GSCREG: searching %d regions: %d - %d\n",nsrch1,jr1,jr2); } if (verbose) fprintf(stderr,"GSCREG: RA: %.5f - %.5f, Dec: %.5f - %.5f\n",ra1,ra2,dec1,dec2); if (nsrch < 1) { return (0); } nrgn = 0; for (iwrap = 0; iwrap < nwrap; iwrap++) { for (irow = ir1 - 1; irow < ir2; irow++) { /* Read next line of region table */ nbr = fitsrtline (ift,nbhead,ltab,table,irow,nchar,fitsline); if (nbr < nchar) { fprintf (stderr,"GSREG: %d / %d bytes read for row %d\n",nbr,nchar,irow); break; } /* Declination range of the gs region */ /* note: southern dechi and declow are reversed */ dechi = gscdec (fitsline, 10, 11, 12); declow = gscdec (fitsline, 7, 8, 9); if (dechi > declow) { decmin = declow; decmax = dechi; } else { decmax = declow; decmin = dechi; } if (decmax >= dec1 && decmin <= dec2) { /* Right ascension range of the Guide Star Catalog region */ ralow = gscra (fitsline, 1, 2, 3); rahi = gscra (fitsline, 4, 5, 6); if (rahi <= 0.0) rahi = 360.0; /* Check RA if 0h RA not between region RA limits */ if (ra1 < ra2) { if (ralow <= ra2 && rahi >= ra1) { /* Get region number from FITS table */ regnum = ftgeti4 (fitsline, &rkw[0]); if (verbose) fprintf (stderr,"GSCREG: Region %d added to search\n",regnum); /* Add this region to list, if there is space */ if (nrgn < nrmax) { rgns[nrgn] = regnum; nrgn = nrgn + 1; } } } /* Check RA if 0h RA is between region RA limits */ else { if (ralow > rahi) rahi = rahi + 360.0; if (ralow <= ra2 || rahi >= ra1) { /* Get region number from FITS table */ regnum = ftgeti4 (fitsline, &rkw[0]); if (verbose) fprintf (stderr,"GSCREG: Region %d added to search\n",regnum); /* Add this region to list, if there is space */ if (nrgn < nrmax) { rgns[nrgn] = regnum; nrgn = nrgn + 1; } } } } } /* Handle wrap-around through the equator */ ir1 = jr1; ir2 = jr2; jr1 = 0; jr2 = 0; } (void) close (ift); return (nrgn); } /* GSCRA -- returns right ascension in degrees from the GSC index table * This is converted from the hours, minutes, and seconds columns. */ double gscra (fitsline, hcol, mcol, scol) char *fitsline; /* Index table line */ int hcol; /* Column index for hours */ int mcol; /* Column index for minutes */ int scol; /* Column index for seconds */ { double ra; /* Right ascension in fractional degrees */ double hrs; /* Hours of right ascension */ double min; /* Minutes of right ascension */ double sec; /* Seconds of right ascension */ /* hours of right ascension */ hrs = ftgetr8 (fitsline, &rkw[hcol]); /* minutes of right ascension */ min = ftgetr8 (fitsline, &rkw[mcol]); /* seconds of right ascension */ sec = ftgetr8 (fitsline, &rkw[scol]); /* right ascension in degrees */ ra = hrs + (min / 60.0) + (sec / 3600.0); ra = ra * 15.0; return (ra); } /* GSCDEC -- returns the declination in degrees from the GSC index table. * This is converted from the sign, degrees, minutes, and seconds columns. */ double gscdec (fitsline, sgncol, dcol, mcol) char *fitsline; /* Index table line */ int sgncol; /* Column index for sign */ int dcol; /* Column index for degrees */ int mcol; /* Column index for minutes */ { double dec; /* Declination in fractional degrees */ char sgn[4]; /* Sign of declination */ double deg; /* Degrees of declination*/ double min; /* Minutes of declination */ /* Get declination sign from table */ (void) ftgetc (fitsline, &rkw[sgncol], sgn, 3); /* Get degrees of declination from table */ deg = ftgetr8 (fitsline, &rkw[dcol]); /* Get minutes of declination from table */ min = ftgetr8 (fitsline, &rkw[mcol]); dec = deg + (min / 60.0); /* Negative declination */ if (strchr (sgn, '-') != NULL) dec = -dec; return (dec); } /* GSCZONE -- find the zone number where a declination can be found */ int gsczone (dec) double dec; /* declination in degrees */ { int zone; /* gsc zone (returned) */ double zonesize; int ndeczones = 12; /* number of declination zones per hemisphere */ /* Width of declination zones */ zonesize = 90.0 / ndeczones; zone = ((int) (dec / zonesize)); if (dec < 0) zone = ndeczones - zone; return (zone); } /* GSCPATH -- Get HST Guide Star Catalog region FITS file pathname */ static void gscpath (refcat, regnum, path) int refcat; /* Catalog code (GSC or GSCACT) */ int regnum; /* Guide Star Catalog region number */ char *path; /* Pathname of GSC region FITS file */ { int zone = 0; /* Name of Guide Star Catalog zone directory */ int i; /* Get zone directory name given region number */ for (i = 0; i < 24; i++) { if (regnum >= zreg1[i] && regnum <= zreg2[i]) { zone = i; break; } } /* Set the pathname using the appropriate GSC CDROM directory */ /* Northern hemisphere disk (volume 1) */ if (regnum < zreg1[13]) { if (refcat == GSCACT) sprintf (path,"%s/%s/%04d.gsc", cdna, zdir[zone], regnum); else sprintf (path,"%s/gsc/%s/%04d.gsc", cdn, zdir[zone], regnum); } /* Southern hemisphere disk (volume 2) */ else { if (refcat == GSCACT) sprintf (path,"%s/%s/%04d.gsc", cdsa, zdir[zone], regnum); else sprintf (path,"%s/gsc/%s/%04d.gsc", cds, zdir[zone], regnum); } return; } /* Feb 16 1996 New program * May 14 1996 Change arguments to FITSRTOPEN * May 17 1996 Fix bug so equal magnitude limits accepts anything * May 17 1996 Use new FITSRTOPEN which internalizes FITS header * May 24 1996 Fix string decoding bug and region search * May 31 1996 Use stream I/O * Jun 10 1996 Remove unused variables after using lint * Jul 1 1996 Fix GSC pathname * Aug 6 1996 Minor changes after lint * Sep 17 1996 Fix bug causing incomplete region access; improve logging * Oct 17 1996 Change FITS table entry calls * Nov 13 1996 Return no more than maximum star number * Nov 13 1996 Write all error messages to stderr with subroutine names * Nov 15 1996 Implement search radius; change input arguments * Dec 12 1996 Make logging run on single line per region * Dec 17 1996 Add code to keep brightest or closest stars if too many found * Dec 18 1996 Add code to get star information by number * * Mar 20 1997 Remove unused variables and fixed logging in GSCRNUM after lint * Oct 10 1997 Use standard I/O instead of stream I/O when reading FITS files * Nov 6 1997 Do not print overrun unless logging * * May 13 1998 Do not set classd in gscread() * May 13 1998 Print all stars if classd is < -1 * May 27 1998 Include fitsio.h instead of fitshead.h * Jun 24 1998 Add string lengths to ra2str() and dec2str() calls * Aug 6 1998 Change fitsio.h to fitsfile.h * Sep 16 1998 Use limiting radius, if present * Sep 22 1998 Convert to desired output coordinate system * Oct 26 1998 Fix bug in region selection * Oct 29 1998 Correctly assign numbers when too many stars are found * * May 25 1999 Allocate table buffer only once * Jun 16 1999 Use SearchLim() * Aug 16 1999 Add RefLim() to get converted search coordinates right * Aug 16 1999 Fix bug to fix failure to search across 0:00 RA * Aug 25 1999 Return real number of stars from gscread() * Sep 10 1999 Set class selection with subroutine, not argument * Sep 16 1999 Fix bug which didn't always return closest stars * Sep 16 1999 Add distsort argument so brightest stars in circle works, too * Sep 22 1999 Rewrite table allocation so it works; make ltab static * Oct 21 1999 Include wcscat.h, unistd.h * * Mar 27 2000 Drop unused variables after lint * Mar 28 2000 Make default to read all classes * Jun 26 2000 Add coordinate system to SearchLim() arguments * Nov 29 2000 Add option to read cataog across the web * Dec 11 2000 Allow search engine URL in cdn[] * Dec 12 2000 Fix wrong web subroutine in gscrnum() * * Apr 24 2001 Add bandpass code and number of entries to object class * Apr 24 2001 Return individual entries if class is < -1 * May 23 2001 Add support for GSC-ACT * May 30 2001 Use GSC_NORTH and GSCACT_NORTH instead of *_PATH for consistency * Jun 27 2001 Print stars as found in gscread() if nstarmax < 1 * Jun 27 2001 Allocate distance array only if larger one is needed * Jun 27 2001 Add gscfree() to free table buffer and distance array * Sep 11 2001 Use single magnitude argument to gscread() and webread() * Sep 21 2001 Clean up web interface * Nov 20 2001 Change cos(degrad)) to cosdeg() * * Mar 28 2002 Change pathnames to /data/astrocat * Jul 31 2002 Always check for GSCACT_PATH, not GSCA_PATH * Oct 2 2002 Fix pass-through tab table header * * Mar 10 2003 Improve position limits * Apr 3 2003 Drop wrap in gscread(); add test for npos in gscread() * Apr 14 2003 Explicitly get revision date if nstarmax < 1 * Aug 22 2003 Add dradi for inner edge of annulus search * Sep 25 2003 Add gscbin() to fill an image with sources * Oct 6 2003 Update gscread() and gscbin() for improved RefLim() * Nov 18 2003 Initialize image size and bits/pixel from header in gscbin() * Dec 1 2003 Add missing tab to n=-1 header * Dec 12 2003 Fix bug in wcs2pix() call in gscbin() * * Aug 27 2004 Include math.h * * Jun 20 2006 Initialize uninitialized variables * Nov 16 2006 Fix binning * * Jan 10 2007 Add match=1 argument to webrnum() * Jan 10 2007 Rewrite web access in gscread() and gscrnum() to reduce code * * Sep 22 2009 Initialize lengths of FITS table columns * Sep 22 2009 Change region table keywords from DEC*LOW to DEC*LO */ wcstools-3.9.5/libwcs/hput.c0000664000016200001660000007720711750060473015102 0ustar minkoirsys/*** File libwcs/hput.c *** September 9, 2011 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1995-2011 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: hput.c (Put FITS Header parameter values) * Purpose: Implant values for parameters into FITS header string * Subroutine: hputi4 (hstring,keyword,ival) sets int ival * Subroutine: hputr4 (hstring,keyword,rval) sets real*4 rval * Subroutine: hputr8 (hstring,keyword,dval) sets real*8 dval * Subroutine: hputnr8 (hstring,keyword,ndec,dval) sets real*8 dval * Subroutine: hputra (hstring,keyword,lval) sets right ascension as string * Subroutine: hputdec (hstring,keyword,lval) sets declination as string * Subroutine: hputl (hstring,keyword,lval) sets logical lval * Subroutine: hputs (hstring,keyword,cval) sets character string adding '' * Subroutine: hputm (hstring,keyword,cval) sets multi-line character string * Subroutine: hputc (hstring,keyword,cval) sets character string cval * Subroutine: hdel (hstring,keyword) deletes entry for keyword keyword * Subroutine: hadd (hplace,keyword) adds entry for keyword at hplace * Subroutine: hchange (hstring,keyword1,keyword2) changes keyword for entry * Subroutine: hputcom (hstring,keyword,comment) sets comment for parameter keyword * Subroutine: ra2str (out, lstr, ra, ndec) converts RA from degrees to string * Subroutine: dec2str (out, lstr, dec, ndec) converts Dec from degrees to string * Subroutine: deg2str (out, lstr, deg, ndec) converts degrees to string * Subroutine: num2str (out, num, field, ndec) converts number to string * Subroutine: getltime () returns current local time as ISO-style string * Subroutine: getutime () returns current UT as ISO-style string */ #include #include /* NULL, strlen, strstr, strcpy */ #include #include #include #include "fitshead.h" static int verbose=0; /* Set to 1 to print error messages and other info */ static void fixnegzero(); /* HPUTI4 - Set int keyword = ival in FITS header string */ int hputi4 (hstring,keyword,ival) char *hstring; /* FITS-style header information in the format = {/ } each entry is padded with spaces to 80 characters */ const char *keyword; /* Name of the variable in header to be returned. If no line begins with this string, one is created. The first 8 characters of keyword must be unique. */ int ival; /* int number */ { char value[30]; /* Translate value from binary to ASCII */ sprintf (value,"%d",ival); /* Put value into header string */ return (hputc (hstring,keyword,value)); } /* HPUTR4 - Set float keyword = rval in FITS header string */ int hputr4 (hstring, keyword, rval) char *hstring; /* FITS header string */ const char *keyword; /* Keyword name */ const float *rval; /* float number */ { char value[30]; /* Translate value from binary to ASCII */ sprintf (value, "%f", *rval); /* Remove sign if string is -0 or extension thereof */ fixnegzero (value); /* Put value into header string */ return (hputc (hstring, keyword, value)); } /* HPUTR8 - Set double keyword = dval in FITS header string */ int hputr8 (hstring, keyword, dval) char *hstring; /* FITS header string */ const char *keyword; /* Keyword name */ const double dval; /* double number */ { char value[30]; /* Translate value from binary to ASCII */ sprintf (value, "%g", dval); /* Remove sign if string is -0 or extension thereof */ fixnegzero (value); /* Put value into header string */ return (hputc (hstring, keyword, value)); } /* HPUTNR8 - Set double keyword = dval in FITS header string */ int hputnr8 (hstring, keyword, ndec, dval) char *hstring; /* FITS header string */ const char *keyword; /* Keyword name */ const int ndec; /* Number of decimal places to print */ const double dval; /* double number */ { char value[30]; char format[8]; int i, lval; /* Translate value from binary to ASCII */ if (ndec < 0) { sprintf (format, "%%.%dg", -ndec); sprintf (value, format, dval); lval = (int) strlen (value); for (i = 0; i < lval; i++) if (value[i] == 'e') value[i] = 'E'; } else { sprintf (format, "%%.%df", ndec); sprintf (value, format, dval); } /* Remove sign if string is -0 or extension thereof */ fixnegzero (value); /* Put value into header string */ return (hputc (hstring, keyword, value)); } /* HPUTRA - Set double keyword = hh:mm:ss.sss in FITS header string */ int hputra (hstring, keyword, ra) char *hstring; /* FITS header string */ const char *keyword; /* Keyword name */ const double ra; /* Right ascension in degrees */ { char value[30]; /* Translate value from binary to ASCII */ ra2str (value, 30, ra, 3); /* Remove sign if string is -0 or extension thereof */ fixnegzero (value); /* Put value into header string */ return (hputs (hstring, keyword, value)); } /* HPUTDEC - Set double keyword = dd:mm:ss.sss in FITS header string */ int hputdec (hstring, keyword, dec) char *hstring; /* FITS header string */ const char *keyword; /* Keyword name */ const double dec; /* Declination in degrees */ { char value[30]; /* Translate value from binary to ASCII */ dec2str (value, 30, dec, 2); /* Remove sign if string is -0 or extension thereof */ fixnegzero (value); /* Put value into header string */ return (hputs (hstring, keyword, value)); } /* FIXNEGZERO -- Drop - sign from beginning of any string which is all zeros */ static void fixnegzero (string) char *string; { int i, lstr; if (string[0] != '-') return; /* Drop out if any non-zero digits in this string */ lstr = (int) strlen (string); for (i = 1; i < lstr; i++) { if (string[i] > '0' && string[i] <= '9') return; if (string[i] == 'd' || string[i] == 'e' || string[i] == ' ') break; } /* Drop - from start of string; overwrite string in place */ for (i = 1; i < lstr; i++) string[i-1] = string[i]; string[lstr-1] = (char) 0; return; } /* HPUTL - Set keyword = F if lval=0, else T, in FITS header string */ int hputl (hstring, keyword,lval) char *hstring; /* FITS header */ const char *keyword; /* Keyword name */ const int lval; /* logical variable (0=false, else true) */ { char value[8]; /* Translate value from binary to ASCII */ if (lval) strcpy (value, "T"); else strcpy (value, "F"); /* Put value into header string */ return (hputc (hstring,keyword,value)); } /* HPUTM - Set multi-line character string in FITS header string */ /* return number of keywords written */ int hputm (hstring,keyword,cval) char *hstring; /* FITS header */ const char *keyword; /* Keyword name root (6 characters or less) */ const char *cval; /* character string containing the value for variable keyword. trailing and leading blanks are removed. */ { int lroot, lcv, i, ii, nkw, lkw, lval; int comment = 0; const char *v; char keyroot[8], newkey[12], value[80]; char squot = 39; /* If COMMENT or HISTORY, use the same keyword on every line */ lkw = (int) strlen (keyword); if (lkw == 7 && (strncmp (keyword,"COMMENT",7) == 0 || strncmp (keyword,"HISTORY",7) == 0)) { comment = 1; lroot = 0; } /* Set up keyword root, shortening it to 6 characters, if necessary */ else { comment = 0; strcpy (keyroot, keyword); lroot = (int) strlen (keyroot); if (lroot > 6) { keyroot[6] = (char) 0; lroot = 6; } } /* Write keyword value one line of up to 67 characters at a time */ ii = '1'; nkw = 0; lcv = (int) strlen (cval); if (!comment) { strcpy (newkey, keyroot); strcat (newkey, "_"); newkey[lroot+2] = (char) 0; } v = cval; while (lcv > 0) { if (lcv > 67) lval = 67; else lval = lcv; value[0] = squot; for (i = 1; i <= lval; i++) value[i] = *v++; /* Pad short strings to 8 characters */ if (lval < 8) { for (i = lval+1; i < 9; i++) value[i] = ' '; lval = 8; } value[lval+1] = squot; value[lval+2] = (char) 0; /* Add this line to the header */ if (comment) i = hputc (hstring, keyroot, value); else { newkey[lroot+1] = ii; ii++; i = hputc (hstring, newkey, value); } if (i != 0) return (i); nkw++; if (lcv > 67) lcv = lcv - 67; else break; } return (nkw); } /* HPUTS - Set character string keyword = 'cval' in FITS header string */ int hputs (hstring,keyword,cval) char *hstring; /* FITS header */ const char *keyword; /* Keyword name */ const char *cval; /* character string containing the value for variable keyword. trailing and leading blanks are removed. */ { char squot = 39; char value[80]; int lcval, i, lkeyword; /* If COMMENT or HISTORY, just add it as is */ lkeyword = (int) strlen (keyword); if (lkeyword == 7 && (strncmp (keyword,"COMMENT",7) == 0 || strncmp (keyword,"HISTORY",7) == 0)) return (hputc (hstring,keyword,cval)); /* find length of variable string */ lcval = (int) strlen (cval); if (lcval > 67) lcval = 67; /* Put single quote at start of string */ value[0] = squot; strncpy (&value[1],cval,lcval); /* If string is less than eight characters, pad it with spaces */ if (lcval < 8) { for (i = lcval; i < 8; i++) { value[i+1] = ' '; } lcval = 8; } /* Add single quote and null to end of string */ value[lcval+1] = squot; value[lcval+2] = (char) 0; /* Put value into header string */ return (hputc (hstring,keyword,value)); } /* HPUTC - Set character string keyword = value in FITS header string */ /* Return -1 if error, 0 if OK */ int hputc (hstring,keyword,value) char *hstring; const char *keyword; const char *value; /* character string containing the value for variable keyword. trailing and leading blanks are removed. */ { char squot = 39; char line[100]; char newcom[50]; char *vp, *v1, *v2, *q1, *q2, *c1, *ve; int lkeyword, lcom, lval, lc, lv1, lhead, lblank, ln, nc, i; /* Find length of keyword, value, and header */ lkeyword = (int) strlen (keyword); lval = (int) strlen (value); lhead = gethlength (hstring); /* If COMMENT or HISTORY, always add it just before the END */ if (lkeyword == 7 && (strncmp (keyword,"COMMENT",7) == 0 || strncmp (keyword,"HISTORY",7) == 0)) { /* First look for blank lines before END */ v1 = blsearch (hstring, "END"); /* Otherwise, create a space for it at the end of the header */ if (v1 == NULL) { /* Find end of header */ v1 = ksearch (hstring,"END"); /* Align pointer at start of 80-character line */ lc = v1 - hstring; ln = lc / 80; nc = ln * 80; v1 = hstring + nc; v2 = v1 + 80; /* If header length is exceeded, return error code */ if (v2 - hstring > lhead) { return (-1); } /* Move END down 80 characters */ strncpy (v2, v1, 80); } else v2 = v1 + 80; /* Insert keyword */ strncpy (v1,keyword,7); /* Pad with spaces */ for (vp = v1+lkeyword; vp < v2; vp++) *vp = ' '; if (lval > 71) lv1 = 71; else lv1 = lval; /* Insert comment */ strncpy (v1+9,value,lv1); return (0); } /* Otherwise search for keyword */ else v1 = ksearch (hstring,keyword); /* If parameter is not found, find a place to put it */ if (v1 == NULL) { /* First look for blank lines before END */ v1 = blsearch (hstring, "END"); /* Otherwise, create a space for it at the end of the header */ if (v1 == NULL) { ve = ksearch (hstring,"END"); v1 = ve; /* Align pointer at start of 80-character line */ lc = v1 - hstring; ln = lc / 80; nc = ln * 80; v1 = hstring + nc; v2 = v1 + 80; /* If header length is exceeded, return error code */ if (v2 - hstring > lhead) { return (-1); } strncpy (v2, ve, 80); } else v2 = v1 + 80; lcom = 0; newcom[0] = 0; } /* Otherwise, extract the entry for this keyword from the header */ else { /* Align pointer at start of 80-character line */ lc = v1 - hstring; ln = lc / 80; nc = ln * 80; v1 = hstring + nc; v2 = v1 + 80; strncpy (line, v1, 80); line[80] = 0; v2 = v1 + 80; /* check for quoted value */ q1 = strchr (line, squot); if (q1 != NULL) { q2 = strchr (q1+1,squot); if (q2 != NULL) c1 = strchr (q2,'/'); else c1 = strrchr (line+79,'/'); } else c1 = strchr (line,'/'); /* extract comment and discount trailing spaces */ if (c1 != NULL) { lcom = 80 - (c1 + 2 - line); strncpy (newcom, c1+2, lcom); vp = newcom + lcom - 1; while (vp-- > newcom && *vp == ' ') lcom--; } else { newcom[0] = 0; lcom = 0; } } /* Fill new entry with spaces */ for (vp = v1; vp < v2; vp++) *vp = ' '; /* Copy keyword to new entry */ strncpy (v1, keyword, lkeyword); /* Add parameter value in the appropriate place */ vp = v1 + 8; *vp = '='; vp = v1 + 9; *vp = ' '; vp = vp + 1; if (*value == squot) { strncpy (vp, value, lval); if (lval+12 > 31) lc = lval + 12; else lc = 30; } else { vp = v1 + 30 - lval; strncpy (vp, value, lval); lc = 30; } /* Add comment in the appropriate place */ if (lcom > 0) { if (lc+2+lcom > 80) lcom = 77 - lc; vp = v1 + lc; /* Jul 16 1997: was vp = v1 + lc * 2 */ *vp++ = ' '; *vp++ = '/'; *vp++ = ' '; lblank = v2 - vp; for (i = 0; i < lblank; i++) vp[i] = ' '; if (lcom > lblank) lcom = lblank; strncpy (vp, newcom, lcom); } if (verbose) { if (lcom > 0) fprintf (stderr,"HPUT: %s = %s / %s\n",keyword, value, newcom); else fprintf (stderr,"HPUT: %s = %s\n",keyword, value); } return (0); } /* HPUTCOM - Set comment for keyword or on line in FITS header string */ int hputcom (hstring,keyword,comment) char *hstring; const char *keyword; const char *comment; { char squot, slash, space; char line[100]; int lkeyword, lcom, lhead, i, lblank, ln, nc, lc; char *vp, *v1, *v2, *c0, *c1, *q1, *q2; squot = (char) 39; slash = (char) 47; space = (char) 32; /* Find length of variable name */ lkeyword = (int) strlen (keyword); lhead = gethlength (hstring); lcom = (int) strlen (comment); /* If COMMENT or HISTORY, always add it just before the END */ if (lkeyword == 7 && (strncmp (keyword,"COMMENT",7) == 0 || strncmp (keyword,"HISTORY",7) == 0)) { /* Find end of header */ v1 = ksearch (hstring,"END"); /* Align pointer at start of 80-character line */ lc = v1 - hstring; ln = lc / 80; nc = ln * 80; v1 = hstring + nc; v2 = v1 + 80; /* If header length is exceeded, return error code */ if (v2 - hstring > lhead) { return (-1); } /* Move END down 80 characters */ strncpy (v2, v1, 80); /* blank out new line and insert keyword */ for (vp = v1; vp < v2; vp++) *vp = ' '; strncpy (v1, keyword, lkeyword); c0 = v1 + lkeyword; } /* Search header string for variable name */ else { v1 = ksearch (hstring,keyword); /* If parameter is not found, return without doing anything */ if (v1 == NULL) { if (verbose) fprintf (stderr,"HPUTCOM: %s not found\n",keyword); return (-1); } /* Align pointer at start of 80-character line */ lc = v1 - hstring; ln = lc / 80; nc = ln * 80; v1 = hstring + nc; v2 = v1 + 80; /* Extract entry for this variable from the header */ strncpy (line, v1, 80); line[80] = '\0'; /* Null-terminate line before strchr call */ /* check for quoted value */ q1 = strchr (line,squot); c1 = strchr (line,slash); if (q1 != NULL) { if (c1 != NULL && q1 < c1) { q2 = strchr (q1+1, squot); if (q2 == NULL) { q2 = c1 - 1; while (*q2 == space) q2--; q2++; } else if (c1 < q2) c1 = strchr (q2, slash); } else if (c1 == NULL) { q2 = strchr (q1+1, squot); if (q2 == NULL) { q2 = line + 79; while (*q2 == space) q2--; q2++; } } else q1 = NULL; q2 = NULL; } else q2 = NULL; if (c1 != NULL) c0 = v1 + (c1 - line) - 1; else if (q2 == NULL || q2-line < 30) c0 = v1 + 30; else c0 = v1 + (q2 - line) + 1; /* allan: 1997-09-30, was c0=q2+2 */ /* If comment will not fit at all, return */ if (c0 - v1 > 77) return (-1); strncpy (c0, " / ",3); } /* Create new entry */ if (lcom > 0) { c1 = c0 + 3; lblank = v1 + 79 - c1; if (lcom > lblank) lcom = lblank; for (i = 0; i < lblank; i++) c1[i] = ' '; strncpy (c1, comment, lcom); } if (verbose) { fprintf (stderr,"HPUTCOM: %s / %s\n",keyword,comment); } return (0); } static int leaveblank = 0; /* If 1, leave blank line when deleting */ void setleaveblank (lb) int lb; { leaveblank = lb; return; } static int headshrink=1; /* Set to 1 to drop line after deleting keyword */ void setheadshrink (hsh) int hsh; {headshrink = hsh; return;} /* HDEL - Set character string keyword = value in FITS header string * returns 1 if entry deleted, else 0 */ int hdel (hstring,keyword) char *hstring; /* FITS header */ const char *keyword; /* Keyword of entry to be deleted */ { char *v, *v1, *v2, *ve; /* Search for keyword */ v1 = ksearch (hstring,keyword); /* If keyword is not found, return header unchanged */ if (v1 == NULL) { return (0); } /* Find end of header */ ve = ksearch (hstring,"END"); /* If headshrink is 0, leave END where it is */ if (!leaveblank && !headshrink) ve = ve - 80; /* Cover deleted keyword line with spaces */ if (leaveblank) { v2 = v1 + 80; for (v = ve; v < v2; v++) *v = ' '; } /* Shift rest of header up one line */ else { for (v = v1; v < ve; v = v + 80) { v2 = v + 80; strncpy (v, v2, 80); } /* Cover former last line with spaces */ v2 = ve + 80; for (v = ve; v < v2; v++) *v = ' '; } return (1); } /* HADD - Add character string keyword = value to FITS header string * returns 1 if entry added, else 0 * Call hputx() to put value into entry */ int hadd (hplace, keyword) char *hplace; /* FITS header position for new keyword */ const char *keyword; /* Keyword of entry to be deleted */ { char *v, *v1, *v2, *ve; int i, lkey; /* Find end of header */ ve = ksearch (hplace,"END"); /* If END is not found, return header unchanged */ if (ve == NULL) { return (0); } v1 = hplace; /* Shift rest of header down one line */ /* limit bug found by Paolo Montegriffo fixed 2000-04-19 */ for (v = ve; v >= v1; v = v - 80) { v2 = v + 80; strncpy (v2, v, 80); } /* Cover former first line with new keyword */ lkey = (int) strlen (keyword); strncpy (hplace, keyword, lkey); if (lkey < 8) { for (i = lkey; i < 8; i++) hplace[i] = ' '; hplace[8] = '='; } for (i = 9; i < 80; i++) hplace[i] = ' '; return (1); } /* HCHANGE - Changes keyword for entry from keyword1 to keyword2 in FITS header string * returns 1 if entry changed, else 0 */ int hchange (hstring, keyword1, keyword2) char *hstring; /* FITS header */ const char *keyword1; /* Keyword to be changed */ const char *keyword2; /* New keyword name */ { char *v, *v1; const char *v2; int lv2, i; /* Search for keyword */ v1 = ksearch (hstring,keyword1); /* If keyword is not found, return header unchanged */ if (!v1) return (0); else { lv2 = (int) strlen (keyword2); v = v1; v2 = keyword2; for (i = 0; i < 8; i++) { if (i < lv2) v[i] = v2[i]; else v[i] = ' '; } } return (1); } /* Write the right ascension ra in sexagesimal format into string*/ void ra2str (string, lstr, ra, ndec) char *string; /* Character string (returned) */ int lstr; /* Maximum number of characters in string */ double ra; /* Right ascension in degrees */ int ndec; /* Number of decimal places in seconds */ { double a,b; double seconds; char tstring[64]; int hours; int minutes; int isec, ltstr; double dsgn; /* Keep RA between 0 and 360 */ if (ra < 0.0 ) { ra = -ra; dsgn = -1.0; } else dsgn = 1.0; ra = fmod(ra, 360.0); ra *= dsgn; if (ra < 0.0) ra = ra + 360.0; a = ra / 15.0; /* Convert to hours */ hours = (int) a; /* Compute minutes */ b = (a - (double)hours) * 60.0; minutes = (int) b; /* Compute seconds */ seconds = (b - (double)minutes) * 60.0; if (ndec > 5) { if (seconds > 59.999999) { seconds = 0.0; minutes = minutes + 1; } if (minutes > 59) { minutes = 0; hours = hours + 1; } hours = hours % 24; (void) sprintf (tstring,"%02d:%02d:%09.6f",hours,minutes,seconds); } else if (ndec > 4) { if (seconds > 59.99999) { seconds = 0.0; minutes = minutes + 1; } if (minutes > 59) { minutes = 0; hours = hours + 1; } hours = hours % 24; (void) sprintf (tstring,"%02d:%02d:%08.5f",hours,minutes,seconds); } else if (ndec > 3) { if (seconds > 59.9999) { seconds = 0.0; minutes = minutes + 1; } if (minutes > 59) { minutes = 0; hours = hours + 1; } hours = hours % 24; (void) sprintf (tstring,"%02d:%02d:%07.4f",hours,minutes,seconds); } else if (ndec > 2) { if (seconds > 59.999) { seconds = 0.0; minutes = minutes + 1; } if (minutes > 59) { minutes = 0; hours = hours + 1; } hours = hours % 24; (void) sprintf (tstring,"%02d:%02d:%06.3f",hours,minutes,seconds); } else if (ndec > 1) { if (seconds > 59.99) { seconds = 0.0; minutes = minutes + 1; } if (minutes > 59) { minutes = 0; hours = hours + 1; } hours = hours % 24; (void) sprintf (tstring,"%02d:%02d:%05.2f",hours,minutes,seconds); } else if (ndec > 0) { if (seconds > 59.9) { seconds = 0.0; minutes = minutes + 1; } if (minutes > 59) { minutes = 0; hours = hours + 1; } hours = hours % 24; (void) sprintf (tstring,"%02d:%02d:%04.1f",hours,minutes,seconds); } else { isec = (int)(seconds + 0.5); if (isec > 59) { isec = 0; minutes = minutes + 1; } if (minutes > 59) { minutes = 0; hours = hours + 1; } hours = hours % 24; (void) sprintf (tstring,"%02d:%02d:%02d",hours,minutes,isec); } /* Move formatted string to returned string */ ltstr = (int) strlen (tstring); if (ltstr < lstr-1) strcpy (string, tstring); else { strncpy (string, tstring, lstr-1); string[lstr-1] = 0; } return; } /* Write the variable a in sexagesimal format into string */ void dec2str (string, lstr, dec, ndec) char *string; /* Character string (returned) */ int lstr; /* Maximum number of characters in string */ double dec; /* Declination in degrees */ int ndec; /* Number of decimal places in arcseconds */ { double a, b, dsgn, deg1; double seconds; char sign; int degrees; int minutes; int isec, ltstr; char tstring[64]; /* Keep angle between -180 and 360 degrees */ deg1 = dec; if (deg1 < 0.0 ) { deg1 = -deg1; dsgn = -1.0; } else dsgn = 1.0; deg1 = fmod(deg1, 360.0); deg1 *= dsgn; if (deg1 <= -180.0) deg1 = deg1 + 360.0; a = deg1; /* Set sign and do all the rest with a positive */ if (a < 0) { sign = '-'; a = -a; } else sign = '+'; /* Convert to degrees */ degrees = (int) a; /* Compute minutes */ b = (a - (double)degrees) * 60.0; minutes = (int) b; /* Compute seconds */ seconds = (b - (double)minutes) * 60.0; if (ndec > 5) { if (seconds > 59.999999) { seconds = 0.0; minutes = minutes + 1; } if (minutes > 59) { minutes = 0; degrees = degrees + 1; } (void) sprintf (tstring,"%c%02d:%02d:%09.6f",sign,degrees,minutes,seconds); } else if (ndec > 4) { if (seconds > 59.99999) { seconds = 0.0; minutes = minutes + 1; } if (minutes > 59) { minutes = 0; degrees = degrees + 1; } (void) sprintf (tstring,"%c%02d:%02d:%08.5f",sign,degrees,minutes,seconds); } else if (ndec > 3) { if (seconds > 59.9999) { seconds = 0.0; minutes = minutes + 1; } if (minutes > 59) { minutes = 0; degrees = degrees + 1; } (void) sprintf (tstring,"%c%02d:%02d:%07.4f",sign,degrees,minutes,seconds); } else if (ndec > 2) { if (seconds > 59.999) { seconds = 0.0; minutes = minutes + 1; } if (minutes > 59) { minutes = 0; degrees = degrees + 1; } (void) sprintf (tstring,"%c%02d:%02d:%06.3f",sign,degrees,minutes,seconds); } else if (ndec > 1) { if (seconds > 59.99) { seconds = 0.0; minutes = minutes + 1; } if (minutes > 59) { minutes = 0; degrees = degrees + 1; } (void) sprintf (tstring,"%c%02d:%02d:%05.2f",sign,degrees,minutes,seconds); } else if (ndec > 0) { if (seconds > 59.9) { seconds = 0.0; minutes = minutes + 1; } if (minutes > 59) { minutes = 0; degrees = degrees + 1; } (void) sprintf (tstring,"%c%02d:%02d:%04.1f",sign,degrees,minutes,seconds); } else { isec = (int)(seconds + 0.5); if (isec > 59) { isec = 0; minutes = minutes + 1; } if (minutes > 59) { minutes = 0; degrees = degrees + 1; } (void) sprintf (tstring,"%c%02d:%02d:%02d",sign,degrees,minutes,isec); } /* Move formatted string to returned string */ ltstr = (int) strlen (tstring); if (ltstr < lstr-1) strcpy (string, tstring); else { strncpy (string, tstring, lstr-1); string[lstr-1] = 0; } return; } /* Write the angle a in decimal format into string */ void deg2str (string, lstr, deg, ndec) char *string; /* Character string (returned) */ int lstr; /* Maximum number of characters in string */ double deg; /* Angle in degrees */ int ndec; /* Number of decimal places in degree string */ { char degform[8]; int field, ltstr; char tstring[64]; double deg1; double dsgn; /* Keep angle between -180 and 360 degrees */ deg1 = deg; if (deg1 < 0.0 ) { deg1 = -deg1; dsgn = -1.0; } else dsgn = 1.0; deg1 = fmod(deg1, 360.0); deg1 *= dsgn; if (deg1 <= -180.0) deg1 = deg1 + 360.0; /* Write angle to string, adding 4 digits to number of decimal places */ field = ndec + 4; if (ndec > 0) { sprintf (degform, "%%%d.%df", field, ndec); sprintf (tstring, degform, deg1); } else { sprintf (degform, "%%%4d", field); sprintf (tstring, degform, (int)deg1); } /* Move formatted string to returned string */ ltstr = (int) strlen (tstring); if (ltstr < lstr-1) strcpy (string, tstring); else { strncpy (string, tstring, lstr-1); string[lstr-1] = 0; } return; } /* Write the variable a in decimal format into field-character string */ void num2str (string, num, field, ndec) char *string; /* Character string (returned) */ double num; /* Number */ int field; /* Number of characters in output field (0=any) */ int ndec; /* Number of decimal places in degree string */ { char numform[8]; if (field > 0) { if (ndec > 0) { sprintf (numform, "%%%d.%df", field, ndec); sprintf (string, numform, num); } else { sprintf (numform, "%%%dd", field); sprintf (string, numform, (int)num); } } else { if (ndec > 0) { sprintf (numform, "%%.%df", ndec); sprintf (string, numform, num); } else { sprintf (string, "%d", (int)num); } } return; } /* Dec 14 1995 Original subroutines * Feb 5 1996 Added HDEL to delete keyword entry from FITS header * Feb 7 1996 Add EOS to LINE in HPUTC * Feb 21 1996 Add RA2STR and DEC2STR string routines * Jul 19 1996 Add HPUTRA and HPUTDEC * Jul 22 1996 Add HCHANGE to change keywords * Aug 5 1996 Add HPUTNR8 to save specific number of decimal places * Oct 15 1996 Fix spelling * Nov 1 1996 Add DEG2STR to set specific number of decimal places * Nov 1 1996 Allow DEC2STR to handle upt to 6 decimal places * * Mar 20 1997 Fix format error in DEG2STR * Jul 7 1997 Fix 2 errors in HPUTCOM found by Allan Brighton * Jul 16 1997 Fix error in HPUTC found by Allan Brighton * Jul 17 1997 Fix error in HPUTC found by Allan Brighton * Sep 30 1997 Fix error in HPUTCOM found by Allan Brighton * Dec 15 1997 Fix minor bugs after lint * Dec 31 1997 Always put two hour digits in RA2STR * * Feb 25 1998 Add HADD to insert keywords at specific locations * Mar 27 1998 If n is negative, write g format in HPUTNR8() * Apr 24 1998 Add NUM2STR() for easy output formatting * Apr 30 1998 Use BLSEARCH() to overwrite blank lines before END * May 27 1998 Keep Dec between -90 and +90 in DEC2STR() * May 28 1998 Keep RA between 0 and 360 in RA2STR() * Jun 2 1998 Fix bug when filling in blank lines before END * Jun 24 1998 Add string length to ra2str(), dec2str(), and deg2str() * Jun 25 1998 Make string converstion subroutines more robust * Aug 31 1998 Add getltime() and getutime() * Sep 28 1998 Null-terminate comment in HPUTCOM (Allan Brighton) * Oct 1 1998 Change clock declaration in getltime() from int (Allan Brighton) * * Jan 28 1999 Fix bug to avoid writing HISTORY or COMMENT past 80 characters * Jul 14 1999 Pad string in hputs() to minimum of 8 characters * Aug 16 1999 Keep angle between -180 and +360 in dec2str() * Oct 6 1999 Reallocate header buffer if it is too small in hputc() * Oct 14 1999 Do not reallocate header; return error if not successful * * Mar 2 2000 Do not add quotes if adding HISTORY or COMMENT with hputs() * Mar 22 2000 Move getutime() and getltime() to dateutil.c * Mar 27 2000 Add hputm() for muti-line keywords * Mar 27 2000 Fix bug testing for space to fit comment in hputcom() * Apr 19 2000 Fix bug in hadd() which overwrote line * Jun 2 2000 Dropped unused variable lv in hputm() after lint * Jul 20 2000 Drop unused variables blank and i in hputc() * * Jan 11 2001 Print all messages to stderr * Jan 18 2001 Drop declaration of blsearch(); it is in fitshead.h * * Jan 4 2002 Fix placement of comments * * Jul 1 2004 Add headshrink to optionally keep blank lines in header * Sep 3 2004 Fix bug so comments are not pushed onto next line if long value * Sep 16 2004 Add fixnegzero() to avoid putting signed zero values in header * * May 22 2006 Add option to leave blank line when deleting a keyword * Jun 15 2006 Fix comment alignment in hputc() and hputcom() * Jun 20 2006 Initialized uninitialized variables in hputm() and hputcom() * * Jan 4 2007 Declare keyword to be const * Jan 4 2007 Drop unused subroutine hputi2() * Jan 5 2007 Drop ksearch() declarations; it is now in fitshead.h * Jan 16 2007 Fix bugs in ra2str() and dec2str() so ndec=0 works * Aug 20 2007 Fix bug so comments after quoted keywords work * Aug 22 2007 If closing quote not found, make one up * * Sep 9 2011 Always initialize q2 and lroot */ wcstools-3.9.5/libwcs/iget.c0000664000016200001660000003534611750060473015050 0ustar minkoirsys/*** File libwcs/iget.c *** January 4, 2007 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1998-2007 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: iget.c (Get IRAF FITS Header parameter values) * Purpose: Extract values for variables from IRAF keyword value string * Subroutine: mgeti4 (hstring,mkey,keyword,ival) returns long integer * Subroutine: mgetr8 (hstring,mkey,keyword,dval) returns double * Subroutine: mgetstr (hstring,mkey,keyword,lstr,str) returns character string * Subroutine: igeti4 (hstring,keyword,ival) returns long integer * Subroutine: igetr4 (hstring,keyword,rval) returns real * Subroutine: igetr8 (hstring,keyword,dval) returns double * Subroutine: igets (hstring,keyword,lstr,str) returns character string * Subroutine: igetc (hstring,keyword) returns character string * Subroutine: isearch (hstring,keyword) returns pointer to header string entry */ #include /* NULL, strlen, strstr, strcpy */ #include #include "fitshead.h" /* FITS header extraction subroutines */ #include #ifndef VMS #include #else #define INT_MAX 2147483647 /* Biggest number that can fit in long */ #define SHRT_MAX 32767 #endif #define MAX_LVAL 2000 static char *isearch(); static char val[30]; /* Extract long value for variable from IRAF multiline keyword value */ int mgeti4 (hstring, mkey, keyword, ival) const char *hstring; /* Character string containing FITS or IRAF header information in the format = ... */ const char *mkey; /* Character string containing the name of the multi-line keyword, the string value of which contains the desired keyword, the value of which is returned. */ const char *keyword; /* Character string containing the name of the keyword within the multiline IRAF keyword */ int *ival; /* Integer value returned */ { char *mstring; mstring = malloc (MAX_LVAL); if (hgetm (hstring, mkey, MAX_LVAL, mstring)) { if (igeti4 (mstring, keyword, ival)) { free (mstring); return (1); } else { free (mstring); return (0); } } else { free (mstring); return (0); } } /* Extract double value for variable from IRAF multiline keyword value */ int mgetr8 (hstring, mkey, keyword, dval) const char *hstring; /* Character string containing FITS or IRAF header information in the format = ... */ const char *mkey; /* Character string containing the name of the multi-line keyword, the string value of which contains the desired keyword, the value of which is returned. */ const char *keyword; /* Character string containing the name of the keyword within the multiline IRAF keyword */ double *dval; /* Integer value returned */ { char *mstring; mstring = malloc (MAX_LVAL); if (hgetm (hstring, mkey, MAX_LVAL, mstring)) { if (igetr8 (mstring, keyword, dval)) { free (mstring); return (1); } else { free (mstring); return (0); } } else { free (mstring); return (0); } } /* Extract string value for variable from IRAF keyword value string */ int mgetstr (hstring, mkey, keyword, lstr, str) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *mkey; /* Character string containing the name of the multi-line keyword, the string value of which contains the desired keyword, the value of which is returned. */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ const int lstr; /* Size of str in characters */ char *str; /* String (returned) */ { char *mstring; mstring = malloc (MAX_LVAL); if (hgetm (hstring, mkey, MAX_LVAL, mstring)) { if (igets (mstring, keyword, lstr, str)) { free (mstring); return (1); } else { free (mstring); return (0); } } else { free (mstring); return (0); } } /* Extract long value for variable from IRAF keyword value string */ int igeti4 (hstring, keyword, ival) const char *hstring; /* character string containing IRAF header information in the format = ... */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ int *ival; /* Integer value returned */ { char *value; double dval; int minint; /* Get value from header string */ value = igetc (hstring,keyword); /* Translate value from ASCII to binary */ if (value != NULL) { minint = -INT_MAX - 1; strcpy (val, value); dval = atof (val); if (dval+0.001 > INT_MAX) *ival = INT_MAX; else if (dval >= 0) *ival = (int) (dval + 0.001); else if (dval-0.001 < minint) *ival = minint; else *ival = (int) (dval - 0.001); return (1); } else { return (0); } } /* Extract integer*2 value for variable from IRAF keyword value string */ int igeti2 (hstring,keyword,ival) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ short *ival; { char *value; double dval; int minshort; /* Get value from header string */ value = igetc (hstring,keyword); /* Translate value from ASCII to binary */ if (value != NULL) { strcpy (val, value); dval = atof (val); minshort = -SHRT_MAX - 1; if (dval+0.001 > SHRT_MAX) *ival = SHRT_MAX; else if (dval >= 0) *ival = (short) (dval + 0.001); else if (dval-0.001 < minshort) *ival = minshort; else *ival = (short) (dval - 0.001); return (1); } else { return (0); } } /* Extract real value for variable from IRAF keyword value string */ int igetr4 (hstring,keyword,rval) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ float *rval; { char *value; /* Get value from header string */ value = igetc (hstring,keyword); /* Translate value from ASCII to binary */ if (value != NULL) { strcpy (val, value); *rval = (float) atof (val); return (1); } else { return (0); } } /* Extract real*8 value for variable from IRAF keyword value string */ int igetr8 (hstring,keyword,dval) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ double *dval; { char *value,val[30]; /* Get value from header string */ value = igetc (hstring,keyword); /* Translate value from ASCII to binary */ if (value != NULL) { strcpy (val, value); *dval = atof (val); return (1); } else { return (0); } } /* Extract string value for variable from IRAF keyword value string */ int igets (hstring, keyword, lstr, str) const char *hstring; /* character string containing FITS header information in the format = {/ } */ const char *keyword; /* character string containing the name of the keyword the value of which is returned. hget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ const int lstr; /* Size of str in characters */ char *str; /* String (returned) */ { char *value; int lval; /* Get value from header string */ value = igetc (hstring,keyword); if (value != NULL) { lval = strlen (value); if (lval < lstr) strcpy (str, value); else if (lstr > 1) strncpy (str, value, lstr-1); else str[0] = value[0]; return (1); } else return (0); } /* Extract character value for variable from IRAF keyword value string */ char * igetc (hstring,keyword0) const char *hstring; /* character string containing IRAF keyword value string in the format = {/ } */ const char *keyword0; /* character string containing the name of the keyword the value of which is returned. iget searches for a line beginning with this string. if "[n]" is present, the n'th token in the value is returned. (the first 8 characters must be unique) */ { static char cval[MAX_LVAL]; char *value; char cwhite[8]; char lbracket[2],rbracket[2]; char keyword[16]; char line[MAX_LVAL]; char *vpos,*cpar; char *c1, *brack1, *brack2; int ipar, i; lbracket[0] = 91; lbracket[1] = 0; rbracket[0] = 93; rbracket[1] = 0; /* Find length of variable name */ strcpy (keyword,keyword0); brack1 = strsrch (keyword,lbracket); if (brack1 != NULL) *brack1 = '\0'; /* Search header string for variable name */ vpos = isearch (hstring,keyword); /* Exit if not found */ if (vpos == NULL) { return (NULL); } /* Initialize returned value to nulls */ for (i = 0; i < MAX_LVAL; i++) line[i] = 0; /* If quoted value, copy until second quote is reached */ i = 0; if (*vpos == '"') { vpos++; while (*vpos && *vpos != '"' && i < MAX_LVAL) line[i++] = *vpos++; } /* Otherwise copy until next space or tab */ else { while (*vpos != ' ' && *vpos != (char)9 && *vpos > 0 && i < MAX_LVAL) line[i++] = *vpos++; } /* If keyword has brackets, extract appropriate token from value */ if (brack1 != NULL) { c1 = (char *) (brack1 + 1); brack2 = strsrch (c1, rbracket); if (brack2 != NULL) { *brack2 = '\0'; ipar = atoi (c1); if (ipar > 0) { cwhite[0] = ' '; cwhite[1] = ','; cwhite[2] = '\0'; cpar = strtok (line, cwhite); for (i = 1; i < ipar; i++) { cpar = strtok (NULL, cwhite); } if (cpar != NULL) { strcpy (cval,cpar); } else value = NULL; } } } else strcpy (cval, line); value = cval; return (value); } /* Find value for specified IRAF keyword */ static char * isearch (hstring,keyword) /* Find entry for keyword keyword in IRAF keyword value string hstring. NULL is returned if the keyword is not found */ const char *hstring; /* character string containing fits-style header information in the format = {/ } the default is that each entry is 80 characters long; however, lines may be of arbitrary length terminated by nulls, carriage returns or linefeeds, if packed is true. */ const char *keyword; /* character string containing the name of the variable to be returned. isearch searches for a line beginning with this string. The string may be a character literal or a character variable terminated by a null or '$'. it is truncated to 8 characters. */ { char *loc, *headnext, *headlast, *pval; int lastchar, nextchar, lkey, nleft, lhstr; /* Search header string for variable name */ lhstr = 0; while (lhstr < 57600 && hstring[lhstr] != 0) lhstr++; headlast = (char *) hstring + lhstr; headnext = (char *) hstring; pval = NULL; lkey = strlen (keyword); while (headnext < headlast) { nleft = headlast - headnext; loc = strnsrch (headnext, keyword, nleft); /* Exit if keyword is not found */ if (loc == NULL) { break; } nextchar = (int) *(loc + lkey); lastchar = (int) *(loc - 1); /* If parameter name in header is longer, keep searching */ if (nextchar != 61 && nextchar > 32 && nextchar < 127) headnext = loc + 1; /* If start of string, keep it */ else if (loc == hstring) { pval = loc; break; } /* If preceeded by a blank or tab, keep it */ else if (lastchar == 32 || lastchar == 9) { pval = loc; break; } else headnext = loc + 1; } /* Find start of value string for this keyword */ if (pval != NULL) { pval = pval + lkey; while (*pval == ' ' || *pval == '=') pval++; } /* Return pointer to calling program */ return (pval); } /* Mar 12 1998 New subroutines * Apr 15 1998 Set IGET() and ISEARCH() static when defined * Apr 24 1998 Add MGETI4(), MGETR8(), and MGETS() for single step IRAF ext. * Jun 1 1998 Add VMS patch from Harry Payne at STScI * Jul 9 1998 Fix bracket token extraction after Paul Sydney * May 5 1999 values.h -> POSIX limits.h: MAXINT->INT_MAX, MAXSHORT->SHRT_MAX * Oct 21 1999 Fix declarations after lint * * Feb 11 2000 Stop search for end of quoted keyword if more than 500 chars * Jul 20 2000 Drop unused variables squot, dquot, and slash in igetc() * * Jun 26 2002 Change maximum string length from 600 to 2000; use MAX_LVAL * Jun 26 2002 Stop search for end of quoted keyword if > MAX_LVAL chars * * Sep 23 2003 Change mgets() to mgetstr() to avoid name collision at UCO Lick * * Feb 26 2004 Make igetc() accessible from outside this file * * Jan 4 2007 Declare header, keyword to be const */ wcstools-3.9.5/libwcs/imgetwcs.c0000664000016200001660000006300112733304232015723 0ustar minkoirsys/*** File libwcs/imgetwcs.c *** June 24, 2016 *** By Jessica Mink, jmink@cfa.harvard.edu (remotely based on UIowa code) *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2016 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include #include "wcs.h" #include "lwcs.h" /* Get the C* WCS fields in a FITS header based on a reference catalog * do it by finding stars in the image and in the reference catalog and * finding the rotation and offsets which result in a best-fit. * verbose generates extra info on stderr. * try using deeper reference star catalog searches if there is trouble. * return 1 if all ok, else 0 */ /* These parameters can be set on the command line */ static double secpix0 = PSCALE; /* Set image scale--override header */ static double secpix2 = PSCALE; /* Set image scale 2--override header */ static double *cd0 = NULL; /* Set CD matrix--override header */ static double rot0 = 361.0; /* Initial image rotation */ static int comsys = WCS_J2000; /* Command line center coordinte system */ static int wp0 = 0; /* Initial width of image */ static int hp0 = 0; /* Initial height of image */ static double ra0 = -99.0; /* Initial center RA in degrees */ static double dec0 = -99.0; /* Initial center Dec in degrees */ static double xref0 = -99999.0; /* Reference pixel X coordinate */ static double yref0 = -99999.0; /* Reference pixel Y coordinate */ static int ptype0 = -1; /* Projection type to fit */ static int nctype = NWCSTYPE; /* Number of possible projections */ static char ctypes[NWCSTYPE][4]; /* 3-letter codes for projections */ static int usecdelt = 0; /* Use CDELT if 1, else CD matrix */ static char *dateobs0 = NULL; /* Initial DATE-OBS value in FITS date format */ struct WorldCoor *ChangeFITSWCS(); /* Set a nominal world coordinate system from image header info. * If the image center is not FK5 (J2000) equinox, convert it * Return a WCS structure if OK, else return NULL */ struct WorldCoor * GetFITSWCS (filename, header, verbose, cra, cdec, dra, ddec, secpix, wp, hp, sysout, eqout) char *filename; /* FITS or IRAF file name */ char *header; /* Image FITS header */ int verbose; /* Extra printing if =1 */ double *cra; /* Center right ascension in degrees (returned) */ double *cdec; /* Center declination in degrees (returned) */ double *dra; /* Right ascension half-width in degrees (returned) */ double *ddec; /* Declination half-width in degrees (returned) */ double *secpix; /* Arcseconds per pixel (returned) */ int *wp; /* Image width in pixels (returned) */ int *hp; /* Image height in pixels (returned) */ int *sysout; /* Coordinate system to return (0=image, returned) */ double *eqout; /* Equinox to return (0=image, returned) */ { int naxes; double eq1, x, y; double ra1, dec1, dx, dy; double xmin, xmax, ymin, ymax, ra2, dec2, ra3, dec3, ra4, dec4; double dra0, dra1, dra2, dra3, dra4; struct WorldCoor *wcs; char rstr[64], dstr[64], cstr[16]; /* Initialize WCS structure from possibly revised FITS header */ wcs = ChangeFITSWCS (filename, header, verbose); if (wcs == NULL) { return (NULL); } *hp = (int) wcs->nypix; *wp = (int) wcs->nxpix; /* If incomplete WCS in header, drop out */ if (nowcs (wcs)) { setwcsfile (filename); /* wcserr(); */ if (verbose) fprintf (stderr,"Insufficient information for initial WCS\n"); return (NULL); } /* If in linear coordinates, do not print as sexigesimal */ if (wcs->sysout < 1 || wcs->sysout == 6 || wcs->sysout == 10) wcs->degout = 1; /* Set flag to get appropriate equinox for catalog search */ if (!*sysout) *sysout = wcs->syswcs; if (*eqout == 0.0) *eqout = wcs->equinox; eq1 = wcs->equinox; if (wcs->coorflip) { ra1 = wcs->crval[1]; dec1 = wcs->crval[0]; } else { ra1 = wcs->crval[0]; dec1 = wcs->crval[1]; } /* Print reference pixel position and value */ if (verbose && (eq1 != *eqout || wcs->syswcs != *sysout)) { if (wcs->degout) { deg2str (rstr, 32, ra1, 6); deg2str (dstr, 32, dec1, 6); } else { ra2str (rstr, 32, ra1, 3); dec2str (dstr, 32, dec1, 2); } wcscstr (cstr, wcs->syswcs, wcs->equinox, wcs->epoch); fprintf (stderr,"Reference pixel (%.2f,%.2f) %s %s %s\n", wcs->xrefpix, wcs->yrefpix, rstr, dstr, cstr); } /* Get coordinates of corners for size for catalog searching */ dx = wcs->nxpix; dy = wcs->nypix; xmin = 0.5; ymin = 0.5; xmax = 0.5 + dx; ymax = 0.5 + dy; pix2wcs (wcs, xmin, ymin, &ra1, &dec1); pix2wcs (wcs, xmin, ymax, &ra2, &dec2); pix2wcs (wcs, xmax, ymin, &ra3, &dec3); pix2wcs (wcs, xmax, ymax, &ra4, &dec4); /* Convert search corners to output coordinate system and equinox */ if (wcs->syswcs > 0 && wcs->syswcs != 6 && wcs->syswcs != 10) { wcscon (wcs->syswcs,*sysout,wcs->equinox,*eqout,&ra1,&dec1,wcs->epoch); wcscon (wcs->syswcs,*sysout,wcs->equinox,*eqout,&ra2,&dec2,wcs->epoch); wcscon (wcs->syswcs,*sysout,wcs->equinox,*eqout,&ra3,&dec3,wcs->epoch); wcscon (wcs->syswcs,*sysout,wcs->equinox,*eqout,&ra4,&dec4,wcs->epoch); } /* Find center and convert to output coordinate system and equinox */ x = 0.5 + (dx * 0.5); y = 0.5 + (dy * 0.5); pix2wcs (wcs, x, y, cra, cdec); if (wcs->syswcs > 0 && wcs->syswcs != 6 && wcs->syswcs != 10) wcscon (wcs->syswcs,*sysout,wcs->equinox,*eqout,cra,cdec,wcs->epoch); /* Find maximum half-width in declination */ *ddec = fabs (dec1 - *cdec); if (fabs (dec2 - *cdec) > *ddec) *ddec = fabs (dec2 - *cdec); if (fabs (dec3 - *cdec) > *ddec) *ddec = fabs (dec3 - *cdec); if (fabs (dec4 - *cdec) > *ddec) *ddec = fabs (dec4 - *cdec); /* Find maximum half-width in right ascension */ dra0 = (dx / dy) * (*ddec / cos (*cdec)); dra1 = ra1 - *cra; dra2 = ra2 - *cra; if (*cra < 0 && *cra + dra0 > 0.0) { dra1 = -(dra1 - 360.0); dra2 = -(dra2 - 360.0); } if (dra1 > 180.0) dra1 = dra1 - 360.0; else if (dra1 < -180.0) dra1 = dra1 + 360.0; else if (dra1 < 0.0) dra1 = -dra1; if (dra2 > 180.0) dra2 = dra2 - 360.0; else if (dra2 < -180.0) dra2 = dra2 + 360.0; else if (dra2 < 0.0) dra2 = -dra2; dra3 = *cra - ra3; dra4 = *cra - ra4; if (*cra > 0 && *cra - dra0 < 0.0) { dra3 = dra3 + 360.0; dra4 = dra4 + 360.0; } if (dra3 > 180.0) dra3 = dra3 - 360.0; else if (dra3 < -180.0) dra3 = dra3 + 360.0; else if (dra3 < 0.0) dra3 = -dra3; if (dra4 > 180.0) dra4 = dra4 - 360.0; else if (dra4 < -180.0) dra4 = dra4 + 360.0; else if (dra4 < 0.0) dra4 = -dra4; *dra = dra1; if (dra2 > *dra) *dra = dra2; if (dra3 > *dra) *dra = dra3; if (dra4 > *dra) *dra = dra4; /* wcssize (wcs, cra, cdec, dra, ddec); */ /* Set reference pixel to center of image if it has not been set */ if (wcs->xref == -999.0 && wcs->yref == -999.0) { wcs->xref = *cra; wcs->cel.ref[0] = *cra; wcs->crval[0] = *cra; wcs->yref = *cdec; wcs->cel.ref[1] = *cdec; wcs->crval[1] = *cdec; ra1 = *cra; dec1 = *cdec; if (wcs->xrefpix == 0.0 && wcs->yrefpix == 0.0) { wcs->xrefpix = 0.5 + (double) wcs->nxpix * 0.5; wcs->yrefpix = 0.5 + (double) wcs->nypix * 0.5; } wcs->xinc = *dra * 2.0 / (double) wcs->nxpix; wcs->yinc = *ddec * 2.0 / (double) wcs->nypix; /* hchange (header,"PLTRAH","PLT0RAH"); wcs->plate_fit = 0; */ } /* Convert center to desired coordinate system */ else if (wcs->syswcs != *sysout && wcs->equinox != *eqout) { wcscon (wcs->syswcs, *sysout, wcs->equinox, *eqout, &ra1, &dec1, wcs->epoch); if (wcs->coorflip) { wcs->yref = ra1; wcs->xref = dec1; } else { wcs->xref = ra1; wcs->yref = dec1; } } /* Compute plate scale to return if it was not set on the command line */ if (secpix0 <= 0.0) { pix2wcs (wcs, wcs->xrefpix-0.5, wcs->yrefpix, &ra1, &dec1); pix2wcs (wcs, wcs->xrefpix+0.5, wcs->yrefpix, &ra2, &dec2); *secpix = 3600.0 * wcsdist (ra1, dec1, ra2, dec2); } wcs->crval[0] = wcs->xref; wcs->crval[1] = wcs->yref; if (wcs->coorflip) { wcs->cel.ref[0] = wcs->crval[1]; wcs->cel.ref[1] = wcs->crval[0]; } else { wcs->cel.ref[0] = wcs->crval[0]; wcs->cel.ref[1] = wcs->crval[1]; } if (wcs->syswcs > 0 && wcs->syswcs != 6 && wcs->syswcs != 10) { wcs->cel.flag = 0; wcs->wcsl.flag = 0; } else { wcs->lin.flag = LINSET; wcs->wcsl.flag = WCSSET; } wcs->equinox = *eqout; wcs->syswcs = *sysout; wcs->sysout = *sysout; wcs->eqout = *eqout; wcs->sysin = *sysout; wcs->eqin = *eqout; wcscstr (cstr,*sysout,*eqout,wcs->epoch); strcpy (wcs->radecsys, cstr); strcpy (wcs->radecout, cstr); strcpy (wcs->radecin, cstr); wcsininit (wcs, wcs->radecsys); wcsoutinit (wcs, wcs->radecsys); naxes = wcs->naxis; if (naxes < 1 || naxes > 9) { naxes = wcs->naxes; wcs->naxis = naxes; } if (usecdelt) { hputnr8 (header, "CDELT1", 9, wcs->xinc); if (naxes > 1) { hputnr8 (header, "CDELT2", 9, wcs->yinc); hputnr8 (header, "CROTA2", 9, wcs->rot); } hdel (header, "CD1_1"); hdel (header, "CD1_2"); hdel (header, "CD2_1"); hdel (header, "CD2_2"); } else { hputnr8 (header, "CD1_1", 9, wcs->cd[0]); if (naxes > 1) { hputnr8 (header, "CD1_2", 9, wcs->cd[1]); hputnr8 (header, "CD2_1", 9, wcs->cd[2]); hputnr8 (header, "CD2_2", 9, wcs->cd[3]); } } /* Print reference pixel position and value */ if (verbose) { if (wcs->degout) { deg2str (rstr, 32, ra1, 6); deg2str (dstr, 32, dec1, 6); } else { ra2str (rstr, 32, ra1, 3); dec2str (dstr, 32, dec1, 2); } wcscstr (cstr,*sysout,*eqout,wcs->epoch); fprintf (stderr,"Reference pixel (%.2f,%.2f) %s %s %s\n", wcs->xrefpix, wcs->yrefpix, rstr, dstr, cstr); } /* Image size for catalog search */ if (verbose) { if (wcs->degout) { deg2str (rstr, 32, *cra, 6); deg2str (dstr, 32, *cdec, 6); } else { ra2str (rstr, 32, *cra, 3); dec2str (dstr, 32, *cdec, 2); } wcscstr (cstr, *sysout, *eqout, wcs->epoch); fprintf (stderr,"Search at %s %s %s", rstr, dstr, cstr); if (wcs->degout) { deg2str (rstr, 32, *dra, 6); deg2str (dstr, 32, *ddec, 6); } else { ra2str (rstr, 32, *dra, 3); dec2str (dstr, 32, *ddec, 2); } fprintf (stderr," +- %s %s\n", rstr, dstr); fprintf (stderr,"Image width=%d height=%d, %g arcsec/pixel\n", *wp, *hp, *secpix); } return (wcs); } /* ChangeFITSWCS: Modify FITS WCS header from command line values */ struct WorldCoor * ChangeFITSWCS (filename, header, verbose) char *filename; /* FITS or IRAF file name */ char *header; /* Image FITS header */ int verbose; /* Extra printing if =1 */ { int nax, i, hp, wp; double xref, yref, degpix, secpix; struct WorldCoor *wcs; char temp[16]; char *cwcs; /* Set the world coordinate system from the image header */ if (strlen (filename) > 0) { cwcs = strchr (filename, '%'); if (cwcs != NULL) cwcs++; } if (!strncmp (header, "END", 3)) { cwcs = NULL; for (i = 0; i < 2880; i++) header[i] = (char) 32; hputl (header, "SIMPLE", 1); hputi4 (header, "BITPIX", 0); hputi4 (header, "NAXIS", 2); hputi4 (header, "NAXIS1", 1); hputi4 (header, "NAXIS2", 1); } /* Set image dimensions */ nax = 0; if (hp0 > 0 || wp0 > 0) { hp = hp0; wp = wp0; if (hp > 0 && wp > 0) nax = 2; else nax = 1; hputi4 (header, "NAXIS", nax); hputi4 (header, "NAXIS1", wp); hputi4 (header, "NAXIS2", hp); } else if (hgeti4 (header,"NAXIS",&nax) < 1 || nax < 1) { if (hgeti4 (header, "WCSAXES", &nax) < 1) return (NULL); else { if (hgeti4 (header, "IMAGEW", &wp) < 1) return (NULL); if (hgeti4 (header, "IMAGEH", &hp) < 1) return (NULL); } } else { if (hgeti4 (header,"NAXIS1",&wp) < 1) return (NULL); if (hgeti4 (header,"NAXIS2",&hp) < 1) return (NULL); } /* Set plate center from command line, if it is there */ if (ra0 > -99.0 && dec0 > -99.0) { hputnr8 (header, "CRVAL1" ,8,ra0); hputnr8 (header, "CRVAL2" ,8,dec0); hputra (header, "RA", ra0); hputdec (header, "DEC", dec0); if (comsys == WCS_B1950) { hputi4 (header, "EPOCH", 1950); hputi4 (header, "EQUINOX", 1950); hputs (header, "RADECSYS", "FK4"); } else { hputi4 (header, "EPOCH", 2000); hputi4 (header, "EQUINOX", 2000); if (comsys == WCS_GALACTIC) hputs (header, "RADECSYS", "GALACTIC"); else if (comsys == WCS_ECLIPTIC) hputs (header, "RADECSYS", "ECLIPTIC"); else if (comsys == WCS_ICRS) hputs (header, "RADECSYS", "ICRS"); else hputs (header, "RADECSYS", "FK5"); } if (hgetr8 (header, "SECPIX", &secpix)) { degpix = secpix / 3600.0; hputnr8 (header, "CDELT1", 8, -degpix); hputnr8 (header, "CDELT2", 8, degpix); hdel (header, "CD1_1"); hdel (header, "CD1_2"); hdel (header, "CD2_1"); hdel (header, "CD2_2"); } } if (ptype0 > -1 && ptype0 < nctype) { strcpy (temp,"RA---"); strcat (temp, ctypes[ptype0]); hputs (header, "CTYPE1", temp); strcpy (temp,"DEC--"); strcat (temp, ctypes[ptype0]); hputs (header, "CTYPE2", temp); } /* Set reference pixel from command line, if it is there */ if (xref0 > -99999.0 && yref0 > -99999.0) { hputr8 (header, "CRPIX1", xref0); hputr8 (header, "CRPIX2", yref0); } else if (hgetr8 (header, "CRPIX1", &xref) < 1) { xref = 0.5 + (double) wp / 2.0; yref = 0.5 + (double) hp / 2.0; hputnr8 (header, "CRPIX1", 3, xref); hputnr8 (header, "CRPIX2", 3, yref); } /* Set plate scale from command line, if it is there */ if (secpix0 != 0.0 || cd0 != NULL) { if (secpix2 != 0.0) { secpix = 0.5 * (secpix0 + secpix2); hputnr8 (header, "SECPIX1", 5, secpix0); hputnr8 (header, "SECPIX2", 5, secpix2); degpix = -secpix0 / 3600.0; hputnr8 (header, "CDELT1", 8, degpix); degpix = secpix2 / 3600.0; hputnr8 (header, "CDELT2", 8, degpix); hdel (header, "CD1_1"); hdel (header, "CD1_2"); hdel (header, "CD2_1"); hdel (header, "CD2_2"); } else if (secpix0 != 0.0) { secpix = secpix0; hputnr8 (header, "SECPIX", 5, secpix); degpix = secpix / 3600.0; hputnr8 (header, "CDELT1", 8, -degpix); hputnr8 (header, "CDELT2", 8, degpix); hdel (header, "CD1_1"); hdel (header, "CD1_2"); hdel (header, "CD2_1"); hdel (header, "CD2_2"); } else { hputr8 (header, "CD1_1", cd0[0]); hputr8 (header, "CD1_2", cd0[1]); hputr8 (header, "CD2_1", cd0[2]); hputr8 (header, "CD2_2", cd0[3]); hdel (header, "CDELT1"); hdel (header, "CDELT2"); hdel (header, "CROTA1"); hdel (header, "CROTA2"); } if (!ksearch (header,"CRVAL1")) { hgetra (header, "RA", &ra0); hgetdec (header, "DEC", &dec0); hputnr8 (header, "CRVAL1", 8, ra0); hputnr8 (header, "CRVAL2", 8, dec0); } if (!ksearch (header,"CRPIX1")) { xref = (double) wp / 2.0; yref = (double) hp / 2.0; hputnr8 (header, "CRPIX1", 3, xref); hputnr8 (header, "CRPIX2", 3, yref); } if (!ksearch (header,"CTYPE1")) { if (comsys == WCS_GALACTIC) { hputs (header, "CTYPE1", "GLON-TAN"); hputs (header, "CTYPE2", "GLAT-TAN"); } else { hputs (header, "CTYPE1", "RA---TAN"); hputs (header, "CTYPE2", "DEC--TAN"); } } } /* Set rotation angle from command line, if it is there */ if (rot0 < 361.0) { hputnr8 (header, "CROTA1", 5, rot0); hputnr8 (header, "CROTA2", 5, rot0); } /* Set observation date for epoch, if it is there */ if (dateobs0 != NULL) hputs (header, "DATE-OBS", dateobs0); /* Initialize WCS structure from FITS header */ wcs = wcsinitn (header, cwcs); /* If incomplete WCS in header, drop out */ if (nowcs (wcs)) { setwcsfile (filename); /* wcserr(); */ if (verbose) fprintf (stderr,"Insufficient information for initial WCS\n"); return (NULL); } return (wcs); } void setcdelt() /* Set flag to use CDELTn, not CD matrix */ {usecdelt = 1; return;} void setnpix (nx, ny) /* Set image size */ int nx, ny; { wp0 = nx; hp0 = ny; return; } void setrot (rot) double rot; { rot0 = rot; return; } void setsecpix (secpix) /* Set first axis arcseconds per pixel */ double secpix; { secpix0 = secpix; return; } double getsecpix () /* Return first axis arcseconds per pixel */ { return (secpix0); } void setsecpix2 (secpix) /* Set second axis arcseconds per pixel */ double secpix; { secpix2 = secpix; return; } void setcd (cd) /* Set initial CD matrix */ double *cd; { int i; if (cd0 != NULL) free (cd0); cd0 = (double *) calloc (4, sizeof (double)); for (i = 0; i < 4; i++) cd0[i] = cd[i]; return; } void setsys (comsys0) /* Set WCS coordinates as FK4 */ int comsys0; { comsys = comsys0; return; } void setcenter (rastr, decstr) /* Set center sky coordinates in strings */ char *rastr, *decstr; { ra0 = str2ra (rastr); dec0 = str2dec (decstr); return; } void setdcenter (ra, dec) /* Set center sky coordinates in degrees */ double ra, dec; { ra0 = ra; dec0 = dec; return; } void getcenter (ra, dec) /* Return initial reference sky coordinates */ double *ra, *dec; { *ra = ra0; *dec = dec0; return; } void setrefpix (x, y) /* Set reference pixel image coordinates */ double x, y; { xref0 = x; yref0 = y; return; } void getrefpix (x, y) /* Return initial ref pixel image coordinates */ double *x, *y; { *x = xref0; *y = yref0; return; } void setproj (ptype) char* ptype; { int i; /* Set up array of projection types */ strcpy (ctypes[0], "LIN"); strcpy (ctypes[1], "AZP"); strcpy (ctypes[2], "SZP"); strcpy (ctypes[3], "TAN"); strcpy (ctypes[4], "SIN"); strcpy (ctypes[5], "STG"); strcpy (ctypes[6], "ARC"); strcpy (ctypes[7], "ZPN"); strcpy (ctypes[8], "ZEA"); strcpy (ctypes[9], "AIR"); strcpy (ctypes[10], "CYP"); strcpy (ctypes[11], "CAR"); strcpy (ctypes[12], "MER"); strcpy (ctypes[13], "CEA"); strcpy (ctypes[14], "COP"); strcpy (ctypes[15], "COD"); strcpy (ctypes[16], "COE"); strcpy (ctypes[17], "COO"); strcpy (ctypes[18], "BON"); strcpy (ctypes[19], "PCO"); strcpy (ctypes[20], "SFL"); strcpy (ctypes[21], "PAR"); strcpy (ctypes[22], "AIT"); strcpy (ctypes[23], "MOL"); strcpy (ctypes[24], "CSC"); strcpy (ctypes[25], "QSC"); strcpy (ctypes[26], "TSC"); strcpy (ctypes[27], "NCP"); strcpy (ctypes[28], "GLS"); strcpy (ctypes[29], "DSS"); strcpy (ctypes[30], "PLT"); strcpy (ctypes[31], "TNX"); strcpy (ctypes[32], "ZPX"); strcpy (ctypes[33], "TPV"); ptype0 = -1; ptype[3] = (char) 0; for (i = 0; i < nctype; i++) { if (!strcasecmp (ptype, ctypes[i])) ptype0 = i; } return; } void setdateobs (dateobs) char *dateobs; { dateobs0 = calloc (strlen (dateobs), sizeof (char)); strcpy (dateobs0, dateobs); return; } /* Feb 29 1996 New program * May 23 1996 Use pre-existing WCS for center, if it is present * May 29 1996 Simplify program by always using WCS structure * Jun 12 1996 Be more careful with nominal WCS setting * Jul 3 1996 Set epoch from old equinox if not already set * Jul 19 1996 Set image center in WCS if DSS WCS * Aug 5 1996 Check for SECPIX1 as well as SECPIX * Aug 7 1996 Save specified number of decimal places in header parameters * Aug 7 1996 Rename old center parameters * Aug 26 1996 Decrease default pixel tolerance from 20 to 10 * Sep 1 1996 Set plate scale default in lwcs.h * Sep 3 1996 Fix bug to set plate scale from command line * Oct 15 1996 Break off from imsetwcs.c * Oct 16 1996 Clean up center setting so eqref is used * Oct 17 1996 Do not print error messages unless verbose is set * Oct 30 1996 Keep equinox from image if EQREF is zero * Nov 1 1996 Declare undeclared subroutines; remove unused variables * Nov 4 1996 Add reference pixel and projection to wcsset() call * Nov 14 1996 Add GetLimits() to deal with search limits around the poles * Nov 15 1996 Drop GetLimits(); code moved to individual catalog routines * Dec 10 1996 Fix precession and make equinox double * Feb 19 1997 If eqout is 0, use equinox of image * Feb 24 1997 Always convert center to output equinox (bug fix) * Mar 20 1997 Declare EQ2 double instead of int, fixing a bug * Jul 11 1997 Allow external (command line) setting of reference pixel coords * Sep 26 1997 Set both equinox and epoch if input center coordinates * Nov 3 1997 Separate WCS reference pixel from search center * Dec 8 1997 Set CDELTn using SECPIX if it is in the header * * Jan 6 1998 Do not print anything unless verbose is set * Jan 29 1998 Use flag to allow AIPS classic WCS subroutines * Mar 1 1998 Set x and y plate scales from command line if there are two * Mar 2 1998 Do not reset plate solution switch * Mar 6 1998 Add option to reset center sky coordinates in degrees * Mar 6 1998 Add option to set projection type * Mar 18 1998 Initialize reference pixel if CDELTn's being set * Mar 20 1998 Only set CTYPEn if CDELTn or CRVALn are set * Apr 10 1998 Add option to set search area to circle or box * Apr 20 1998 Move GetArea() to scat.c * Apr 24 1998 Always convert image reference coordinate to catalog equinox * Apr 28 1998 Change coordinate system flags to WCS_* * Jun 1 1998 Print error message if WCS cannot be initialized * Jun 24 1998 Add string lengths to ra2str() and dec2str() calls * Jun 25 1998 Leave use of AIPS wcs to wcs.c file * Sep 17 1998 Add sysout to argument list and use scscon() for conversion * Sep 25 1998 Make sysout==0 indicate output in image coordinate system * Oct 28 1998 Set coordinate system properly to sysout/eqout in GetFITSWCS() * * Apr 7 1999 Add filename argument to GetFITSWCS * Apr 29 1999 Add option to set image size * Jun 2 1999 Fix sign of CDELT1 if secpix2 and secpix0 are set * Jul 7 1999 Fix conversion of center coordinates to refsys * Jul 9 1999 Fix bug which reset command-line-set reference pixel coordinate * Oct 21 1999 Fix declarations after lint * Nov 1 1999 Add option to write CD matrix * Nov 1 1999 If CDELTn set from command line delete previous header CD matrix * Nov 12 1999 Add galactic coordinates as command line option * Nov 16 1999 Set radecsys correctly for command line galactic * * Feb 15 2000 Add option to override the header CD matrix (like CDELTs) * Feb 29 2000 Fix bug, converting reference pixel WCS coordinates everywhere * Mar 27 2000 Drop unused subroutine setradius() * May 24 2000 Print degrees in debugging messages if output format * Sep 14 2000 Set xinc and yinc correctly if center pixel in header * * Jan 11 2001 All printing to stderr * Sep 19 2001 Drop fitshead.h; it is in wcs.h * Oct 19 2001 Allow DATE-OBS to be set * * Apr 3 2002 Update projection types to match list in wcs.h and wcs.c * Aug 2 2002 Add getsecpix(), getrefpix(), getcneter() to return presets * * Mar 25 2003 Fix GetFITSWCS() to return correct search area for rotated image * Mar 25 2003 Write out CTYPEn with quotes * Mar 27 2003 Fix half-pixel bug in computation of image center * Apr 3 2003 Drop unused variables after lint * Jun 6 2003 Set xref and yref to center if -999, not 0 * Jul 21 2003 Fix bug setting secpix if it was not set on the command line * (found by Takehiko Wada, ISAS) * Sep 23 2003 In setproj(), use strcasecmp() instead of strcmp() * Sep 26 2003 If reference pixel not set, set center correctly * Oct 6 2003 Change wcs->naxes to wcs->naxis to match WCSLIB 3.2 * Dec 3 2003 Add wcs->naxes back as an alternative * * Jul 26 2004 Fix image size when wrapping around RA=0:00 * Sep 16 2004 Fix verbose mode search size in GetFITSWCS() * Oct 29 2004 Fix problem setting RA size from limits * * Jan 20 2005 Fix cel.ref assignment if axis are switched * Jul 20 2005 Fix bug which reversed dimensions when setting image size * Jul 21 2005 Fix bug which caused bad results at RA ~= 0.0 * Aug 30 2005 Implement multiple WCS's, though not modification thereof, yet * Nov 1 2005 Set RADECSYS to ICRS if appropriate * * Oct 30 2006 Do not precess LINEAR or XY coordinates * * Jun 1 2007 In GetFITSWCS, deal with no input file * Jun 5 2007 Add ChangeFITSWCS to set header WCS arguments and WCS * Jul 3 2007 Fix bug by setting hp and wp * Jul 26 2007 If first line of header is END, initialize other needed values * Oct 19 2007 Return NULL from GetFITSWCS() immediately if no WCS in header * * Mar 24 2009 Set dimensions from IMAGEW and IMAGEH if WCSAXES > 0 * * Apr 06 2010 Set hp from IMAGEH in ChangeFITSWCS() (from Paul Liptack) * Apr 7 2010 In ChangeFITSWCS() set number of WCS projections from NWCSTYPE * * Sep 1 2011 Add ZPX and TPV projections to setproj() * * Jun 24 2016 ptype contains only first 3 letters of projection codes */ wcstools-3.9.5/libwcs/imhfile.c0000664000016200001660000014774511750060473015544 0ustar minkoirsys/*** File imhfile.c *** March 27, 2012 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2012 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: imhfile.c (IRAF .imh image file reading and writing) * Purpose: Read and write IRAF image files (and translate headers) * Subroutine: check_immagic (irafheader, teststring ) * Verify that file is valid IRAF imhdr or impix * Subroutine: irafrhead (filename, lfhead, fitsheader, lihead) * Read IRAF image header * Subroutine: irafrimage (fitsheader) * Read IRAF image pixels (call after irafrhead) * Subroutine: same_path (pixname, hdrname) * Put filename and header path together * Subroutine: iraf2fits (hdrname, irafheader, nbiraf, nbfits) * Convert IRAF image header to FITS image header * Subroutine: irafwhead (hdrname, irafheader, fitsheader) * Write IRAF header file * Subroutine: irafwimage (hdrname, irafheader, fitsheader, image ) * Write IRAF image and header files * Subroutine: fits2iraf (fitsheader, irafheader) * Convert FITS image header to IRAF image header * Subroutine: irafgeti4 (irafheader, offset) * Get 4-byte integer from arbitrary part of IRAF header * Subroutine: irafgetc2 (irafheader, offset) * Get character string from arbitrary part of IRAF v.1 header * Subroutine: irafgetc (irafheader, offset) * Get character string from arbitrary part of IRAF header * Subroutine: iraf2str (irafstring, nchar) * Convert 2-byte/char IRAF string to 1-byte/char string * Subroutine: str2iraf (string, irafstring, nchar) * Convert 1-byte/char string to IRAF 2-byte/char string * Subroutine: irafswap (bitpix,string,nbytes) * Swap bytes in string in place, with FITS bits/pixel code * Subroutine: irafswap2 (string,nbytes) * Swap bytes in string in place * Subroutine irafswap4 (string,nbytes) * Reverse bytes of Integer*4 or Real*4 vector in place * Subroutine irafswap8 (string,nbytes) * Reverse bytes of Real*8 vector in place * Subroutine irafsize (filename) * Return length of file in bytes * Subroutine isiraf (filename) * Return 1 if IRAF .imh file, else 0 * Copyright: 2000 Smithsonian Astrophysical Observatory * You may do anything you like with this file except remove * this copyright. The Smithsonian Astrophysical Observatory * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. */ #include /* define stderr, FD, and NULL */ #include #include #include #include #include #include #include "fitsfile.h" /* Parameters from iraf/lib/imhdr.h for IRAF version 1 images */ #define SZ_IMPIXFILE 79 /* name of pixel storage file */ #define SZ_IMHDRFILE 79 /* length of header storage file */ #define SZ_IMTITLE 79 /* image title string */ #define LEN_IMHDR 2052 /* length of std header */ /* Parameters from iraf/lib/imhdr.h for IRAF version 2 images */ #define SZ_IM2PIXFILE 255 /* name of pixel storage file */ #define SZ_IM2HDRFILE 255 /* name of header storage file */ #define SZ_IM2TITLE 383 /* image title string */ #define LEN_IM2HDR 2046 /* length of std header */ /* Offsets into header in bytes for parameters in IRAF version 1 images */ #define IM_HDRLEN 12 /* Length of header in 4-byte ints */ #define IM_PIXTYPE 16 /* Datatype of the pixels */ #define IM_NDIM 20 /* Number of dimensions */ #define IM_LEN 24 /* Length (as stored) */ #define IM_PHYSLEN 52 /* Physical length (as stored) */ #define IM_PIXOFF 88 /* Offset of the pixels */ #define IM_CTIME 108 /* Time of image creation */ #define IM_MTIME 112 /* Time of last modification */ #define IM_LIMTIME 116 /* Time of min,max computation */ #define IM_MAX 120 /* Maximum pixel value */ #define IM_MIN 124 /* Maximum pixel value */ #define IM_PIXFILE 412 /* Name of pixel storage file */ #define IM_HDRFILE 572 /* Name of header storage file */ #define IM_TITLE 732 /* Image name string */ /* Offsets into header in bytes for parameters in IRAF version 2 images */ #define IM2_HDRLEN 6 /* Length of header in 4-byte ints */ #define IM2_PIXTYPE 10 /* Datatype of the pixels */ #define IM2_SWAPPED 14 /* Pixels are byte swapped */ #define IM2_NDIM 18 /* Number of dimensions */ #define IM2_LEN 22 /* Length (as stored) */ #define IM2_PHYSLEN 50 /* Physical length (as stored) */ #define IM2_PIXOFF 86 /* Offset of the pixels */ #define IM2_CTIME 106 /* Time of image creation */ #define IM2_MTIME 110 /* Time of last modification */ #define IM2_LIMTIME 114 /* Time of min,max computation */ #define IM2_MAX 118 /* Maximum pixel value */ #define IM2_MIN 122 /* Maximum pixel value */ #define IM2_PIXFILE 126 /* Name of pixel storage file */ #define IM2_HDRFILE 382 /* Name of header storage file */ #define IM2_TITLE 638 /* Image name string */ /* Codes from iraf/unix/hlib/iraf.h */ #define TY_CHAR 2 #define TY_SHORT 3 #define TY_INT 4 #define TY_LONG 5 #define TY_REAL 6 #define TY_DOUBLE 7 #define TY_COMPLEX 8 #define TY_POINTER 9 #define TY_STRUCT 10 #define TY_USHORT 11 #define TY_UBYTE 12 #define LEN_IRAFHDR 25000 #define LEN_PIXHDR 1024 #define LEN_FITSHDR 11520 int check_immagic(); int irafgeti4(); float irafgetr4(); char *irafgetc2(); char *irafgetc(); char *iraf2str(); static char *same_path(); static void irafputr4(); static void irafputi4(); static void irafputc2(); static void irafputc(); static void str2iraf(); static int headswap=-1; /* =1 to swap data bytes of foreign IRAF file */ static void irafswap(); static void irafswap2(); static void irafswap4(); static void irafswap8(); int head_version (); int pix_version (); int irafncmp (); static int machswap(); static int irafsize(); #define SECONDS_1970_TO_1980 315532800L /* Subroutine: irafrhead * Purpose: Open and read the iraf .imh file, translating it to FITS, too. * Returns: NULL if failure, else pointer to IRAF .imh image header * Notes: The imhdr format is defined in iraf/lib/imhdr.h, some of * which defines or mimicked, above. */ char * irafrhead (filename, lihead) char *filename; /* Name of IRAF header file */ int *lihead; /* Length of IRAF image header in bytes (returned) */ { FILE *fd; int nbr; char *irafheader; int nbhead, nbytes; int imhver; headswap = -1; *lihead = 0; /* open the image header file */ fd = fopen (filename, "rb"); if (fd == NULL) { fprintf (stderr, "IRAFRHEAD: cannot open file %s to read\n", filename); return (NULL); } /* Find size of image header file */ if ((nbhead = irafsize (fd)) <= 0) { fprintf (stderr, "IRAFRHEAD: cannot read file %s, size = %d\n", filename, nbhead); return (NULL); } /* allocate initial sized buffer */ nbytes = nbhead + 5000; irafheader = (char *) calloc (nbytes/4, 4); if (irafheader == NULL) { (void)fprintf(stderr, "IRAFRHEAD Cannot allocate %d-byte header\n", nbytes); return (NULL); } *lihead = nbytes; /* Read IRAF header */ nbr = fread (irafheader, 1, nbhead, fd); fclose (fd); /* Reject if header less than minimum length */ if (nbr < LEN_PIXHDR) { (void)fprintf(stderr, "IRAFRHEAD header file %s: %d / %d bytes read.\n", filename,nbr,LEN_PIXHDR); free (irafheader); return (NULL); } /* Check header magic word */ imhver = head_version (irafheader); if (imhver < 1) { free (irafheader); (void)fprintf(stderr, "IRAFRHEAD: %s is not a valid IRAF image header\n", filename); return(NULL); } /* check number of image dimensions if (imhver == 2) ndim = irafgeti4 (irafheader, IM2_NDIM]) else ndim = irafgeti4 (irafheader, IM_NDIM]) if (ndim < 2) { free (irafheader); (void)fprintf(stderr, "File %s does not contain 2d image\n", filename); return (NULL); } */ return (irafheader); } char * irafrimage (fitsheader) char *fitsheader; /* FITS image header (filled) */ { FILE *fd; char *bang; int naxis, naxis1, naxis2, naxis3, npaxis1, npaxis2,bitpix, bytepix, pixswap, i; char *image; int nbr, nbimage, nbaxis, nbl, nbdiff, lpname; char *pixheader; char *linebuff, *pixchar; int imhver, lpixhead, len; char pixname[SZ_IM2PIXFILE+1]; char newpixname[SZ_IM2HDRFILE+1]; /* Convert pixel file name to character string */ hgetm (fitsheader, "PIXFIL", SZ_IM2PIXFILE, pixname); /* Drop trailing spaces */ lpname = strlen (pixname); pixchar = pixname + lpname - 1; while (*pixchar == ' ') *pixchar = (char) 0; hgeti4 (fitsheader, "PIXOFF", &lpixhead); /* Open pixel file, ignoring machine name if present */ if ((bang = strchr (pixname, '!')) != NULL ) fd = fopen (bang + 1, "rb"); else fd = fopen (pixname, "rb"); /* If not at pathname in header, try same directory as header file */ if (!fd) { hgetm (fitsheader, "IMHFIL", SZ_IM2HDRFILE, newpixname); len = strlen (newpixname); newpixname[len-3] = 'p'; newpixname[len-2] = 'i'; newpixname[len-1] = 'x'; fd = fopen (newpixname, "rb"); } /* Print error message and exit if pixel file is not found */ if (!fd) { (void)fprintf(stderr, "IRAFRIMAGE: Cannot open IRAF pixel file %s\n", pixname); return (NULL); } /* Read pixel header */ pixheader = (char *) calloc (lpixhead/4, 4); if (pixheader == NULL) { (void)fprintf(stderr, "IRAFRIMAGE Cannot allocate %d-byte pixel header\n", lpixhead); return (NULL); } nbr = fread (pixheader, 1, lpixhead, fd); /* Check size of pixel header */ if (nbr < lpixhead) { (void)fprintf(stderr, "IRAF pixel file %s: %d / %d bytes read.\n", pixname,nbr,LEN_PIXHDR); free (pixheader); fclose (fd); return (NULL); } /* check pixel header magic word */ imhver = pix_version (pixheader); if (imhver < 1) { (void)fprintf(stderr, "File %s not valid IRAF pixel file.\n", pixname); free (pixheader); fclose (fd); return(NULL); } free (pixheader); /* Find number of bytes to read */ hgeti4 (fitsheader,"NAXIS",&naxis); hgeti4 (fitsheader,"NAXIS1",&naxis1); hgeti4 (fitsheader,"NAXIS2",&naxis2); hgeti4 (fitsheader,"NPAXIS1",&npaxis1); hgeti4 (fitsheader,"NPAXIS2",&npaxis2); hgeti4 (fitsheader,"BITPIX",&bitpix); if (bitpix < 0) bytepix = -bitpix / 8; else bytepix = bitpix / 8; /* If either dimension is one and image is 3-D, read all three dimensions */ if (naxis == 3 && ((naxis1 == 1) | (naxis2 == 1))) { hgeti4 (fitsheader,"NAXIS3",&naxis3); nbimage = naxis1 * naxis2 * naxis3 * bytepix; } else { nbimage = naxis1 * naxis2 * bytepix; naxis3 = 1; } if (bytepix > 4) image = (char *) calloc (nbimage/8, 8); else if (bytepix > 2) image = (char *) calloc (nbimage/4, 4); else if (bytepix > 1) image = (char *) calloc (nbimage/2, 2); else image = (char *) calloc (nbimage, 1); if (image == NULL) { (void)fprintf(stderr, "IRAFRIMAGE Cannot allocate %d-byte image buffer\n", nbimage); return (NULL); } /* Read IRAF image all at once if physical and image dimensions are the same */ if (npaxis1 == naxis1) nbr = fread (image, 1, nbimage, fd); /* Read IRAF image one line at a time if physical and image dimensions differ */ else { nbdiff = (npaxis1 - naxis1) * bytepix; nbaxis = naxis1 * bytepix; linebuff = image; nbr = 0; if (naxis2 == 1 && naxis3 > 1) naxis2 = naxis3; for (i = 0; i < naxis2; i++) { nbl = fread (linebuff, 1, nbaxis, fd); nbr = nbr + nbl; (void) fseek (fd, nbdiff, SEEK_CUR); linebuff = linebuff + nbaxis; } } fclose (fd); /* Check size of image */ if (nbr < nbimage) { (void)fprintf(stderr, "IRAF pixel file %s: %d / %d bytes read.\n", pixname,nbr,nbimage); free (image); return (NULL); } /* Byte-reverse image, if necessary */ pixswap = 0; hgetl (fitsheader, "PIXSWAP", &pixswap); if (pixswap) irafswap (bitpix, image, nbimage); return (image); } /* Return IRAF image format version number from magic word in IRAF header*/ int head_version (irafheader) char *irafheader; /* IRAF image header from file */ { /* Check header file magic word */ if (irafncmp (irafheader, "imhdr", 5) != 0 ) { if (strncmp (irafheader, "imhv2", 5) != 0) return (0); else return (2); } else return (1); } /* Return IRAF image format version number from magic word in IRAF pixel file */ int pix_version (irafheader) char *irafheader; /* IRAF image header from file */ { /* Check pixel file header magic word */ if (irafncmp (irafheader, "impix", 5) != 0) { if (strncmp (irafheader, "impv2", 5) != 0) return (0); else return (2); } else return (1); } /* Verify that file is valid IRAF imhdr or impix by checking first 5 chars * Returns: 0 on success, 1 on failure */ int irafncmp (irafheader, teststring, nc) char *irafheader; /* IRAF image header from file */ char *teststring; /* C character string to compare */ int nc; /* Number of characters to compate */ { char *line; headswap = -1; if ((line = iraf2str (irafheader, nc)) == NULL) return (1); if (strncmp (line, teststring, nc) == 0) { free (line); return (0); } else { free (line); return (1); } } /* Convert IRAF image header to FITS image header, returning FITS header */ char * iraf2fits (hdrname, irafheader, nbiraf, nbfits) char *hdrname; /* IRAF header file name (may be path) */ char *irafheader; /* IRAF image header */ int nbiraf; /* Number of bytes in IRAF header */ int *nbfits; /* Number of bytes in FITS header (returned) */ { char *objname; /* object name from FITS file */ int lstr, i, j, k, ib, nax, nbits, nl; int lname = 0; char *pixname, *newpixname, *bang, *chead; char *fitsheader; int nblock, nlines; char *fhead, *fhead1, *fp, endline[81]; char irafchar; char fitsline[81]; char *dstring; int pixtype; int imhver, n, imu, pixoff, impixoff, immax, immin, imtime; int imndim, imlen, imphyslen, impixtype, pixswap, hpixswap, mtime; float rmax, rmin; headswap = -1; /* Set up last line of FITS header */ (void)strncpy (endline,"END", 3); for (i = 3; i < 80; i++) endline[i] = ' '; endline[80] = 0; /* Check header magic word */ imhver = head_version (irafheader); if (imhver < 1) { (void)fprintf(stderr, "File %s not valid IRAF image header\n", hdrname); return(NULL); } if (imhver == 2) { nlines = 24 + ((nbiraf - LEN_IM2HDR) / 81); imndim = IM2_NDIM; imlen = IM2_LEN; imphyslen = IM2_PHYSLEN; impixtype = IM2_PIXTYPE; impixoff = IM2_PIXOFF; imtime = IM2_MTIME; immax = IM2_MAX; immin = IM2_MIN; } else { nlines = 24 + ((nbiraf - LEN_IMHDR) / 162); imndim = IM_NDIM; imlen = IM_LEN; imphyslen = IM_PHYSLEN; impixtype = IM_PIXTYPE; impixoff = IM_PIXOFF; imtime = IM_MTIME; immax = IM_MAX; immin = IM_MIN; } /* Initialize FITS header */ nblock = (nlines * 80) / 2880; *nbfits = (nblock + 5) * 2880 + 4; fitsheader = (char *) calloc (*nbfits, 1); if (fitsheader == NULL) { (void)fprintf(stderr, "IRAF2FITS Cannot allocate %d-byte FITS header\n", *nbfits); return (NULL); } hlength (fitsheader, *nbfits); fhead = fitsheader; (void)strncpy (fitsheader, endline, 80); hputl (fitsheader, "SIMPLE", 1); fhead = fhead + 80; /* Set pixel size in FITS header */ pixtype = irafgeti4 (irafheader, impixtype); switch (pixtype) { case TY_CHAR: nbits = 8; break; case TY_UBYTE: nbits = 8; break; case TY_SHORT: nbits = 16; break; case TY_USHORT: nbits = -16; break; case TY_INT: case TY_LONG: nbits = 32; break; case TY_REAL: nbits = -32; break; case TY_DOUBLE: nbits = -64; break; default: (void)fprintf(stderr,"Unsupported data type: %d\n", pixtype); return (NULL); } hputi4 (fitsheader,"BITPIX",nbits); hputcom (fitsheader,"BITPIX", "IRAF .imh pixel type"); fhead = fhead + 80; /* Set image dimensions in FITS header */ nax = irafgeti4 (irafheader, imndim); hputi4 (fitsheader,"NAXIS",nax); hputcom (fitsheader,"NAXIS", "IRAF .imh naxis"); fhead = fhead + 80; n = irafgeti4 (irafheader, imlen); hputi4 (fitsheader, "NAXIS1", n); hputcom (fitsheader,"NAXIS1", "IRAF .imh image naxis[1]"); fhead = fhead + 80; if (nax > 1) { n = irafgeti4 (irafheader, imlen+4); hputi4 (fitsheader, "NAXIS2", n); hputcom (fitsheader,"NAXIS2", "IRAF .imh image naxis[2]"); } else hputi4 (fitsheader, "NAXIS2", 1); hputcom (fitsheader,"NAXIS2", "IRAF .imh naxis[2]"); fhead = fhead + 80; if (nax > 2) { n = irafgeti4 (irafheader, imlen+8); hputi4 (fitsheader, "NAXIS3", n); hputcom (fitsheader,"NAXIS3", "IRAF .imh image naxis[3]"); fhead = fhead + 80; } if (nax > 3) { n = irafgeti4 (irafheader, imlen+12); hputi4 (fitsheader, "NAXIS4", n); hputcom (fitsheader,"NAXIS4", "IRAF .imh image naxis[4]"); fhead = fhead + 80; } /* Set object name in FITS header */ if (imhver == 2) objname = irafgetc (irafheader, IM2_TITLE, SZ_IM2TITLE); else objname = irafgetc2 (irafheader, IM_TITLE, SZ_IMTITLE); if ((lstr = strlen (objname)) < 8) { for (i = lstr; i < 8; i++) objname[i] = ' '; objname[8] = 0; } hputs (fitsheader,"OBJECT",objname); hputcom (fitsheader,"OBJECT", "IRAF .imh title"); free (objname); fhead = fhead + 80; /* Save physical axis lengths so image file can be read */ n = irafgeti4 (irafheader, imphyslen); hputi4 (fitsheader, "NPAXIS1", n); hputcom (fitsheader,"NPAXIS1", "IRAF .imh physical naxis[1]"); fhead = fhead + 80; if (nax > 1) { n = irafgeti4 (irafheader, imphyslen+4); hputi4 (fitsheader, "NPAXIS2", n); hputcom (fitsheader,"NPAXIS2", "IRAF .imh physical naxis[2]"); fhead = fhead + 80; } if (nax > 2) { n = irafgeti4 (irafheader, imphyslen+8); hputi4 (fitsheader, "NPAXIS3", n); hputcom (fitsheader,"NPAXIS3", "IRAF .imh physical naxis[3]"); fhead = fhead + 80; } if (nax > 3) { n = irafgeti4 (irafheader, imphyslen+12); hputi4 (fitsheader, "NPAXIS4", n); hputcom (fitsheader,"NPAXIS4", "IRAF .imh physical naxis[4]"); fhead = fhead + 80; } /* Save image minimum and maximum in header */ rmax = irafgetr4 (irafheader, immax); rmin = irafgetr4 (irafheader, immin); if (rmin != rmax) { hputr4 (fitsheader, "IRAFMIN", &rmin); fhead = fhead + 80; hputcom (fitsheader,"IRAFMIN", "IRAF .imh minimum"); hputr4 (fitsheader, "IRAFMAX", &rmax); hputcom (fitsheader,"IRAFMAX", "IRAF .imh maximum"); fhead = fhead + 80; } /* Save image header filename in header */ nl = hputm (fitsheader,"IMHFIL",hdrname); if (nl > 0) { lname = strlen (hdrname); strcpy (fitsline, "IRAF header file name"); if (lname < 43) hputcom (fitsheader,"IMHFIL_1", fitsline); else if (lname > 67 && lname < 110) hputcom (fitsheader,"IMHFIL_2", fitsline); else if (lname > 134 && lname < 177) hputcom (fitsheader,"IMHFIL_3", fitsline); } if (nl > 0) fhead = fhead + (nl * 80); /* Save image pixel file pathname in header */ if (imhver == 2) pixname = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE); else pixname = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE); if (strncmp(pixname, "HDR", 3) == 0 ) { newpixname = same_path (pixname, hdrname); free (pixname); pixname = newpixname; } if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) { newpixname = same_path (pixname, hdrname); free (pixname); pixname = newpixname; } if ((bang = strchr (pixname, '!')) != NULL ) nl = hputm (fitsheader,"PIXFIL",bang+1); else nl = hputm (fitsheader,"PIXFIL",pixname); free (pixname); if (nl > 0) { strcpy (fitsline, "IRAF .pix pixel file"); if (lname < 43) hputcom (fitsheader,"PIXFIL_1", fitsline); else if (lname > 67 && lname < 110) hputcom (fitsheader,"PIXFIL_2", fitsline); else if (lname > 134 && lname < 177) hputcom (fitsheader,"PIXFIL_3", fitsline); } if (nl > 0) fhead = fhead + (nl * 80); /* Save image offset from star of pixel file */ pixoff = irafgeti4 (irafheader, impixoff); pixoff = (pixoff - 1) * 2; hputi4 (fitsheader, "PIXOFF", pixoff); hputcom (fitsheader,"PIXOFF", "IRAF .pix pixel offset (Do not change!)"); fhead = fhead + 80; /* Save IRAF file format version in header */ hputi4 (fitsheader,"IMHVER",imhver); hputcom (fitsheader,"IMHVER", "IRAF .imh format version (1 or 2)"); fhead = fhead + 80; /* Set flag if header numbers are byte-reversed on this machine */ if (machswap() != headswap) hputl (fitsheader, "HEADSWAP", 1); else hputl (fitsheader, "HEADSWAP", 0); hputcom (fitsheader,"HEADSWAP", "IRAF header, FITS byte orders differ if T"); fhead = fhead + 80; /* Set flag if image pixels are byte-reversed on this machine */ if (imhver == 2) { hpixswap = irafgeti4 (irafheader, IM2_SWAPPED); if (headswap && !hpixswap) pixswap = 1; else if (!headswap && hpixswap) pixswap = 1; else pixswap = 0; } else pixswap = headswap; if (machswap() != pixswap) hputl (fitsheader, "PIXSWAP", 1); else hputl (fitsheader, "PIXSWAP", 0); hputcom (fitsheader,"PIXSWAP", "IRAF pixels, FITS byte orders differ if T"); fhead = fhead + 80; /* Read modification time */ mtime = irafgeti4 (irafheader, imtime); if (mtime == 0) dstring = lt2fd (); else dstring = tsi2fd (mtime); hputs (fitsheader, "DATE-MOD", dstring); hputcom (fitsheader,"DATE-MOD", "Date of latest file modification"); free (dstring); fhead = fhead + 80; /* Add user portion of IRAF header to FITS header */ fitsline[80] = 0; if (imhver == 2) { imu = LEN_IM2HDR; chead = irafheader; j = 0; for (k = 0; k < 80; k++) fitsline[k] = ' '; for (i = imu; i < nbiraf; i++) { irafchar = chead[i]; if (irafchar == 0) break; else if (irafchar == 10) { (void)strncpy (fhead, fitsline, 80); /* fprintf (stderr,"%80s\n",fitsline); */ if (strncmp (fitsline, "OBJECT ", 7) != 0) { fhead = fhead + 80; } for (k = 0; k < 80; k++) fitsline[k] = ' '; j = 0; } else { if (j > 80) { if (strncmp (fitsline, "OBJECT ", 7) != 0) { (void)strncpy (fhead, fitsline, 80); /* fprintf (stderr,"%80s\n",fitsline); */ j = 9; fhead = fhead + 80; } for (k = 0; k < 80; k++) fitsline[k] = ' '; } if (irafchar > 32 && irafchar < 127) fitsline[j] = irafchar; j++; } } } else { imu = LEN_IMHDR; chead = irafheader; if (headswap == 1) ib = 0; else ib = 1; for (k = 0; k < 80; k++) fitsline[k] = ' '; j = 0; for (i = imu; i < nbiraf; i=i+2) { irafchar = chead[i+ib]; if (irafchar == 0) break; else if (irafchar == 10) { if (strncmp (fitsline, "OBJECT ", 7) != 0) { (void)strncpy (fhead, fitsline, 80); fhead = fhead + 80; } /* fprintf (stderr,"%80s\n",fitsline); */ j = 0; for (k = 0; k < 80; k++) fitsline[k] = ' '; } else { if (j > 80) { if (strncmp (fitsline, "OBJECT ", 7) != 0) { (void)strncpy (fhead, fitsline, 80); j = 9; fhead = fhead + 80; } /* fprintf (stderr,"%80s\n",fitsline); */ for (k = 0; k < 80; k++) fitsline[k] = ' '; } if (irafchar > 32 && irafchar < 127) fitsline[j] = irafchar; j++; } } } /* Add END to last line */ (void)strncpy (fhead, endline, 80); /* Find end of last 2880-byte block of header */ fhead = ksearch (fitsheader, "END") + 80; nblock = *nbfits / 2880; fhead1 = fitsheader + (nblock * 2880); /* Pad rest of header with spaces */ strncpy (endline," ",3); for (fp = fhead; fp < fhead1; fp = fp + 80) { (void)strncpy (fp, endline,80); } return (fitsheader); } int irafwhead (hdrname, lhead, irafheader, fitsheader) char *hdrname; /* Name of IRAF header file */ int lhead; /* Length of IRAF header */ char *irafheader; /* IRAF header */ char *fitsheader; /* FITS image header */ { int fd; int nbw, nbhead, lphead, pixswap; /* Get rid of redundant header information */ hgeti4 (fitsheader, "PIXOFF", &lphead); hgeti4 (fitsheader, "PIXSWAP", &pixswap); /* Write IRAF header file */ /* Convert FITS header to IRAF header */ irafheader = fits2iraf (fitsheader, irafheader, lhead, &nbhead); if (irafheader == NULL) { fprintf (stderr, "IRAFWIMAGE: file %s header error\n", hdrname); return (-1); } /* Open the output file */ if (!access (hdrname, 0)) { fd = open (hdrname, O_WRONLY); if (fd < 3) { fprintf (stderr, "IRAFWIMAGE: file %s not writeable\n", hdrname); return (0); } } else { fd = open (hdrname, O_RDWR+O_CREAT, 0666); if (fd < 3) { fprintf (stderr, "IRAFWIMAGE: cannot create file %s\n", hdrname); return (0); } } /* Write IRAF header to disk file */ nbw = write (fd, irafheader, nbhead); (void) ftruncate (fd, nbhead); close (fd); if (nbw < nbhead) { (void)fprintf(stderr, "IRAF header file %s: %d / %d bytes written.\n", hdrname, nbw, nbhead); return (-1); } return (nbw); } /* IRAFWIMAGE -- write IRAF .imh header file and .pix image file * No matter what the input, this always writes in the local byte order */ int irafwimage (hdrname, lhead, irafheader, fitsheader, image ) char *hdrname; /* Name of IRAF header file */ int lhead; /* Length of IRAF header */ char *irafheader; /* IRAF header */ char *fitsheader; /* FITS image header */ char *image; /* IRAF image */ { int fd; char *bang; int nbw, bytepix, bitpix, naxis, naxis1, naxis2, nbimage, lphead; char *pixn, *newpixname; char pixname[SZ_IM2PIXFILE+1]; int imhver, pixswap; hgeti4 (fitsheader, "IMHVER", &imhver); if (!hgetm (fitsheader, "PIXFIL", SZ_IM2PIXFILE, pixname)) { if (imhver == 2) pixn = irafgetc (irafheader, IM2_PIXFILE, SZ_IM2PIXFILE); else pixn = irafgetc2 (irafheader, IM_PIXFILE, SZ_IMPIXFILE); if (strncmp(pixn, "HDR", 3) == 0 ) { newpixname = same_path (pixn, hdrname); strcpy (pixname, newpixname); free (newpixname); } else { if ((bang = strchr (pixn, '!')) != NULL ) strcpy (pixname, bang+1); else strcpy (pixname, pixn); } free (pixn); } /* Find number of bytes to write */ hgeti4 (fitsheader,"NAXIS",&naxis); hgeti4 (fitsheader,"NAXIS1",&naxis1); hgeti4 (fitsheader,"NAXIS2",&naxis2); hgeti4 (fitsheader,"BITPIX",&bitpix); if (bitpix < 0) bytepix = -bitpix / 8; else bytepix = bitpix / 8; /* If either dimension is one and image is 3-D, read all three dimensions */ if (naxis == 3 && ((naxis1 == 1) | (naxis2 == 1))) { int naxis3; hgeti4 (fitsheader,"NAXIS3",&naxis3); nbimage = naxis1 * naxis2 * naxis3 * bytepix; } else nbimage = naxis1 * naxis2 * bytepix; /* Read information about pixel file from header */ hgeti4 (fitsheader, "PIXOFF", &lphead); hgeti4 (fitsheader, "PIXSWAP", &pixswap); /* Write IRAF header file */ if (irafwhead (hdrname, lhead, irafheader, fitsheader)) return (0); /* Open the output file */ if (!access (pixname, 0)) { fd = open (pixname, O_WRONLY); if (fd < 3) { fprintf (stderr, "IRAFWIMAGE: file %s not writeable\n", pixname); return (0); } } else { fd = open (pixname, O_RDWR+O_CREAT, 0666); if (fd < 3) { fprintf (stderr, "IRAFWIMAGE: cannot create file %s\n", pixname); return (0); } } /* Write header to IRAF pixel file */ if (imhver == 2) irafputc ("impv2", irafheader, 0, 5); else irafputc2 ("impix", irafheader, 0, 5); nbw = write (fd, irafheader, lphead); /* Byte-reverse image, if necessary */ if (pixswap) irafswap (bitpix, image, nbimage); /* Write data to IRAF pixel file */ nbw = write (fd, image, nbimage); close (fd); return (nbw); } /* Put filename and header path together */ static char * same_path (pixname, hdrname) char *pixname; /* IRAF pixel file pathname */ char *hdrname; /* IRAF image header file pathname */ { int len, plen; char *newpixname; newpixname = (char *) calloc (SZ_IM2PIXFILE, 1); /* Pixel file is in same directory as header */ if (strncmp(pixname, "HDR$", 4) == 0 ) { (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE); /* find the end of the pathname */ len = strlen (newpixname); #ifndef VMS while( (len > 0) && (newpixname[len-1] != '/') ) #else while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') ) #endif len--; /* add name */ newpixname[len] = '\0'; plen = strlen (pixname) - 4; if (len + plen > SZ_IM2PIXFILE) (void)strncat (newpixname, &pixname[4], SZ_IM2PIXFILE - len); else (void)strncat (newpixname, &pixname[4], plen); } /* Bare pixel file with no path is assumed to be same as HDR$filename */ else if (strchr (pixname, '/') == NULL && strchr (pixname, '$') == NULL) { (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE); /* find the end of the pathname */ len = strlen (newpixname); #ifndef VMS while( (len > 0) && (newpixname[len-1] != '/') ) #else while( (len > 0) && (newpixname[len-1] != ']') && (newpixname[len-1] != ':') ) #endif len--; /* add name */ newpixname[len] = '\0'; (void)strncat (newpixname, pixname, SZ_IM2PIXFILE); } /* Pixel file has same name as header file, but with .pix extension */ else if (strncmp (pixname, "HDR", 3) == 0) { /* load entire header name string into name buffer */ (void)strncpy (newpixname, hdrname, SZ_IM2PIXFILE); len = strlen (newpixname); newpixname[len-3] = 'p'; newpixname[len-2] = 'i'; newpixname[len-1] = 'x'; } return (newpixname); } /* Convert FITS image header to IRAF image header, returning IRAF header */ /* No matter what the input, this always writes in the local byte order */ char * fits2iraf (fitsheader, irafheader, nbhead, nbiraf) char *fitsheader; /* FITS image header */ char *irafheader; /* IRAF image header (returned updated) */ int nbhead; /* Length of IRAF header */ int *nbiraf; /* Length of returned IRAF header */ { int i, n, pixoff, lhdrdir; short *irafp, *irafs, *irafu; char *iraf2u, *iraf2p, *filename, *hdrdir; char *fitsend, *fitsp, pixfile[SZ_IM2PIXFILE], hdrfile[SZ_IM2HDRFILE]; char title[SZ_IM2TITLE], temp[80]; int nax, nlfits, imhver, nbits, pixtype, hdrlength, mtime; int imndim, imlen, imphyslen, impixtype, imhlen, imtime, immax, immin; float rmax, rmin; hgeti4 (fitsheader, "IMHVER", &imhver); hdel (fitsheader, "IMHVER"); hdel (fitsheader, "IMHVER"); hgetl (fitsheader, "HEADSWAP", &headswap); hdel (fitsheader, "HEADSWAP"); hdel (fitsheader, "HEADSWAP"); if (imhver == 2) { imhlen = IM2_HDRLEN; imndim = IM2_NDIM; imlen = IM2_LEN; imtime = IM2_MTIME; imphyslen = IM2_PHYSLEN; impixtype = IM2_PIXTYPE; immax = IM2_MAX; immin = IM2_MIN; } else { imhlen = IM_HDRLEN; imndim = IM_NDIM; imlen = IM_LEN; imtime = IM_MTIME; imphyslen = IM_PHYSLEN; impixtype = IM_PIXTYPE; immax = IM_MAX; immin = IM_MIN; } /* Delete FITS header keyword not needed by IRAF */ hdel (fitsheader,"SIMPLE"); /* Set IRAF image data type */ hgeti4 (fitsheader,"BITPIX", &nbits); switch (nbits) { case 8: pixtype = TY_CHAR; break; case -8: pixtype = TY_UBYTE; break; case 16: pixtype = TY_SHORT; break; case -16: pixtype = TY_USHORT; break; case 32: pixtype = TY_INT; break; case -32: pixtype = TY_REAL; break; case -64: pixtype = TY_DOUBLE; break; default: (void)fprintf(stderr,"Unsupported data type: %d\n", nbits); return (NULL); } irafputi4 (irafheader, impixtype, pixtype); hdel (fitsheader,"BITPIX"); /* Set IRAF image dimensions */ hgeti4 (fitsheader,"NAXIS",&nax); irafputi4 (irafheader, imndim, nax); hdel (fitsheader,"NAXIS"); hgeti4 (fitsheader, "NAXIS1", &n); irafputi4 (irafheader, imlen, n); irafputi4 (irafheader, imphyslen, n); hdel (fitsheader,"NAXIS1"); hgeti4 (fitsheader,"NAXIS2",&n); irafputi4 (irafheader, imlen+4, n); irafputi4 (irafheader, imphyslen+4, n); hdel (fitsheader,"NAXIS2"); if (nax > 2) { hgeti4 (fitsheader,"NAXIS3",&n); irafputi4 (irafheader, imlen+8, n); irafputi4 (irafheader, imphyslen+8, n); hdel (fitsheader,"NAXIS3"); } if (nax > 3) { hgeti4 (fitsheader,"NAXIS4",&n); irafputi4 (irafheader, imlen+12, n); irafputi4 (irafheader, imphyslen+12, n); hdel (fitsheader,"NAXIS4"); } /* Set image pixel value limits */ rmin = 0.0; hgetr4 (fitsheader, "IRAFMIN", &rmin); rmax = 0.0; hgetr4 (fitsheader, "IRAFMAX", &rmax); if (rmin != rmax) { irafputr4 (irafheader, immax, rmax); irafputr4 (irafheader, immin, rmin); } hdel (fitsheader, "IRAFMIN"); hdel (fitsheader, "IRAFMAX"); /* Replace pixel file name, if it is in the FITS header */ if (hgetm (fitsheader, "PIXFIL", SZ_IM2PIXFILE, pixfile)) { if (strchr (pixfile, '/')) { if (hgetm (fitsheader, "IMHFIL", SZ_IM2HDRFILE, hdrfile)) { hdrdir = strrchr (hdrfile, '/'); if (hdrdir != NULL) { lhdrdir = hdrdir - hdrfile + 1; if (!strncmp (pixfile, hdrfile, lhdrdir)) { filename = pixfile + lhdrdir; strcpy (temp, "HDR$"); strcat (temp,filename); strcpy (pixfile, temp); } } if (pixfile[0] != '/' && pixfile[0] != 'H') { strcpy (temp, "HDR$"); strcat (temp,pixfile); strcpy (pixfile, temp); } } } if (imhver == 2) irafputc (pixfile, irafheader, IM2_PIXFILE, SZ_IM2PIXFILE); else irafputc2 (pixfile, irafheader, IM_PIXFILE, SZ_IMPIXFILE); hdel (fitsheader,"PIXFIL_1"); hdel (fitsheader,"PIXFIL_2"); hdel (fitsheader,"PIXFIL_3"); hdel (fitsheader,"PIXFIL_4"); } /* Replace header file name, if it is in the FITS header */ if (hgetm (fitsheader, "IMHFIL", SZ_IM2HDRFILE, pixfile)) { if (!strchr (pixfile,'/') && !strchr (pixfile,'$')) { strcpy (temp, "HDR$"); strcat (temp,pixfile); strcpy (pixfile, temp); } if (imhver == 2) irafputc (pixfile, irafheader, IM2_HDRFILE, SZ_IM2HDRFILE); else irafputc2 (pixfile, irafheader, IM_HDRFILE, SZ_IMHDRFILE); hdel (fitsheader, "IMHFIL_1"); hdel (fitsheader, "IMHFIL_2"); hdel (fitsheader, "IMHFIL_3"); hdel (fitsheader, "IMHFIL_4"); } /* Replace image title, if it is in the FITS header */ if (hgets (fitsheader, "OBJECT", SZ_IM2TITLE, title)) { if (imhver == 2) irafputc (title, irafheader, IM2_TITLE, SZ_IM2TITLE); else irafputc2 (title, irafheader, IM_TITLE, SZ_IMTITLE); hdel (fitsheader, "OBJECT"); } hgeti4 (fitsheader, "PIXOFF", &pixoff); hdel (fitsheader, "PIXOFF"); hdel (fitsheader, "PIXOFF"); hdel (fitsheader, "PIXSWAP"); hdel (fitsheader, "PIXSWAP"); hdel (fitsheader, "DATE-MOD"); hdel (fitsheader, "DATE-MOD"); fitsend = ksearch (fitsheader,"END"); /* Find length of FITS header */ fitsend = ksearch (fitsheader,"END"); nlfits = ((fitsend - fitsheader) / 80); /* Find new length of IRAF header */ if (imhver == 2) *nbiraf = LEN_IM2HDR + (81 * nlfits); else *nbiraf = LEN_IMHDR + (162 * nlfits); if (*nbiraf > nbhead) irafheader = realloc (irafheader, *nbiraf); /* Reset modification time */ mtime = lt2tsi (); irafputi4 (irafheader, imtime, mtime); /* Replace user portion of IRAF header with remaining FITS header */ if (imhver == 2) { iraf2u = irafheader + LEN_IM2HDR; iraf2p = iraf2u; for (fitsp = fitsheader; fitsp < fitsend; fitsp = fitsp + 80) { for (i = 0; i < 80; i++) *iraf2p++ = fitsp[i]; *iraf2p++ = 10; } *iraf2p++ = 0; *nbiraf = iraf2p - irafheader; hdrlength = 1 + *nbiraf / 2; } else { irafs = (short *)irafheader; irafu = irafs + (LEN_IMHDR / 2); irafp = irafu; for (fitsp = fitsheader; fitsp < fitsend; fitsp = fitsp + 80) { for (i = 0; i < 80; i++) *irafp++ = (short) fitsp[i]; *irafp++ = 10; } *irafp++ = 0; *irafp++ = 32; *nbiraf = 2 * (irafp - irafs); hdrlength = *nbiraf / 4; } /* Length of header file */ irafputi4 (irafheader, imhlen, hdrlength); /* Offset in .pix file to first pixel data hputi4 (fitsheader, "PIXOFF", pixoff); */ /* Return number of bytes in new IRAF header */ return (irafheader); } int irafgeti4 (irafheader, offset) char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before number */ { char *ctemp, *cheader; int temp; cheader = irafheader; ctemp = (char *) &temp; /* If header swap flag not set, set it now */ if (headswap < 0) { if (cheader[offset] > 0) headswap = 1; else headswap = 0; } if (machswap() != headswap) { ctemp[3] = cheader[offset]; ctemp[2] = cheader[offset+1]; ctemp[1] = cheader[offset+2]; ctemp[0] = cheader[offset+3]; } else { ctemp[0] = cheader[offset]; ctemp[1] = cheader[offset+1]; ctemp[2] = cheader[offset+2]; ctemp[3] = cheader[offset+3]; } return (temp); } float irafgetr4 (irafheader, offset) char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before number */ { char *ctemp, *cheader; float temp; cheader = irafheader; ctemp = (char *) &temp; /* If header swap flag not set, set it now */ if (headswap < 0) { if (cheader[offset] > 0) headswap = 1; else headswap = 0; } if (machswap() != headswap) { ctemp[3] = cheader[offset]; ctemp[2] = cheader[offset+1]; ctemp[1] = cheader[offset+2]; ctemp[0] = cheader[offset+3]; } else { ctemp[0] = cheader[offset]; ctemp[1] = cheader[offset+1]; ctemp[2] = cheader[offset+2]; ctemp[3] = cheader[offset+3]; } return (temp); } /* IRAFGETC2 -- Get character string from arbitrary part of v.1 IRAF header */ char * irafgetc2 (irafheader, offset, nc) char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before string */ int nc; /* Maximum number of characters in string */ { char *irafstring, *string; irafstring = irafgetc (irafheader, offset, 2*(nc+1)); string = iraf2str (irafstring, nc); free (irafstring); return (string); } /* IRAFGETC -- Get character string from arbitrary part of IRAF header */ char * irafgetc (irafheader, offset, nc) char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before string */ int nc; /* Maximum number of characters in string */ { char *ctemp, *cheader; int i; cheader = irafheader; ctemp = (char *) calloc (nc+1, 1); if (ctemp == NULL) { (void)fprintf(stderr, "IRAFGETC Cannot allocate %d-byte variable\n", nc+1); return (NULL); } for (i = 0; i < nc; i++) { ctemp[i] = cheader[offset+i]; if (ctemp[i] > 0 && ctemp[i] < 32) ctemp[i] = ' '; } return (ctemp); } /* Convert IRAF 2-byte/char string to 1-byte/char string */ char * iraf2str (irafstring, nchar) char *irafstring; /* IRAF 2-byte/character string */ int nchar; /* Number of characters in string */ { char *string; int i, j; /* Set swap flag according to position of nulls in 2-byte characters */ if (headswap < 0) { if (irafstring[0] != 0 && irafstring[1] == 0) headswap = 1; else if (irafstring[0] == 0 && irafstring[1] != 0) headswap = 0; else return (NULL); } string = (char *) calloc (nchar+1, 1); if (string == NULL) { (void)fprintf(stderr, "IRAF2STR Cannot allocate %d-byte variable\n", nchar+1); return (NULL); } /* Swap bytes, if requested */ if (headswap) j = 0; else j = 1; /* Convert appropriate byte of input to output character */ for (i = 0; i < nchar; i++) { string[i] = irafstring[j]; j = j + 2; } return (string); } /* IRAFPUTI4 -- Insert 4-byte integer into arbitrary part of IRAF header */ static void irafputi4 (irafheader, offset, inum) char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before number */ int inum; /* Number to put into header */ { char *cn, *chead; chead = irafheader; cn = (char *) &inum; if (headswap < 0) headswap = 0; if (headswap != machswap()) { chead[offset+3] = cn[0]; chead[offset+2] = cn[1]; chead[offset+1] = cn[2]; chead[offset] = cn[3]; } else { chead[offset] = cn[0]; chead[offset+1] = cn[1]; chead[offset+2] = cn[2]; chead[offset+3] = cn[3]; } return; } /* IRAFPUTR4 -- Insert 4-byte real number into arbitrary part of IRAF header */ static void irafputr4 (irafheader, offset, rnum) char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before number */ float rnum; /* Number to put into header */ { char *cn, *chead; chead = irafheader; cn = (char *) &rnum; if (headswap < 0) headswap = 0; if (headswap != machswap()) { chead[offset+3] = cn[0]; chead[offset+2] = cn[1]; chead[offset+1] = cn[2]; chead[offset] = cn[3]; } else { chead[offset] = cn[0]; chead[offset+1] = cn[1]; chead[offset+2] = cn[2]; chead[offset+3] = cn[3]; } return; } /* IRAFPUTC2 -- Insert character string into arbitrary part of v.1 IRAF header */ static void irafputc2 (string, irafheader, offset, nc) char *string; /* String to insert into header */ char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before string */ int nc; /* Maximum number of characters in string */ { char *irafstring; irafstring = (char *) calloc (2 * nc, 1); if (irafstring == NULL) { (void)fprintf(stderr, "IRAFPUTC2 Cannot allocate %d-byte variable\n", 2 * nc); } str2iraf (string, irafstring, nc); irafputc (irafstring, irafheader, offset, 2*nc); return; } /* IRAFPUTC -- Insert character string into arbitrary part of IRAF header */ static void irafputc (string, irafheader, offset, nc) char *string; /* String to insert into header */ char *irafheader; /* IRAF image header */ int offset; /* Number of bytes to skip before string */ int nc; /* Maximum number of characters in string */ { char *chead; int i; chead = irafheader; for (i = 0; i < nc; i++) chead[offset+i] = string[i]; return; } /* STR2IRAF -- Convert 1-byte/char string to IRAF 2-byte/char string */ static void str2iraf (string, irafstring, nchar) char *string; /* 1-byte/character string */ char *irafstring; /* IRAF 2-byte/character string */ int nchar; /* Maximum number of characters in IRAF string */ { int i, j, nc, nbytes; nc = strlen (string); /* Fill output string with zeroes */ nbytes = nchar * 2; for (i = 0; i < nbytes; i++) irafstring[i] = 0; /* If swapped, start with first byte of 2-byte characters */ if (headswap) j = 0; else j = 1; /* Move input characters to appropriate bytes of output */ for (i = 0; i < nchar; i++) { if (i > nc) irafstring[j] = 0; else irafstring[j] = string[i]; j = j + 2; } return; } /* IRAFSWAP -- Reverse bytes of any type of vector in place */ static void irafswap (bitpix, string, nbytes) int bitpix; /* Number of bits per pixel */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ char *string; /* Address of starting point of bytes to swap */ int nbytes; /* Number of bytes to swap */ { switch (bitpix) { case 16: if (nbytes < 2) return; irafswap2 (string,nbytes); break; case 32: if (nbytes < 4) return; irafswap4 (string,nbytes); break; case -16: if (nbytes < 2) return; irafswap2 (string,nbytes); break; case -32: if (nbytes < 4) return; irafswap4 (string,nbytes); break; case -64: if (nbytes < 8) return; irafswap8 (string,nbytes); break; } return; } /* IRAFSWAP2 -- Swap bytes in string in place */ static void irafswap2 (string,nbytes) char *string; /* Address of starting point of bytes to swap */ int nbytes; /* Number of bytes to swap */ { char *sbyte, temp, *slast; slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp = sbyte[0]; sbyte[0] = sbyte[1]; sbyte[1] = temp; sbyte= sbyte + 2; } return; } /* IRAFSWAP4 -- Reverse bytes of Integer*4 or Real*4 vector in place */ static void irafswap4 (string,nbytes) char *string; /* Address of Integer*4 or Real*4 vector */ int nbytes; /* Number of bytes to reverse */ { char *sbyte, *slast; char temp0, temp1, temp2, temp3; slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp3 = sbyte[0]; temp2 = sbyte[1]; temp1 = sbyte[2]; temp0 = sbyte[3]; sbyte[0] = temp0; sbyte[1] = temp1; sbyte[2] = temp2; sbyte[3] = temp3; sbyte = sbyte + 4; } return; } /* IRAFSWAP8 -- Reverse bytes of Real*8 vector in place */ static void irafswap8 (string,nbytes) char *string; /* Address of Real*8 vector */ int nbytes; /* Number of bytes to reverse */ { char *sbyte, *slast; char temp[8]; slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp[7] = sbyte[0]; temp[6] = sbyte[1]; temp[5] = sbyte[2]; temp[4] = sbyte[3]; temp[3] = sbyte[4]; temp[2] = sbyte[5]; temp[1] = sbyte[6]; temp[0] = sbyte[7]; sbyte[0] = temp[0]; sbyte[1] = temp[1]; sbyte[2] = temp[2]; sbyte[3] = temp[3]; sbyte[4] = temp[4]; sbyte[5] = temp[5]; sbyte[6] = temp[6]; sbyte[7] = temp[7]; sbyte = sbyte + 8; } return; } /* Set flag if machine on which program is executing is not FITS byte order * ( i.e., if it is an Alpha or PC instead of a Sun ) */ static int machswap () { char *ctest; int itest; itest = 1; ctest = (char *)&itest; if (*ctest) return (1); else return (0); } /* ISIRAF -- return 1 if IRAF imh file, else 0 */ int isiraf (filename) char *filename; /* Name of file for which to find size */ { if (strchr (filename, '=')) return (0); else if (strsrch (filename, ".imh")) return (1); else return (0); } /* IRAFSIZE -- return size of file in bytes */ static int irafsize (diskfile) FILE *diskfile; /* Descriptor of file for which to find size */ { long filesize; long offset; offset = (long) 0; /* Move to end of the file */ if (fseek (diskfile, offset, SEEK_END) == 0) { /* Position is the size of the file */ filesize = ftell (diskfile); /* Move file pointer back tot he start of the file */ fseek (diskfile, offset, SEEK_SET); } else filesize = -1; return (filesize); } /* Feb 15 1996 New file * Apr 10 1996 Add more documentation * Apr 17 1996 Print error message on open failure * Jun 5 1996 Add byte swapping (reversal); use streams * Jun 10 1996 Make fixes after running lint * Jun 12 1996 Use IMSWAP subroutines instead of local ones * Jul 3 1996 Go back to using local IRAFSWAP subroutines * Jul 3 1996 Write to pixel file from FITS header * Jul 10 1996 Allocate all headers * Aug 13 1996 Add unistd.h to include list * Aug 26 1996 Allow 1-d images; fix comments; fix arguments after lint * Aug 26 1996 Add IRAF header lingth argument to IRAFWIMAGE and IRAFWHEAD * Aug 28 1996 Clean up code in IRAF2FITS * Aug 30 1996 Use write instead of fwrite * Sep 4 1996 Fix write mode bug * Oct 15 1996 Drop unused variables * Oct 17 1996 Minor fix after lint; cast arguments to STR2IRAF * * May 15 1997 Fix returned header length in IRAF2FITS * Dec 19 1997 Add IRAF version 2 .imh files * * Jan 2 1998 Allow uneven length of user parameter lines in IRAF headers * Jan 6 1998 Fix output of imh2 headers; allow newlines in imh1 headers * Jan 14 1998 Handle byte reversing correctly * Apr 17 1998 Add new IRAF data types unsigned char and unsigned short * Apr 30 1998 Fix error return if illegal data type after Allan Brighton * May 15 1998 Delete header keywords used for IRAF binary values * May 15 1998 Fix bug so FITS OBJECT is put into IRAF title * May 26 1998 Fix bug in fits2iraf keeping track of end of header * May 27 1998 Include fitsio.h instead of fitshead.h * Jun 4 1998 Write comments into header for converted IRAF binary values * Jun 4 1998 Pad FITS strings to 8 character minimum * Jul 24 1998 Write header file length to IRAF header file * Jul 27 1998 Print error messages to stderr for all failed malloc's * Jul 27 1998 Fix bug padding FITS header with spaces in iraf2fits * Jul 27 1998 Write modification time to IRAF header file * Aug 6 1998 Change fitsio.h to fitsfile.h; imhio.c to imhfile.c * Oct 1 1998 Set irafswap flag only once per file * Oct 5 1998 Add subroutines irafsize() and isiraf() * Nov 16 1998 Fix byte-swap checking * * Jan 27 1999 Read and write all of 3D image if one dimension is =1 * Jul 13 1999 Improve error messages; change irafsize() argument to fd * Sep 22 1999 Don't copy OBJECT keyword from .imh file; use binary title * Oct 14 1999 Set FITS header length * Oct 20 1999 Allocate 5000 extra bytes for IRAF header * Nov 2 1999 Fix getclocktime() to use only time.h subroutines * Nov 2 1999 Add modification date and time to FITS header in iraf2fits() * Nov 24 1999 Delete HEADSWAP, IMHVER, DATE-MOD from header before writing * Nov 29 1999 Delete PIXSWAP, IRAF-MIN, IRAF-MAX from header before writing * * Jan 13 2000 Fix bug which dropped characters in iraf2fits() * Feb 3 2000 Declare timezone long, not time_t; drop unused variable * Mar 7 2000 Add more code to keep pixel file path short * Mar 10 2000 Fix bugs when writing .imh file headers * Mar 21 2000 Change computation of IRAF time tags to use only data structure * Mar 22 2000 Move IRAF time tag computation to lt2tsi() in dateutil.c * Mar 24 2000 Use Unix file update time if none in header * Mar 27 2000 Use hputm() to save file paths up to 256 characters * Mar 27 2000 Write filename comments after 1st keyword with short value * Mar 27 2000 Allocate pixel file name in same_path to imh2 length * Mar 29 2000 Add space after last linefeed of header in fits2iraf() * Apr 28 2000 Dimension pixname in irafwimage() * May 1 2000 Fix code for updating pixel file name with HDR$ in fits2iraf() * Jun 2 2000 Drop unused variables in fits2iraf() after lint * Jun 12 2000 If pixel filename has no / or $, use same path as header file * Sep 6 2000 Use header directory if pixel file not found at its pathname * * Jan 11 2001 Print all messages to stderr * Aug 24 2001 In isiraf(), return 0 if argument contains an equal sign * * Apr 8 2002 Fix bug in error message for unidentified nbits in fits2iraf() * * Feb 4 2003 Open catalog file rb instead of r (Martin Ploner, Bern) * Oct 31 2003 Read image only in irafrimage() if physical dimension > image dim. * Nov 3 2003 Set NAXISi to image, not physical dimensions in iraf2fits() * * Jun 13 2005 Drop trailing spaces on pixel file name * * Jun 20 2006 Initialize uninitialized variables * * Jan 4 2007 Change hputr4() calls to send pointer to value * Jan 8 2007 Drop unused variable nbx in irafrimage() * Jan 8 2007 Align header and image buffers properly by 4 and by BITPIX * * May 20 2011 Free newpixname, not pixname in irafwimage() * * Mar 27 2012 Fix pixname's appending to newpixname to avoid overflow */ wcstools-3.9.5/libwcs/imio.c0000664000016200001660000011152412044271625015046 0ustar minkoirsys/*** File wcslib/imio.c *** October 30, 2012 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2012 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: imio.c (image pixel manipulation) * Purpose: Read and write pixels from arbitrary data type 2D arrays * Subroutine: getpix (image, bitpix, w, h, bz, bs, x, y) * Read pixel from 2D image of any numeric type (0,0 lower left) * Subroutine: getpix1 (image, bitpix, w, h, bz, bs, x, y) * Read pixel from 2D image of any numeric type (1,1 lower left) * Subroutine: putpix (image, bitpix, w, h, bz, bs, x, y, dpix) * Write pixel into 2D image of any numeric type (0,0 lower left) * Subroutine: putpix1 (image, bitpix, w, h, bz, bs, x, y, dpix) * Write pixel into 2D image of any numeric type (1,1 lower left) * Subroutine: addpix (image, bitpix, w, h, bz, bs, x, y, dpix) * Copy pixel into 2D image of any numeric type (0,0 lower left) * Subroutine: addpix1 (image, bitpix, w, h, bz, bs, x, y, dpix) * Add pixel into 2D image of any numeric type (1,1 lower left) * Subroutine: maxvec (image, bitpix, bz, bs, pix1, npix) * Get maximum of vector from 2D image of any numeric type * Subroutine: minvec (image, bitpix, bz, bs, pix1, npix) * Get minimum of vector from 2D image of any numeric type * Subroutine: getvec (image, bitpix, bz, bs, pix1, npix, dvec) * Get vector from 2D image of any numeric type * Subroutine: putvec (image, bitpix, bz, bs, pix1, npix, dvec) * Copy pixel vector into a vector of any numeric type * Subroutine: addvec (image, bitpix, bz, bs, pix1, npix, dpix) * Add constant to pixel values in a vector * Subroutine: multvec (image, bitpix, bz, bs, pix1, npix, dpix) * Multiply pixel values in a vector by a constant * Subroutine: fillvec (image, bitpix, bz, bs, pix1, npix, dpix) * Copy pixel value in a vector of any numeric type * Subroutine: fillvec1 (image, bitpix, bz, bs, pix1, npix, dpix) * Copy pixel value int a vector of any numeric type * Subroutine: movepix (image1, bitpix, w1, x1, y1, image2, w2, x2, y2) * Copy pixel from one image location to another * Subroutine: imswap (bitpix,string,nbytes) * Swap bytes in string in place, with FITS bits/pixel code * Subroutine: imswap2 (string,nbytes) * Swap bytes in string in place * Subroutine imswap4 (string,nbytes) * Reverse bytes of Integer*4 or Real*4 vector in place * Subroutine imswap8 (string,nbytes) * Reverse bytes of Real*8 vector in place * Subroutine imswapped () * Return 1 if PC/DEC byte order, else 0 */ #include #include #include "fitsfile.h" static int scale = 1; /* If 0, skip scaling step */ void setscale (scale0) int scale0; {scale = scale0; return;} /* GETPIX1 -- Get pixel from 2D FITS image of any numeric type */ double getpix1 (image, bitpix, w, h, bzero, bscale, x, y) char *image; /* Image array as 1-D vector */ int bitpix; /* FITS bits per pixel */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ int w; /* Image width in pixels */ int h; /* Image height in pixels */ double bzero; /* Zero point for pixel scaling */ double bscale; /* Scale factor for pixel scaling */ int x; /* One-based horizontal pixel number */ int y; /* One-based vertical pixel number */ { return (getpix (image, bitpix, w, h, bzero, bscale, x-1, y-1)); } /* GETPIX -- Get pixel from 2D image of any numeric type */ double getpix (image, bitpix, w, h, bzero, bscale, x, y) char *image; /* Image array as 1-D vector */ int bitpix; /* FITS bits per pixel */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ int w; /* Image width in pixels */ int h; /* Image height in pixels */ double bzero; /* Zero point for pixel scaling */ double bscale; /* Scale factor for pixel scaling */ int x; /* Zero-based horizontal pixel number */ int y; /* Zero-based vertical pixel number */ { short *im2; int *im4; unsigned char *im1; unsigned short *imu; float *imr; double *imd; double dpix; /* Return 0 if coordinates are not inside image */ if (x < 0 || x >= w) return (0.0); if (y < 0 || y >= h) return (0.0); /* Extract pixel from appropriate type of array */ switch (bitpix) { case 8: im1 = (unsigned char *)image; dpix = (double) im1[(y*w) + x]; break; case 16: im2 = (short *)image; dpix = (double) im2[(y*w) + x]; break; case 32: im4 = (int *)image; dpix = (double) im4[(y*w) + x]; break; case -16: imu = (unsigned short *)image; dpix = (double) imu[(y*w) + x]; break; case -32: imr = (float *)image; dpix = (double) imr[(y*w) + x]; break; case -64: imd = (double *)image; dpix = imd[(y*w) + x]; break; default: dpix = 0.0; } if (scale) return (bzero + (bscale * dpix)); else return (dpix); } /* PUTPIX1 -- Copy pixel into 2D FITS image of any numeric type */ void putpix1 (image, bitpix, w, h, bzero, bscale, x, y, dpix) char *image; int bitpix; /* Number of bits per pixel */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ int w; /* Image width in pixels */ int h; /* Image height in pixels */ double bzero; /* Zero point for pixel scaling */ double bscale; /* Scale factor for pixel scaling */ int x; /* One-based horizontal pixel number */ int y; /* One-based vertical pixel number */ double dpix; { putpix (image, bitpix, w, h, bzero, bscale, x-1, y-1, dpix); return; } /* PUTPIX -- Copy pixel into 2D image of any numeric type */ void putpix (image, bitpix, w, h, bzero, bscale, x, y, dpix) char *image; int bitpix; /* Number of bits per pixel */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ int w; /* Image width in pixels */ int h; /* Image height in pixels */ double bzero; /* Zero point for pixel scaling */ double bscale; /* Scale factor for pixel scaling */ int x; int y; double dpix; { double *imd; float *imr; int *im4; short *im2; unsigned short *imu; unsigned char *im1; /* Return if coordinates are not inside image */ if (x < 0 || x >= w) return; if (y < 0 || y >= h) return; if (scale) dpix = (dpix - bzero) / bscale; switch (bitpix) { case 8: im1 = (unsigned char *)image; if (dpix < 0) im1[(y*w) + x] = (unsigned char) (dpix - 0.5); else im1[(y*w) + x] = (unsigned char) (dpix + 0.5); break; case 16: im2 = (short *)image; if (dpix < 0) im2[(y*w) + x] = (short) (dpix - 0.5); else im2[(y*w) + x] = (short) (dpix + 0.5); break; case 32: im4 = (int *)image; if (dpix < 0) im4[(y*w) + x] = (int) (dpix - 0.5); else im4[(y*w) + x] = (int) (dpix + 0.5); break; case -16: imu = (unsigned short *)image; if (dpix < 0) imu[(y*w) + x] = (unsigned short) 0; else imu[(y*w) + x] = (unsigned short) (dpix + 0.5); break; case -32: imr = (float *)image; imr[(y*w) + x] = (float) dpix; break; case -64: imd = (double *)image; imd[(y*w) + x] = dpix; break; } return; } /* ADDPIX1 -- Add pixel value into 2D FITS image of any numeric type */ void addpix1 (image, bitpix, w, h, bzero, bscale, x, y, dpix) char *image; int bitpix; /* Number of bits per pixel */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ int w; /* Image width in pixels */ int h; /* Image height in pixels */ double bzero; /* Zero point for pixel scaling */ double bscale; /* Scale factor for pixel scaling */ int x; /* One-based horizontal pixel number */ int y; /* One-based vertical pixel number */ double dpix; /* Value to add to pixel */ { addpix (image, bitpix, w, h, bzero, bscale, x-1, y-1, dpix); return; } /* ADDPIX -- Add constant to pixel values in 2D image of any numeric type */ void addpix (image, bitpix, w, h, bzero, bscale, x, y, dpix) char *image; int bitpix; /* Number of bits per pixel */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ int w; /* Image width in pixels */ int h; /* Image height in pixels */ double bzero; /* Zero point for pixel scaling */ double bscale; /* Scale factor for pixel scaling */ int x; /* Zero-based horizontal pixel number */ int y; /* Zero-based vertical pixel number */ double dpix; /* Value to add to pixel */ { double *imd; float *imr; int *im4; short *im2; unsigned short *imu; unsigned char *im1; int ipix; /* Return if coordinates are not inside image */ if (x < 0 || x >= w) return; if (y < 0 || y >= h) return; if (scale) dpix = (dpix - bzero) / bscale; ipix = (y * w) + x; switch (bitpix) { case 8: im1 = (unsigned char *)image; if (dpix < 0) image[ipix] = im1[ipix] + (unsigned char) (dpix - 0.5); else image[ipix] = im1[ipix] + (unsigned char) (dpix + 0.5); break; case 16: im2 = (short *)image; if (dpix < 0) im2[ipix] = im2[ipix] + (short) (dpix - 0.5); else im2[ipix] = im2[ipix] + (short) (dpix + 0.5); break; case 32: im4 = (int *)image; if (dpix < 0) im4[ipix] = im4[ipix] + (int) (dpix - 0.5); else im4[ipix] = im4[ipix] + (int) (dpix + 0.5); break; case -16: imu = (unsigned short *)image; if (dpix > 0) imu[ipix] = imu[ipix] + (unsigned short) (dpix + 0.5); break; case -32: imr = (float *)image; imr[ipix] = imr[ipix] + (float) dpix; break; case -64: imd = (double *)image; imd[ipix] = imd[ipix] + dpix; break; } return; } /* MOVEPIX -- Copy pixel between images */ void movepix (image1, bitpix1, w1, x1, y1, image2, bitpix2, w2, x2, y2) char *image1; /* Pointer to first pixel in input image */ int bitpix1; /* Bits per input pixel (FITS codes) */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ int w1; /* Number of horizontal pixels in input image */ int x1, y1; /* Row and column for input pixel */ char *image2; /* Pointer to first pixel in output image */ int bitpix2; /* Bits per output pixel (FITS codes) */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ int w2; /* Number of horizontal pixels in output image */ int x2, y2; /* Row and column for output pixel */ { double dpix, *imd1, *imd2; float rpix, *imr1, *imr2; int *imi1, *imi2; short *ims1, *ims2; unsigned short *imu1, *imu2; unsigned char *imc1, *imc2; if (x1 < 0 || x2 < 0 || x1 >= w1 || x2 >= w2) return; if (y1 < 0 || y2 < 0) return; switch (bitpix1) { case 8: imc1 = (unsigned char *)image1; switch (bitpix2) { case 8: imc2 = (unsigned char *)image2; imc2[(y2*w2) + x2] = imc1[(y1*w1) + x1]; break; case 16: ims2 = (short *)image2; ims2[(y2*w2) + x2] = (short) imc1[(y1*w1) + x1]; break; case 32: imi2 = (int *)image2; imi2[(y2*w2) + x2] = (int) imc1[(y1*w1) + x1]; break; case -16: imu2 = (unsigned short *)image2; imu2[(y2*w2) + x2] = (unsigned short) imc1[(y1*w1) + x1]; break; case -32: imr2 = (float *)image2; imr2[(y2*w2) + x2] = (float) imc1[(y1*w1) + x1]; break; case -64: imd2 = (double *)image2; imd2[(y2*w2) + x2] = (double) imc1[(y1*w1) + x1]; break; } break; case 16: ims1 = (short *)image1; switch (bitpix2) { case 8: imc2 = (unsigned char *)image1; imc2[(y2*w2) + x2] = (unsigned char) ims1[(y1*w1) + x1]; break; case 16: ims2 = (short *)image2; ims2[(y2*w2) + x2] = ims1[(y1*w1) + x1]; break; case 32: imi2 = (int *)image2; imi2[(y2*w2) + x2] = (int) ims1[(y1*w1) + x1]; break; case -16: imu2 = (unsigned short *)image2; imu2[(y2*w2) + x2] = (unsigned short) ims1[(y1*w1) + x1]; break; case -32: imr2 = (float *)image2; imr2[(y2*w2) + x2] = (float) ims1[(y1*w1) + x1]; break; case -64: imd2 = (double *)image2; imd2[(y2*w2) + x2] = (double) ims1[(y1*w1) + x1]; break; } break; case 32: imi1 = (int *)image1; switch (bitpix2) { case 8: imc2 = (unsigned char *)image2; imc2[(y2*w2) + x2] = (unsigned char) imi1[(y1*w1) + x1]; break; case 16: ims2 = (short *)image2; ims2[(y2*w2) + x2] = (short) imi1[(y1*w1) + x1]; break; case 32: imi2 = (int *)image2; imi2[(y2*w2) + x2] = imi1[(y1*w1) + x1]; break; case -16: imu2 = (unsigned short *)image2; imu2[(y2*w2) + x2] = (unsigned short) imi1[(y1*w1) + x1]; break; case -32: imr2 = (float *)image2; imr2[(y2*w2) + x2] = (float) imi1[(y1*w1) + x1]; break; case -64: imd2 = (double *)image2; imd2[(y2*w2) + x2] = (double) imi1[(y1*w1) + x1]; break; } break; case -16: imu1 = (unsigned short *)image1; switch (bitpix2) { case 8: imc2 = (unsigned char *)image2; imc2[(y2*w2) + x2] = (unsigned char) imu1[(y1*w1) + x1]; break; case 16: ims2 = (short *)image2; ims2[(y2*w2) + x2] = (short) imu1[(y1*w1) + x1]; break; case 32: imi2 = (int *)image2; imi2[(y2*w2) + x2] = (int) imu1[(y1*w1) + x1]; break; case -16: imu2 = (unsigned short *)image2; imu2[(y2*w2) + x2] = imu1[(y1*w1) + x1]; break; case -32: imr2 = (float *)image2; imr2[(y2*w2) + x2] = (float) imu1[(y1*w1) + x1]; break; case -64: imd2 = (double *)image2; imd2[(y2*w2) + x2] = (double) imu1[(y1*w1) + x1]; break; } break; case -32: imr1 = (float *)image1; rpix = imr1[(y1*w1) + x1]; switch (bitpix2) { case 8: imc2 = (unsigned char *)image2; if (rpix < 0.0) imc2[(y2*w2) + x2] = (unsigned char) 0; else imc2[(y2*w2) + x2] = (unsigned char) (rpix + 0.5); break; case 16: ims2 = (short *)image2; if (rpix < 0.0) ims2[(y2*w2) + x2] = (short) (rpix - 0.5); else ims2[(y2*w2) + x2] = (short) (rpix + 0.5); break; case 32: imi2 = (int *)image2; if (rpix < 0.0) imi2[(y2*w2) + x2] = (int) (rpix - 0.5); else imi2[(y2*w2) + x2] = (int) (rpix + 0.5); break; case -16: imu2 = (unsigned short *)image2; if (rpix < 0.0) imu2[(y2*w2) + x2] = (unsigned short) 0; else imu2[(y2*w2) + x2] = (unsigned short) (rpix + 0.5); break; case -32: imr2 = (float *)image2; imr2[(y2*w2) + x2] = rpix; break; case -64: imd2 = (double *)image2; imd2[(y2*w2) + x2] = (double) rpix; break; } break; case -64: imd1 = (double *)image1; dpix = imd1[(y1*w1) + x1]; switch (bitpix2) { case 8: imc2 = (unsigned char *)image2; if (dpix < 0.0) imc2[(y2*w2) + x2] = (unsigned char) 0; else imc2[(y2*w2) + x2] = (unsigned char) (dpix + 0.5); break; case 16: ims2 = (short *)image2; if (dpix < 0.0) ims2[(y2*w2) + x2] = (short) (dpix - 0.5); else ims2[(y2*w2) + x2] = (short) (dpix + 0.5); break; case 32: imi2 = (int *)image2; if (dpix < 0.0) imi2[(y2*w2) + x2] = (int) (dpix - 0.5); else imi2[(y2*w2) + x2] = (int) (dpix + 0.5); break; case -16: imu2 = (unsigned short *)image2; if (dpix < 0.0) imu2[(y2*w2) + x2] = (unsigned short) 0; else imu2[(y2*w2) + x2] = (unsigned short) (dpix + 0.5); break; case -32: imr2 = (float *)image2; imr2[(y2*w2) + x2] = (float) dpix; break; case -64: imd2 = (double *)image2; imd2[(y2*w2) + x2] = dpix; break; } break; } return; } /* MAXVEC -- Get maximum value in vector from 2D image of any numeric type */ double maxvec (image, bitpix, bzero, bscale, pix1, npix) char *image; /* Image array from which to read vector */ int bitpix; /* Number of bits per pixel in image */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ double bzero; /* Zero point for pixel scaling */ double bscale; /* Scale factor for pixel scaling */ int pix1; /* Offset of first pixel to check */ int npix; /* Number of pixels to check */ { short *im2, imax2, ip2; int *im4, imax4, ip4; unsigned short *imu, imaxu, ipu; float *imr, imaxr, ipr; double *imd; double dmax = 0.0; double ipd; int ipix, pix2; unsigned char *imc, imaxc, ipc; pix2 = pix1 + npix; switch (bitpix) { case 8: imc = (unsigned char *)(image); imaxc = *(imc + pix1); for (ipix = pix1; ipix < pix2; ipix++) { ipc = *(imc + ipix); if (ipc > imaxc) imaxc = ipc; } dmax = (double) imaxc; break; case 16: im2 = (short *)image; imax2 = *(im2 + pix1); for (ipix = pix1; ipix < pix2; ipix++) { ip2 = *(im2 + ipix); if (ip2 > imax2) imax2 = ip2; } dmax = (double) imax2; break; case 32: im4 = (int *)image; imax4 = *(im4 + pix1); for (ipix = pix1; ipix < pix2; ipix++) { ip4 = *(im4 + ipix); if (ip4 > imax4) imax4 = ip4; } dmax = (double) imax4; break; case -16: imu = (unsigned short *)image; imaxu = *(imu + pix1); for (ipix = pix1; ipix < pix2; ipix++) { ipu = *(imu + ipix); if (ipu > imaxu) imaxu = ipu; } dmax = (double) imaxu; break; case -32: imr = (float *)image; imaxr = *(imr + pix1); for (ipix = pix1; ipix < pix2; ipix++) { ipr = *(imr + ipix); if (ipr > imaxr) imax2 = ipr; } dmax = (double) imaxr; break; case -64: imd = (double *)image; dmax = *(imd + pix1); for (ipix = pix1; ipix < pix2; ipix++) { ipd = *(imd + ipix); if (ipd > dmax) dmax = ipd; } break; } /* Scale data if either BZERO or BSCALE keyword has been set */ if (scale && (bzero != 0.0 || bscale != 1.0)) dmax = (dmax * bscale) + bzero; return (dmax); } /* MINVEC -- Get minimum value in vector from 2D image of any numeric type */ double minvec (image, bitpix, bzero, bscale, pix1, npix) char *image; /* Image array from which to read vector */ int bitpix; /* Number of bits per pixel in image */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ double bzero; /* Zero point for pixel scaling */ double bscale; /* Scale factor for pixel scaling */ int pix1; /* Offset of first pixel to check */ int npix; /* Number of pixels to check */ { short *im2, imin2, ip2; int *im4, imin4, ip4; unsigned short *imu, iminu, ipu; float *imr, iminr, ipr; double *imd, ipd; double dmin = 0.0; int ipix, pix2; unsigned char *imc, cmin, cp; pix2 = pix1 + npix; switch (bitpix) { case 8: imc = (unsigned char *)image; cmin = *(imc + pix1); for (ipix = pix1; ipix < pix2; ipix++) { cp = *(imc + ipix); if (cp < cmin) cmin = cp; } dmin = (double) cmin; break; case 16: im2 = (short *)image + pix1; imin2 = *im2; for (ipix = pix1; ipix < pix2; ipix++) { ip2 = *(im2 + ipix); if (ip2 < imin2) imin2 = ip2; } dmin = (double) imin2; break; case 32: im4 = (int *)image; imin4 = *(im4 + pix1); for (ipix = pix1; ipix < pix2; ipix++) { ip4 = *(im4 + ipix); if (ip4 < imin4) imin4 = ip4; } dmin = (double) imin4; break; case -16: imu = (unsigned short *)image; iminu = *(imu + pix1); for (ipix = pix1; ipix < pix2; ipix++) { ipu = *(imu + ipix); if (ipu < iminu) iminu = ipu; } dmin = (double) iminu; break; case -32: imr = (float *)image; iminr = *(imr + pix1); for (ipix = pix1; ipix < pix2; ipix++) { ipr = *(imr + ipix); if (ipr < iminr) iminr = ipr; } dmin = (double) iminr; break; case -64: imd = (double *)image; dmin = *(imd + pix1); for (ipix = pix1; ipix < pix2; ipix++) { ipd = *(imd + ipix); if (ipd < dmin) dmin = ipd; } break; } /* Scale data if either BZERO or BSCALE keyword has been set */ if (scale && (bzero != 0.0 || bscale != 1.0)) dmin = (dmin * bscale) + bzero; return (dmin); } /* ADDVEC -- Add constant to pixel values in 2D image of any numeric type */ void addvec (image, bitpix, bzero, bscale, pix1, npix, dpix) char *image; /* Image array from which to extract vector */ int bitpix; /* Number of bits per pixel in image */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ double bzero; /* Zero point for pixel scaling */ double bscale; /* Scale factor for pixel scaling */ int pix1; /* Offset of first pixel to extract */ int npix; /* Number of pixels to extract */ double dpix; /* Value to add to pixels */ { unsigned char *imc, ccon; short *im2, jcon; int *im4, icon; unsigned short *imu, ucon; float *imr, rcon; double *imd; int ipix, pix2; pix2 = pix1 + npix; if (scale) dpix = (dpix - bzero) / bscale; switch (bitpix) { case 8: imc = (unsigned char *) (image + pix1); if (dpix < 0) ccon = (unsigned char) (dpix - 0.5); else ccon = (unsigned char) (dpix + 0.5); for (ipix = pix1; ipix < pix2; ipix++) *imc++ += ccon; break; case 16: im2 = (short *) (image + pix1); if (dpix < 0) jcon = (short) (dpix - 0.5); else jcon = (short) (dpix + 0.5); for (ipix = pix1; ipix < pix2; ipix++) *im2++ += jcon; break; case 32: im4 = (int *) (image + pix1); if (dpix < 0) icon = (int) (dpix - 0.5); else icon = (int) (dpix + 0.5); for (ipix = pix1; ipix < pix2; ipix++) *im4++ += icon; break; case -16: imu = (unsigned short *) (image + pix1); if (dpix > 0) { ucon = (unsigned short) (dpix + 0.5); imu = (unsigned short *) (image + pix1); for (ipix = pix1; ipix < pix2; ipix++) *imu++ += ucon; } else { icon = (int) (dpix - 0.5); imu = (unsigned short *) (image + pix1); for (ipix = pix1; ipix < pix2; ipix++) { unsigned short tmp = (icon + (int) *imu); *imu++ += tmp; } } break; case -32: rcon = (float) dpix; imr = (float *) (image + pix1); for (ipix = pix1; ipix < pix2; ipix++) *imr++ += rcon; break; case -64: imd = (double *) (image + pix1); for (ipix = pix1; ipix < pix2; ipix++) *imd++ += dpix; break; } return; } /* MULTVEC -- Multiply pixel values in place in 2D image of any numeric type */ void multvec (image, bitpix, bzero, bscale, pix1, npix, dpix) char *image; /* Image array from which to extract vector */ int bitpix; /* Number of bits per pixel in image */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ double bzero; /* Zero point for pixel scaling */ double bscale; /* Scale factor for pixel scaling */ int pix1; /* Offset of first pixel to extract */ int npix; /* Number of pixels to extract */ double dpix; /* Value by which to multiply pixels */ { char *imc, ccon; short *im2, jcon; int *im4, icon, isint; unsigned short *imu, ucon; float *imr, rcon; double *imd, dcon, dval; int ipix, pix2; pix2 = pix1 + npix; if (scale) dpix = (dpix - bzero) / bscale; ipix = (int) dpix; dcon = (double) ipix; if (dcon == dpix) isint = 1; else isint = 0; switch (bitpix) { case 8: imc = image + pix1; if (isint) { if (dpix < 0) ccon = (char) (dpix - 0.5); else ccon = (char) (dpix + 0.5); for (ipix = pix1; ipix < pix2; ipix++) *imc++ *= ccon; } else { for (ipix = pix1; ipix < pix2; ipix++) { dval = ((double) *imc) * dpix; if (dval < 256.0) *imc++ = (char) dval; else *imc++ = (char) 255; } } break; case 16: im2 = (short *) (image + pix1); if (isint) { im2 = (short *)image; if (dpix < 0) jcon = (short) (dpix - 0.5); else jcon = (short) (dpix + 0.5); for (ipix = pix1; ipix < pix2; ipix++) *im2++ *= jcon; } else { for (ipix = pix1; ipix < pix2; ipix++) { dval = ((double) *im2) * dpix; if (dval < 32768.0) *im2++ = (short) dval; else *im2++ = (short) 32767; } } break; case 32: im4 = (int *) (image + pix1); if (isint) { if (dpix < 0) icon = (int) (dpix - 0.5); else icon = (int) (dpix + 0.5); for (ipix = pix1; ipix < pix2; ipix++) *im4++ *= icon; } else { for (ipix = pix1; ipix < pix2; ipix++) { dval = ((double) *im4) * dpix; if (dval < 32768.0) *im4++ = (int) dval; else *im4++ = (int) 32767; } } break; case -16: imu = (unsigned short *) (image + pix1); if (dpix > 0) { ucon = (unsigned short) (dpix + 0.5); imu = (unsigned short *) (image + pix1); for (ipix = pix1; ipix < pix2; ipix++) *imu++ *= ucon; } break; case -32: rcon = (float) dpix; imr = (float *) (image + pix1); for (ipix = pix1; ipix < pix2; ipix++) *imr++ *= rcon; break; case -64: imd = (double *) (image + pix1); for (ipix = pix1; ipix < pix2; ipix++) *imd++ *= dpix; break; } return; } /* GETVEC -- Get vector from 2D image of any numeric type */ void getvec (image, bitpix, bzero, bscale, pix1, npix, dvec0) char *image; /* Image array from which to extract vector */ int bitpix; /* Number of bits per pixel in image */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ double bzero; /* Zero point for pixel scaling */ double bscale; /* Scale factor for pixel scaling */ int pix1; /* Offset of first pixel to extract */ int npix; /* Number of pixels to extract */ double *dvec0; /* Vector of pixels (returned) */ { short *im2; int *im4; unsigned short *imu; float *imr; double *imd; double *dvec; int ipix, pix2; pix2 = pix1 + npix; dvec = dvec0; switch (bitpix) { case 8: for (ipix = pix1; ipix < pix2; ipix++) *dvec++ = (double) *(image + ipix); break; case 16: im2 = (short *)image; for (ipix = pix1; ipix < pix2; ipix++) *dvec++ = (double) *(im2 + ipix); break; case 32: im4 = (int *)image; for (ipix = pix1; ipix < pix2; ipix++) *dvec++ = (double) *(im4 + ipix); break; case -16: imu = (unsigned short *)image; for (ipix = pix1; ipix < pix2; ipix++) *dvec++ = (double) *(imu + ipix); break; case -32: imr = (float *)image; for (ipix = pix1; ipix < pix2; ipix++) *dvec++ = (double) *(imr + ipix); break; case -64: imd = (double *)image; for (ipix = pix1; ipix < pix2; ipix++) *dvec++ = (double) *(imd + ipix); break; } /* Scale data if either BZERO or BSCALE keyword has been set */ if (scale && (bzero != 0.0 || bscale != 1.0)) { dvec = dvec0; for (ipix = pix1; ipix < pix2; ipix++) { *dvec = (*dvec * bscale) + bzero; dvec++; } } return; } /* PUTVEC -- Copy pixel vector into 2D image of any numeric type */ void putvec (image, bitpix, bzero, bscale, pix1, npix, dvec) char *image; /* Image into which to copy vector */ int bitpix; /* Number of bits per pixel im image */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ double bzero; /* Zero point for pixel scaling */ double bscale; /* Scale factor for pixel scaling */ int pix1; /* Offset of first pixel of vector in image */ int npix; /* Number of pixels to copy */ double *dvec; /* Vector of pixels to copy */ { short *im2; int *im4; unsigned short *imu; float *imr; double *imd; int ipix, pix2; double *dp = dvec; pix2 = pix1 + npix; /* Scale data if either BZERO or BSCALE keyword has been set */ if (scale && (bzero != 0.0 || bscale != 1.0)) { for (ipix = pix1; ipix < pix2; ipix++) { *dp = (*dp - bzero) / bscale; dp++; } dp = dvec; } switch (bitpix) { case 8: for (ipix = pix1; ipix < pix2; ipix++) *(image+ipix) = (char) *dp++; break; case 16: im2 = (short *)image; for (ipix = pix1; ipix < pix2; ipix++) { if (*dp < 0.0) *(im2+ipix) = (short) (*dp++ - 0.5); else *(im2+ipix) = (short) (*dp++ + 0.5); } break; case 32: im4 = (int *)image; for (ipix = pix1; ipix < pix2; ipix++) { if (*dp < 0.0) *(im4+ipix) = (int) (*dp++ - 0.5); else *(im4+ipix) = (int) (*dp++ + 0.5); } break; case -16: imu = (unsigned short *)image; for (ipix = pix1; ipix < pix2; ipix++) { if (*dp < 0.0) *(imu+ipix) = (unsigned short) 0; else *(imu+ipix) = (unsigned short) (*dp++ + 0.5); } break; case -32: imr = (float *)image; for (ipix = pix1; ipix < pix2; ipix++) *(imr+ipix) = (float) *dp++; break; case -64: imd = (double *)image; for (ipix = pix1; ipix < pix2; ipix++) *(imd+ipix) = (double) *dp++; break; } return; } /* FILLVEC1 -- Copy single value into a vector of any numeric type */ void fillvec1 (image, bitpix, bzero, bscale, pix1, npix, dpix) char *image; /* Vector to fill */ int bitpix; /* Number of bits per pixel im image */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ double bzero; /* Zero point for pixel scaling */ double bscale; /* Scale factor for pixel scaling */ int pix1; /* First pixel to fill */ int npix; /* Number of pixels to fill */ double dpix; /* Value with which to fill pixels */ { fillvec (image, bitpix, bzero, bscale, pix1-1, npix, dpix); return; } /* FILLVEC -- Copy single value into a vector of any numeric type */ void fillvec (image, bitpix, bzero, bscale, pix1, npix, dpix) char *image; /* Vector to fill */ int bitpix; /* Number of bits per pixel im image */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ double bzero; /* Zero point for pixel scaling */ double bscale; /* Scale factor for pixel scaling */ int pix1; /* First pixel to fill */ int npix; /* Number of pixels to fill */ double dpix; /* Value with which to fill pixels */ { char ipc; short *im2, ip2; int *im4, ip4; unsigned short *imu, ipu; float *imr, ipr; double *imd; int ipix, pix2; double dp; pix2 = pix1 + npix; /* Scale data if either BZERO or BSCALE keyword has been set */ dp = dpix; if (scale && (bzero != 0.0 || bscale != 1.0)) dp = (dp - bzero) / bscale; switch (bitpix) { case 8: if (dp < 0.0) ipc = (char) (dp - 0.5); else ipc = (char) (dp + 0.5); for (ipix = pix1; ipix < pix2; ipix++) image[ipix] = ipc; break; case 16: im2 = (short *)image; if (dp < 0.0) ip2 = (short) (dp - 0.5); else ip2 = (short) (dp + 0.5); for (ipix = pix1; ipix < pix2; ipix++) im2[ipix] = ip2; break; case 32: im4 = (int *)image; if (dp < 0.0) ip4 = (int) (dp - 0.5); else ip4 = (int) (dp + 0.5); for (ipix = pix1; ipix < pix2; ipix++) im4[ipix] = ip4; break; case -16: imu = (unsigned short *)image; if (dp < 0.0) ipu = (unsigned short) (dp - 0.5); else ipu = (unsigned short) (dp + 0.5); for (ipix = pix1; ipix < pix2; ipix++) imu[ipix] = ipu; break; case -32: imr = (float *)image; ipr = (float) dp; for (ipix = pix1; ipix < pix2; ipix++) imr[ipix] = ipr; break; case -64: imd = (double *)image; for (ipix = pix1; ipix < pix2; ipix++) imd[ipix] = dp; break; } return; } /* IMSWAP -- Reverse bytes of any type of vector in place */ void imswap (bitpix, string, nbytes) int bitpix; /* Number of bits per pixel */ /* 16 = short, -16 = unsigned short, 32 = int */ /* -32 = float, -64 = double */ char *string; /* Address of starting point of bytes to swap */ int nbytes; /* Number of bytes to swap */ { switch (bitpix) { case 8: break; case 16: if (nbytes < 2) return; imswap2 (string,nbytes); break; case 32: if (nbytes < 4) return; imswap4 (string,nbytes); break; case -16: if (nbytes < 2) return; imswap2 (string,nbytes); break; case -32: if (nbytes < 4) return; imswap4 (string,nbytes); break; case -64: if (nbytes < 8) return; imswap8 (string,nbytes); break; } return; } /* IMSWAP2 -- Swap bytes in string in place */ void imswap2 (string,nbytes) char *string; /* Address of starting point of bytes to swap */ int nbytes; /* Number of bytes to swap */ { char *sbyte, temp, *slast; slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp = sbyte[0]; sbyte[0] = sbyte[1]; sbyte[1] = temp; sbyte= sbyte + 2; } return; } /* IMSWAP4 -- Reverse bytes of Integer*4 or Real*4 vector in place */ void imswap4 (string,nbytes) char *string; /* Address of Integer*4 or Real*4 vector */ int nbytes; /* Number of bytes to reverse */ { char *sbyte, *slast; char temp0, temp1, temp2, temp3; slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp3 = sbyte[0]; temp2 = sbyte[1]; temp1 = sbyte[2]; temp0 = sbyte[3]; sbyte[0] = temp0; sbyte[1] = temp1; sbyte[2] = temp2; sbyte[3] = temp3; sbyte = sbyte + 4; } return; } /* IMSWAP8 -- Reverse bytes of Real*8 vector in place */ void imswap8 (string,nbytes) char *string; /* Address of Real*8 vector */ int nbytes; /* Number of bytes to reverse */ { char *sbyte, *slast; char temp[8]; slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp[7] = sbyte[0]; temp[6] = sbyte[1]; temp[5] = sbyte[2]; temp[4] = sbyte[3]; temp[3] = sbyte[4]; temp[2] = sbyte[5]; temp[1] = sbyte[6]; temp[0] = sbyte[7]; sbyte[0] = temp[0]; sbyte[1] = temp[1]; sbyte[2] = temp[2]; sbyte[3] = temp[3]; sbyte[4] = temp[4]; sbyte[5] = temp[5]; sbyte[6] = temp[6]; sbyte[7] = temp[7]; sbyte = sbyte + 8; } return; } /* IMSWAPPED -- Returns 0 if big-endian (Sun,Mac), 1 if little-endian(PC,Alpha) */ int imswapped () { char *ctest; int itest; itest = 1; ctest = (char *)&itest; if (*ctest) return (1); else return (0); } /* Apr 17 1996 New file * May 22 1996 Add H so that PUTPIX and GETPIX can check coordinates * Jun 11 1996 Simplify NEWIMAGE subroutine * Jun 12 1996 Add byte-swapping subroutines * * Jul 24 1997 Add 8-bit option to subroutines * * May 27 1998 Include imio.h instead of fitshead.h * Jun 17 1998 Fix bug, changing all unsigned int's to unsigned short's * * Apr 29 1999 Add scaling to getpix, putpix, getvec, and putvec * Apr 29 1999 Fix bug in getvec in dealing with 1-byte data * Sep 14 1999 Change dp incrementing so it works on Alpha compiler * Sep 27 1999 Add interface for 1-based (FITS) image access * Sep 27 1999 Add addpix() and addpix1() * Dec 14 1999 In putpix(), addpix(), putvec(), round when output is integer * * Sep 20 2000 In getvec(), scale only if necessary * * Nov 27 2001 In movepix(), add char to char move * * Jan 23 2002 Add global scale switch to turn off scaling * Jun 4 2002 In getvec() and putvec(), change dpix to dvec * Jun 4 2002 Add addvec() to add to a vector * Jul 19 2002 Fix getvec() bug rescaling scaled numbers * * May 20 2003 Declare scale0 in setscale() * * Jan 28 2004 Add image limit check to movepix() * Feb 27 2004 Add fillvec() and fillvec1() to set vector to a constant * * Jun 27 2005 Fix major bug in fillvec(); pass value dpix in fillvec1(), too * Aug 18 2005 Add maxvec(), addvec(), and multvec() * * Mar 1 2006 Fix bug of occasional double application of bscale in getvec() * Apr 3 2006 Fix bad cast in unisigned int section of addvec() * May 3 2006 Code fixes in addpix and multpix suggested by Robert Lupton * Jun 8 2006 Drop erroneous second im2 assignment without offset in addvec() * Jun 20 2006 Fix typos masquerading as unitialized variables * * Jan 8 2007 Include fitsfile.h instead of imio.h * Jun 11 2007 Add minvec() and speed up maxvec() * * Apr 12 2012 Fix 8-bit variables to be unsigned char * Oct 19 2012 Fix errors with character images in minvec() and maxvec() * Oct 31 2012 Fix errors with short images in minvec() and maxvec() * Oct 31 2012 Drop unused variable il2 from minvec() */ wcstools-3.9.5/libwcs/imrotate.c0000664000016200001660000004546111750060474015744 0ustar minkoirsys/*** File libwcs/imrotate.c *** June 26, 2008 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2008 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include #include "fitsfile.h" static void RotWCSFITS(); /* rotate all the C* fields */ /* Rotate an image by 90, 180, or 270 degrees, with an optional * reflection across the vertical or horizontal axis. * verbose generates extra info on stdout. * return NULL if successful or rotated image. */ char * RotFITS (pathname,header,image0,xshift,yshift,rotate,mirror,bitpix2,rotwcs,verbose) char *pathname; /* Name of file which is being changed */ char *header; /* FITS header */ char *image0; /* Unrotated image pixels */ int xshift; /* Number of pixels to shift image horizontally, +=right */ int yshift; /* Number of pixels to shift image vertically, +=right */ int rotate; /* Angle to by which to rotate image (90, 180, 270) */ int mirror; /* Reflect image around 1=vertical, 2=horizontal axis */ int bitpix2; /* Number of bits per pixel in output image */ int rotwcs; /* If not =0, rotate WCS keywords, else leave them */ int verbose; { int bitpix1, ny, nx, nax; int x1, y1, x2, y2, nbytes; char *rotimage; char *image; char history[128]; char *filename; double crpix; image = NULL; rotimage = NULL; if (rotate == 1) rotate = 90; else if (rotate == 2) rotate = 180; else if (rotate == 3) rotate = 270; else if (rotate < 0) rotate = rotate + 360; filename = strrchr (pathname,'/'); if (filename) filename = filename + 1; else filename = pathname; /* Get image size */ nax = 0; if (hgeti4 (header,"NAXIS",&nax) < 1) { if (verbose) printf ("RotFITS: Not an image (NAXIS=%d)\n",nax); return (NULL); } else { if (hgeti4 (header,"NAXIS1",&nx) < 1) { if (verbose) printf ("RotFITS: Not an image (NAXIS1=%d)\n",nx); return (NULL); } else { if (hgeti4 (header,"NAXIS2",&ny) < 1) { if (verbose) printf ("RotFITS: Not an image (NAXIS2=%d)\n",ny); return (NULL); } } } bitpix1 = 16; hgeti4 (header,"BITPIX", &bitpix1); if (bitpix2 == 0) bitpix2 = bitpix1; /* Shift WCS fields in header */ if (rotwcs && hgetr8 (header, "CRPIX1", &crpix)) { crpix = crpix + xshift; hputr8 (header, "CRPIX1", crpix); } if (rotwcs && hgetr8 (header, "CRPIX2", &crpix)) { crpix = crpix + yshift; hputr8 (header, "CRPIX2", crpix); } /* Rotate WCS fields in header */ if (rotwcs && (rotate != 0 || mirror)) RotWCSFITS (header, rotate, mirror, verbose); /* Compute size of image in bytes */ switch (bitpix2) { case 8: nbytes = nx * ny; break; case 16: nbytes = nx * ny * 2; break; case 32: nbytes = nx * ny * 4; break; case -16: nbytes = nx * ny * 2; break; case -32: nbytes = nx * ny * 4; break; case -64: nbytes = nx * ny * 8; break; default: if (verbose) printf ("RotFITS: Illegal BITPIX (%d)\n", bitpix2); return (NULL); } if (bitpix1 != bitpix2) { sprintf (history,"Copy of image %s bits per pixel %d -> %d", filename, bitpix1, bitpix2); hputc (header,"HISTORY",history); if (verbose) fprintf (stderr,"%s\n",history); } /* Shift image first */ if (xshift != 0 || yshift != 0) { /* Allocate buffer for shifted image */ image = (char *) calloc (nbytes, 1); if (image == NULL) { if (verbose) printf ("RotFITS: Cannot allocate %d bytes for shifted image\n", nbytes); return (NULL); } for (x1 = 0; x1 < nx; x1++) { x2 = x1 + xshift; for (y1 = 0; y1 < ny; y1++) { y2 = y1 + yshift; if (y2 < ny) movepix (image0,bitpix1,nx,x1,y1,image,bitpix2,nx,x2,y2); } } sprintf (history,"Copy of image %s shifted by dx=%d dy=%d", filename, xshift, yshift); hputc (header,"HISTORY",history); if (rotate == 0 && !mirror) return (image); } else image = image0; /* Allocate buffer for rotated image */ rotimage = (char *) calloc (nbytes, 1); if (rotimage == NULL) { if (verbose) printf ("RotFITS: Cannot allocate %d bytes for new image\n", nbytes); return (NULL); } /* Mirror image without rotation */ if (rotate < 45 && rotate > -45) { if (mirror == 1) { for (x1 = 0; x1 < nx; x1++) { x2 = nx - x1 - 1; for (y1 = 0; y1 < ny; y1++) { movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,nx,x2,y1); } } sprintf (history,"Copy of image %s reflected",filename); hputc (header,"HISTORY",history); } else if (mirror == 2) { for (y1 = 0; y1 < ny; y1++) { y2 = ny - y1 - 1; for (x1 = 0; x1 < nx; x1++) { movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,nx,x1,y2); } } sprintf (history,"Copy of image %s flipped",filename); hputc (header,"HISTORY",history); } else { for (y1 = 0; y1 < ny; y1++) { for (x1 = 0; x1 < nx; x1++) { movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,nx,x1,y1); } } } } /* Rotate by 90 degrees */ else if (rotate >= 45 && rotate < 135) { if (mirror == 1) { for (y1 = 0; y1 < ny; y1++) { x2 = ny - y1 - 1; for (x1 = 0; x1 < nx; x1++) { y2 = nx - x1 - 1; movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,ny,x2,y2); } } sprintf (history,"Copy of image %s reflected, rotated 90 degrees", filename); hputc (header,"HISTORY",history); } else if (mirror == 2) { for (y1 = 0; y1 < ny; y1++) { for (x1 = 0; x1 < nx; x1++) { movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,ny,y1,x1); } } sprintf (history,"Copy of image %s flipped, rotated 90 degrees", filename); hputc (header,"HISTORY",history); } else { for (y1 = 0; y1 < ny; y1++) { x2 = ny - y1 - 1; for (x1 = 0; x1 < nx; x1++) { y2 = x1; movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,ny,x2,y2); } } sprintf (history,"Copy of image %s rotated 90 degrees",filename); hputc (header,"HISTORY",history); } hputi4 (header,"NAXIS1",ny); hputi4 (header,"NAXIS2",nx); } /* Rotate by 180 degrees */ else if (rotate >= 135 && rotate < 225) { if (mirror == 1) { for (y1 = 0; y1 < ny; y1++) { y2 = ny - y1 - 1; for (x1 = 0; x1 < nx; x1++) { movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,nx,x1,y2); } } sprintf (history,"Copy of image %s reflected, rotated 180 degrees", filename); hputc (header,"HISTORY",history); } else if (mirror == 2) { for (x1 = 0; x1 < nx; x1++) { x2 = nx - x1 - 1; for (y1 = 0; y1 < ny; y1++) { movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,nx,x2,y1); } } sprintf (history,"Copy of image %s flipped, rotated 180 degrees", filename); hputc (header,"HISTORY",history); } else { for (y1 = 0; y1 < ny; y1++) { y2 = ny - y1 - 1; for (x1 = 0; x1 < nx; x1++) { x2 = nx - x1 - 1; movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,nx,x2,y2); } } sprintf (history,"Copy of image %s rotated 180 degrees",filename); hputc (header,"HISTORY",history); } } /* Rotate by 270 degrees */ else if (rotate >= 225 && rotate < 315) { if (mirror == 1) { for (y1 = 0; y1 < ny; y1++) { for (x1 = 0; x1 < nx; x1++) { movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,ny,y1,x1); } } sprintf (history,"Copy of image %s reflected, rotated 270 degrees", filename); hputc (header,"HISTORY",history); } else if (mirror == 2) { for (y1 = 0; y1 < ny; y1++) { x2 = ny - y1 - 1; for (x1 = 0; x1 < nx; x1++) { y2 = nx - x1 - 1; movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,ny,x2,y2); } } sprintf (history,"Copy of image %s flipped, rotated 270 degrees", filename); hputc (header,"HISTORY",history); } else { for (y1 = 0; y1 < ny; y1++) { x2 = y1; for (x1 = 0; x1 < nx; x1++) { y2 = nx - x1 - 1; movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,ny,x2,y2); } } sprintf (history,"Copy of image %s rotated 270 degrees",filename); hputc (header,"HISTORY",history); } hputi4 (header,"NAXIS1",ny); hputi4 (header,"NAXIS2",nx); } /* If rotating by more than 315 degrees, assume top-bottom reflection */ else if (rotate >= 315 && mirror) { for (y1 = 0; y1 < ny; y1++) { for (x1 = 0; x1 < nx; x1++) { x2 = y1; y2 = x1; movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,ny,x2,y2); } } sprintf (history,"Copy of image %s reflected top to bottom",filename); hputc (header,"HISTORY",history); } if (verbose) fprintf (stderr,"%s\n",history); return (rotimage); } /* rotate all the C* fields. * return 0 if at least one such field is found, else -1. */ static void RotWCSFITS (header, angle, mirror, verbose) char *header; /* FITS header */ int angle; /* Angle to be rotated (0, 90, 180, 270) */ int mirror; /* 1 if mirrored left to right, else 0 */ int verbose; /* Print progress if 1 */ { static char flds[15][8]; char ctype1[16], ctype2[16]; double ctemp1, ctemp2, ctemp3, ctemp4, naxis1, naxis2; int i, n, ndec1, ndec2, ndec3, ndec4; strcpy (flds[0], "CTYPE1"); strcpy (flds[1], "CTYPE2"); strcpy (flds[2], "CRVAL1"); strcpy (flds[3], "CRVAL2"); strcpy (flds[4], "CDELT1"); strcpy (flds[5], "CDELT2"); strcpy (flds[6], "CRPIX1"); strcpy (flds[7], "CRPIX2"); strcpy (flds[8], "CROTA1"); strcpy (flds[9], "CROTA2"); strcpy (flds[10], "IMWCS"); strcpy (flds[11], "CD1_1"); strcpy (flds[12], "CD1_2"); strcpy (flds[13], "CD2_1"); strcpy (flds[14], "CD2_2"); n = 0; hgetr8 (header, "NAXIS1", &naxis1); hgetr8 (header, "NAXIS2", &naxis2); /* Find out if there any WCS keywords in this header */ for (i = 0; i < sizeof(flds)/sizeof(flds[0]); i++) { if (ksearch (header, flds[i]) != NULL) { n++; if (verbose) fprintf (stderr,"%s: found\n", flds[i]); } } /* Return if no WCS keywords to change */ if (n == 0) { if (verbose) fprintf (stderr,"RotWCSFITS: No WCS in header\n"); return; } /* Reset CROTAn and CD matrix if axes have been exchanged */ if (angle == 90) { if (hgetr8 (header, "CROTA1", &ctemp1)) { hgetndec (header, "CROTA1", &ndec1); hputnr8 (header, "CROTA1", ndec1, ctemp1+90.0); } if (hgetr8 (header, "CROTA2", &ctemp2)) { hgetndec (header, "CROTA2", &ndec2); hputnr8 (header, "CROTA2", ndec2, ctemp2+90.0); } } /* Negate rotation angle if mirrored */ if (mirror) { if (hgetr8 (header, "CROTA1", &ctemp1)) { hgetndec (header, "CROTA1", &ndec1); hputnr8 (header, "CROTA1", ndec1, -ctemp1); } if (hgetr8 (header, "CROTA2", &ctemp2)) { hgetndec (header, "CROTA2", &ndec2); hputnr8 (header, "CROTA2", ndec2, -ctemp2); } if (hgetr8 (header, "LTM1_1", &ctemp1)) { hgetndec (header, "LTM1_1", &ndec1); hputnr8 (header, "LTM1_1", ndec1, -ctemp1); } if (hgetr8 (header, "CD1_1", &ctemp1)) hputr8 (header, "CD1_1", -ctemp1); if (hgetr8 (header, "CD1_2", &ctemp1)) hputr8 (header, "CD1_2", -ctemp1); if (hgetr8 (header, "CD2_1", &ctemp1)) hputr8 (header, "CD2_1", -ctemp1); } /* Unbin CRPIX and CD matrix */ if (hgetr8 (header, "LTM1_1", &ctemp1)) { if (ctemp1 != 1.0) { if (hgetr8 (header, "LTM2_2", &ctemp2)) { if (ctemp1 == ctemp2) { double ltv1 = 0.0; double ltv2 = 0.0; if (hgetr8 (header, "LTV1", <v1)) hdel (header, "LTV1"); if (hgetr8 (header, "LTV2", <v1)) hdel (header, "LTV2"); if (hgetr8 (header, "CRPIX1", &ctemp3)) hputr8 (header, "CRPIX1", (ctemp3-ltv1)/ctemp1); if (hgetr8 (header, "CRPIX2", &ctemp3)) hputr8 (header, "CRPIX2", (ctemp3-ltv2)/ctemp1); if (hgetr8 (header, "CD1_1", &ctemp3)) hputr8 (header, "CD1_1", ctemp3/ctemp1); if (hgetr8 (header, "CD1_2", &ctemp3)) hputr8 (header, "CD1_2", ctemp3/ctemp1); if (hgetr8 (header, "CD2_1", &ctemp3)) hputr8 (header, "CD2_1", ctemp3/ctemp1); if (hgetr8 (header, "CD2_2", &ctemp3)) hputr8 (header, "CD2_2", ctemp3/ctemp1); hdel (header, "LTM1_1"); hdel (header, "LTM2_2"); } } } } /* Reset CRPIXn */ if (hgetr8 (header, "CRPIX1", &ctemp1) && hgetr8 (header, "CRPIX2", &ctemp2)) { hgetndec (header, "CRPIX1", &ndec1); hgetndec (header, "CRPIX2", &ndec2); if (mirror) { if (angle == 0) hputnr8 (header, "CRPIX1", ndec1, naxis1-ctemp1); else if (angle == 90) { hputnr8 (header, "CRPIX1", ndec2, naxis2-ctemp2); hputnr8 (header, "CRPIX2", ndec1, naxis1-ctemp1); } else if (angle == 180) { hputnr8 (header, "CRPIX1", ndec1, ctemp1); hputnr8 (header, "CRPIX2", ndec2, naxis2-ctemp2); } else if (angle == 270) { hputnr8 (header, "CRPIX1", ndec2, ctemp2); hputnr8 (header, "CRPIX2", ndec1, ctemp1); } } else { if (angle == 90) { hputnr8 (header, "CRPIX1", ndec2, naxis2-ctemp2); hputnr8 (header, "CRPIX2", ndec1, ctemp1); } else if (angle == 180) { hputnr8 (header, "CRPIX1", ndec1, naxis1-ctemp1); hputnr8 (header, "CRPIX2", ndec2, naxis2-ctemp2); } else if (angle == 270) { hputnr8 (header, "CRPIX1", ndec2, ctemp2); hputnr8 (header, "CRPIX2", ndec1, naxis1-ctemp1); } } } /* Reset CDELTn (degrees per pixel) */ if (hgetr8 (header, "CDELT1", &ctemp1) && hgetr8 (header, "CDELT2", &ctemp2)) { hgetndec (header, "CDELT1", &ndec1); hgetndec (header, "CDELT2", &ndec2); if (mirror) { if (angle == 0) hputnr8 (header, "CDELT1", ndec1, -ctemp1); else if (angle == 90) { hputnr8 (header, "CDELT1", ndec2, -ctemp2); hputnr8 (header, "CDELT2", ndec1, -ctemp1); } else if (angle == 180) { hputnr8 (header, "CDELT1", ndec1, ctemp1); hputnr8 (header, "CDELT2", ndec2, -ctemp2); } else if (angle == 270) { hputnr8 (header, "CDELT1", ndec2, ctemp2); hputnr8 (header, "CDELT2", ndec1, ctemp1); } } else { if (angle == 90) { hputnr8 (header, "CDELT1", ndec2, -ctemp2); hputnr8 (header, "CDELT2", ndec1, ctemp1); } else if (angle == 180) { hputnr8 (header, "CDELT1", ndec1, -ctemp1); hputnr8 (header, "CDELT2", ndec2, -ctemp2); } else if (angle == 270) { hputnr8 (header, "CDELT1", ndec2, ctemp2); hputnr8 (header, "CDELT2", ndec1, -ctemp1); } } } /* Reset CD matrix, if present */ ctemp1 = 0.0; ctemp2 = 0.0; ctemp3 = 0.0; ctemp4 = 0.0; if (hgetr8 (header, "CD1_1", &ctemp1)) { hgetr8 (header, "CD1_2", &ctemp2); hgetr8 (header, "CD2_1", &ctemp3); hgetr8 (header, "CD2_2", &ctemp4); hgetndec (header, "CD1_1", &ndec1); hgetndec (header, "CD1_2", &ndec2); hgetndec (header, "CD2_1", &ndec3); hgetndec (header, "CD2_2", &ndec4); if (mirror) { if (angle == 0) { hputnr8 (header, "CD1_2", ndec2, -ctemp2); hputnr8 (header, "CD2_1", ndec3, -ctemp3); } else if (angle == 90) { hputnr8 (header, "CD1_1", ndec4, -ctemp4); hputnr8 (header, "CD1_2", ndec3, -ctemp3); hputnr8 (header, "CD2_1", ndec2, -ctemp2); hputnr8 (header, "CD2_2", ndec1, -ctemp1); } else if (angle == 180) { hputnr8 (header, "CD1_1", ndec1, ctemp1); hputnr8 (header, "CD1_2", ndec2, ctemp2); hputnr8 (header, "CD2_1", ndec3, -ctemp3); hputnr8 (header, "CD2_2", ndec4, -ctemp4); } else if (angle == 270) { hputnr8 (header, "CD1_1", ndec4, ctemp4); hputnr8 (header, "CD1_2", ndec3, ctemp3); hputnr8 (header, "CD2_1", ndec2, ctemp2); hputnr8 (header, "CD2_2", ndec1, ctemp1); } } else { if (angle == 90) { hputnr8 (header, "CD1_1", ndec4, -ctemp4); hputnr8 (header, "CD1_2", ndec3, -ctemp3); hputnr8 (header, "CD2_1", ndec2, ctemp2); hputnr8 (header, "CD2_2", ndec1, ctemp1); } else if (angle == 180) { hputnr8 (header, "CD1_1", ndec1, -ctemp1); hputnr8 (header, "CD1_2", ndec2, -ctemp2); hputnr8 (header, "CD2_1", ndec3, -ctemp3); hputnr8 (header, "CD2_2", ndec4, -ctemp4); } else if (angle == 270) { hputnr8 (header, "CD1_1", ndec4, ctemp4); hputnr8 (header, "CD1_2", ndec3, ctemp3); hputnr8 (header, "CD2_1", ndec2, -ctemp2); hputnr8 (header, "CD2_2", ndec1, -ctemp1); } } } /* Delete any polynomial solution */ /* (These could maybe be switched, but I don't want to work them out yet */ if (ksearch (header, "CO1_1")) { int i; char keyword[16]; for (i = 1; i < 13; i++) { sprintf (keyword,"CO1_%d", i); hdel (header, keyword); } for (i = 1; i < 13; i++) { sprintf (keyword,"CO2_%d", i); hdel (header, keyword); } } return; } /* May 29 1996 Change name from rotFITS to RotFITS * Jun 4 1996 Fix bug when handling assymetrical images * Jun 5 1996 Print filename, not pathname, in history * Jun 10 1996 Remove unused variables after running lint * Jun 13 1996 Replace image with rotated image * Jun 18 1996 Fix formatting bug in history * * Jul 11 1997 If rotation is 360, flip top bottom if mirror flat is set * * Feb 23 1998 Do not delete WCS if image not rotated or mirrored * May 26 1998 Rotate WCS instead of deleting it * May 27 1998 Include imio.h * Jun 8 1999 Return new image pointer instead of flag; do not free old image * Jun 9 1999 Make history buffer 128 instead of 72 to avoid overflows * Jun 10 1999 Drop image0; use image * Oct 21 1999 Fix hputnr8() calls after lint * * Jan 11 2001 Print all messages to stderr * Jan 17 2001 Reset coordinate direction if image is mirrored * Jan 18 2001 Reset WCS scale if image is binned * Nov 27 2001 Add error messages for all null returns * Nov 27 2001 Add bitpix=8 * * Jan 28 2004 Add xshift and yshift arguments to shift image * Sep 15 2004 Fix bugs in calls to hgetr8 for crpix (found by Rob Creager) * * Aug 17 2005 Add mirror = 2 flag indicating a flip across x axis * * Jun 26 2008 Shift pixels if either xshift or yshift is not zero */ wcstools-3.9.5/libwcs/imsetwcs.c0000664000016200001660000012761011750060474015753 0ustar minkoirsys/*** File libwcs/imsetwcs.c *** May 19, 2010 *** By Jessica Mink, jmink@cfa.harvard.edu (based on UIowa code) *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2010 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include #include "wcs.h" #include "lwcs.h" #include "fitsfile.h" #include "wcscat.h" extern int FindStars(); extern int TriMatch(); extern int FocasMatch(); extern int StarMatch(); extern int ReadMatch(); extern int FitMatch(); extern int WCSMatch(); extern int FitPlate(); extern struct WorldCoor *GetFITSWCS (); extern char *getimcat(); extern void SetFITSWCS(); extern int iscdfit(); extern void setminbin(); extern void setnfit(); extern int getnfit(); /* Set the C* WCS fields in a FITS header based on a reference catalog * by finding stars in the image and in the reference catalog and * fitting the scaling, rotation, and offsets. * verbose generates extra info on stderr. * Try using deeper reference star catalog searches if there is trouble. * Return 1 if all ok, else 0 */ /* These parameters can be set on the command line */ static double tolerance = PIXDIFF; /* +/- this many pixels is a hit */ static double refmag1 = MAGLIM1; /* reference catalog magnitude limit */ static double refmag2 = MAGLIM2; /* reference catalog magnitude limit */ static double frac = 1.0; /* Additional catalog/image stars */ static int nofit = 0; /* if =1, do not fit WCS */ static int maxcat = MAXSTARS; /* Maximum number of catalog stars to use */ static int fitwcs = 1; /* If 1, fit WCS, else use current WCS */ static int fitplate = 0; /* If 1, fit polynomial, else do not */ static double imfrac0 = 0.0; /* If > 0.0, multiply image dimensions by this for search */ static int iterate0 = 0; /* If 1, search field again */ static int toliterate0 = 0; /* if 1, halve tolerances when iter */ static int nfiterate0 = 0; /* if 1, add two parameters to fit */ static int recenter0 = 0; /* If 1, search again with new center*/ static char matchcat[32]=""; /* Match catalog name */ static int irafout = 0; /* if 1, write X Y RA Dec out */ static int magfit = 0; /* If 1, write magnitude polynomial(s) */ static int sortmag = 1; /* Magnitude by which to sort stars */ static int minstars0 = MINSTARS; /* Number of star matches for fit */ static int nmagmax = MAXNMAG; /* Maximum number of magnitudes (etc.) per entry */ static int nxydec = NXYDEC; /* Number of decimal places in image coordinates */ static void PrintRes(); static void CompRes(); extern void SetFITSPlate(); static char *kwt = NULL; /* Keyword returned by ctgread() */ void settabkrw (keyword0) char *keyword0; { kwt = keyword0; return; } /* Set the C* WCS fields in the input image header based on the given limiting * reference mag. * Finding stars in the input image and in the reference catalog between * refmag1 and refmag2 and compute the angle and offsets which result in the best fit. * verbose generates extra info on stdout. * return 0 if all ok, else -1 */ int SetWCSFITS (filename, header, image, refcatname, verbose) char *filename; /* image file name */ char *header; /* FITS header */ char *image; /* Image pixels */ char *refcatname; /* Name of reference catalog */ int verbose; { double *gnum; /* Reference star numbers */ double *gra; /* Reference star right ascensions in degrees */ double *gdec; /* Reference star declinations in degrees */ double *gpra; /* Reference star right ascension proper motions (deg)*/ double *gpdec; /* Reference star declination proper motions (deg) */ double **gm; /* Reference star magnitudes */ double *gx; /* Reference star image X-coordinates in pixels */ double *gy; /* Reference star image Y-coordinates in pixels */ int *gc; /* Reference object types */ int *goff; /* Reference star offscale flags */ int ng; /* Number of reference stars in image */ int nbg; /* Number of brightest reference stars from search */ int nrg; /* Number of brightest reference stars actually used */ double *sx; /* Image star image X-coordinates in pixels */ double *sy; /* Image star image X-coordinates in pixels */ double *sm; /* Image star instrumental magnitude */ int *sp; /* Image star peak fluxes in counts */ int ns; /* Number of image stars */ int nbs; /* Number of brightest image stars actually used */ double cra, cdec; /* Nominal center in degrees from RA/DEC FITS fields */ double dra, ddec; /* Image half-widths in degrees */ double secpix; /* Pixel size in arcseconds */ int imw, imh; /* Image size, pixels */ int imsearch = 1; /* Flag set if image should be searched for sources */ int nmax; /* Maximum number of matches possible (nrg or nbs) */ int lofld = 0; /* Length of object name field in output */ double mag1,mag2; int refcat; /* reference catalog switch */ int nmag, mprop; double dxys; char numstr[32]; int minstars; int ngmax; int nbin, nbytes; int iterate, toliterate, nfiterate; int imag, magsort; int niter = 0; int recenter = recenter0; int ret = 0; int is, ig, igs, i, j; char rstr[32], dstr[32]; double refeq, refep; double maxnum; int nnfld; int refsys; char refcoor[8]; char title[80]; char *imcatname; /* file name for image star catalog, if used */ struct WorldCoor *wcs=0; /* WCS structure */ double *sx1, *sy1, *sm1, *gra1, *gdec1, *gnum1, *gm1; char **gobj, **gobj1; /* Catalog star object names */ double imfrac = imfrac0; int nmatch; double ra,dec; double dx, dy, dx2, dy2, dxy; struct StarCat *starcat; int npfit; int nndec; extern int NParamFit(); extern void setdcenter(),setsys(),setrefpix(),setsecpix(); extern void setsecpix2(),setrot(); iterate = iterate0; toliterate = toliterate0; nfiterate = nfiterate0; gnum = NULL; gra = NULL; gdec = NULL; gpra = NULL; gpdec = NULL; gm = NULL; gx = NULL; gy = NULL; gc = NULL; gobj = NULL; gobj1 = NULL; goff = NULL; sm = NULL; sx = NULL; sy = NULL; sp = NULL; starcat = NULL; imcatname = NULL; ns = 0; if (refmag1 == refmag2) { mag1 = 0.0; mag2 = 0.0; } else { mag1 = refmag1; mag2 = refmag2; } /* Use already-matched stars first, if they are present */ if (strlen (matchcat) > 0) { refsys = WCS_J2000; refeq = 2000.0; if ((nbin = ReadMatch (matchcat, &sx, &sy, &gra, &gdec, verbose)) < 1) { ret = 0; goto out; } if (nbin > 1) WCSMatch (nbin, sx, sy, gra, gdec, verbose); /* Set WCS from image header and command line */ wcs = GetFITSWCS (filename,header,verbose,&cra,&cdec,&dra,&ddec, &secpix, &imw,&imh,&refsys, &refeq); if (nowcs (wcs)) { ret = 0; goto out; } if (getnfit() == 0) { SetFITSWCS (header, wcs); return (1); } nbin = FitMatch (nbin, sx, sy, gra, gdec, wcs, verbose); sm = (double *) calloc (nbin, sizeof (double)); hputs (header, "WCSRFCAT", matchcat); hputs (header, "WCSIMCAT", matchcat); hputi4 (header, "WCSMATCH", nbin); hputi4 (header, "WCSNREF", nbin); if (!(gnum = (double *) calloc (nbin, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gnum\n", nbin*sizeof(double)); for (is = 0; is < nbin; is++) gnum[is] = (double)(is + 1); if (!(gx = (double *) calloc (nbin, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gx\n", nbin*sizeof(double)); if (!(gy = (double *) calloc (nbin, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gy\n", nbin*sizeof(double)); if (!(goff = (int *) calloc (nbin, sizeof(int)))) fprintf (stderr, "Could not calloc %d bytes for goff\n", nbin*sizeof(double)); SetFITSWCS (header, wcs); nrg = nbin; ns = nbin; if (refcatname == NULL) goto match; } /* Set reference catalog coordinate system and epoch */ if (nofit) { refsys = 0; refeq = 0.0; refcat = 0; } else { refcat = RefCat (refcatname,title,&refsys,&refeq,&refep,&mprop,&nmag); wcscstr (refcoor, refsys, refeq, refep); } /* get nominal position and scale */ getfield: wcs = GetFITSWCS (filename,header,verbose,&cra,&cdec,&dra,&ddec,&secpix, &imw,&imh,&refsys, &refeq); if (nowcs (wcs)) { ret = 0; goto out; } refep = wcs->epoch; if (nofit) { SetFITSWCS (header, wcs); ret = 1; goto out; } if (fitwcs) { wcs->prjcode = WCS_TAN; wcseqset (wcs, refeq); } if (refcatname == NULL) { refcatname = CatName (refcat, refcatname); if (refcatname == NULL) { ret = 0; goto out; } } if (imfrac > 0.0) { dra = dra * imfrac; ddec = ddec * imfrac; } if (sortmag > 9) sortmag = CatMagNum (sortmag, refcat); /* Allocate arrays for results of reference star search */ ngmax = maxcat; if (imfrac > 1.0) ngmax = (int) ((double) ngmax * imfrac * imfrac); nbytes = ngmax * sizeof (double); if (!(gnum = (double *) calloc (ngmax, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gnum\n", ngmax*sizeof(double)); if (!(gra = (double *) calloc (ngmax, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gra\n", ngmax*sizeof(double)); if (!(gdec = (double *) calloc (ngmax, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gdec\n", ngmax*sizeof(double)); if (!(gpra = (double *) calloc (ngmax, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gpra\n", ngmax*sizeof(double)); if (!(gpdec = (double *) calloc (ngmax, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gpdec\n", ngmax*sizeof(double)); if (!(gm = (double **) calloc (nmagmax, sizeof(double *)))) fprintf (stderr, "Could not calloc %d bytes for gm\n", nmagmax*sizeof(double *)); else { for (imag = 0; imag < nmagmax; imag++) { if (!(gm[imag] = (double *) calloc (ngmax, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gm\n", ngmax*sizeof(double)); } } if (!(gc = (int *) calloc (ngmax, sizeof(int)))) fprintf (stderr, "Could not calloc %d bytes for gc\n", ngmax*sizeof(int)); if (!(gobj = (char **) calloc (ngmax, sizeof(char *)))) fprintf (stderr, "Could not calloc %d bytes for obj\n", ngmax*sizeof(char *)); else { for (i = 0; i < ngmax; i++) gobj[i] = NULL; } /* Find the nearby reference stars, in ra/dec */ getstars: ng = ctgread (refcatname,refcat,0,cra,cdec,dra,ddec,0.0,0.0,refsys,refeq, refep,mag1,mag2,sortmag,ngmax,&starcat, gnum,gra,gdec,gpra,gpdec,gm,gc,gobj,verbose*100); if (ng > ngmax) nrg = ngmax; else nrg = ng; if (gobj[0] == NULL) gobj1 = NULL; else gobj1 = gobj; minstars = minstars0; npfit = NParamFit (100); if (npfit < minstars0) minstars = 1; if (sortmag > 0 && sortmag <= nmag) magsort = sortmag - 1; else magsort = 0; /* Sort reference stars by brightness (magnitude) */ MagSortStars (gnum, gra, gdec, gpra, gpdec, NULL, NULL, gm, gc, gobj1, nrg, nmagmax, sortmag); /* Project the reference stars into pixels on a plane at ra0/dec0 */ if (!(gx = (double *) calloc (ngmax, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gx\n", ngmax*sizeof(double)); if (!(gy = (double *) calloc (ngmax, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gy\n", ngmax*sizeof(double)); if (!(goff = (int *) calloc (ngmax, sizeof(int)))) fprintf (stderr, "Could not calloc %d bytes for gy\n", ngmax*sizeof(double)); if (!gx || !gy || !goff) { ret = 0; goto out; } /* use the nominal WCS info to find x/y on image */ for (ig = 0; ig < nrg; ig++) { gx[ig] = 0.0; gy[ig] = 0.0; wcs2pix (wcs, gra[ig], gdec[ig], &gx[ig], &gy[ig], &goff[ig]); } /* Note how reference stars were selected */ if (ng > ngmax) { if (verbose) fprintf (stderr,"Using %d / %d reference stars brighter than %.1f\n", nrg, ng, gm[magsort][nrg-1]); } else { if (verbose) { if (refmag1 > 0.0 && refmag2 > 0.0) fprintf (stderr,"Using all %d reference stars from %.1f to %.1f mag.\n", ng, refmag1, refmag2); else if (refmag2 > 0.0) fprintf (stderr,"Using all %d reference stars brighter than %.1f\n", ng,refmag2); else fprintf (stderr,"using all %d reference stars\n", ng); } } if (verbose) { fprintf (stderr,"%s:\n",refcatname); for (ig = 0; ig < nrg; ig++) { if (ig == 0) maxnum = gnum[ig]; else if (gnum[ig] > maxnum) maxnum = gnum[ig]; } nnfld = CatNumLen (refcat, maxnum, 0); nndec = 0; for (ig = 0; ig < nrg; ig++) { ra2str (rstr, 32, gra[ig], 3); dec2str (dstr, 32, gdec[ig], 2); /* Set up object name or number to print */ if (starcat != NULL) { if (starcat->stnum < 0 && gobj1 != NULL) { strncpy (numstr, gobj1[ig], 32); if (lofld > 0) { for (j = 0; j < lofld; j++) { if (!numstr[j]) numstr[j] = ' '; } } } else CatNum (refcat,-nnfld,starcat->nndec,gnum[ig],numstr); } else CatNum (refcat, -nnfld, nndec, gnum[ig], numstr); if (nmag > 0) fprintf (stderr,"%s %s %s %5.2f %6.1f %6.1f\r", numstr,rstr,dstr,gm[magsort][ig],gx[ig],gy[ig]); else fprintf (stderr,"%s %s %s %6.1f %6.1f\r", numstr,rstr,dstr,gx[ig],gy[ig]); } fprintf (stderr,"\n"); } if (nrg < minstars) { if (ng < 0) fprintf (stderr, "Error getting reference stars: %d\n", ng); else if (ng == 0) fprintf (stderr,"No reference stars found in image area\n"); else if (fitwcs) fprintf (stderr, "Found only %d out of %d reference stars needed\n", nrg, minstars); if (ng <= 0 || fitwcs) { ret = 0; goto out; } } /* Discover star-like things in the image, in pixels */ if (imsearch) { ns = FindStars (header, image, &sx, &sy, &sm, &sp, verbose, 0); if (ns < minstars) { if (ns < 0) fprintf (stderr, "Error getting image stars: %d\n", ns); else if (ns == 0) fprintf (stderr,"No stars found in image\n"); else if (fitwcs) fprintf (stderr, "Need at least %d image stars but only found %d\n", minstars, ns); if (ns <= 0 || fitwcs) { ret = 0; iterate = 0; recenter = 0; goto out; } } imsearch = 0; } /* Fit a world coordinate system if requested */ if (fitwcs) { niter++; /* Sort star-like objects in image by brightness (magnitude) */ MagSortStars (NULL,NULL,NULL,NULL,NULL,sx,sy,&sm,sp,NULL,ns,1,1); /* If matching a catalog field the same size as the image field, use only as many star-like objects as reference stars. If using a larger catalog field (imfrac > 0), increase the number of stars proportionately (imfrac^2 * the number of image stars). To adjust for different bandpasses between the image and the reference catalog use frac * the number of reference stars if more than image stars or frac * the number of image stars if more than reference stars. */ if (imfrac > 0.0) { double imfrac2 = imfrac * imfrac; if (ns > (nrg / imfrac2)) { nbs = nrg * frac / imfrac2; if (nbs > ns) nbs = ns; nbg = nrg; } else { nbs = ns; nbg = (int) ((double) nbs * imfrac2); if (nbg > nrg) nbg = nrg; } } else { if (ns > nrg) { nbs = nrg * frac; if (nbs > ns) nbs = ns; nbg = nrg; } else { nbs = ns; nbg = nbs * frac; if (nbg > nrg) nbg = nrg; } } if (verbose) { if (nbg == ng) fprintf (stderr,"Using all %d reference stars\n", ng); else fprintf (stderr,"Using brightest %d / %d reference stars\n", nbg, ng); if (nbs == ns) fprintf (stderr,"Using all %d image stars\n", ns); else fprintf (stderr,"Using brightest %d / %d image stars\n", nbs,ns); } /* Print nominal positions of image stars */ if (verbose) { char rastr[32], decstr[32]; double xmag, mdiff, ra, dec; for (is = 0; is < nbs; is++) { pix2wcs (wcs, sx[is], sy[is], &ra, &dec); ra2str (rastr, 32, ra, 3); dec2str (decstr, 32, dec, 2); xmag = sm[is]; if (nmag > 0 && !is) { mdiff = gm[magsort][0] - xmag; } else { mdiff = 0.0; } xmag = xmag + mdiff; fprintf (stderr,"%4d %s %s %6.2f %6.1f %6.1f %d\r", is+1, rastr, decstr, xmag, sx[is], sy[is], sp[is]); } fprintf (stderr,"\n"); } /* Match offsets between all pairs of image stars and reference stars and fit WCS to matches */ nbin = StarMatch (nbs,sx,sy,refcat,nbg,gnum,gra,gdec,goff,gx,gy, tolerance,wcs,verbose); if (nbin < 0) { fprintf (stderr, "Star registration failed.\n"); ret = 0; goto done; } else if (nbin < minstars0) { fprintf (stderr, "Only %d matches, registration failed.\n", nbin); ret = 0; goto done; } else if (verbose) fprintf (stderr,"%d / %d bin hits\n", nbin, nbg); hputs (header, "WCSRFCAT", refcatname); imcatname = getimcat (); if (strlen (imcatname) == 0) hputs (header, "WCSIMCAT", filename); else hputs (header, "WCSIMCAT", imcatname); hputi4 (header, "WCSMATCH", nbin); if (ns < nbg) hputi4 (header, "WCSNREF", ns); else hputi4 (header, "WCSNREF", nbg); hputnr8 (header, "WCSTOL", 4, tolerance); SetFITSWCS (header, wcs); } /* Match reference and image stars */ match: nmatch = 0; if (verbose || !fitwcs) { imcatname = getimcat (); if (wcs->ncoeff1 > 0) printf ("# %d-term x, %d-term y polynomial fit\n", wcs->ncoeff1, wcs->ncoeff2); else printf ("# Arcsec/Pixel= %.6f %.6f Rotation= %.6f degrees\n", 3600.0*wcs->xinc, 3600.0*wcs->yinc, wcs->rot); ra2str (rstr, 32, wcs->xref, 3); dec2str (dstr, 32, wcs->yref, 2); printf ("# Optical axis= %s %s %s x= %.2f y= %.2f\n", rstr,dstr, refcoor, wcs->xrefpix, wcs->yrefpix); ra = wcs->xref; dec = wcs->yref; if (refsys == WCS_J2000) { fk524e (&ra, &dec, refep); ra2str (rstr, 32, ra, 3); dec2str (dstr, 32, dec, 2); printf ("# Optical axis= %s %s B1950 x= %.2f y= %.2f\n", rstr,dstr, wcs->xrefpix, wcs->yrefpix); } else { fk425e (&ra, &dec, refep); ra2str (rstr, 32, ra, 3); dec2str (dstr, 32, dec, 2); printf ("# Optical axis= %s %s J2000 x= %.2f y= %.2f\n", rstr,dstr, wcs->xrefpix, wcs->yrefpix); } } /* Find star matches for this offset and print them */ /* Use the fit WCS info to find catalog star x/y on image */ for (ig = 0; ig < nrg; ig++) { gx[ig] = 0.0; gy[ig] = 0.0; wcs2pix (wcs, gra[ig], gdec[ig], &gx[ig], &gy[ig], &goff[ig]); } /* Set maximum number of matches which are possible */ if (nrg < ns) nmax = nrg; else nmax = ns; /* Find best catalog matches to stars in image */ nmatch = 0; nbytes = ns * sizeof (double); if (!(gra1 = (double *) calloc (ns, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gra1\n",nbytes); if (!(gdec1 = (double *) calloc (ns, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gdec1\n",nbytes); if (!(gm1 = (double *) calloc (ns, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gm1\n",nbytes); if (!(gnum1 = (double *) calloc (ns, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gnum1\n",nbytes); if (!(sx1 = (double *) calloc (ns, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for sx1\n",nbytes); if (!(sy1 = (double *) calloc (ns, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for sy1\n",nbytes); if (!(sm1 = (double *) calloc (ns, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for sm1\n",nbytes); for (is = 0; is < ns; is++) { dxys = tolerance * tolerance; igs = -1; for (ig = 0; ig < nrg; ig++) { if (!goff[ig]) { dx = gx[ig] - sx[is]; dy = gy[ig] - sy[is]; dx2 = dx * dx; dy2 = dy * dy; dxy = dx2 + dy2; if (dxy < dxys) { dxys = dxy; igs = ig; } } } if (igs > -1) { gnum1[nmatch] = gnum[igs]; if (gm != NULL && nmag > 0) gm1[nmatch] = gm[magsort][igs]; else gm1[nmatch] = 0.0; gra1[nmatch] = gra[igs]; gdec1[nmatch] = gdec[igs]; sx1[nmatch] = sx[is]; sy1[nmatch] = sy[is]; sm1[nmatch] = sm[is]; nmatch++; } } /* If there were any matches found, print them */ if (nmatch > 0) { int rprint = verbose || !fitwcs; hputi4 (header, "WCSMATCH", nmatch); hputi4 (header, "WCSNREF", nmax); hputnr8 (header, "WCSTOL", 4, tolerance); if (rprint) { PrintRes (header,wcs,nmatch,sx1,sy1,sm1,gra1,gdec1,gm1,gnum1, refcat,rprint); if (refcatname == NULL) printf ("# nmatch= %d nstars= %d in and %s niter= %d\n", nmatch, nmax, matchcat, niter); else if (strlen (imcatname) == 0) printf ("# nmatch= %d nstars= %d between %s and %s niter= %d\n", nmatch, nmax, refcatname, filename, niter); else printf ("# nmatch= %d nstars= %d between %s and %s niter= %d\n", nmatch, nmax, refcatname, imcatname, niter); } else CompRes (header,wcs,nmatch,sx1,sy1,sm1,gra1,gdec1,gm1,gnum1); /* Fit the matched catalog and image stars with a polynomial */ if (!iterate && !recenter && fitplate && refcatname != NULL) { if (verbose) fprintf (stderr,"Fitting matched stars with a polynomial\n"); /* Fit residuals */ if (FitPlate (wcs, sx1, sy1, gra1, gdec1, nmatch, fitplate, verbose)) fprintf (stderr,"FitPlate cannot fit matches\n"); /* Print the new residuals */ else if (rprint) { PrintRes (header,wcs,nmatch,sx1,sy1,sm1,gra1,gdec1,gm1,gnum1, refcat,verbose); if (refcatname == NULL) printf ("# nmatch= %d nstars= %d in %s niter= %d\n", nmatch, nmax, matchcat, niter); else if (strlen (imcatname) == 0) printf ("# nmatch= %d nstars= %d between %s and %s niter= %d\n", nmatch, nmax, refcatname, filename, niter); else printf ("# nmatch= %d nstars= %d between %s and %s niter= %d\n", nmatch, nmax, refcatname, imcatname, niter); SetFITSPlate (header, wcs); } else { CompRes (header,wcs,nmatch,sx1,sy1,sm1,gra1,gdec1,gm1,gnum1); SetFITSPlate (header, wcs); } } } else { if (refcatname == NULL) fprintf (stderr, "SetWCSFITS: No matches in %s:\n", matchcat); else if (strlen (imcatname) == 0) fprintf (stderr, "SetWCSFITS: No matches between %s and %s:\n", refcatname, filename); else fprintf (stderr, "SetWCSFITS: No matches between %s and %s:\n", refcatname, imcatname); hputi4 (header, "WCSMATCH", 0); } if (gra1) free ((char *)gra1); if (gdec1) free ((char *)gdec1); if (gm1) free ((char *)gm1); if (gnum1) free ((char *)gnum1); if (sx1) free ((char *)sx1); if (sy1) free ((char *)sy1); if (sm1) free ((char *)sm1); ret = 1; out: if (iterate) { /* setdcenter (wcs->xref, wcs->yref); setsys (wcs->syswcs); setrefpix (wcs->xrefpix, wcs->yrefpix); if (iscdfit()) setcd (wcs->cd); else { setsecpix (-3600.0 * wcs->xinc); setsecpix2 (3600.0 * wcs->yinc); setrot (wcs->rot); } wcsfree (wcs); */ wcssize (wcs, &cra, &cdec, &dra, &ddec); if (cra < 0.0) cra = cra + 360.0; iterate--; imfrac = 0.0; goto getstars; } if (toliterate) { /* setdcenter (wcs->xref, wcs->yref); setsys (wcs->syswcs); setrefpix (wcs->xrefpix, wcs->yrefpix); if (iscdfit()) setcd (wcs->cd); else { setsecpix (-3600.0 * wcs->xinc); setsecpix2 (3600.0 * wcs->yinc); setrot (wcs->rot); } wcsfree (wcs); */ wcssize (wcs, &cra, &cdec, &dra, &ddec); tolerance = tolerance * 0.5; toliterate--; imfrac = 0.0; goto getstars; } if (recenter) { double ra, dec, x, y; x = 0.5 * wcs->nxpix; y = 0.5 * wcs->nypix; pix2wcs (wcs, x, y, &ra, &dec); setdcenter (ra, dec); setsys (wcs->syswcs); setrefpix (x, y); setsecpix (-3600.0 * wcs->xinc); setsecpix2 (3600.0 * wcs->yinc); setrot (wcs->rot); recenter = 0; imfrac = 0.0; if (wcs) { wcsfree (wcs); wcs = NULL; } goto getfield; } if (nfiterate) { int nfit = getnfit (); wcssize (wcs, &cra, &cdec, &dra, &ddec); if (verbose) printf ("\n fitting %d instead of %d parameters\n", nfit+2, nfit); if (nfit < 7) nfit = nfit + 2; setnfit (nfit); nfiterate--; goto getstars; } done: if (wcs) { wcsfree (wcs); wcs = NULL; } /* Free catalog source arrays */ if (gra) free ((char *)gra); if (gdec) free ((char *)gdec); if (gpra) free ((char *)gpra); if (gpdec) free ((char *)gpdec); if (gm) { for (imag = 0; imag < nmagmax; imag++) { if (gm[imag]) free ((char *)gm[imag]); } free ((char *)gm); } if (gnum) free ((char *)gnum); if (gx) free ((char *)gx); if (gy) free ((char *)gy); if (goff) free ((char *)goff); if (gc) free ((char *)gc); /* Free memory used for object names in reference catalog */ if (gobj1 != NULL) { for (i = 0; i < ngmax; i++) { if (gobj[i] != NULL) { free (gobj[i]); gobj[i] = NULL; } } } if (gobj) { free ((char *) gobj); gobj = NULL; } /* Free image source arrays */ if (sx) free ((char *)sx); if (sy) free ((char *)sy); if (sm) free ((char *)sm); if (sp) free ((char *)sp); return (ret); } static void PrintRes (header,wcs,nmatch,sx1,sy1,sm1,gra1,gdec1,gm1,gnum1,refcat,verbose) char *header; /* Image FITS header */ struct WorldCoor *wcs; /* Image World Coordinate System */ int nmatch; /* Number of image/catalog matches */ double *sx1, *sy1; /* Image star pixel coordinates */ double *sm1; /* Plate magnitudes */ double *gra1, *gdec1; /* Reference catalog sky coordinates */ double *gm1; /* Reference catalog magnitudes */ double *gnum1; /* Reference catalog numbers */ int refcat; /* Reference catalog code */ int verbose; /* True for more information */ { int i, goff; double gx, gy, dx, dy, dx2, dy2, dxy, mag0; double sep, sep2, rsep, rsep2, dsep, dsep2; double dmatch, dmatch1, sra, sdec; double sepsum = 0.0; double rsepsum = 0.0; double rsep2sum = 0.0; double dsepsum = 0.0; double dsep2sum = 0.0; double sep2sum = 0.0; double dxsum = 0.0; double dysum = 0.0; double dx2sum = 0.0; double dy2sum = 0.0; double dxysum = 0.0; double coeff[5]; double msig; double maxnum; double cmax; int nnfld; int nxyfld; char rstr[32], dstr[32], numstr[32], xstr[32], ystr[32], mstr[8]; maxnum = 0.0; for (i = 0; i < nmatch; i++) { if (i == 0) maxnum = gnum1[i]; else if (gnum1[i] > maxnum) maxnum = gnum1[i]; } nnfld = CatNumLen (refcat, maxnum, 0); CatMagName (sortmag, refcat, mstr); CatID (numstr, refcat); if (irafout) printf ("# x y ra2000 dec2000 %5s %s", mstr, numstr); else printf ("# %s ra2000 dec2000 %5s X Y magi", mstr, numstr); printf (" dra ddec sep\n"); /* Find maximum image coordinates and set field size accordingly */ cmax = 0.0; for (i = 0; i < nmatch; i++) { if (sx1[i] > cmax) cmax = sx1[i]; if (sy1[i] > cmax) cmax = sy1[i]; } if (cmax > 9999.0) nxyfld = 6 + nxydec; else if (cmax > 999.0) nxyfld = 5 + nxydec; else nxyfld = 4 + nxydec; for (i = 0; i < nmatch; i++) { wcs2pix (wcs, gra1[i], gdec1[i], &gx, &gy, &goff); dx = gx - sx1[i]; dy = gy - sy1[i]; dx2 = dx * dx; dy2 = dy * dy; dxy = dx2 + dy2; dxsum = dxsum + dx; dysum = dysum + dy; dx2sum = dx2sum + dx2; dy2sum = dy2sum + dy2; dxysum = dxysum + sqrt (dxy); pix2wcs (wcs, sx1[i], sy1[i], &sra, &sdec); sep = 3600.0 * wcsdist(gra1[i],gdec1[i],sra,sdec); rsep = 3600.0 * ((gra1[i]-sra) * cos(degrad(sdec))); if (rsep > sep) rsep = 3600.0 * ((gra1[i] - sra - 360.0) * cos(degrad(sdec))); rsep2 = rsep * rsep; dsep = 3600.0 * (gdec1[i] - sdec); dsep2 = dsep * dsep; sepsum = sepsum + sep; rsepsum = rsepsum + rsep; dsepsum = dsepsum + dsep; rsep2sum = rsep2sum + rsep2; dsep2sum = dsep2sum + dsep2; sep2sum = sep2sum + (sep*sep); ra2str (rstr, 32, gra1[i], 3); dec2str (dstr, 32, gdec1[i], 2); num2str (xstr, sx1[i], nxyfld, nxydec); num2str (ystr, sy1[i], nxyfld, nxydec); CatNum (refcat, -nnfld, 0, gnum1[i], numstr); if (irafout) printf (" %s %s %s %s %5.2f %s", xstr, ystr, rstr, dstr, gm1[i], numstr); else printf ("%s %s %s %5.2f %s %s %6.2f ", numstr, rstr, dstr, gm1[i], xstr, ystr, sm1[i]); printf ("%6.2f %6.2f %6.2f\n", rsep, dsep, sep); } dmatch = (double) nmatch; dmatch1 = (double) (nmatch - 1); dx = dxsum / dmatch; dy = dysum / dmatch; dx2 = sqrt (dx2sum / dmatch1); dy2 = sqrt (dy2sum / dmatch1); dxy = dxysum / dmatch; rsep = rsepsum / dmatch; dsep = dsepsum / dmatch; rsep2 = sqrt (rsep2sum / dmatch1); dsep2 = sqrt (dsep2sum / dmatch1); sep = sepsum / dmatch; sep2 = sqrt (sep2sum / dmatch1); printf ("# Mean dx= %.4f/%.4f dy= %.4f/%.4f dxy= %.4f\n", dx, dx2, dy, dy2, dxy); printf ("# Mean dra= %.4f/%.4f ddec= %.4f/%.4f sep= %.4f/%.4f\n", rsep, rsep2, dsep, dsep2, sep, sep2); /* Fit and save image to catalog magnitude calibration polynomial */ if (magfit) { mag0 = sm1[0]; coeff[0] = 0.0; coeff[1] = 0.0; coeff[2] = 0.0; coeff[3] = 0.0; coeff[4] = 0.0; polfit (sm1, gm1, mag0, nmatch, 4, coeff, &msig); printf ("# Plate to catalog mag: mag0=%.6f mcoeff0=%.6f mcoeff1=%.6f\n", mag0, coeff[0], coeff[1]); printf ("# Plate to catalog mag: mcoeff2=%.6f mcoeff3=%.6f sigma=%.3f\n", coeff[2], coeff[3], msig); } hputi4 (header, "WCSMATCH", nmatch); hputnr8 (header, "WCSSEP", 3, sep); return; } static void CompRes (header,wcs,nmatch,sx1,sy1,sm1,gra1,gdec1,gm1,gnum1) char *header; /* Image FITS header */ struct WorldCoor *wcs; /* Image World Coordinate System */ int nmatch; /* Number of image/catalog matches */ double *sx1, *sy1; /* Image star pixel coordinates */ double *sm1; /* Plate magnitudes */ double *gra1, *gdec1; /* Reference catalog sky coordinates */ double *gm1; /* Reference catalog magnitudes */ double *gnum1; /* Reference catalog numbers */ { int i, goff; double gx, gy, dx, dy, dx2, dy2, dxy, mag0; double sep, sep2, rsep, rsep2, dsep, dsep2; double dmatch, dmatch1, sra, sdec; double sepsum = 0.0; double rsepsum = 0.0; double rsep2sum = 0.0; double dsepsum = 0.0; double dsep2sum = 0.0; double sep2sum = 0.0; double dxsum = 0.0; double dysum = 0.0; double dx2sum = 0.0; double dy2sum = 0.0; double dxysum = 0.0; for (i = 0; i < nmatch; i++) { wcs2pix (wcs, gra1[i], gdec1[i], &gx, &gy, &goff); dx = gx - sx1[i]; dy = gy - sy1[i]; dx2 = dx * dx; dy2 = dy * dy; dxy = dx2 + dy2; dxsum = dxsum + dx; dysum = dysum + dy; dx2sum = dx2sum + dx2; dy2sum = dy2sum + dy2; dxysum = dxysum + sqrt (dxy); pix2wcs (wcs, sx1[i], sy1[i], &sra, &sdec); sep = 3600.0 * wcsdist(gra1[i],gdec1[i],sra,sdec); rsep = 3600.0 * ((gra1[i]-sra) * cos(degrad(sdec))); if (rsep > sep) rsep = 3600.0 * ((gra1[i] - sra - 360.0) * cos(degrad(sdec))); rsep2 = rsep * rsep; dsep = 3600.0 * (gdec1[i] - sdec); dsep2 = dsep * dsep; sepsum = sepsum + sep; rsepsum = rsepsum + rsep; dsepsum = dsepsum + dsep; rsep2sum = rsep2sum + rsep2; dsep2sum = dsep2sum + dsep2; sep2sum = sep2sum + (sep*sep); } dmatch = (double) nmatch; dmatch1 = (double) (nmatch - 1); dx = dxsum / dmatch; dy = dysum / dmatch; dx2 = sqrt (dx2sum / dmatch1); dy2 = sqrt (dy2sum / dmatch1); dxy = dxysum / dmatch; rsep = rsepsum / dmatch; dsep = dsepsum / dmatch; rsep2 = sqrt (rsep2sum / dmatch1); dsep2 = sqrt (dsep2sum / dmatch1); sep = sepsum / dmatch; sep2 = sqrt (sep2sum / dmatch1); hputi4 (header, "WCSMATCH", nmatch); hputnr8 (header, "WCSSEP", 3, sep); return; } /* Subroutines to initialize various parameters */ void settolerance (tol) double tol; { tolerance = tol; return; } /* Number of decimal places in X and Y image coordinates of sources */ void setnxydec (ndec) int ndec; { nxydec = ndec; return; } void setirafout () { irafout = 1; return; } void setmatch (cat) char *cat; { strcpy (matchcat, cat); return; } void setreflim (lim1, lim2) double lim1, lim2; { refmag2 = lim2; if (lim1 > -2.0) refmag1 = lim1; return; } void setfitwcs (wfit) int wfit; { fitwcs = wfit; return; } void setfitplate (nc) int nc; { fitplate = nc; return; } void setminstars (minstars) int minstars; { minstars0 = minstars; setminbin (minstars); return; } void setnofit () { nofit = 1; return; } void setfrac (frac0) double frac0; { if (frac0 < 1.0) frac = 1.0 + frac0; else frac = frac0; return; } /* Fraction by which to increase dimensions of area to be searched */ void setimfrac (frac0) double frac0; { if (frac0 > 0.0) imfrac0 = frac0; else imfrac0 = 1.0; return; } void setmaxcat (ncat) int ncat; { if (ncat < 1) maxcat = 25; else maxcat = ncat; return; } void setiterate (iter) int iter; { iterate0 = iterate0 + iter; return; } void setnfiterate (iter) int iter; { nfiterate0 = nfiterate0 + iter; return; } void setiteratet (iter) int iter; { toliterate0 = toliterate0 + iter; return; } void setrecenter (recenter) int recenter; { recenter0 = recenter; return; } void setsortmag (imag) int imag; { sortmag = imag; return; } void setmagfit () {magfit++; return;} /* Feb 29 1996 New program * Apr 30 1996 Add FOCAS-style catalog matching * May 1 1996 Add initial image center from command line * May 2 1996 Set up four star matching modes * May 15 1996 Pass verbose flag; allow other reference catalogs * May 16 1996 Remove sorting to separate file sortstar.c * May 17 1996 Add class and verbose arguments * May 22 1996 Allow for named reference catalog * May 23 1996 Use pre-existing WCS for center, if it is present * May 29 1996 Simplify program by always using WCS structure * May 30 1996 Make reference/image pair matching the default method * Jun 11 1996 Number and zero positions of image stars * Jun 12 1996 Be more careful with nominal WCS setting * Jun 14 1996 Add residual table * Jun 28 1996 Set FITS header from WCS * Jul 3 1996 Set epoch from old equinox if not already set * Jul 19 1996 Declare tabread * Jul 19 1996 Set image center in WCS if DSS WCS * Jul 22 1996 Debug tab table reading * Aug 5 1996 Add option to change WCS projection * Aug 5 1996 Check for SECPIX1 as well as SECPIX * Aug 5 1996 Set number of parameters to fit here * Aug 7 1996 Save specified number of decimal places in header parameters * Aug 7 1996 Rename old center parameters * Aug 26 1996 Decrease default pixel tolerance from 20 to 10 * Aug 26 1996 Drop unused variable EQ in setfitswcs * Aug 28 1996 Improve output format for matched stars * Sep 1 1996 Set some defaults in lwcs.h * Sep 3 1996 Fix bug to set plate scale from command line * Sep 4 1996 Print reference catalog name on separate line from entries * Sep 17 1996 Clean up code * Oct 15 1996 Break off getfitswcs into separate file * Nov 18 1996 Add USNO A catalog searching * Nov 18 1996 Write same number into CROAT2 as CROTA1 * Nov 19 1996 If EPOCH was equinox in original image or not set, set it * Dec 10 1996 Make equinox double in getfitswcs call * * Mar 17 1997 Print found reference stars even when there are not enough * Jul 14 1997 If nfit is negative return with header set for nominal WCS * Aug 4 1997 Reset nfit limit to 7 for reference pixel fit and fix nfit0 bug * Aug 20 1997 Make maximum number of reference stars settable on the command line * Aug 28 1997 Print star ID numbers in appropriate format for each catalog * Aug 28 1997 Add option to match image to reference stars without fitting WCS * Sep 3 1997 Add option to change image dimensions by a fraction * Sep 9 1997 Return with default WCS in header only if nfit < -7 * Sep 9 1997 Print separate right ascension and declination residuals * Sep 11 1997 Print average magnitude as well as value of residuals * Oct 16 1997 Print same information for image stars as for reference stars * Oct 22 1997 Print result of chip rotation as well as optical axis rotation * Nov 6 1997 Move nfit entirely to matchstar * Nov 6 1997 Rearrange output for IMMATCH use, adding filename argument * Nov 14 1997 Increase, not multiply, dimensions by IMFRAC * Nov 17 1997 Initialize both magnitude limits * Dec 1 1997 Fix bug computing RA separation * Dec 16 1997 Fix bug printing no match error message * * Jan 26 1998 Remove chip rotation code * Jan 27 1998 Add switch to use either Calabretta or classic AIPS WCS * Jan 29 1998 Fix summary to keep only one reference star per image star * Feb 3 1998 Add option to improve WCS by fitting residuals * Feb 12 1998 Add USNO SA catalog to reference catalog options * Feb 12 1998 Match stars even if less than the minimum if no WCS fit * Feb 19 1998 Increase number of reference stars if IMFRAC > 1 * Feb 22 1998 Fix residual fitting * Mar 3 1998 Repeat field search and match after first try * Mar 4 1998 Use imfrac on first pass, but not second * Mar 5 1998 Correct number of stars used if IMFRAC > 1 * Mar 6 1998 Add option to use image center for second pass * Mar 25 1998 Change residual polynomial fit to full plate-style polynomial * Mar 25 1998 Move residual printing to a subroutine * Mar 26 1998 Do not fit polynomial until both recenter and iterate done * Mar 27 1998 Save plate fit coefficients to FITS header * Apr 8 1998 Reset equinox to that of reference catalog * Apr 30 1998 Handle prematched star/pixel file * Jun 24 1998 Add string lengths to ra2str() and dec2str() calls * Sep 17 1998 Allow use of catalogs with other than J2000 coordinates * Sep 17 1998 Add coordinate system argument to GetFITSWCS() * Sep 28 1998 Add SAO binary format catalogs (SAO, PPM, IRAS, Tycho) * Sep 28 1998 Pass system, equinox, and epoch to all catalog search programs * Oct 2 1998 Fix arguments in call to GetFITSWCS * Oct 7 1998 Set projection to TAN before fitting * Oct 16 1998 Add option to read from TDC ASCII format catalog * Oct 26 1998 Use passed refcatname and new RefCat subroutine and wcscat.h * Oct 26 1998 Add TDC binary catalog option * Oct 28 1998 Only search for sources in image once * Nov 19 1998 Add catalog name to uacread() call * Dec 1 1998 Add version 2.0 of USNO A and SA catalogs * Dec 8 1998 Add support for ACT and Hipparcos catalogs * Jan 9 1999 Fix bug so that no fit option works * Jan 26 1999 Add option to output matched image/catalog stars * Feb 10 1999 Finish support for ACT reference catalog * Apr 7 1999 Add file name to GetFITSWCS call * Apr 21 1999 Fix RA residual bug: *cos(dec), not /cos(dec) * Jul 7 1999 Fix bug setting secpix when iterating * Jul 7 1999 List catalog and image stars without linefeeds * Jul 9 1999 Log tabread() every 100 if verbose * Jul 23 1999 Add BSC for very wide fields * Jul 26 1999 Add WCSIMCAT, WCSFRCAT, WCSMATCH, and WCSSEP to header * Jul 26 1999 Always compute residuals so WCSMATCH and WCSSEP match WCS * Jul 27 1999 Add WCSNREF, maximum possible matches * Aug 26 1999 Handle true number return from search subroutines * Aug 31 1999 Set image catalog name when only matching stars * Sep 13 1999 Do all catalog searches through catread() * Sep 15 1999 Fix improper uses of ng instead of nrg * Sep 16 1999 Add zero distsort argument to catread() call * Sep 29 1999 Add option to start with pre-matched stars * Oct 22 1999 Change catread() to ctgread() to avoid system conflict * Nov 23 1999 Free wcs only after it is used to set up iterate or recenter * * Feb 8 2000 If iterating, halve pixel tolerance on second pass * Feb 11 2000 Print maximum number of matches with number matched * Feb 15 2000 Drop maximum number of image stars * Feb 15 2000 When iterating, reinitialize CD matrix if it's being fit * Mar 1 2000 Modify residual output so = used instead of : * Mar 1 2000 Add seperate option to tighten tolerances when iterating * Mar 10 2000 Add proper motion arguments to ctgread() * Mar 10 2000 Do not change WCS unless fitting * Mar 13 2000 Use PropCat() to dind out whether catalog has proper motion * Mar 15 2000 Add proper motion arguments to RASortStars() and ctgread() * Mar 28 2000 Separate tolerance reducing iterations and other iterations * May 26 2000 Set catalog number field size using CatNumLen() * Jun 22 2000 Fix bug created in last update (found by J.-B. Marquette) * Jul 12 2000 Add catalog data structre to ctgread() call * Jul 25 2000 Pass address of star catalog data structure address * Dec 6 2000 If no reference catalog is set, skip catalog fit * Dec 6 2000 Drop static refcatname and setrefcat() * Dec 18 2000 Always allocate proper motion arrays; clean up code after lint * Dec 18 2000 Call ReadMatch() to read file of X/Y/RA/Dec matches * * Jan 8 2001 Add verbose flag to ReadMatch() call * Jan 9 2001 Fix bug in FitMatch() call * Jan 11 2001 All output except residuals to stderr * Mar 1 2001 Fill in catalog name using CatName() if not set * Jun 7 2001 Add proper motion flag and number of magnitudes to RefCat() * Jun 11 2001 Set refep from wcs->epoch after WCS is set * Jul 20 2001 FindStars() now returns magnitude instead of flux * Jul 24 2001 Add code to fit plate to catalog magnitude polynomial * Jul 25 2001 Add headings to residual table * Aug 2 2001 If fitting fewer than MINSTARS parameters, allow 1 match * Sep 11 2001 Add magnitude selection * Sep 11 2001 Use single, 2-D magnitude argument to ctgread() * Sep 13 2001 Add reference catalog magnitude selection * Sep 19 2001 Drop fitshead.h; it is in wcs.h * Oct 16 2001 Add command line parameter setting using keyword=value * Oct 29 2001 Print number of matches after residuals to avoid scroll-off * Nov 1 2001 Add goff to StarMatch() arguments * Nov 5 2001 Add refcat and gnum to StarMatch() arguments * Nov 6 2001 If iterating keep exact fit WCS after first pass * Nov 6 2001 Change sb to sm because it is now always a magnitude * Nov 6 2001 Fix image star magnitude sorting error * Nov 7 2001 Allow minimum number of stars for match to be set externally * Nov 7 2001 Drop out if match is unsuccessful * * Jan 18 2002 Allocate sm when using prematched stars * Jan 23 2002 Add zap=0 to FindStar() argument list * Jan 24 2002 Handle catalog nmag = 0 safely * Apr 10 2002 Allow sort/limit magnitude to be specified by letter as well as number * Jul 31 2002 Add iteration with increasing number of parameters to be fit * Aug 2 2002 Use WCSMatch() to set initial values for pre-matched stars * Sep 4 2002 Don't iterate if there is no catalog * * Aug 22 2003 Add inner radius =0.0 argument to ctgread call * Dec 12 2003 Add second argument to CatName() * * Aug 30 2004 Declare void undeclared set*() subroutines * * Mar 30 2006 Allow number of decimal places in image coordinates to be set * Jun 8 2006 Print object name instead of number if necessary * Jun 19 2006 Initialize uninitialized variables * * Jan 9 2006 Drop declarations of fk425e() and fk524e(); moved to wcs.h * Jan 10 2007 Drop setclass() and setplate(); it did not do anything * Jan 11 2007 Include fitsfile.h * Mar 14 2007 Return if -n 0 after computing WCS from match * * Aug 3 2009 If not printing residuals, still compute WCSSEP using CompRes() * Sep 24 2009 Free pointers more carefully * Nov 13 2009 Print catalog magnitude name in residual output header * * May 19 2010 Allocate NMAXMAG instead of number of magnitudes, nmag */ wcstools-3.9.5/libwcs/imutil.c0000664000016200001660000022200212350145013015375 0ustar minkoirsys/*** File libwcs/imutil.c *** June 17, 2014 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 2006-2014 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA */ /* Smooth, fill, or shrink an image */ /* char *FiltFITS(header, image, filter, xsize, ysize, nlog) * Return filtered image buffer * char *FillFITS(header, image, filter, xsize, ysize, nlog) * Return image bufer with bad pixels replaced by filter value * SetBadFITS (header, image, badheader, badimage, nlog) * Set bad pixels in image to BLANK using bad pixel file * SetBadVal (header, image, minpixval, maxpixval, nlog) * Set bad pixels in image to BLANK if value less than minpixval * * char *medfilt (buff, header, ndx, ndy, nlog) * Median filter an image * char *medfill (buff, header, ndx, ndy, nlog) * Set blank pixels to the median of a box around each one * medpix (x, ival, ix, iy, nx, ny, ndx, ndy, bitpix) * medpixi1 (x, ival, ix, iy, nx, ny, ndx, ndy) * medpixi2 (x, ival, ix, iy, nx, ny, ndx, ndy) * medpixi4 (x, ival, ix, iy, nx, ny, ndx, ndy) * medpixr4 (x, ival, ix, iy, nx, ny, ndx, ndy) * medpixr8 (x, ival, ix, iy, nx, ny, ndx, ndy) * Compute median of rectangular group of pixels * * char *meanfilt (buff, header, ndx, ndy, nlog) * Mean filter an image * char *meanfill (buff, header, ndx, ndy, nlog) * Set blank pixels to the mean of a box around each one * meanpix (x, ival, ix, iy, nx, ny, ndx, ndy, bitpix) * meanpixi1 (x, ival, ix, iy, nx, ny, ndx, ndy) * meanpixi2 (x, ival, ix, iy, nx, ny, ndx, ndy) * meanpixi4 (x, ival, ix, iy, nx, ny, ndx, ndy) * meanpixr4 (x, ival, ix, iy, nx, ny, ndx, ndy) * meanpixr8 (x, ival, ix, iy, nx, ny, ndx, ndy) * Compute mean of rectangular group of pixels * * char *gaussfilt (buff, header, ndx, ndy, nlog) * Gaussian filter an image * char *gaussfill (buff, header, ndx, ndy, nlog) * Set blank pixels to the Gaussian weighted sum of a box around each one * gausswt (mx, my, nx) * Compute Gaussian weights for a square region * gausspixi2 (image, ival, ix, iy, nx, ny) * gausspixi4 (image, ival, ix, iy, nx, ny) * gausspixr4 (image, ival, ix, iy, nx, ny) * gausspixr8 (image, ival, ix, iy, nx, ny) * Compute Gaussian-weighted mean of a square group of pixels * * char *ShrinkFITSImage (header, image, xfactor, yfactor, mean, bitpix, nlog) * Return image buffer reduced by a given factor * char *ShrinkFITSHeader (filename, header, xfactor, yfactor, mean, bitpix) Return image header with dimensions reduced by a given factor * double PhotPix (imbuff,header,cx,cy,rad,sumw) * Compute counts within a strictly defined circular aperture */ #include /* NULL, strlen, strstr, strcpy */ #include #include #include #include "fitsfile.h" #define MEDIAN 1 #define MEAN 2 #define GAUSSIAN 3 char *medfilt(); char *meanfilt(); char *gaussfilt(); char *badfill(); char *medfill(); char *meanfill(); char *gaussfill(); void gausswt(); unsigned char medpixi1(); unsigned char meanpixi1(); short medpixi2(); short meanpixi2(); short gausspixi2(); int medpixi4(); int meanpixi4(); int gausspixi4(); float medpixr4(); float meanpixr4(); float gausspixr4(); double medpixr8(); double meanpixr8(); double gausspixr8(); static int bpvalset = 0; static double bpval = -9999.0; static unsigned char bpvali1; static short bpvali2; static int bpvali4; static float bpvalr4; static int nfilled; int getnfilled () { return (nfilled); } void setbadpix (bpval0) double bpval0; { bpvalset = 1; bpval = bpval0; return; } /* Set all pixels to a value computed from a box around each one */ char * FiltFITS (header, image, filter, xsize, ysize, nlog) char *header; /* Image header */ char *image; /* Image bytes to be filtered */ int filter; /* Smoothing filter (median,mean,gaussian) */ int xsize; /* Number of pixels in x (odd, horizontal) */ int ysize; /* Number of pixels in y (odd, vertical) */ int nlog; /* Logging interval in lines */ { if (filter == MEDIAN) return (medfilt (image, header, xsize, ysize, nlog)); else if (filter == GAUSSIAN) return (gaussfilt (image, header, xsize, ysize, nlog)); else return (meanfilt (image, header, xsize, ysize, nlog)); } /* Set BLANK pixels to a value computed from a box around each one */ char * FillFITS (header, image, filter, xsize, ysize, nlog) char *header; /* Image header */ char *image; /* Image bytes to be filtered */ int filter; /* Smoothing filter (median,mean,gaussian) */ int xsize; /* Number of pixels in x (odd, horizontal) */ int ysize; /* Number of pixels in y (odd, vertical) */ int nlog; /* Logging interval in lines */ { if (filter == MEDIAN) return (medfill (image, header, xsize, ysize, nlog)); else if (filter == GAUSSIAN) return (gaussfill (image, header, xsize, ysize, nlog)); else return (meanfill (image, header, xsize, ysize, nlog)); } /* Set bad pixels in image to BLANK using bad pixel file */ char * SetBadFITS (header, image, badheader, badimage, nlog) char *header; /* FITS image header */ char *image; /* Image buffer */ char *badheader; /* FITS bad pixel file image header */ /* Bad pixels have non-zero values */ char *badimage; /* Bad pixel file image buffer */ int nlog; /* Logging interval in pixels */ { char *buffret; /* Modified image buffer (returned) */ int nx,ny; /* Number of columns and rows in image */ int ix,iy; /* Pixel around which to compute mean */ int npix; /* Number of pixels in image */ int bitpix; /* Number of bits per pixel (<0=floating point) */ int bitpixb; /* Number of bits per pixel in bad pixel file */ int nxb,nyb; /* Number of columns and rows in bad pixel image */ int naxes; char *buff; char *buffbad; hgeti4 (header, "BITPIX", &bitpix); hgeti4 (header, "NAXIS", &naxes); hgeti4 (header, "NAXIS1", &nx); if (naxes > 1) hgeti4 (header, "NAXIS2", &ny); else ny = 1; npix = nx * ny; if (!bpvalset) hgetr8 (header, "BLANK", &bpval); hgeti4 (badheader, "BITPIX", &bitpixb); hgeti4 (badheader, "NAXIS", &naxes); hgeti4 (badheader, "NAXIS1", &nxb); if (naxes > 1) hgeti4 (badheader, "NAXIS2", &nyb); else nyb = 1; if (nx != nxb || ny != nyb) { fprintf (stderr, "SetBadFITS: Data file and bad pixel file mismatch %dx%d not %dx%d\n", nx,ny,nxb,nyb); return (NULL); } nfilled = 0; buff = image; buffbad = badimage; buffret = NULL; if (bitpix == 16) { short *b1, *b2, *buffout; bpvali2 = (short) bpval; buffret = (char *) calloc (npix, sizeof (short)); buffout = (short *) buffret; b1 = (short *) buff; b2 = buffout; if (bitpixb == 16) { short *bb; bb = (short *) buffbad; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*bb++) { *b2++ = bpvali2; nfilled++; *b1++; } else { *b2++ = *b1++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"SetBadFITS: %d lines, %d bad pixels set\r", iy+1, nfilled); } } else if (bitpixb == 32) { int *bb; bb = (int *) buffbad; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*bb++) { *b2++ = bpvali2; nfilled++; *b1++; } else { *b2++ = *b1++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"SetBadFITS: %d lines, %d bad pixels set\r", iy+1, nfilled); } } } else if (bitpix == 32) { int *b1, *b2, *buffout; bpvali4 = (int) bpval; buffret = (char *) calloc (npix, sizeof (int)); buffout = (int *) buffret; b1 = (int *) buff; b2 = buffout; if (bitpixb == 16) { short *bb; bb = (short *) buffbad; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*bb++) { *b2++ = bpvali4; nfilled++; *b1++; } else { *b2++ = *b1++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"SetBadFITS: %d lines, %d bad pixels set\r", iy+1, nfilled); } } else if (bitpixb == 32) { int *bb; bb = (int *) buffbad; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*bb++) { *b2++ = bpvali4; nfilled++; *b1++; } else { *b2++ = *b1++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"SetBadFITS: %d lines, %d bad pixels set\r", iy+1, nfilled); } } fprintf (stderr,"\n"); } else if (bitpix == -32) { float *b1, *b2, *buffout; buffret = (char *) calloc (npix, sizeof (float)); buffout = (float *) buffret; bpvalr4 = (float) bpval; b1 = (float *) buff; b2 = buffout; if (bitpixb == 16) { short *bb; bb = (short *) buffbad; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*bb++) { *b2++ = bpvalr4; nfilled++; *b1++; } else { *b2++ = *b1++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"SetBadFITS: %d lines, %d bad pixels set\r", iy+1, nfilled); } } else if (bitpixb == 32) { int *bb; bb = (int *) buffbad; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*bb++) { *b2++ = bpvalr4; nfilled++; *b1++; } else { *b2++ = *b1++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"SetBadFITS: %d lines, %d bad pixels set\r", iy+1, nfilled); } } } else if (bitpix == -64) { double *b1, *b2, *buffout; buffret = (char *) calloc (npix, sizeof (double)); buffout = (double *) buffret; b1 = (double *) buff; b2 = buffout; if (bitpixb == 16) { short *bb; bb = (short *) buffbad; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*bb++) { *b2++ = bpval; nfilled++; *b1++; } else { *b2++ = *b1++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"SetBadFITS: %d lines, %d bad pixels set\r", iy+1, nfilled); } } else if (bitpixb == 32) { int *bb; bb = (int *) buffbad; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*bb++) { *b2++ = bpval; nfilled++; *b1++; } else { *b2++ = *b1++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"SetBadFITS: %d lines, %d bad pixels set\r", iy+1, nfilled); } } } if (nlog > 0) fprintf (stderr,"SetBadFITS: %d lines, %d bad pixels set\n", iy, nfilled); return (buffret); } /* Set bad pixels in image to BLANK if less than minpixval */ char * SetBadVal (header, image, minval, maxval, nlog) char *header; /* FITS image header */ char *image; /* Image buffer */ double minval; /* Minimum good pixel value */ double maxval; /* Maximum good pixel value */ int nlog; /* Logging interval in pixels */ { char *buffret; /* Modified image buffer (returned) */ int nx,ny; /* Number of columns and rows in image */ int ix,iy; /* Pixel around which to compute mean */ int npix; /* Number of pixels in image */ int bitpix; /* Number of bits per pixel (<0=floating point) */ int checkmin = 0; int checkmax = 0; int naxes; char *buff; hgeti4 (header, "BITPIX", &bitpix); hgeti4 (header, "NAXIS", &naxes); hgeti4 (header, "NAXIS1", &nx); if (naxes > 1) hgeti4 (header, "NAXIS2", &ny); else ny = 1; npix = nx * ny; if (!bpvalset) hgetr8 (header, "BLANK", &bpval); if (minval != -9999.0) checkmin++; if (maxval != -9999.0) checkmax++; nfilled = 0; buff = image; buffret = NULL; if (bitpix == 16) { short *bb, *b1, *b2, *buffout, bpvali2, mnvali2,mxvali2; bpvali2 = (short) bpval; mnvali2 = (short) minval; mxvali2 = (short) maxval; buffret = (char *) calloc (npix, sizeof (short)); buffout = (short *) buffret; bb = (short *) buff; b1 = (short *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (checkmin && *bb < mnvali2) { *b2++ = bpvali2; nfilled++; *b1++; } else if (checkmax && *bb > mxvali2) { *b2++ = bpvali2; nfilled++; *b1++; } else { *b2++ = *b1++; } bb++; } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"SetBadVal: %d lines, %d bad pixels set\r", iy+1, nfilled); } } else if (bitpix == 32) { int *bb, *b1, *b2, *buffout, mnvali4, mxvali4, bpvali4; bpvali4 = (int) bpval; mnvali4 = (int) minval; mxvali4 = (int) maxval; buffret = (char *) calloc (npix, sizeof (int)); buffout = (int *) buffret; bb = (int *) buff; b1 = (int *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (checkmin && *bb < mnvali4) { *b2++ = bpvali4; nfilled++; *b1++; } else if (checkmax && *bb > mxvali4) { *b2++ = bpvali4; nfilled++; *b1++; } else { *b2++ = *b1++; } bb++; } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"SetBadVal: %d lines, %d bad pixels set\r", iy+1, nfilled); } } else if (bitpix == -32) { float *bb, *b1, *b2, *buffout, bpvalr4, mnvalr4, mxvalr4; buffret = (char *) calloc (npix, sizeof (float)); buffout = (float *) buffret; bpvalr4 = (float) bpval; mnvalr4 = (float) minval; mxvalr4 = (float) maxval; bb = (float *) buff; b1 = (float *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (checkmin && *bb < mnvalr4) { *b2++ = bpvalr4; nfilled++; *b1++; } else if (checkmax && *bb > mxvalr4) { *b2++ = bpvalr4; nfilled++; *b1++; } else { *b2++ = *b1++; } bb++; } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"SetBadVal: %d lines, %d bad pixels set\r", iy+1, nfilled); } } else if (bitpix == -64) { double *bb, *b1, *b2, *buffout, bpvalr8, mnvalr8, mxvalr8; buffret = (char *) calloc (npix, sizeof (double)); buffout = (double *) buffret; bpvalr8 = (double) bpval; mnvalr8 = (double) minval; mxvalr8 = (double) maxval; bb = (double *) buff; b1 = (double *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (checkmin && *bb < mnvalr8) { *b2++ = bpvalr8; nfilled++; *b1++; } else if (checkmax && *bb > mxvalr8) { *b2++ = bpvalr8; nfilled++; *b1++; } else { *b2++ = *b1++; } bb++; } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"SetBadVal: %d lines, %d bad pixels set\r", iy+1, nfilled); } } if (nlog > 0) fprintf (stderr,"SetBadVal: %d lines, %d bad pixels set\n", iy, nfilled); return (buffret); } /* Median filter an image */ static unsigned char *vi1; /* Working vector to sort for median */ static short *vi2; /* Working vector to sort for median */ static int *vi4; /* Working vector to sort for median */ static float *vr4; /* Working vector to sort for median */ static double *vr8; /* Working vector to sort for median */ char * medfilt (buff, header, ndx, ndy, nlog) char *buff; /* Image buffer */ char *header; /* FITS image header */ int ndx; /* Number of columns over which to compute the median */ int ndy; /* Number of rows over which to compute the median */ int nlog; /* Logging interval in pixels */ { char *buffret; /* Modified image buffer (returned) */ int nx,ny; /* Number of columns and rows in image */ int ix,iy; /* Pixel around which to compute median */ int npix; /* Number of pixels in image */ int bitpix; /* Number of bits per pixel (<0=floating point) */ int naxes; hgeti4 (header, "BITPIX", &bitpix); hgeti4 (header, "NAXIS", &naxes); hgeti4 (header, "NAXIS1", &nx); if (naxes > 1) hgeti4 (header, "NAXIS2", &ny); else ny = 1; npix = nx * ny; hgetr8 (header, "BLANK", &bpval); buffret = NULL; if (bitpix == 16) { short *b1,*b2, *buffout; bpvali2 = (short) bpval; vi2 = NULL; buffret = (char *) calloc (npix, sizeof (short)); buffout = (short *) buffret; b1 = (short *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { *b2++ = medpixi2 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEDFILT: %d lines filtered\r", iy+1); } fprintf (stderr,"\n"); free (vi2); vi2 = NULL; } else if (bitpix == 32) { int *b1, *b2, *buffout; bpvali4 = (int) bpval; vi4 = NULL; buffret = (char *) calloc (npix, sizeof (int)); buffout = (int *) buffret; b1 = (int *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { *b2++ = medpixi4 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEDFILT: %d lines filtered\r", iy+1); } fprintf (stderr,"\n"); free (vi4); vi4 = NULL; } else if (bitpix == -32) { float *b1, *b2, *buffout; buffret = (char *) calloc (npix, sizeof (float)); buffout = (float *) buffret; b1 = (float *) buff; b2 = buffout; bpvalr4 = (float) bpval; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { *b2++ = medpixr4 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEDFILT: %d lines filtered\r", iy+1); } fprintf (stderr,"\n"); free (vr4); vr4 = NULL; } else if (bitpix == -64) { double *b1, *b2, *buffout; buffret = (char *) calloc (npix, sizeof (double)); buffout = (double *) buffret; b1 = (double *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { *b2++ = medpixr8 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEDFILT: %d lines filtered\r", iy+1); } fprintf (stderr,"\n"); free (vr8); vr8 = NULL; } if (nlog > 0) fprintf (stderr,"MEDFILT: %d lines filtered\n", iy); return (buffret); } /* Set blank pixels to the median of a box around each one */ char * medfill (buff, header, ndx, ndy, nlog) char *buff; /* Image buffer */ char *header; /* FITS image header */ int ndx; /* Number of columns over which to compute the median */ int ndy; /* Number of rows over which to compute the median */ int nlog; /* Logging interval in pixels */ { char *buffret; /* Modified image buffer (returned) */ int nx,ny; /* Number of columns and rows in image */ int ix,iy; /* Pixel around which to compute median */ int npix; /* Number of pixels in image */ int bitpix; /* Number of bits per pixel (<0=floating point) */ int naxes; hgeti4 (header, "BITPIX", &bitpix); hgeti4 (header, "NAXIS", &naxes); hgeti4 (header, "NAXIS1", &nx); if (naxes > 1) hgeti4 (header, "NAXIS2", &ny); else ny = 1; npix = nx * ny; hgetr8 (header, "BLANK", &bpval); nfilled = 0; buffret = NULL; if (bitpix == 16) { short *b1,*b2, *buffout; bpvali2 = (short) bpval; vi2 = NULL; buffret = (char *) calloc (npix, sizeof (short)); buffout = (short *) buffret; b1 = (short *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*b1 != bpvali2) *b2++ = *b1++; else { *b2++ = medpixi2 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); nfilled++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEDFILL: %d lines, %d pixels filled\r", iy+1, nfilled); } free (vi2); vi2 = NULL; } else if (bitpix == 32) { int *b1, *b2, *buffout; bpvali4 = (int) bpval; vi4 = NULL; buffret = (char *) calloc (npix, sizeof (int)); buffout = (int *) buffret; b1 = (int *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*b1 != bpvali4) *b2++ = *b1++; else { *b2++ = medpixi4 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); nfilled++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEDFILL: %d lines, %d pixels filled\r", iy+1, nfilled); } free (vi4); vi4 = NULL; } else if (bitpix == -32) { float *b1, *b2, *buffout; buffret = (char *) calloc (npix, sizeof (float)); buffout = (float *) buffret; bpvalr4 = (float) bpval; b1 = (float *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*b1 != bpvalr4) *b2++ = *b1++; else { *b2++ = medpixr4 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); nfilled++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEDFILL: %d lines, %d pixels filled\r", iy+1, nfilled); } free (vr4); vr4 = NULL; } else if (bitpix == -64) { double *b1, *b2, *buffout; buffret = (char *) calloc (npix, sizeof (double)); buffout = (double *) buffret; b1 = (double *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*b1 != bpval) *b2++ = *b1++; else { *b2++ = medpixr8 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); nfilled++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEDFILL: %d lines, %d pixels filled\r", iy+1, nfilled); } free (vr8); vr8 = NULL; } if (nlog > 0) fprintf (stderr,"MEDFILL: %d lines, %d pixels filled\n", iy, nfilled); return (buffret); } /* Compute median of rectangular group of pixels */ double medpix (buff, ix, iy, nx, ny, ndx, ndy, bitpix) char *buff; /* Image buffer */ int ix,iy; /* Pixel around which to compute median */ int nx,ny; /* Number of columns and rows in image */ int ndx; /* Number of columns over which to compute the median */ int ndy; /* Number of rows over which to compute the median */ int bitpix; /* Number of bits in pixels; negative are floating point */ { if (bitpix == 16) { unsigned char cval, *cbuff; cval = (char) 0; cbuff = (unsigned char *) buff; return ((double) medpixi1 (cbuff, cval, ix, iy, nx, ny, ndx, ndy)); } else if (bitpix == 16) { short jval, *jbuff; jval = 0; jbuff = (short *) buff; return ((double) medpixi2 (jbuff, jval, ix, iy, nx, ny, ndx, ndy)); } else if (bitpix == 32) { int ival, *ibuff; ival = 0; ibuff = (int *) buff; return ((double) medpixi4 (ibuff, ival, ix, iy, nx, ny, ndx, ndy)); } else if (bitpix == -32) { float rval, *rbuff; rval = 0.0; rbuff = (float *) buff; return ((double) medpixr4 (rbuff, rval, ix, iy, nx, ny, ndx, ndy)); } else if (bitpix == -64) { double dval, *dbuff; dval = 0.0; dbuff = (double *) buff; return (medpixr8 (dbuff, dval, ix, iy, nx, ny, ndx, ndy)); } else return (0.0); } unsigned char medpixi1 (x, ival, ix, iy, nx, ny, ndx, ndy) unsigned char *x; /* Image buffer */ unsigned char ival; /* Value at this pixel */ int ix,iy; /* Pixel around which to compute median */ int nx,ny; /* Number of columns and rows in image */ int ndx; /* Number of columns over which to compute the median */ int ndy; /* Number of rows over which to compute the median */ { unsigned char xx, *vecj, *img; int n, i, j; int nx2, ny2, npix; int jx, jx1, jx2, jy, jy1, jy2; /* Allocate working buffer if it hasn't already been allocated */ npix = ndx * ndy; if (vi1 == NULL) { vi1 = (unsigned char *) calloc (npix, sizeof (unsigned char)); if (vi1 == NULL) { fprintf (stderr, "MEDPIXI1: Could not allocate %d-pixel buffer\n",npix); return (0); } } n = ndx * ndy; if (n <= 0) return (0.0); else if (n == 1) return (*(x + (iy * ny) + ix)); /* Compute limits for this pixel */ nx2 = ndx / 2; jx1 = ix - nx2; if (jx1 < 0) jx1 = 0; jx2 = ix + nx2 + 1; if (jx2 > nx) jx2 = nx; ny2 = ndy / 2; jy1 = iy - ny2; if (jy1 < 0) jy1 = 0; jy2 = iy + ny2 + 1; if (jy2 > ny) jy2 = ny; /* Initialize actual number of pixels used for this pixel */ n = 0; /* Set up working vector for this pixel */ vecj = vi1; for (jy = jy1; jy < jy2; jy++) { img = x + (jy * nx) + jx1; for (jx = jx1; jx < jx2; jx++) { if (*img != bpvali1) { *vecj++ = *img; n++; } img++; } } /* If no good pixels, return old value */ if (n < 1) return (ival); /* Sort numbers in working vector */ else { for (j = 2; j <= n; j++) { xx = vi1[j]; i = j - 1; while (i > 0 && vi1[i] > xx) { vi1[i+1] = vi1[i]; i--; } vi1[i+1] = xx; } /* Middle number is the median */ return (vi1[n/2]); } } short medpixi2 (x, ival, ix, iy, nx, ny, ndx, ndy) short *x; /* Image buffer */ short ival; /* Value at this pixel */ int ix,iy; /* Pixel around which to compute median */ int nx,ny; /* Number of columns and rows in image */ int ndx; /* Number of columns over which to compute the median */ int ndy; /* Number of rows over which to compute the median */ { short xx, *vecj, *img; int n, i, j; int nx2, ny2, npix; int jx, jx1, jx2, jy, jy1, jy2; /* Allocate working buffer if it hasn't already been allocated */ npix = ndx * ndy; if (vi2 == NULL) { vi2 = (short *) calloc (npix, sizeof (short)); if (vi2 == NULL) { fprintf (stderr, "MEDPIXI2: Could not allocate %d-pixel buffer\n",npix); return (0); } } n = ndx * ndy; if (n <= 0) return (0.0); else if (n == 1) return (*(x + (iy * ny) + ix)); /* Compute limits for this pixel */ nx2 = ndx / 2; jx1 = ix - nx2; if (jx1 < 0) jx1 = 0; jx2 = ix + nx2 + 1; if (jx2 > nx) jx2 = nx; ny2 = ndy / 2; jy1 = iy - ny2; if (jy1 < 0) jy1 = 0; jy2 = iy + ny2 + 1; if (jy2 > ny) jy2 = ny; /* Initialize actual number of pixels used for this pixel */ n = 0; /* Set up working vector for this pixel */ vecj = vi2; for (jy = jy1; jy < jy2; jy++) { img = x + (jy * nx) + jx1; for (jx = jx1; jx < jx2; jx++) { if (*img != bpvali2) { *vecj++ = *img; n++; } img++; } } /* If no good pixels, return old value */ if (n < 1) return (ival); /* Sort numbers in working vector */ else { for (j = 2; j <= n; j++) { xx = vi2[j]; i = j - 1; while (i > 0 && vi2[i] > xx) { vi2[i+1] = vi2[i]; i--; } vi2[i+1] = xx; } /* Middle number is the median */ return (vi2[n/2]); } } /* Compute median of rectangular group of pixels */ int medpixi4 (x, ival, ix, iy, nx, ny, ndx, ndy) int *x; /* Image buffer */ int ival; /* Current pixel */ int ix,iy; /* Pixel around which to compute median */ int nx,ny; /* Number of columns and rows in image */ int ndx; /* Number of columns over which to compute the median */ int ndy; /* Number of rows over which to compute the median */ { int xx, *vecj, *img; int n, i, j; int nx2, ny2, npix; int jx, jx1, jx2, jy, jy1, jy2; /* Allocate working buffer if it hasn't already been allocated */ npix = ndx * ndy; if (vi4 == NULL) { vi4 = (int *) calloc (npix, sizeof (int)); if (vi4 == NULL) { fprintf (stderr, "MEDIANI4: Could not allocate %d-pixel buffer\n",npix); return (0); } } n = ndx * ndy; if (n <= 0) return (0.0); else if (n == 1) return (*(x + (iy * ny) + ix)); /* Compute limits for this pixel */ nx2 = ndx / 2; jx1 = ix - nx2; if (jx1 < 0) jx1 = 0; jx2 = ix + nx2 + 1; if (jx2 > nx) jx2 = nx; ny2 = ndy / 2; jy1 = iy - ny2; if (jy1 < 0) jy1 = 0; jy2 = iy + ny2 + 1; if (jy2 > ny) jy2 = ny; /* Intitialize actual number of pixels used for this pixel */ n = 0; /* Set up working vector for this pixel */ vecj = vi4; for (jy = jy1; jy < jy2; jy++) { img = x + (jy * nx) + jx1; for (jx = jx1; jx < jx2; jx++) { if (*img != bpvali4) { *vecj++ = *img; n++; } img++; } } /* If no good pixels, return old value */ if (n < 1) return (ival); /* Sort numbers in working vector */ else { for (j = 2; j <= n; j++) { xx = vi4[j]; i = j - 1; while (i > 0 && vi4[i] > xx) { vi4[i+1] = vi4[i]; i--; } vi4[i+1] = xx; } /* Middle number is the median */ return (vi4[n/2]); } } float medpixr4 (x, rval, ix, iy, nx, ny, ndx, ndy) float *x; /* Image buffer */ float rval; /* Image value at this pixel */ int ix,iy; /* Pixel around which to compute median */ int nx,ny; /* Number of columns and rows in image */ int ndx; /* Number of columns over which to compute the median */ int ndy; /* Number of rows over which to compute the median */ { float xx, *vecj, *img; int n, i, j; int nx2, ny2, npix; int jx, jx1, jx2, jy, jy1, jy2; /* Allocate working buffer if it hasn't already been allocated */ npix = ndx * ndy; if (vr4 == NULL) { vr4 = (float *) calloc (npix, sizeof (float)); if (vr4 == NULL) { fprintf (stderr, "MEDIANR4: Could not allocate %d-pixel buffer\n",npix); return (0); } } n = ndx * ndy; if (n <= 0) return (0.0); else if (n == 1) return (*(x + (iy * ny) + ix)); /* Compute limits for this pixel */ nx2 = ndx / 2; jx1 = ix - nx2; if (jx1 < 0) jx1 = 0; jx2 = ix + nx2 + 1; if (jx2 > nx) jx2 = nx; ny2 = ndy / 2; jy1 = iy - ny2; if (jy1 < 0) jy1 = 0; jy2 = iy + ny2 + 1; if (jy2 > ny) jy2 = ny; /* Initialize actual number of pixels used for this pixel */ n = 0; /* Set up working vector for this pixel */ vecj = vr4; for (jy = jy1; jy < jy2; jy++) { img = x + (jy * nx) + jx1; for (jx = jx1; jx < jx2; jx++) { if (*img != bpvalr4 && !isnan(*img)) { *vecj++ = *img; n++; } img++; } } /* If no good pixels, return old value */ if (n < 1) return (rval); /* Sort numbers in working vector */ else { for (j = 2; j <= n; j++) { xx = vr4[j]; i = j - 1; while (i > 0 && vr4[i] > xx) { vr4[i+1] = vr4[i]; i--; } vr4[i+1] = xx; } /* Middle number is the median */ return (vr4[n/2]); } } double medpixr8 (x, dval, ix, iy, nx, ny, ndx, ndy) double *x; /* Image buffer */ double dval; /* Image value of this pixel */ int ix,iy; /* Pixel around which to compute median */ int nx,ny; /* Number of columns and rows in image */ int ndx; /* Number of columns over which to compute the median */ int ndy; /* Number of rows over which to compute the median */ { double xx, *vecj, *img; int n, i, j; int nx2, ny2, npix; int jx, jx1, jx2, jy, jy1, jy2; /* Allocate working buffer if it hasn't already been allocated */ npix = ndx * ndy; if (vr8 == NULL) { vr8 = (double *) calloc (npix, sizeof (double)); if (vr8 == NULL) { fprintf (stderr, "MEDIANR8: Could not allocate %d-pixel buffer\n",npix); return (0); } } n = ndx * ndy; if (n <= 0) return (0.0); else if (n == 1) return (*(x + (iy * ny) + ix)); /* Compute limits for this pixel */ nx2 = ndx / 2; jx1 = ix - nx2; if (jx1 < 0) jx1 = 0; jx2 = ix + nx2 + 1; if (jx2 > nx) jx2 = nx; ny2 = ndy / 2; jy1 = iy - ny2; if (jy1 < 0) jy1 = 0; jy2 = iy + ny2 + 1; if (jy2 > ny) jy2 = ny; /* Initialize actual number of pixels used for this pixel */ n = 0; /* Set up working vector for this pixel */ vecj = vr8; for (jy = jy1; jy < jy2; jy++) { img = x + (jy * nx) + jx1; for (jx = jx1; jx < jx2; jx++) { if (*img != bpval && !isnan(*img)) { *vecj++ = *img; n++; } img++; } } /* If no good pixels, return old value */ if (n < 1) return (dval); /* Sort numbers in working vector */ else { for (j = 2; j <= n; j++) { xx = vr8[j]; i = j - 1; while (i > 0 && vr8[i] > xx) { vr8[i+1] = vr8[i]; i--; } vr8[i+1] = xx; } /* Middle number is the median */ return (vr8[n/2]); } } /* Mean filter an image */ char * meanfilt (buff, header, ndx, ndy, nlog) char *buff; /* Image buffer */ char *header; /* FITS image header */ int ndx; /* Number of columns over which to compute the mean */ int ndy; /* Number of rows over which to compute the mean */ int nlog; /* Logging interval in pixels */ { char *buffret; /* Modified image buffer (returned) */ int nx,ny; /* Number of columns and rows in image */ int ix,iy; /* Pixel around which to compute mean */ int npix; /* Number of pixels in image */ int bitpix; /* Number of bits per pixel (<0=floating point) */ int naxes; hgeti4 (header, "BITPIX", &bitpix); hgeti4 (header, "NAXIS", &naxes); hgeti4 (header, "NAXIS1", &nx); if (naxes > 1) hgeti4 (header, "NAXIS2", &ny); else ny = 1; npix = nx * ny; hgetr8 (header, "BLANK", &bpval); buffret = NULL; if (bitpix == 16) { short *b1, *b2, *buffout; bpvali2 = (short) bpval; vi2 = NULL; buffret = (char *) calloc (npix, sizeof (short)); buffout = (short *) buffret; b1 = (short *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { *b2++ = meanpixi2 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEANFILT: %d lines filtered\r", iy+1); } free (vi2); vi2 = NULL; } else if (bitpix == 32) { int *b1, *b2, *buffout; bpvali4 = (int) bpval; vi4 = NULL; buffret = (char *) calloc (npix, sizeof (int)); buffout = (int *) buffret; b1 = (int *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { *b2++ = meanpixi4 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEANFILT: %d lines filtered\r", iy+1); } free (vi4); vi4 = NULL; } else if (bitpix == -32) { float *b1, *b2, *buffout; buffret = (char *) calloc (npix, sizeof (float)); buffout = (float *) buffret; bpvalr4 = (float) bpval; b1 = (float *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { *b2++ = meanpixr4 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEANFILT: %d lines filtered\r", iy+1); } free (vr4); vr4 = NULL; } else if (bitpix == -64) { double *b1, *b2, *buffout; buffret = (char *) calloc (npix, sizeof (double)); buffout = (double *) buffret; b1 = (double *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { *b2++ = meanpixr8 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEANFILT: %d lines filtered\r", iy+1); } free (vr8); vr8 = NULL; } if (nlog > 0) fprintf (stderr,"MEANFILT: %d lines filtered\n", iy); return (buffret); } /* Set blank pixels to the mean of a box around each one */ char * meanfill (buff, header, ndx, ndy, nlog) char *buff; /* Image buffer */ char *header; /* FITS image header */ int ndx; /* Number of columns over which to compute the mean */ int ndy; /* Number of rows over which to compute the mean */ int nlog; /* Logging interval in pixels */ { char *buffret; /* Modified image buffer (returned) */ int nx,ny; /* Number of columns and rows in image */ int ix,iy; /* Pixel around which to compute mean */ int npix; /* Number of pixels in image */ int bitpix; /* Number of bits per pixel (<0=floating point) */ int naxes; hgeti4 (header, "BITPIX", &bitpix); hgeti4 (header, "NAXIS", &naxes); hgeti4 (header, "NAXIS1", &nx); if (naxes > 1) hgeti4 (header, "NAXIS2", &ny); else ny = 1; npix = nx * ny; hgetr8 (header, "BLANK", &bpval); nfilled = 0; buffret = NULL; if (bitpix == 16) { short *b1, *b2, *buffout; bpvali2 = (short) bpval; vi2 = NULL; buffret = (char *) calloc (npix, sizeof (short)); buffout = (short *) buffret; b1 = (short *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*b1 != bpvali2) *b2++ = *b1++; else { *b2++ = meanpixi2 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); nfilled++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEANFILL: %d lines, %d pixels filled\r", iy+1, nfilled); } free (vi2); vi2 = NULL; } else if (bitpix == 32) { int *b1, *b2, *buffout; bpvali4 = (int) bpval; vi4 = NULL; buffret = (char *) calloc (npix, sizeof (int)); buffout = (int *) buffret; b1 = (int *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*b1 != bpvali4) *b2++ = *b1++; else { *b2++ = meanpixi4 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); nfilled++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEANFILL: %d lines, %d pixels filled\r", iy+1, nfilled); } free (vi4); vi4 = NULL; } else if (bitpix == -32) { float *b1, *b2, *buffout; buffret = (char *) calloc (npix, sizeof (float)); buffout = (float *) buffret; bpvalr4 = (float) bpval; b1 = (float *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*b1 != bpvalr4) *b2++ = *b1++; else { *b2++ = meanpixr4 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); nfilled++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEANFILL: %d lines, %d pixels filled\r", iy+1, nfilled); } free (vr4); vr4 = NULL; } else if (bitpix == -64) { double *b1, *b2, *buffout; buffret = (char *) calloc (npix, sizeof (double)); buffout = (double *) buffret; b1 = (double *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*b1 != bpval) *b2++ = *b1++; else { *b2++ = meanpixr8 (buff, *b1++, ix, iy, nx, ny, ndx, ndy); nfilled++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"MEANFILL: %d lines, %d pixels filled\r", iy+1, nfilled); } free (vr8); vr8 = NULL; } if (nlog > 0) fprintf (stderr,"MEANFILL: %d lines, %d pixels filled\n", iy, nfilled); return (buffret); } /* Compute mean of rectangular group of pixels */ double meanpix (buff, ix, iy, nx, ny, ndx, ndy, bitpix) char *buff; /* Image buffer */ int ix,iy; /* Pixel around which to compute median */ int nx,ny; /* Number of columns and rows in image */ int ndx; /* Number of columns over which to compute the median */ int ndy; /* Number of rows over which to compute the median */ int bitpix; /* Number of bits in pixels; negative are floating point */ { if (bitpix == 8) { unsigned char cval, *cbuff; cval = 0; cbuff = (unsigned char *) buff; return ((double) meanpixi1 (cbuff, cval, ix, iy, nx, ny, ndx, ndy)); } else if (bitpix == 16) { short jval, *jbuff; jval = 0; jbuff = (short *) buff; return ((double) meanpixi2 (jbuff, jval, ix, iy, nx, ny, ndx, ndy)); } else if (bitpix == 32) { int ival, *ibuff; ival = 0; ibuff = (int *) buff; return ((double) meanpixi4 (ibuff, ival, ix, iy, nx, ny, ndx, ndy)); } else if (bitpix == -32) { float rval, *rbuff; rval = 0.0; rbuff = (float *) buff; return ((double) meanpixr4 (rbuff, rval, ix, iy, nx, ny, ndx, ndy)); } else if (bitpix == -64) { double dval, *dbuff; dval = 0.0; dbuff = (double *) buff; return (meanpixr8 (dbuff, dval, ix, iy, nx, ny, ndx, ndy)); } else return (0.0); } unsigned char meanpixi1 (x, ival, ix, iy, nx, ny, ndx, ndy) unsigned char *x; /* Image buffer */ unsigned char ival; /* Image pixel value */ int ix,iy; /* Pixel around which to compute median */ int nx,ny; /* Number of columns and rows in image */ int ndx; /* Number of columns over which to compute the median */ int ndy; /* Number of rows over which to compute the median */ { double sum, newval; unsigned char *img; int n, nx2, ny2; int jx, jx1, jx2, jy, jy1, jy2; n = ndx * ndy; if (n <= 0) return (0.0); else if (n == 1) return (*(x + (iy * ny) + ix)); /* Compute limits for this pixel */ nx2 = ndx / 2; jx1 = ix - nx2; if (jx1 < 0) jx1 = 0; jx2 = ix + nx2 + 1; if (jx2 > nx) jx2 = nx; ny2 = ndy / 2; jy1 = iy - ny2; if (jy1 < 0) jy1 = 0; jy2 = iy + ny2 + 1; if (jy2 > ny) jy2 = ny; /* Initialize actual number of pixels used for this pixel */ n = 0; /* Compute total counts around this pixel */ sum = 0.0; for (jy = jy1; jy < jy2; jy++) { img = x + (jy * nx) + jx1; for (jx = jx1; jx < jx2; jx++) { if (*img != bpvali1) { sum = sum + (double) *img; n++; } img++; } } if (n < 1) return (ival); else { newval = sum / (double) n; if (newval > 255.0) newval = 255.0; if (newval < 0.0) newval = 0.0; return ((unsigned char) newval); } } short meanpixi2 (x, ival, ix, iy, nx, ny, ndx, ndy) short *x; /* Image buffer */ short ival; /* Image pixel value */ int ix,iy; /* Pixel around which to compute median */ int nx,ny; /* Number of columns and rows in image */ int ndx; /* Number of columns over which to compute the median */ int ndy; /* Number of rows over which to compute the median */ { double sum; short *img; int n, nx2, ny2; int jx, jx1, jx2, jy, jy1, jy2; n = ndx * ndy; if (n <= 0) return (0.0); else if (n == 1) return (*(x + (iy * ny) + ix)); /* Compute limits for this pixel */ nx2 = ndx / 2; jx1 = ix - nx2; if (jx1 < 0) jx1 = 0; jx2 = ix + nx2 + 1; if (jx2 > nx) jx2 = nx; ny2 = ndy / 2; jy1 = iy - ny2; if (jy1 < 0) jy1 = 0; jy2 = iy + ny2 + 1; if (jy2 > ny) jy2 = ny; /* Initialize actual number of pixels used for this pixel */ n = 0; /* Compute total counts around this pixel */ sum = 0.0; for (jy = jy1; jy < jy2; jy++) { img = x + (jy * nx) + jx1; for (jx = jx1; jx < jx2; jx++) { if (*img != bpvali2) { sum = sum + (double) *img; n++; } img++; } } if (n < 1) return (ival); else return ((short) (sum / (double) n)); } int meanpixi4 (x, ival, ix, iy, nx, ny, ndx, ndy) int *x; /* Image buffer */ int ival; /* Image pixel value */ int ix,iy; /* Pixel around which to compute median */ int nx,ny; /* Number of columns and rows in image */ int ndx; /* Number of columns over which to compute the median */ int ndy; /* Number of rows over which to compute the median */ { double sum; int *img; int n, nx2, ny2; int jx, jx1, jx2, jy, jy1, jy2; n = ndx * ndy; if (n <= 0) return (0.0); else if (n == 1) return (*(x + (iy * ny) + ix)); /* Compute limits for this pixel */ nx2 = ndx / 2; jx1 = ix - nx2; if (jx1 < 0) jx1 = 0; jx2 = ix + nx2 + 1; if (jx2 > nx) jx2 = nx; ny2 = ndy / 2; jy1 = iy - ny2; if (jy1 < 0) jy1 = 0; jy2 = iy + ny2 + 1; if (jy2 > ny) jy2 = ny; /* Initialize actual number of pixels used for this pixel */ n = 0; /* Set up working vector for this pixel */ sum = 0.0; for (jy = jy1; jy < jy2; jy++) { img = x + (jy * nx) + jx1; for (jx = jx1; jx < jx2; jx++) { if (*img != bpvali4) { sum = sum + (double) *img; n++; } img++; } } if (n < 1) return (ival); else return ((int) (sum / (double) n)); } float meanpixr4 (x, rval, ix, iy, nx, ny, ndx, ndy) float *x; /* Image buffer */ float rval; /* Image pixel value */ int ix,iy; /* Pixel around which to compute median */ int nx,ny; /* Number of columns and rows in image */ int ndx; /* Number of columns over which to compute the median */ int ndy; /* Number of rows over which to compute the median */ { double sum; float *img; int n, nx2, ny2; int jx, jx1, jx2, jy, jy1, jy2; n = ndx * ndy; if (n <= 0) return (0.0); else if (n == 1) return (*(x + (iy * ny) + ix)); /* Compute limits for this pixel */ nx2 = ndx / 2; jx1 = ix - nx2; if (jx1 < 0) jx1 = 0; jx2 = ix + nx2 + 1; if (jx2 > nx) jx2 = nx; ny2 = ndy / 2; jy1 = iy - ny2; if (jy1 < 0) jy1 = 0; jy2 = iy + ny2 + 1; if (jy2 > ny) jy2 = ny; /* Initialize actual number of pixels used for this pixel */ n = 0; /* Set up working vector for this pixel */ sum = 0.0; for (jy = jy1; jy < jy2; jy++) { img = x + (jy * nx) + jx1; for (jx = jx1; jx < jx2; jx++) { if (*img != bpvalr4 && !isnan (*img)) { sum = sum + (double) *img; n++; } img++; } } if (n < 1) return (rval); else return ((float) (sum / (double) n)); } double meanpixr8 (x, dval, ix, iy, nx, ny, ndx, ndy) double *x; /* Image buffer */ double dval; /* Image pixel value */ int ix,iy; /* Pixel around which to compute median */ int nx,ny; /* Number of columns and rows in image */ int ndx; /* Number of columns over which to compute the median */ int ndy; /* Number of rows over which to compute the median */ { double *img; double sum; int n, nx2, ny2; int jx, jx1, jx2, jy, jy1, jy2; n = ndx * ndy; if (n <= 0) return (0.0); else if (n == 1) return (*(x + (iy * ny) + ix)); /* Compute limits for this pixel */ nx2 = ndx / 2; jx1 = ix - nx2; if (jx1 < 0) jx1 = 0; jx2 = ix + nx2 + 1; if (jx2 > nx) jx2 = nx; ny2 = ndy / 2; jy1 = iy - ny2; if (jy1 < 0) jy1 = 0; jy2 = iy + ny2 + 1; if (jy2 > ny) jy2 = ny; /* Initialize actual number of pixels used for this pixel */ n = 0; /* Set up working vector for this pixel */ sum = 0.0; for (jy = jy1; jy < jy2; jy++) { img = x + (jy * nx) + jx1; for (jx = jx1; jx < jx2; jx++) { if (*img != bpval && !isnan (*img)) { sum = sum + (double) *img; n++; } img++; } } if (n < 1) return (dval); else return (sum / (double) n); } /* Gaussian filter an image */ char * gaussfilt (buff, header, ndx, ndy, nlog) char *buff; /* Image buffer */ char *header; /* FITS image header */ int ndx; /* Number of columns over which to compute the Gaussian */ int ndy; /* Number of rows over which to compute the Gaussian */ int nlog; /* Logging interval in pixels */ { char *buffret; /* Modified image buffer (returned) */ int nx,ny; /* Number of columns and rows in image */ int ix,iy; /* Pixel around which to compute median */ int npix; /* Number of pixels in image */ int bitpix; /* Number of bits per pixel (<0=floating point) */ int naxes; hgeti4 (header, "BITPIX", &bitpix); hgeti4 (header, "NAXIS", &naxes); hgeti4 (header, "NAXIS1", &nx); if (naxes > 1) hgeti4 (header, "NAXIS2", &ny); else ny = 1; npix = nx * ny; hgetr8 (header, "BLANK", &bpval); gausswt (ndx, ndy, nx); buffret = NULL; if (bitpix == 16) { short *b1, *b2, *buffout; bpvali2 = (short) bpval; buffret = (char *) calloc (npix, sizeof (short)); buffout = (short *) buffret; b1 = (short *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { *b2++ = gausspixi2 (buff, *b1++, ix, iy, nx, ny); } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"GAUSSFILT: %d/%d lines filtered\r", iy+1,ny); } fprintf (stderr,"\n"); } else if (bitpix == 32) { int *b1, *b2, *buffout; bpvali4 = (int) bpval; buffret = (char *) calloc (npix, sizeof (int)); buffout = (int *) buffret; b1 = (int *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { *b2++ = gausspixi4 (buff, *b1++, ix, iy, nx, ny); } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"GAUSSFILT: %d/%d lines filtered\r", iy+1,ny); } fprintf (stderr,"\n"); } else if (bitpix == -32) { float *b1, *b2, *buffout; bpvalr4 = (float) bpval; buffret = (char *) calloc (npix, sizeof (float)); buffout = (float *) buffret; b1 = (float *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { *b2++ = gausspixr4 (buff, *b1++, ix, iy, nx, ny); } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"GAUSSFILT: %d/%d lines filtered\r", iy+1,ny); } fprintf (stderr,"\n"); } else if (bitpix == -64) { double *b1, *b2, *buffout; buffret = (char *) calloc (npix, sizeof (double)); buffout = (double *) buffret; b1 = (double *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { *b2++ = gausspixr8 (buff, *b1++, ix, iy, nx, ny); } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"GAUSSFILT: %d/%d lines filtered\r", iy+1,ny); } fprintf (stderr,"\n"); } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"GAUSSFILT: %d/%d lines filtered\n", iy,ny); return (buffret); } /* Set blank pixels to the Gaussian weighted sum of a box around each one */ char * gaussfill (buff, header, ndx, ndy, nlog) char *buff; /* Image buffer */ char *header; /* FITS image header */ int ndx; /* Number of columns over which to compute the mean */ int ndy; /* Number of rows over which to compute the mean */ int nlog; /* Logging interval in pixels */ { char *buffret; /* Modified image buffer (returned) */ int nx,ny; /* Number of columns and rows in image */ int ix,iy; /* Pixel around which to compute median */ int npix; /* Number of pixels in image */ int bitpix; /* Number of bits per pixel (<0=floating point) */ int naxes; hgeti4 (header, "BITPIX", &bitpix); hgeti4 (header, "NAXIS", &naxes); hgeti4 (header, "NAXIS1", &nx); if (naxes > 1) hgeti4 (header, "NAXIS2", &ny); else ny = 1; npix = nx * ny; hgetr8 (header, "BLANK", &bpval); nfilled = 0; gausswt (ndx, nx); buffret = NULL; if (bitpix == 16) { short *b1, *b2, *buffout; bpvali2 = (short) bpval; buffret = (char *) calloc (npix, sizeof (short)); buffout = (short *) buffret; b1 = (short *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*b1 != bpvali2) *b2++ = *b1++; else { *b2++ = gausspixi2 (buff, *b1++, ix, iy, nx, ny); nfilled++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"GAUSSFILL: %d lines, %d pixels filled\r", iy+1, nfilled); } } else if (bitpix == 32) { int *b1, *b2, *buffout; bpvali4 = (int) bpval; buffret = (char *) calloc (npix, sizeof (int)); buffout = (int *) buffret; b1 = (int *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*b1 != bpvali4) *b2++ = *b1++; else { *b2++ = gausspixi4 (buff, *b1++, ix, iy, nx, ny); nfilled++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"GAUSSFILL: %d lines, %d pixels filled\r", iy+1, nfilled); } } else if (bitpix == -32) { float *b1, *b2, *buffout; buffret = (char *) calloc (npix, sizeof (float)); buffout = (float *) buffret; bpvalr4 = (float) bpval; b1 = (float *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*b1 != bpvalr4) *b2++ = *b1++; else { *b2++ = gausspixr4 (buff, *b1++, ix, iy, nx, ny); nfilled++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"GAUSSFILL: %d lines, %d pixels filled\r", iy+1, nfilled); } } else if (bitpix == -64) { double *b1, *b2, *buffout; buffret = (char *) calloc (npix, sizeof (double)); buffout = (double *) buffret; b1 = (double *) buff; b2 = buffout; for (iy = 0; iy < ny; iy++) { for (ix = 0; ix < nx; ix++) { if (*b1 != bpval) *b2++ = *b1++; else { *b2++ = gausspixr8 (buff, *b1++, ix, iy, nx, ny); nfilled++; } } if (nlog > 0 && (iy+1)%nlog == 0) fprintf (stderr,"GAUSSFILL: %d lines, %d pixels filled\r", iy+1, nfilled); } } if (nlog > 0) fprintf (stderr,"GAUSSFILL: %d lines, %d pixels filled\n", iy, nfilled); return (buffret); } /* Compute Gaussian weighting function */ static double *gwt = NULL; static int *ixbox; /* Vector of x offsets in image */ static int *iybox; /* Vector of y offsets in image */ static int *ipbox; /* Vector of pixel offsets in image */ static int npbox; /* Number of pixels in replacement vector */ static int mpbox = 1; /* Minimum number of good pixels to use value */ void setminpix (minpix) int minpix; { mpbox = minpix; return; } static double hwidth = 1.0; /* Half-width at half-height of Gaussian */ void setghwidth (ghwidth) double ghwidth; { hwidth = ghwidth; return; } static int nsub = 1; /* Number of sub-computations per pixel */ void setsubpix (nsubpix) double nsubpix; { nsub = nsubpix; return; } /* Compute Gaussian weights for a square region */ void gausswt (mx, my, nx) int mx; /* Width in pixels over which to compute the Gaussian */ int my; /* Height in pixels over which to compute the Gaussian */ int nx; /* Number of columns (naxis1) in image */ { int i, idr, idc, jx, jy, jr; double dsub, xd0, xd, xdr, xdc, twt, rad2; extern void setscale(); setscale (0); dsub = (double) nsub; xd0 = (dsub - 1.0) / (dsub * 2.0); xd = 1.0 / (hwidth * dsub); twt = 0.0; if (gwt != NULL) { free (gwt); free (ixbox); free (iybox); free (ipbox); } npbox = mx * my; gwt = (double *) calloc (npbox, sizeof(double)); ixbox = (int *) calloc (npbox, sizeof(int)); iybox = (int *) calloc (npbox, sizeof(int)); ipbox = (int *) calloc (npbox, sizeof(int)); idr = (-my / 2) - 1; i = 0; for (jy = 0; jy < my; jy++) { idr++; idc = (-mx / 2) - 1; for (jx = 0; jx < mx; jx++) { idc++; gwt[i] = 0.0; xdr = ((double) idr - xd0) / hwidth; for (jr = 0; jr < nsub; jr++) { xdc = ((double)(idc) - xd0) / hwidth; for (jr = 0; jr < nsub; jr++) { rad2 = (xdc * xdc) + (xdr * xdr); gwt[i] = gwt[i] + exp (-rad2 / 2.0); xdc = xdc + xd; } xdr = xdr + xd; } twt = twt + gwt[i]; iybox[i] = idc; ixbox[i] = idr; ipbox[i] = (idr * nx) + idc; i++; } } /* Normalize to 1.0 */ for (i = 0; i < npbox; i++) gwt[i] = gwt[i] / twt; return; } /* Compute Gaussian-weighted mean of a square group of pixels */ /* gausswt() must be called first to set up weighting vector */ short gausspixi2 (image, ival, ix, iy, nx, ny) short *image; /* Image buffer */ short ival; /* Pixel value */ int ix,iy; /* Pixel around which to compute Gaussian-weighted mean */ int nx,ny; /* Number of columns and rows in image */ { short *img; double twt, tpix; double flux; int i, ixi, iyi; int np; if (npbox <= 1) return (ival); twt = 0.0; tpix = 0.0; np = 0; for (i = 0; i < npbox; i++) { ixi = ix + ixbox[i]; iyi = iy + iybox[i]; if (ixi > -1 && iyi > -1 && ixi < nx && iyi < ny) { img = image + (iyi * nx) + ixi; if (*img != bpvali2) { flux = (double) image[ixi + (iyi * nx)]; twt = twt + gwt[i]; tpix = tpix + gwt[i] * flux; np++; } } } /* If enough surrounding pixels are non-zero, replace the current pixel */ if (np > mpbox && twt > 0.0) { if (twt < 1.0) tpix = tpix / twt; return ((short) tpix); } else return (ival); } int gausspixi4 (image, ival, ix, iy, nx, ny) int *image; /* Image buffer */ int ival; /* Pixel value */ int ix,iy; /* Pixel around which to compute Gaussian-weighted mean */ int nx,ny; /* Number of columns and rows in image */ { double twt, tpix; double flux; int *img; int i, ixi, iyi; int np; if (npbox <= 1) return (ival); twt = 0.0; tpix = 0.0; np = 0; for (i = 0; i < npbox; i++) { ixi = ix + ixbox[i]; iyi = iy + iybox[i]; if (ixi > -1 && iyi > -1 && ixi < nx && iyi < ny) { img = image + (iyi * nx) + ixi; if (*img != bpvali4) { flux = (double) image[ixi + (iyi * nx)]; twt = twt + gwt[i]; tpix = tpix + gwt[i] * flux; np++; } } } /* If enough surrounding pixels are non-zero, replace the current pixel */ if (np > mpbox && twt > 0.0) { if (twt < 1.0) tpix = tpix / twt; return ((int) tpix); } else return (ival); } float gausspixr4 (image, rval, ix, iy, nx, ny) float *image; /* Image buffer */ float rval; /* Pixel value */ int ix,iy; /* Pixel around which to compute Gaussian-weighted mean */ int nx,ny; /* Number of columns and rows in image */ { double twt, tpix; double flux; float *img; int i, ixi, iyi; int np; if (npbox <= 1) return (rval); twt = 0.0; tpix = 0.0; np = 0; for (i = 0; i < npbox; i++) { ixi = ix + ixbox[i]; iyi = iy + iybox[i]; if (ixi > -1 && iyi > -1 && ixi < nx && iyi < ny) { img = image + (iyi * nx) + ixi; /* printf ("%04d,%04d %04d,%04d: %g\n", ix, iy, ixi, iyi, *img); */ if (*img != bpvalr4 && !isnan (*img)) { flux = (double) image[ixi + (iyi * nx)]; twt = twt + gwt[i]; tpix = tpix + gwt[i] * flux; np++; } } } /* If enough surrounding pixels are non-zero, replace the current pixel */ if (np > mpbox && twt > 0.0) { if (twt < 1.0) tpix = tpix / twt; return ((float) tpix); } else return (rval); } double gausspixr8 (image, dval, ix, iy, nx, ny) double *image; /* Image buffer */ double dval; /* Pixel value */ int ix,iy; /* Pixel around which to compute Gaussian-weighted mean */ int nx,ny; /* Number of columns and rows in image */ { double *img; double twt, tpix; double flux; int i, ixi, iyi; int np; if (npbox <= 1) return (dval); twt = 0.0; tpix = 0.0; np = 0; for (i = 0; i < npbox; i++) { ixi = ix + ixbox[i]; iyi = iy + iybox[i]; if (ixi > -1 && iyi > -1 && ixi < nx && iyi < ny) { img = image + (iyi * nx) + ixi; if (*img != bpval && !isnan (*img)) { flux = image[ixi + (iyi * nx)]; twt = twt + gwt[i]; tpix = tpix + gwt[i] * flux; np++; } } } /* If enough surrounding pixels are non-zero, replace the current pixel */ if (np > mpbox && twt > 0.0) { if (twt < 1.0) tpix = tpix / twt; return (tpix); } else return (dval); } /* Return image buffer reduced by a given factor */ char * ShrinkFITSImage (header, image, xfactor, yfactor, mean, bitpix, nlog) char *header; /* Image header */ char *image; /* Image bytes to be filtered */ int xfactor; /* Factor by which to reduce horizontal size of image */ int yfactor; /* Factor by which to reduce vertical size of image */ int mean; /* If 0, sum pixels, else substitute mean */ int bitpix; /* Number of bits per output pixel (neg=f.p.) */ int nlog; /* Logging interval in lines */ { char *image1; int nx,ny; /* Number of columns and rows in input image */ int nx1,ny1; /* Number of columns and rows in input image */ int ix,iy; /* Output pixel coordinates */ int jx,jy; /* Input pixel coordinates */ int kx, ky; int nxf, nyf; int npix1; /* Number of pixels in output image */ int bitsin; /* Number of bits per input pixel (<0=floating point) */ int naxes; double pixij; /* Summed value of rebinned pixel */ double bzero, bscale; double pixval, dnp; short *buffi2 = NULL; int *buffi4 = NULL; float *buffr4 = NULL; double *buffr8 = NULL; /* Get bits per pixel in input image */ hgeti4 (header, "BITPIX", &bitsin); if (bitpix == 0) { bitpix = bitsin; mean = 1; } /* Get scaling of input image, if any */ bzero = 0.0; hgetr8 (header, "BZERO", &bzero); bscale = 1.0; hgetr8 (header, "BSCALE", &bscale); /* Get size of input horizontal axis */ hgeti4 (header, "NAXIS1", &nx); /* Set horizontal axis for output image */ if (nx > xfactor) nx1 = nx / xfactor; else nx1 = nx; /* Get number of axes */ hgeti4 (header, "NAXIS", &naxes); /* Set vertical axis for output image */ if (naxes > 1) { hgeti4 (header, "NAXIS2", &ny); if (ny > yfactor) ny1 = ny / yfactor; else ny1 = ny; } else { ny = 1; ny1 = 1; } npix1 = nx1 * ny1; /* Allocate output image buffer and initialize pointer into it */ image1 = NULL; if (bitpix == 16) { image1 = (char *) calloc (npix1, sizeof (short)); buffi2 = (short *) image1; } else if (bitpix == 32) { image1 = (char *) calloc (npix1, sizeof (int)); buffi4 = (int *) image1; } else if (bitpix == -32) { image1 = (char *) calloc (npix1, sizeof (float)); buffr4 = (float *) image1; } else if (bitpix == -64) { image1 = (char *) calloc (npix1, sizeof (double)); buffr8 = (double *) image1; } /* Fill output buffer */ for (jy = 0; jy < ny1; jy++) { for (jx = 0; jx < nx1; jx++) { pixij = 0.0; ky = (jy * yfactor); if (ky + yfactor > ny) nyf = ny - ky + 1; else nyf = yfactor; dnp = 0.0; for (iy = 0; iy < nyf; iy++) { kx = (jx * xfactor); if (kx + xfactor > nx) nxf = nx - kx + 1; else nxf = xfactor; for (ix = 0; ix < nxf; ix++) { pixval = getpix (image, bitsin, nx,ny,bzero,bscale,kx++,ky); pixij = pixij + pixval; dnp++; } ky++; } if (mean) { switch (bitpix) { case 16: *buffi2++ = (short) (pixij / dnp); break; case 32: *buffi4++ = (int) (pixij / dnp); break; case -32: *buffr4++ = (float) (pixij / dnp); break; case -64: *buffr8++ = (pixij / dnp); break; } } else { switch (bitpix) { case 16: if (pixij < 32768.0) *buffi2++ = (short) pixij; else *buffi2++ = 32767; break; case 32: *buffi4++ = (int) pixij; break; case -32: *buffr4++ = (float) pixij; break; case -64: *buffr8++ = pixij; break; } } } if ((jy+1)%nlog == 0) fprintf (stderr,"IMRESIZE: %d/%d lines created\r", jy+1, ny1); } if (nlog > 0) fprintf (stderr,"\n"); return (image1); } /* Return image header with dimensions reduced by a given factor */ char * ShrinkFITSHeader (filename, header, xfactor, yfactor, mean, bitpix) char *filename; /* Name of image file before shrinking */ char *header; /* Image header */ int xfactor; /* Factor by which to reduce horizontal size of image */ int yfactor; /* Factor by which to reduce vertical size of image */ int mean; /* If 0, sum pixels, else substitute mean */ int bitpix; /* Number of bits per output pixel (neg=f.p.) */ { char *newhead; /* New header for shrunken file */ char history[64]; int nbhead; /* Number of bytes in header */ int naxes; int nblocks; int nx, ny, nx1, ny1; double crpix1, crpix2, cdelt1, cdelt2; double dfac; nbhead = strlen (header); nblocks = nbhead / 2880; if (nblocks * 2880 < nbhead) nblocks = nblocks + 1; nbhead = 2880 * (nblocks +1); newhead = (char *) calloc (nbhead, 1); strcpy (newhead, header); /* Set pixel size in bits */ if (bitpix == 0) { hgeti4 (header, "BITPIX", &bitpix); mean = 1; } hputi4 (newhead, "BITPIX", bitpix); /* Set new image horizontal dimension */ hgeti4 (header, "NAXIS1", &nx); if (nx > xfactor) nx1 = nx / xfactor; else nx1 = nx; hputi4 (newhead, "NAXIS1", nx1); /* Set new image vertical dimension */ hgeti4 (header, "NAXIS", &naxes); if (naxes > 1) { hgeti4 (header, "NAXIS2", &ny); if (ny > yfactor) ny1 = ny / yfactor; else ny1 = ny; hputi4 (newhead, "NAXIS2", ny1); } else { ny = 1; ny1 = 1; } /* Fix WCS */ dfac = (double) xfactor; if (hgetr8 (header, "CRPIX1", &crpix1)) { crpix1 = (crpix1 / dfac) + 0.5; hputr8 (newhead, "CRPIX1", crpix1); } if (hgetr8 (header, "CDELT1", &cdelt1)) { cdelt1 = (cdelt1 * dfac); hputr8 (newhead, "CDELT1", cdelt1); } if (hgetr8 (header, "CD1_1", &cdelt1)) { cdelt1 = (cdelt1 * dfac); hputr8 (newhead, "CD1_1", cdelt1); } if (hgetr8 (header, "CD1_2", &cdelt1)) { cdelt1 = (cdelt1 * dfac); hputr8 (newhead, "CD1_2", cdelt1); } dfac = (double) yfactor; if (hgetr8 (header, "CRPIX2", &crpix2)) { crpix2 = (crpix2 / dfac) + 0.5; hputr8 (newhead, "CRPIX2", crpix2); } if (hgetr8 (header, "CDELT2", &cdelt2)) { cdelt2 = (cdelt2 * dfac); hputr8 (newhead, "CDELT2", cdelt2); } if (hgetr8 (header, "CD2_1", &cdelt2)) { cdelt2 = (cdelt2 * dfac); hputr8 (newhead, "CD2_1", cdelt2); } if (hgetr8 (header, "CD2_2", &cdelt2)) { cdelt2 = (cdelt2 * dfac); hputr8 (newhead, "CD2_2", cdelt2); } /* Add keyword to denote this operation */ if (strlen (filename) < 40) sprintf (history, "%s blocked %dx%d", filename, xfactor, yfactor); else sprintf (history, "%40s blocked / %dx%d", filename, xfactor, yfactor); if (mean) strcat (history, " mean"); else strcat (history, " sum"); hputs (newhead, "IMSHRINK", history); return (newhead); } static double apint(); static double imapfr(); /* PhotPix -- Compute counts within a strictly defined circular aperture * returns sum of pixel flux * Jul 4 1984 Original Fortran program by Sam Conner at MIT * Mar 2 1987 Ported to Unix by Jessica Mink at SAO * Jan 30 2002 translated from Fortran to C by Jessica Mink at SAO */ double PhotPix (imbuff,header,cx,cy,rad,sumw) char *imbuff; /* address of start of image buffer */ char *header; /* image FITS header */ double cx,cy; /* center x,y of aperture */ double rad; /* radius of aperture */ double *sumw; /* sum of values of pixel weights (returned) */ { double x, y, factor, flux, bs, bz, wsum; int ix1, ix2, iy1, iy2, ix, iy, bitpix, nx, ny; *sumw = 0.0; wsum = 0.0; hgeti4 (header, "BITPIX", &bitpix); hgeti4 (header, "NAXIS1", &nx); hgeti4 (header, "NAXIS2", &ny); hgetr8 (header, "BSCALE", &bs); hgetr8 (header, "BZERO", &bz); /* Find range of ys to check */ iy1 = (int) (cy - rad); iy2 = (int) (cy + rad + 0.99999); if (iy1 < 1) iy1 = 1; if (iy2 > ny) iy2 = ny; /* Find range of xs to check */ ix1 = (int) (cx - rad); ix2 = (int) (cx + rad + 0.99999); if (ix1 < 1) ix1 = 1; if (ix2 > nx) ix2 = nx; for (iy = iy1; iy <= iy2; iy++) { y = (double) iy; for (ix = ix1; ix <= ix2; ix++) { x = (double) ix; factor = imapfr (x,y,cx,cy,rad); *sumw = *sumw + factor; flux = getpix1 (imbuff, bitpix, nx, ny, bz, bs, ix, iy); wsum = wsum + (factor * flux); /* fprintf (stderr, "IMAPSB: (%d,%d)= %f weight= %f\n", ix,iy,flux,factor); */ } } /* fprintf (stderr, "IMAPSB: sum of weights = %f\n", *sumw); fprintf (stderr, "IMAPSB: sum of weighted intensity = %f\n", wsum); */ return (wsum); } /* IMAPFR -- Determine the fraction of a square pixel that is included * within the boundary of a circle of arbitrary center and radius */ static double imapfr (pcol,prow,ccol,crow,rad) double pcol,prow; /* column, row of pixel */ double ccol,crow; /* column, row of center of circle */ double rad; /* radius of circle in pixels */ { int icorn[4], ncorn, j, i; double dist, xdiff, y0, y1, ydiff, x0, x1, x, y, dc5, dr5; double cterm, ulim, llim, dc, dr, dx, dy; double frac; /* fraction of pixel within circle */ /* Compute distance to center of circle from most distant corner of pixel */ dc = fabs (pcol - ccol); dr = fabs (prow - crow); dc5 = dc + 0.5; dr5 = dr + 0.5; dist = sqrt ((dc5 * dc5) + (dr5 * dr5)); dc5 = dc - 0.5; dr5 = dr - 0.5; /* if the pixel is completely enclosed by the aperture, return 1 */ if (dist <= rad) return (1.0); /* if the pixel is not completely included, compute distance from the center of the circle to the nearest point on the periphery of the pixel*/ if ((pcol-0.5) < ccol && ccol < (pcol+.5)) { dist = dr5; /* the pixel is completely excluded from the aperture */ if (dist >= rad) return (0.0); else if ((prow - 0.5) < crow && crow < (prow + 0.5)) { dist = dc5; /* the pixel is completely excluded from the aperture */ if (dist >= rad) return (0.0); } else dist = sqrt (dc5*dc5 + dr5*dr5); /* the pixel is completely excluded from the aperture */ if (dist >= rad) return (0.0); } /* If the pixel is partially included in the aperture, determine how many corners are enclosed */ ncorn = 1; y = prow - 1.5; for (i = 0; i < 2; i++) { y = y + 1.0; x = pcol - 1.50; for (j = 0; j < 2; j++) { icorn[j+(i*2)] = 0; x = x + 1.0; dx = x - ccol; dy = y - crow; dist = sqrt (dx*dx + dy*dy); if (dist < rad) { ncorn = ncorn + 1; icorn[j+(i*2)] = 1; } } } /* Depending on number of corners enclosed, branch to appropriate computation */ /* If no corners are enclosed, determine whether the slice is vertical or horizontal */ if (ncorn < 1) { /* If the slice is vertical (at the sides of the aperture, at extreme x), determine the limits of integration */ if ((pcol - 0.5) >= ccol || ccol >= (pcol + 0.5)) { xdiff = fabs (pcol - ccol) - 0.5; dx = sqrt (rad*rad - xdiff*xdiff); y0 = crow - dx; y1 = crow + dx; if (ccol >= pcol) x = pcol + 0.5; else x = pcol - 0.5; /* Evaluate integral */ frac = -xdiff * (y1 - y0) + apint ((y1 - crow), rad) - apint ((y0 - crow), rad); return (frac); } /* If the slice is horizontal (at top or bottom of the aperture, at extreme y), determine the limits of integration. */ else { ydiff = fabs (prow - crow) - 0.5; dy = sqrt (rad*rad - ydiff*ydiff); x0 = ccol - dy; x1 = ccol + dy; if (crow >= prow) y = prow + 0.5; else y = prow - 0.5; /* Evaluate integral */ frac = -ydiff*(x1 - x0) + apint ((x1 - ccol),rad) - apint ((x0 - ccol),rad); return (frac); } } /* if one corner is enclosed, find direction (ne,nw,se,sw) from the center*/ else if (ncorn < 2) { if (pcol < ccol) { /* Determine the limits of integration */ ydiff = fabs (prow - crow) - 0.5;; x0 = ccol - sqrt (rad*rad - ydiff*ydiff); if (crow >= prow) y = prow + 0.5; else y = prow - 0.5; /* Evaluate integral */ frac = -ydiff*(pcol + 0.5 - x0) + apint ((pcol + 0.5 - ccol),rad) - apint ((x0 - ccol),rad); return (frac); } else { /* Determine the limits of integration */ ydiff = fabs (crow - prow) - 0.5; x1 = ccol + sqrt (rad*rad - ydiff*ydiff); if (crow >= prow) y = prow + 0.5; else y = prow - 0.5; /* Evaluate integral */ frac = -ydiff*(x1 - pcol + 0.5) + apint ((x1 - ccol),rad) - apint ((pcol - .5 - ccol),rad); return (frac); } } /* If two corners are enclosed, this problem has two cases: one in which the aperture boundary intersects the pixel boundary twice, and another in which it intersects the pixel boundaries 4 times */ /* determine whether this may be a 4-intersection configuration */ else if (ncorn < 3) { if (((pcol - 0.5) < ccol && ccol < (pcol + .5) && (fabs(crow - prow) + 0.5) < rad) || ((prow - 0.5) < crow && crow < (prow + 0.5) && (fabs(ccol - pcol) + 0.5) < rad)) { /* if the pixel boundary intersects the aperture boundary in four places, determine whether the pixel is east-west or north-south. */ /* pixel is east-west */ if ((pcol - 0.5) >= ccol || (pcol + 0.5) <= ccol) { xdiff = dc + 0.5; /* Determine the limits of integration */ dx = sqrt (rad*rad - xdiff*xdiff); y0 = crow - dx; y1 = crow + dx; if (pcol >= ccol) x = pcol + .5; else x = pcol - .5; frac = 1. - xdiff*(y0 - y1 + 1.0) + apint ((y0 - crow), rad) - apint ((prow - 0.5 - crow), rad) + apint ((prow + 0.5 - crow), rad) - apint ((y1 - crow), rad); return (frac); } /* Pixel is north-south */ else { ydiff = dr + 0.5; /* determine the limits of integration */ dy = sqrt (rad*rad - ydiff*ydiff); /* x0 is the x-coordinate of the small x intercept */ x0 = ccol - dy; /* x1 is the x-coordinate of the large x intercept */ x1 = ccol + dy; if (prow >= crow) y = prow + 0.5; else y = prow - 0.5; frac = 1. - ydiff * (x0 - x1 + 1.0) + apint ((x0 - ccol), rad) - apint ((pcol - 0.5 - ccol), rad) + apint ((pcol + 0.5 - ccol), rad) - apint ((x1 - ccol), rad); return (frac); } } /* in the two-intersection case, determine which corners are included */ else { /* the pixel is north or south of the center of the aperture */ if (icorn[0]*icorn[1] == 1 || icorn[2]*icorn[3] == 1) { cterm = 0.5 - dr; ulim = apint ((pcol + 0.5 - ccol) ,rad); llim = apint ((pcol - 0.5 - ccol) ,rad); frac = cterm + ulim - llim; return (frac); } /* the pixel is east or west of the center */ else { cterm = 0.5 - dc; ulim = apint ((prow + 0.5 - crow), rad); llim = apint ((prow - 0.5 - crow), rad); frac = cterm + ulim - llim; return (frac); } } } /* if three corners are enclosed, determine whether the corner in question is east or west of the center of the aperture */ else { if (pcol > ccol) { ydiff = dr + 0.5; if (prow >= crow) y = prow + 0.5; else y = prow - 0.5; x0 = ccol + sqrt (rad*rad - ydiff*ydiff); frac = 1.0 - (ydiff * (pcol + 0.5 - x0)) + apint ((pcol + 0.5 - ccol), rad) - apint ((x0 - ccol), rad); return (frac); } else { ydiff = dr + 0.5; if (prow >= crow) y = prow + 0.5; else y = prow - 0.5; x0 = ccol - sqrt (rad*rad - ydiff*ydiff); frac = 1. - ydiff*(x0 - pcol + 0.5) + apint ((x0 - ccol),rad) - apint ((pcol - 0.5 - ccol),rad); return (frac); } } } /* APINT -- Evaluate the integral of sqrt (rad**2 - x**2) dx at one limit */ static double apint (x, rad) double x; double rad; { double x2,rad2,arg,arg2,arcsin,pi; pi = 3.141592654; arg = x / rad; x2 = x * x; rad2 = rad * rad; arg2 = x2 / rad2; arcsin = atan2 (arg, sqrt (1.0 - arg2)); if ((1. - fabs (arg)) < 0.000001) { if (arg >= 0) arcsin = pi / 2.0; else arcsin = -pi / 2.0; } return (0.5 * (x * sqrt (rad2 - x2) + rad2 * arcsin)); } /* Oct 25 2005 New subroutine translated from Fortran imlib/smooth.f * * Jan 25 2006 Add subroutines to shrink an image * Mar 1 2006 Add subroutines for Gaussian smoothing/filling * Apr 3 2006 Fix error return in gausspix() * Apr 3 2006 Include math.h and fitsfile.h (instead of fitshead.h) * Apr 7 2006 Add filling subroutines medfill(), meanfill(), gaussfill() * Apr 7 2006 Add subtroutine to set bad pixels from second image * Apr 27 2006 Add and correct comments * May 8 2006 Print final number of pixels filled; add getnfilled() * May 16 2006 Do not use BLANK from bad pixel file if set on command line * Jun 20 2006 Drop unused variables * Jun 30 2006 Add number of lines in output image to log message * Jul 5 2006 Add SetBadVal() to set pixels less than min to bad * Jul 6 2006 Make both dimensions variable for Gaussian * Jul 7 2006 SetBadVal() now checks min and max allowable values * Sep 25 2006 Fix bug so CDELT1 and CDELT2 are scaled correctly * * Jan 8 2007 Drop unused variables from SetBadVal() * Jan 11 2007 Add circular aperture photometry in PhotPix() * * May 15 2012 Add medpix() and meanpix() to generalize across pixel size * May 16 2012 Add medpixi1() and meanpixi1() to handle 8-bit images * * Jun 17 2014 Ignore NaN pixels */ wcstools-3.9.5/libwcs/lin.c0000664000016200001660000003042411750060474014673 0ustar minkoirsys/*============================================================================= * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-2002, Mark Calabretta * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Correspondence concerning WCSLIB may be directed to: * Internet email: mcalabre@atnf.csiro.au * Postal address: Dr. Mark Calabretta, * Australia Telescope National Facility, * P.O. Box 76, * Epping, NSW, 2121, * AUSTRALIA * *============================================================================= * * C routines which implement the FITS World Coordinate System (WCS) * convention. * * Summary of routines * ------------------- * These utility routines apply the linear transformation defined by the WCS * FITS header cards. There are separate routines for the image-to-pixel, * linfwd(), and pixel-to-image, linrev(), transformations. * * An initialization routine, linset(), computes intermediate values from * the transformation parameters but need not be called explicitly - see the * explanation of lin.flag below. * * An auxiliary matrix inversion routine, matinv(), is included. It uses * LU-triangular factorization with scaled partial pivoting. * * * Initialization routine; linset() * -------------------------------- * Initializes members of a linprm data structure which hold intermediate * values. Note that this routine need not be called directly; it will be * invoked by linfwd() and linrev() if the "flag" structure member is * anything other than a predefined magic value. * * Given and/or returned: * lin linprm* Linear transformation parameters (see below). * * Function return value: * int Error status * 0: Success. * 1: Memory allocation error. * 2: PC matrix is singular. * * Forward transformation; linfwd() * -------------------------------- * Compute pixel coordinates from image coordinates. Note that where * celestial coordinate systems are concerned the image coordinates * correspond to (x,y) in the plane of projection, not celestial (lng,lat). * * Given: * imgcrd const double[] * Image (world) coordinate. * * Given and returned: * lin linprm* Linear transformation parameters (see below). * * Returned: * pixcrd d[] Pixel coordinate. * * Function return value: * int Error status * 0: Success. * 1: The transformation is not invertible. * * Reverse transformation; linrev() * -------------------------------- * Compute image coordinates from pixel coordinates. Note that where * celestial coordinate systems are concerned the image coordinates * correspond to (x,y) in the plane of projection, not celestial (lng,lat). * * Given: * pixcrd const double[] * Pixel coordinate. * * Given and/or returned: * lin linprm* Linear transformation parameters (see below). * * Returned: * imgcrd d[] Image (world) coordinate. * * Function return value: * int Error status * 0: Success. * 1: Error. * * Linear transformation parameters * -------------------------------- * The linprm struct consists of the following: * * int flag * This flag must be set to zero whenever any of the following members * are set or modified. This signals the initialization routine, * linset(), to recompute intermediaries. * int naxis * Number of image axes. * double *crpix * Pointer to the first element of an array of double containing the * coordinate reference pixel, CRPIXn. * double *pc * Pointer to the first element of the PC (pixel coordinate) * transformation matrix. The expected order is * * lin.pc = {PC1_1, PC1_2, PC2_1, PC2_2}; * * This may be conveniently constructed from a two-dimensional array * via * * double m[2][2] = {{PC1_1, PC1_2}, * {PC2_1, PC2_2}}; * * which is equivalent to, * * double m[2][2]; * m[0][0] = PC1_1; * m[0][1] = PC1_2; * m[1][0] = PC2_1; * m[1][1] = PC2_2; * * for which the storage order is * * PC1_1, PC1_2, PC2_1, PC2_2 * * so it would be legitimate to set lin.pc = *m. * double *cdelt * Pointer to the first element of an array of double containing the * coordinate increments, CDELTn. * * The remaining members of the linprm struct are maintained by the * initialization routine and should not be modified. * * double *piximg * Pointer to the first element of the matrix containing the product * of the CDELTn diagonal matrix and the PC matrix. * double *imgpix * Pointer to the first element of the inverse of the piximg matrix. * * linset allocates storage for the above arrays using malloc(). Note, * however, that these routines do not free this storage so if a linprm * variable has itself been malloc'd then these structure members must be * explicitly freed before the linprm variable is free'd otherwise a memory * leak will result. * * Author: Mark Calabretta, Australia Telescope National Facility * $Id: lin.c,v 2.8 2002/01/30 06:04:03 mcalabre Exp $ *===========================================================================*/ #include #include #include "wcslib.h" /* Map error number to error message for each function. */ const char *linset_errmsg[] = { 0, "Memory allocation error", "PC matrix is singular"}; const char *linfwd_errmsg[] = { 0, "Memory allocation error", "PC matrix is singular"}; const char *linrev_errmsg[] = { 0, "Memory allocation error", "PC matrix is singular"}; int linset(lin) struct linprm *lin; { int i, ij, j, mem, n; n = lin->naxis; /* Allocate memory for internal arrays. */ mem = n * n * sizeof(double); lin->piximg = (double*)malloc(mem); if (lin->piximg == (double*)0) return 1; lin->imgpix = (double*)malloc(mem); if (lin->imgpix == (double*)0) { free(lin->piximg); return 1; } /* Compute the pixel-to-image transformation matrix. */ for (i = 0, ij = 0; i < n; i++) { for (j = 0; j < n; j++, ij++) { lin->piximg[ij] = lin->cdelt[i] * lin->pc[ij]; } } /* Compute the image-to-pixel transformation matrix. */ if (matinv(n, lin->piximg, lin->imgpix)) return 2; lin->flag = LINSET; return 0; } /*--------------------------------------------------------------------------*/ int linfwd(imgcrd, lin, pixcrd) const double imgcrd[]; struct linprm *lin; double pixcrd[]; { int i, ij, j, n; n = lin->naxis; if (lin->flag != LINSET) { if (linset(lin)) return 1; } for (i = 0, ij = 0; i < n; i++) { pixcrd[i] = 0.0; for (j = 0; j < n; j++, ij++) { pixcrd[i] += lin->imgpix[ij] * imgcrd[j]; } } for (j = 0; j < n; j++) { pixcrd[j] += lin->crpix[j]; } return 0; } /*--------------------------------------------------------------------------*/ int linrev(pixcrd, lin, imgcrd) const double pixcrd[]; struct linprm *lin; double imgcrd[]; { int i, ij, j, n; double temp; n = lin->naxis; if (lin->flag != LINSET) { if (linset(lin)) return 1; } for (i = 0; i < n; i++) { imgcrd[i] = 0.0; } for (j = 0; j < n; j++) { temp = pixcrd[j] - lin->crpix[j]; for (i = 0, ij = j; i < n; i++, ij+=n) { imgcrd[i] += lin->piximg[ij] * temp; } } return 0; } /*--------------------------------------------------------------------------*/ int matinv(n, mat, inv) const int n; const double mat[]; double inv[]; { register int i, ij, ik, j, k, kj, pj; int itemp, mem, *mxl, *lxm, pivot; double colmax, *lu, *rowmax, dtemp; /* Allocate memory for internal arrays. */ mem = n * sizeof(int); if ((mxl = (int*)malloc(mem)) == (int*)0) return 1; if ((lxm = (int*)malloc(mem)) == (int*)0) { free(mxl); return 1; } mem = n * sizeof(double); if ((rowmax = (double*)malloc(mem)) == (double*)0) { free(mxl); free(lxm); return 1; } mem *= n; if ((lu = (double*)malloc(mem)) == (double*)0) { free(mxl); free(lxm); free(rowmax); return 1; } /* Initialize arrays. */ for (i = 0, ij = 0; i < n; i++) { /* Vector which records row interchanges. */ mxl[i] = i; rowmax[i] = 0.0; for (j = 0; j < n; j++, ij++) { dtemp = fabs(mat[ij]); if (dtemp > rowmax[i]) rowmax[i] = dtemp; lu[ij] = mat[ij]; } /* A row of zeroes indicates a singular matrix. */ if (rowmax[i] == 0.0) { free(mxl); free(lxm); free(rowmax); free(lu); return 2; } } /* Form the LU triangular factorization using scaled partial pivoting. */ for (k = 0; k < n; k++) { /* Decide whether to pivot. */ colmax = fabs(lu[k*n+k]) / rowmax[k]; pivot = k; for (i = k+1; i < n; i++) { ik = i*n + k; dtemp = fabs(lu[ik]) / rowmax[i]; if (dtemp > colmax) { colmax = dtemp; pivot = i; } } if (pivot > k) { /* We must pivot, interchange the rows of the design matrix. */ for (j = 0, pj = pivot*n, kj = k*n; j < n; j++, pj++, kj++) { dtemp = lu[pj]; lu[pj] = lu[kj]; lu[kj] = dtemp; } /* Amend the vector of row maxima. */ dtemp = rowmax[pivot]; rowmax[pivot] = rowmax[k]; rowmax[k] = dtemp; /* Record the interchange for later use. */ itemp = mxl[pivot]; mxl[pivot] = mxl[k]; mxl[k] = itemp; } /* Gaussian elimination. */ for (i = k+1; i < n; i++) { ik = i*n + k; /* Nothing to do if lu[ik] is zero. */ if (lu[ik] != 0.0) { /* Save the scaling factor. */ lu[ik] /= lu[k*n+k]; /* Subtract rows. */ for (j = k+1; j < n; j++) { lu[i*n+j] -= lu[ik]*lu[k*n+j]; } } } } /* mxl[i] records which row of mat corresponds to row i of lu. */ /* lxm[i] records which row of lu corresponds to row i of mat. */ for (i = 0; i < n; i++) { lxm[mxl[i]] = i; } /* Determine the inverse matrix. */ for (i = 0, ij = 0; i < n; i++) { for (j = 0; j < n; j++, ij++) { inv[ij] = 0.0; } } for (k = 0; k < n; k++) { inv[lxm[k]*n+k] = 1.0; /* Forward substitution. */ for (i = lxm[k]+1; i < n; i++) { for (j = lxm[k]; j < i; j++) { inv[i*n+k] -= lu[i*n+j]*inv[j*n+k]; } } /* Backward substitution. */ for (i = n-1; i >= 0; i--) { for (j = i+1; j < n; j++) { inv[i*n+k] -= lu[i*n+j]*inv[j*n+k]; } inv[i*n+k] /= lu[i*n+i]; } } free(mxl); free(lxm); free(rowmax); free(lu); return 0; } /* Dec 20 1999 Doug Mink - Include wcslib.h, which includes lin.h * * Feb 15 2001 Doug Mink - Add comments for WCSLIB 2.6; no code changes * Sep 19 2001 Doug Mink - Add above change to WCSLIB 2.7 code * Nov 20 2001 Doug Mink - Always include stdlib.h * * Jan 15 2002 Bill Joye - Add ifdef so this compiles on MacOS/X * * Nov 18 2003 Doug Mink - Include stdlib.h instead of malloc.h */ wcstools-3.9.5/libwcs/log.c0000664000016200001660000000556111750060474014676 0ustar minkoirsys/*============================================================================ * * WCSLIB 4.2 - an implementation of the FITS WCS standard. * Copyright (C) 1995-2005, Mark Calabretta * * WCSLIB is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * WCSLIB 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 General Public License for more * details. * * You should have received a copy of the GNU General Public License along * with WCSLIB; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA * * Correspondence concerning WCSLIB may be directed to: * Internet email: mcalabre@atnf.csiro.au * Postal address: Dr. Mark Calabretta * Australia Telescope National Facility, CSIRO * PO Box 76 * Epping NSW 1710 * AUSTRALIA * * Author: Mark Calabretta, Australia Telescope National Facility * http://www.atnf.csiro.au/~mcalabre/index.html * $Id: log.c,v 4.2 2005/09/21 13:21:57 cal103 Exp $ *===========================================================================*/ #include #include "log.h" /* Map status return value to message. */ const char *log_errmsg[] = { "Success", "", "Invalid log-coordinate reference value", "One or more of the x coordinates were invalid"}; /*--------------------------------------------------------------------------*/ int logx2s( double crval, int nx, int sx, int slogc, const double x[], double logc[], int stat[]) { register int ix; register int *statp; register const double *xp; register double *logcp; if (crval <= 0.0) { return 2; } xp = x; logcp = logc; statp = stat; for (ix = 0; ix < nx; ix++, xp += sx, logcp += slogc) { *logcp = crval * exp((*xp) / crval); *(statp++) = 0; } return 0; } /*--------------------------------------------------------------------------*/ int logs2x( double crval, int nlogc, int slogc, int sx, const double logc[], double x[], int stat[]) { int status; register int ilogc; register int *statp; register const double *logcp; register double *xp; if (crval <= 0.0) { return 2; } xp = x; logcp = logc; statp = stat; status = 0; for (ilogc = 0; ilogc < nlogc; ilogc++, logcp += slogc, xp += sx) { if (*logcp > 0.0) { *xp = crval * log(*logcp / crval); *(statp++) = 0; } else { *(statp++) = 1; status = 4; } } return status; } wcstools-3.9.5/libwcs/matchstar.c0000664000016200001660000015527712726340006016111 0ustar minkoirsys/*** File libwcs/matchstar.c *** June 9, 2016 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2016 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ /* StarMatch (ns, sx, sy, ng, gra, gdec, goff, gx, gy, tol, wcs, nfit, debug) * Find shift, scale, and rotation of image stars to best-match reference stars * * ReadMatch (filename, sx, sy, gra, gdec, debug) * Read in x, y, RA, and Dec of pre-match stars in image * * WCSMatch (nmatch, sbx, sby, gbra, gbdec, debug) * Find shift, scale, and rotation of image stars to best-match reference stars * * FitMatch (ns, sx, sy, ng, gra, gdec, gx, gy, tol, wcs, nfit, debug) * Fit shift, scale, and rotation of image stars to RA/Dec/X/Y matches * * wcs_amoeba (wcs0) Set up temp arrays and call multivariate solver * chisqr (v) Compute the chisqr of the vector v * amoeba (p, y, ndim, ftol, itmax, funk, nfunk) * Multivariate solver from Numerical Recipes */ #include #include #include #include #include "wcs.h" #include "lwcs.h" #include "fitsfile.h" #include "wcscat.h" #define NPAR 8 #define NPAR1 9 #define ABS(a) ((a) < 0 ? (-(a)) : (a)) static void wcs_amoeba (); extern void setnofit(); extern int getfilelines(); /* Statics used by the chisqr evaluator */ static double *sx_p; static double *sy_p; static double *gra_p; static double *gdec_p; static double xref_p, yref_p; static double xrefpix, yrefpix; static int nbin_p; static int nfit; /* Number of parameters to fit */ static int pfit0 = 0; /* List of parameters to fit, 1 per digit */ static int cdfit = 0; /* 1 if CD matrix has been fit */ static int resid_refine = 0; static int minbin=2; /* Minimum number of coincidence hits needed */ static int minmatch0 = MINMATCH; /* matches to drop out of loop */ static int nitmax0 = NMAX; /* max iterations to stop fit */ static int binarray; /* If =1, bin matched stars */ static int vfit[NPAR1]; /* Parameters being fit: index to value vector 1= RA, 2= Dec, 3= X plate scale, 4= Y plate scale 5= rotation, 6= second rotation (skew), 7= optical axis X,8= optical axis Y */ /* Find shift, scale, and rotation of image stars to best-match reference stars * Get best match by finding which offsets between pairs of s's and g's * work for the most other pairs of s's and g's * N.B. we assume rotation will be "small enough" so that initial guesses can * be done using just shifts. * Return count of total coincidences found, else 0 if none or -1 if trouble. */ int StarMatch (ns,sx,sy,refcat,ng,gnum,gra,gdec,goff,gx,gy,tol,wcs,debug) int ns; /* Number of image stars */ double *sx; /* Image star X coordinates in pixels */ double *sy; /* Image star Y coordinates in pixels */ int refcat; /* Reference Catalog code */ int ng; /* Number of reference stars */ double *gnum; /* Reference star catalog numbers */ double *gra; /* Reference star right ascensions in degrees */ double *gdec; /* Reference star right ascensions in degrees */ int *goff; /* Reference star offscale flags */ double *gx; /* Reference star X coordinates in pixels */ double *gy; /* Reference star Y coordinates in pixels */ double tol; /* +/- this many pixels is a hit */ struct WorldCoor *wcs; /* World coordinate structure (fit returned) */ int debug; { double dx, bestdx, dxi; double dy, bestdy, dyi; double dx2, dy2, dxy, dxys, dxs, dys, dxsum, dysum; double *mx, *my, *mxy; int nmatch; int s, g, si, gi, igs; int nbin; double *sbx, *sby; /* malloced array of s stars in best bin */ double *gbra, *gbdec; /* malloced array of g stars in best bin */ int peaks[NPEAKS+1]; /* history of bin counts */ int dxpeaks[NPEAKS+1], dypeaks[NPEAKS+1]; /* history of dx/dy at peaks */ int npeaks; /* entries in use in peaks[] */ int maxnbin, i, nmatchd; int minmatch; int *is, *ig, *ibs, *ibg; char rastr[32], decstr[32], numstr[32]; double xref0, yref0, xinc0, yinc0, rot0, xrefpix0, yrefpix0, cd0[4]; int bestbin; /* Number of coincidences for refit */ int pfit; /* List of parameters to fit, 1 per digit */ char vpar[16]; /* List of parameters to fit */ char *vi; char vc; int ParamFit(); double tol2 = tol * tol; double maxnum; int nnfld = 0; /* Set minimum number of matches between image and reference stars to fit */ if (ns > ng) { minmatch = 0.5 * ng; if (minmatch > minmatch0) minmatch = 0.25 * ng; if (minmatch > minmatch0) minmatch = minmatch0; } else { minmatch = 0.5 * ns; if (minmatch > minmatch0) minmatch = 0.25 * ns; if (minmatch > minmatch0) minmatch = minmatch0; } /* Set format for numbers, if listed */ if (debug) { maxnum = gnum[0]; for (gi = 1; gi < ng; gi++) { if (gnum[gi] > maxnum) maxnum = gnum[gi]; } nnfld = CatNumLen (refcat, maxnum, 0); } /* Set maximum number of matches and allocate match indices */ if (ng > ns) maxnbin = (int) ((double) ng * 1.25); else maxnbin = (int) ((double) ns * 1.25); if (debug) fprintf (stderr,"Match history: nim=%d nref=%d tol=%3.0f minbin=%d minmatch=%d):\n", ns, ng, tol, minbin, minmatch); /* Allocate arrays in which to save match information */ is = (int *) calloc (maxnbin, sizeof(int)); ig = (int *) calloc (maxnbin, sizeof(int)); ibs = (int *) calloc (maxnbin, sizeof(int)); ibg = (int *) calloc (maxnbin, sizeof(int)); /* Try matching stars using the current WCS first */ nmatch = 0; bestdx = 0.0; bestdy = 0.0; dxsum = 0.0; dysum = 0.0; dxs = 0.0; dys = 0.0; /* Build 2-d histogram of offset distribution */ if (binarray) { int nbx, nnbx, nbx2, nby, nnby, nby2; int idxmax, idymax, idx, idy, tol2; int *obin, *obini, nset, npos; /* Loop through image stars */ tol2 = 2 * (int) tol; nbx = wcs->nxpix / tol2; nnbx = -nbx; nbx2 = 2 * nbx; nby = wcs->nypix / tol2; nby2 = 2 * nby; nnby = -nby; obin = calloc (nbx2 * nby2, sizeof(int)); nset = 0; npos = 0; for (s = 0; s < ns; s++) { /* Loop through reference catalog stars */ for (g = 0; g < ng; g++) { dx = gx[g] - sx[s]; dy = gy[g] - sy[s]; /* Add to number in this offset bin */ idx = (int) (dx / tol2); idy = (int) (dy / tol2); if (idx > nnbx && idx < nbx && idy > nnby && idy < nby) { obin[((idy+nby) * nbx2) + idx + nbx]++; nset++; } npos++; } } /* Find offset bin with maximim number of entries */ idxmax = 0; idymax = 0; nmatch = 0; obini = obin; for (idy = nnby; idy < nby; idy++) { for (idx = nnbx; idx < nbx; idx++) { if (*obini > nmatch) { idxmax = idx; idymax = idy; nmatch = *obini; if (debug) fprintf (stderr, "%5d at offset %5d, %5d\n", *obini, idx*tol2, idy*tol2); } obini++; } } /* If we found enough matches, we can proceed with this offset */ if (nmatch >= minmatch) { bestdx = tol2 * (double) (idxmax - nbx); bestdy = tol2 * (double) (idymax - nby); if (debug) fprintf (stderr, "%d matches found at mean offset %6.3f %6.3f\n", nmatch, bestdx, bestdy); } free (obin); } /* Vote for closest match */ else { mx = (double *) calloc (maxnbin, sizeof(double)); my = (double *) calloc (maxnbin, sizeof(double)); mxy = (double *) calloc (maxnbin, sizeof(double)); /* Loop through image stars */ for (s = 0; s < ns; s++) { dxys = tol2; igs = -1; /* Loop through reference catalog stars */ for (g = 0; g < ng; g++) { /* Try reference catalog star only if it is on the image */ dx = gx[g] - sx[s]; dy = gy[g] - sy[s]; dx2 = dx * dx; dy2 = dy * dy; dxy = dx2 + dy2; /* Check offset less than tolerance or this star's closest match */ if (dxy < dxys) { dxys = dxy; dxs = dx; dys = dy; igs = g; ibs[nmatch] = s; ibg[nmatch] = g; } } /* If a match was found */ if (igs > -1) { /* if new match is closer than old match, replace it */ if (mxy[igs] > 0.0) { if (dxy < mxy[igs]) { dxsum = dxsum - mx[igs]; dysum = dysum - my[igs]; dxsum = dxsum + dxs; dysum = dysum + dys; if (debug) { CatNum (refcat, nnfld, 0, gnum[ibg[nmatch]], numstr); ra2str (rastr, 31, gra[ibg[nmatch]], 3); dec2str (decstr, 31, gdec[ibg[nmatch]], 2); fprintf (stderr, "*%3d %s %s %s %7.2f %7.2f %7.2f %7.2f %5.2f %5.2f %5.2f\n", nmatch, numstr, rastr, decstr, gx[ibg[nmatch]], gy[ibg[nmatch]], sx[ibs[nmatch]], sy[ibs[nmatch]], dxs, dys, sqrt (dxys)); } } } /* If not matched before, use new match */ else { dxsum = dxsum + dxs; dysum = dysum + dys; if (debug) { CatNum (refcat, nnfld, 0, gnum[ibg[nmatch]], numstr); ra2str (rastr, 31, gra[ibg[nmatch]], 3); dec2str (decstr, 31, gdec[ibg[nmatch]], 2); fprintf (stderr, " %3d %s %s %s %7.2f %7.2f %7.2f %7.2f %5.2f %5.2f %5.2f\n", nmatch, numstr, rastr, decstr, gx[ibg[nmatch]], gy[ibg[nmatch]], sx[ibs[nmatch]], sy[ibs[nmatch]], dxs, dys, sqrt (dxys)); } nmatch++; mx[igs] = dxs; my[igs] = dys; mxy[igs] = dxy; } } } free (mxy); free (mx); free (my); /* If we found enough matches, we can proceed with this offset */ if (nmatch >= minmatch) { bestdx = dxsum / (double) nmatch; bestdy = dysum / (double) nmatch; if (debug) fprintf (stderr, "%d matches found at mean offset %6.3f %6.3f\n", nmatch, bestdx, bestdy); } } /* Otherwise, we will look for a coarse alignment assuming no additional rotation. * This will allow us to collect a set of stars that correspond and * establish an initial guess of the solution. */ if (nmatch < minmatch) { if (debug) fprintf (stderr, "%d matches found less than %d minimum\n", nmatch, minmatch); npeaks = 0; nmatch = 0; for (i = 0; i < NPEAKS; i++) { peaks[i] = 0; dxpeaks[i] = 0; dypeaks[i] = 0; } bestdx = 0.0; bestdy = 0.0; for (s = 0; s < ns; s++) { for (g = 0; g < ng; g++) { dx = gx[g] - sx[s]; dy = gy[g] - sy[s]; nbin = 0; for (gi = 0; gi < ng; gi++) { for (si = 0; si < ns; si++) { dxi = gx[gi] - sx[si] - dx; if (dxi < 0) dxi = -dxi; dyi = gy[gi] - sy[si] - dy; if (dyi < 0) dyi = -dyi; if (dxi <= tol && dyi <= tol) { /* if (debug) fprintf (stderr,"%d %d %d %d %5.1f %5.1f %5.1f %5.1f\n", g,s,gi,si,dx,dy,dxi,dyi); */ is[nbin] = si; ig[nbin] = gi; nbin++; } } } /* if (debug) fprintf (stderr,"%d %d %d %d %d\n", g,s,gi,si,nbin); */ if (nbin > 1 && nbin >= nmatch) { int i; nmatch = nbin; bestdx = (double) dx; bestdy = (double) dy; for (i = 0; i < nbin; i++) { ibs[i] = is[i]; ibg[i] = ig[i]; } /* keep last NPEAKS nmatchs, dx and dy; * put newest first in arrays */ if (npeaks > 0) { for (i = npeaks; i > 0; i--) { peaks[i] = peaks[i-1]; dxpeaks[i] = dxpeaks[i-1]; dypeaks[i] = dypeaks[i-1]; } } peaks[0] = nmatch; if (bestdx > 0.0) dxpeaks[0] = (int) (bestdx + 0.5); else dxpeaks[0] = (int) (bestdx - 0.5); if (bestdy > 0) dypeaks[0] = (int) (bestdy + 0.5); else dypeaks[0] = (int) (bestdy - 0.5); if (npeaks < NPEAKS) npeaks++; if (debug) fprintf (stderr,"%d: %d/%d matches at image %d cat %d: dx= %d dy= %d\n", npeaks, nmatch, minmatch, s, g, dxpeaks[0], dypeaks[0]); } if (nmatch > minmatch) break; } if (nmatch > minmatch) break; } /* if (debug) { int i; for (i = 0; i < npeaks; i++) fprintf (stderr," %d bins at dx=%d dy=%d\n", peaks[i], dxpeaks[i], dypeaks[i]); } */ /* peak is broad */ if (npeaks < 2 || peaks[1] == peaks[0]) { if (debug) fprintf (stderr," Broad peak of %d bins at dx=%.0f dy=%.0f\n", peaks[0], bestdx, bestdy); } } /* too few hits */ if (nmatch < minbin) return (nmatch); /* Get X and Y coordinates of matches from best binning */ nmatchd = nmatch * sizeof (double); if (!(sbx = (double *) malloc (nmatchd))) fprintf (stderr," Could not allocate %d bytes for SBX\n", nmatchd); if (!(sby = (double *) malloc (nmatchd))) fprintf (stderr," Could not allocate %d bytes for SBY\n", nmatchd); if (!(gbra = (double *) malloc (nmatchd))) fprintf (stderr," Could not allocate %d bytes for GBRA\n", nmatchd); if (!(gbdec = (double *) malloc (nmatchd))) fprintf (stderr," Could not allocate %d bytes for GBDEC\n", nmatchd); for (i = 0; i < nmatch; i++) { sbx[i] = sx[ibs[i]]; sby[i] = sy[ibs[i]]; gbra[i] = gra[ibg[i]]; gbdec[i] = gdec[ibg[i]]; } /* Reset image center based on star matching */ wcs->xref = wcs->xref + (bestdx * wcs->xinc); if (wcs->xref < 0.0) wcs->xref = 360.0 + wcs->xref; wcs->yref = wcs->yref + (bestdy * wcs->yinc); /* Fit WCS to matched stars */ /* Provide non-parametric access to the star lists */ sx_p = sbx; sy_p = sby; gra_p = gbra; gdec_p = gbdec; xref_p = wcs->xref; yref_p = wcs->yref; xrefpix = wcs->xrefpix; yrefpix = wcs->yrefpix; nbin_p = nmatch; /* Number of parameters to fit from command line or number of matches */ pfit = ParamFit (nmatch); /* Get parameters to fit from digits of pfit */ sprintf (vpar, "%d", pfit); nfit = 0; vfit[0] = -1; for (i = 1; i < NPAR1; i++) { vc = i + 48; vi = strchr (vpar, vc); if (vi != NULL) { vfit[i] = vi - vpar; nfit++; } else vfit[i] = -1; } /* Set initial guesses for parameters which are being fit */ xref0 = wcs->xref; yref0 = wcs->yref; xinc0 = wcs->xinc; yinc0 = wcs->yinc; rot0 = wcs->rot; xrefpix0 = wcs->xrefpix; yrefpix0 = wcs->yrefpix; cd0[0] = wcs->cd[0]; cd0[1] = wcs->cd[1]; cd0[2] = wcs->cd[2]; cd0[3] = wcs->cd[3]; if (vfit[6] > -1) cdfit = 1; else cdfit = 0; /* Fit image star coordinates to reference star positions */ wcs_amoeba (wcs); if (debug) { fprintf (stderr,"\nAmoeba fit:\n"); ra2str (rastr, 31, xref0, 3); dec2str (decstr, 31, yref0, 2); fprintf (stderr," initial guess:\n"); if (vfit[6] > -1) fprintf (stderr," cra= %s cdec= %s cd = %9.7f,%9.7f,%9.7f,%9.7f ", rastr, decstr, cd0[0], cd0[1], cd0[2], cd0[3]); else fprintf (stderr," cra= %s cdec= %s del=%7.4f,%7.4f rot=%7.4f ", rastr, decstr, xinc0*3600.0, yinc0*3600.0, rot0); fprintf (stderr,"(%8.2f,%8.2f\n", xrefpix0, yrefpix0); ra2str (rastr, 31, wcs->xref, 3); dec2str (decstr, 31, wcs->yref, 2); fprintf (stderr,"\nfirst solution:\n"); if (vfit[6] > -1) fprintf (stderr," cra= %s cdec= %s cd = %9.7f,%9.7f,%9.7f,%9.7f ", rastr,decstr,wcs->cd[0],wcs->cd[1],wcs->cd[2],wcs->cd[3]); else fprintf (stderr," cra= %s cdec= %s del=%7.4f,%7.4f rot=%7.4f ", rastr,decstr,3600.0*wcs->xinc,3600.0*wcs->yinc,wcs->rot); fprintf (stderr,"(%8.2f,%8.2f)\n", wcs->xrefpix, wcs->yrefpix); } /* If we have extra bins, repeat with the best ones */ bestbin = nfit + 1; if (resid_refine && nmatch > bestbin) { double *resid = (double *) malloc (nmatch * sizeof(double)); double *xe = (double *) malloc (nmatch * sizeof(double)); double *ye = (double *) malloc (nmatch * sizeof(double)); int i, j; double xmean, ymean, rmean, xsumsq, ysumsq, diff; double mx, my, xsig, ysig, rsig, siglim; char wcstring[64]; double xsum = 0.0; double ysum = 0.0; double rsum = 0.0; double dmatch = (double)nmatch; double dmatch1 = (double)(nmatch - 1); /* Compute residuals at each star location */ for (i = 0; i < nmatch; i++) { pix2wcs (wcs, sbx[i], sby[i], &mx, &my); xe[i] = (mx - gbra[i]) * 3600.0; ye[i] = (my - gbdec[i]) * 3600.0; resid[i] = sqrt (xe[i]*xe[i] + ye[i]*ye[i]); if (debug) { pix2wcst (wcs, sbx[i], sby[i], wcstring, 64); fprintf (stderr,"%3d (%8.3f,%8.3f) -> %s %6.3f %6.3f %6.3f\n", i, sbx[i], sby[i], wcstring, xe[i], ye[i], resid[i]); } xsum = xsum + xe[i]; ysum = ysum + ye[i]; rsum = rsum + resid[i]; } /* Compute means and standard deviations */ xmean = xsum / dmatch; ymean = ysum / dmatch; rmean = rsum / dmatch; xsumsq = 0.0; ysumsq = 0.0; for (i = 0; i < nmatch; i++) { diff = xe[i] - xmean; xsumsq = xsumsq + (diff * diff); diff = ye[i] - ymean; ysumsq = ysumsq + (diff * diff); } xsig = sqrt (xsumsq / dmatch1); ysig = sqrt (ysumsq / dmatch1); rsig = sqrt ((xsumsq + ysumsq)/ dmatch1); siglim = 2.0 * rsig; if (debug) { fprintf (stderr,"Mean x: %6.3f/%6.3f y: %6.3f/%6.3f r: %6.3f/%6.3f\n", xmean, xsig, ymean, ysig, rmean, rsig); } /* sort by increasing total residual */ for (i = 0; i < nmatch-1; i++) { for (j = i+1; j < nmatch; j++) { if (resid[j] < resid[i]) { double tmp; tmp = sbx[i]; sbx[i] = sbx[j]; sbx[j] = tmp; tmp = sby[i]; sby[i] = sby[j]; sby[j] = tmp; tmp = gbra[i]; gbra[i] = gbra[j]; gbra[j] = tmp; tmp = gbdec[i]; gbdec[i] = gbdec[j]; gbdec[j] = tmp; tmp = resid[i]; resid[i] = resid[j]; resid[j] = tmp; } } } /* Cut off points at residual of two sigma */ for (i = 0; i < nmatch; i++) { if (resid[i] > siglim) { if (i > bestbin) bestbin = i - 1; break; } } xref_p = wcs->xref; if (xref_p < 0.0) xref_p = 360.0 + xref_p; yref_p = wcs->yref; xrefpix = wcs->xrefpix; yrefpix = wcs->yrefpix; nbin_p = bestbin; wcs_amoeba (wcs); if (debug) { ra2str (rastr, 31, wcs->xref, 3); dec2str (decstr, 31, wcs->yref, 2); fprintf (stderr,"\nresid solution:\n"); fprintf (stderr,"\n%d points < %.3f arcsec residuals refit\n", bestbin, siglim); fprintf (stderr," cra= %s cdec= %s del=%7.4f,%7.4f rot=%7.4f ", rastr, decstr, 3600.0*wcs->xinc, 3600.0*wcs->yinc, wcs->rot); fprintf (stderr,"(%8.2f,%8.2f)\n", wcs->xrefpix, wcs->yrefpix); } free (resid); free (xe); free (ye); } free (sbx); free (sby); free (gbra); free (gbdec); free (is); free (ig); free (ibs); free (ibg); return (nmatch); } int ParamFit (nbin) int nbin; /* Number of point to be fit */ { int pfit; if (pfit0 != 0) { if (pfit0 < 3) pfit = 12; else if (pfit0 == 3) /* Fit center and plate scale */ pfit = 123; else if (pfit0 == 4) /* Fit center, plate scale, rotation */ pfit = 1235; else if (pfit0 == 5) /* Fit center, x&y plate scales, rotation */ pfit = 12345; else if (pfit0 == 6) /* Fit center, x&y plate scales, x&y rotations */ pfit = 123456; else if (pfit0 == 7) /* Fit center, x&y plate scales, rotation, refpix */ pfit = 1234578; else if (pfit0 == 8) /* Fit center, x&y plate scales, x&y rotation, refpix */ pfit = 12345678; else pfit = pfit0; } else if (nbin < 4) pfit = 12; else if (nbin < 6) pfit = 123; else pfit = 12345; return (pfit); } int NParamFit (nbin) int nbin; /* Number of point to be fit */ { int pfit; pfit = ParamFit (nbin); if (pfit < 1) return (0); else if (pfit < 10) return (1); else if (pfit < 100) return (2); else if (pfit < 1000) return (3); else if (pfit < 10000) return (4); else if (pfit < 100000) return (5); else if (pfit < 1000000) return (6); else if (pfit < 10000000) return (7); else return (8); } int ReadMatch (filename, sx, sy, sra, sdec, debug) char *filename; /* Name of file containing matches */ double **sx; /* Image star X coordinates in pixels */ double **sy; /* Image star Y coordinates in pixels */ double **sra; /* Probable image star right ascensions in degrees */ double **sdec; /* Probable image star declinations in degrees */ int debug; /* Printed debugging information if not zero */ { int nbytes, nread, ir, ntok, itok, iytok; double *tx, *ty, *tra, *tdec, ra, dec, x, y; int ndec; int nmatch = 0; /* Number of matches read from file */ char rastr[32], decstr[32]; /* If tab file, read from ra, dec, x, y columns */ if (istab (filename)) { } /* Otherwise, assume first 4 columns are x, y, ra, dec */ else { char line[1025]; char *nextline, *lastchar; FILE *fd; struct Tokens tokens; /* Token structure */ char *cwhite; /* additional whitespace characters */ char token[256]; cwhite = NULL; /* Open input file */ if (!strcmp (filename, "stdin")) { fd = stdin; nread = 1000; } else { nread = getfilelines (filename); if (!(fd = fopen (filename, "r"))) { fprintf (stderr, "ReadMatch: Match file %s could not be opened\n", filename); return (0); } } nbytes = nread * sizeof (double); if (!(tra = (double *) calloc (nread, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gra\n", nbytes); if (!(tdec = (double *) calloc (nread, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gdec\n", nbytes); if (!(tx = (double *) calloc (nread, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for sx\n", nbytes); if (!(ty = (double *) calloc (nread, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for sy\n", nbytes); *sra = tra; *sdec = tdec; *sx = tx; *sy = ty; nmatch = 0; nextline = line; for (ir = 0; ir < nread; ir++) { if (fgets (line, 1024, fd) == NULL) break; /* Skip lines with comments */ if (line[0] == '#') continue; /* Drop linefeeds */ lastchar = nextline + strlen(nextline) - 1; if (*lastchar < 32) *lastchar = (char) 0; /* Read X, Y, RA, and Dec from each line, skipping line if all four are not present and numbers */ ntok = setoken (&tokens, line, cwhite); if (ntok < 1) break; if (ntok < 4) continue; /* if (debug) fprintf (stderr, "%d: %s\n", nmatch, line); */ /* Image X coordinate or RA */ itok = 1; if (getoken(&tokens, itok, token, 256)) { /* Read RA, Dec, X, Y if first token has : in it */ if (isnum (token) == 3) { ra = str2ra (token); iytok = 4; if (getoken(&tokens, 2, token, 256)) dec = str2dec (token); if (getoken(&tokens, 3, token, 256)) { if (isnum (token)) x = atof (token); else { iytok = 5; if (getoken(&tokens, 4, token, 256)) { if (isnum (token)) x = atof (token); else continue; } } } if (getoken(&tokens, iytok, token, 256)) { if (isnum (token) == 1 || isnum (token) == 2) y = atof (token); else continue; } tx[nmatch] = x; ty[nmatch] = y; tra[nmatch] = ra; tdec[nmatch] = dec; nmatch++; continue; } if (isnum (token)) x = atof (token); else continue; } else continue; /* Image Y coordinate */ itok++; if (getoken(&tokens, itok, token, 256)) { if (isnum (token) == 1 || isnum (token) == 2) y = atof (token); else continue; } else continue; /* Right ascension */ itok++; if (getoken(&tokens, itok, token, 256)) { /* If first number is integer, read as h m s */ if (isnum (token) == 1) { ra = atof (token); itok++; if (getoken(&tokens, itok, token, 256)) { if (isnum (token) == 2) ra = ra + (atof (token) / 60.0); else if (isnum (token) == 1) { ra = ra + (atof (token) / 60.0); itok++; if (getoken(&tokens, itok, token, 256)) { if (isnum (token) == 1 || isnum (token) == 2) ra = ra + (atof (token) / 3600.0); } } } ra = ra * 15.0; } else ra = str2ra (token); } else continue; /* Declination */ itok++; if (getoken(&tokens, itok, token, 256)) { if (isnum (token) == 1) { dec = atof (token); itok++; if (strchr (token, '-') != NULL) ndec = 1; else ndec = 0; if (getoken(&tokens, itok, token, 256)) { if (isnum (token) == 2) { if (ndec) dec = dec - (atof (token) / 60.0); else dec = dec + (atof (token) / 60.0); } else if (isnum (token) == 1) { if (ndec) dec = dec - (atof (token) / 60.0); else dec = dec + (atof (token) / 60.0); itok++; if (getoken(&tokens, itok, token, 256)) { if (isnum (token) == 1 || isnum (token) == 2) { if (ndec) dec = dec - (atof (token) / 3600.0); else dec = dec + (atof (token) / 3600.0); } } } } } else dec = str2dec (token); } else continue; tx[nmatch] = x; ty[nmatch] = y; tra[nmatch] = ra; tdec[nmatch] = dec; if (debug) { ra2str (rastr, 31, tra[nmatch], 3); dec2str (decstr, 31, tdec[nmatch], 2); fprintf (stderr, "ReadMatch: %d: %8.3f %8.3f %s %s\n", nmatch, tx[nmatch], ty[nmatch], rastr, decstr); } nmatch++; } } return (nmatch); } /* Find shift, scale, and rotation of image stars to best-match reference stars */ void WCSMatch (nmatch, sbx, sby, gbra, gbdec, debug) int nmatch; /* Number of matched stars */ double *sbx; /* Image star X coordinates in pixels */ double *sby; /* Image star Y coordinates in pixels */ double *gbra; /* Reference star right ascensions in degrees */ double *gbdec; /* Reference star right ascensions in degrees */ int debug; /* Printed debugging information if not zero */ { int i; double xdiff, ydiff; int nsc, j, nq[5]; double dnsc, tx, ty, tra, tdec, tdiff; double cra, cdec, cx, cy, scale; double rai; double dmatch; double skydiff, imdiff; char rastr[32], decstr[32]; extern double getsecpix(); extern void getcenter(),getrefpix(),setdcenter(),setrefpix(),setsecpix(); /* Too few hits */ if (nmatch < 2) { if (debug) { fprintf (stderr, "WCSMatch: %d matched stars < 2\n", nmatch); } return; } /* Check for RA crossing 0:00:00 */ for (i = 0; i < 5; i++) nq[i] = 0; /* Get number of matches in each quadrant */ for (i = 0; i < nmatch; i++) { rai = gbra[i]; if (rai >= 0.0 && rai < 90.0) nq[1] = nq[1] + 1; else if (rai >= 90.0 && rai < 180.0) nq[2] = nq[2] + 1; else if (rai >= 180.0 && rai < 270.0) nq[3] = nq[3] + 1; else nq[4] = nq[4] + 1; } if (debug) { fprintf (stderr,"WCSMatch: %d matched stars: %d %d %d %d per quadrant:\n", nmatch, nq[1], nq[2], nq[3], nq[4]); } /* If matches in quadrants 1 and 4, but not 2 or 3, center RAs on 0:00 */ if (nq[1] > 0 && nq[4] > 0 && nq[2] < 1 && nq[3] < 1) { for (i = 0; i < nmatch; i++) { if (gbra[i] >= 270.0 && gbra[i] < 361.0) gbra[i] = gbra[i] - 360.0; if (debug) { dec2str (rastr, 31, gbra[i], 3); dec2str (decstr, 31, gbdec[i], 2); fprintf (stderr, "%d: %8.3f %8.3f %s %s\n", i, sbx[i], sby[i], rastr, decstr); } } } /* Compute plate scale and center of stars */ dnsc = 0.0; tx = 0.0; ty = 0.0; tra = 0.0; tdec = 0.0; tdiff = 0.0; for (i = 0; i < nmatch-1; i++) { tx = tx + sbx[i]; ty = ty + sby[i]; tra = tra + gbra[i]; tdec = tdec + gbdec[i]; for (j = i+1; j < nmatch; j++) { skydiff = wcsdist (gbra[i], gbdec[i], gbra[j], gbdec[j]); xdiff = sbx[j] - sbx[i]; ydiff = sby[j] - sby[i]; imdiff = sqrt ((xdiff * xdiff) + (ydiff * ydiff)); if (imdiff > 0) { scale = skydiff / imdiff; tdiff = tdiff + scale; dnsc = dnsc + 1.0; } else scale = 0.0; if (debug) { fprintf (stderr,"%d %d: sky: %8g, image: %8g, %8g deg/pix", i, j, skydiff, imdiff, scale); fprintf (stderr," = %8g arcsec/pix %10g\n", scale * 3600.0, tdiff); } } } tx = tx + sbx[nmatch-1]; ty = ty + sby[nmatch-1]; tra = tra + gbra[nmatch-1]; tdec = tdec + gbdec[nmatch-1]; /* Reset image center based on star matching */ cra = -99.0; cdec = -99.0; getcenter (&cra, &cdec); dmatch = (double) nmatch; if (cra == -99.0 && cdec == -99.0) { cra = tra / dmatch; cdec = tdec / dmatch; setdcenter (cra, cdec); } cx = -99999.0; cy = -99999.0; getrefpix (&cx, &cy); if (cx == -99999.0) { cx = tx / dmatch; cy = ty / dmatch; setrefpix (cx, cy); } scale = 0.0; scale = getsecpix(); if (scale == 0.0) { scale = tdiff / dnsc; setsecpix (3600.0 * scale); } if (debug) { fprintf (stderr, "cra= %8g cdec = %8g xref=%8g yref=%8g\n", cra, cdec, cx, cy); fprintf (stderr,"scale = %8g deg/pix = %8g arcsec/pix\n", scale, scale*3600.0); } return; } /* Find shift, scale, and rotation of image stars to best-match reference stars * Return count of total coincidences found, else 0 if none or -1 if trouble. */ int FitMatch (nmatch, sbx, sby, gbra, gbdec, wcs, debug) int nmatch; /* Number of matched stars */ double *sbx; /* Image star X coordinates in pixels */ double *sby; /* Image star Y coordinates in pixels */ double *gbra; /* Reference star right ascensions in degrees */ double *gbdec; /* Reference star right ascensions in degrees */ struct WorldCoor *wcs; /* World coordinate structure (fit returned) */ int debug; /* Printed debugging information if not zero */ { int i; char rastr[32], decstr[32]; double xref0, yref0, xinc0, yinc0, rot0, xrefpix0, yrefpix0, cd0[4]; int bestbin; /* Number of coincidences for refit */ int pfit; /* List of parameters to fit, 1 per digit */ char vpar[16]; /* List of parameters to fit */ double xdiff, ydiff; char *vi; char vc; int nsc, j; /* double equinox = wcs->equinox; */ double tx = 0.0; double ty = 0.0; double tra = 0.0; double tdec = 0.0; double tdiff = 0.0; double scale; /* double dmatch; */ double skydiff, imdiff; /* dmatch = (double) nmatch; */ /* Too few hits */ if (nmatch < minbin) { if (debug) { fprintf (stderr,"%d matched stars < %d\n", nmatch, minbin); } return (nmatch); } else if (debug) { fprintf (stderr,"%d matched stars:\n", nmatch); } /* Compute plate scale and center of stars */ nsc = 0; for (i = 0; i < nmatch; i++) { tx = tx + sbx[i]; ty = ty + sby[i]; tra = tra + gbra[i]; tdec = tdec + gbdec[i]; for (j = i+1; j < nmatch; j++) { skydiff = wcsdist (gbra[i], gbdec[i], gbra[j], gbdec[j]); xdiff = sbx[j] - sbx[i]; ydiff = sby[j] - sby[i]; imdiff = sqrt ((xdiff * xdiff) + (ydiff * ydiff)); scale = skydiff / imdiff; tdiff = tdiff + scale; nsc++; if (debug) { fprintf (stderr,"%d %d: sky: %8g, image: %8g, %8g deg/pix", i, j, skydiff, imdiff, scale); fprintf (stderr," = %8g arcsec/pix\n", scale * 3600.0); } } } /* Reset image center in WCS data structure based on star matching */ /* cra = tra / dmatch; cdec = tdec / dmatch; cx = tx / dmatch; cy = ty / dmatch; scale = tdiff / (double) nsc; if (debug) fprintf (stderr,"scale = %8g deg/pix = %8g arcsec/pix\n", scale, scale*3600.0); wcsreset (wcs, cx, cy, cra, cdec, scale, 0.0, 0.0, NULL, equinox); */ /* Provide non-parametric access to the star lists */ sx_p = sbx; sy_p = sby; gra_p = gbra; gdec_p = gbdec; xref_p = wcs->xref; if (xref_p < 0.0) xref_p = 360.0 + xref_p; yref_p = wcs->yref; xrefpix = wcs->xrefpix; yrefpix = wcs->yrefpix; nbin_p = nmatch; /* Number of parameters to fit from command line or number of matches */ if (pfit0 != 0) { if (pfit0 < 3) pfit = 12; else if (pfit0 == 3) /* Fit center and plate scale */ pfit = 123; else if (pfit0 == 4) /* Fit center, plate scale, rotation */ pfit = 1235; else if (pfit0 == 5) /* Fit center, x&y plate scales, rotation */ pfit = 12345; else if (pfit0 == 6) /* Fit center, x&y plate scales, x&y rotations */ pfit = 123456; else if (pfit0 == 7) /* Fit center, x&y plate scales, rotation, refpix */ pfit = 1234578; else if (pfit0 == 8) /* Fit center, x&y plate scales, x&y rotation, refpix */ pfit = 12345678; else pfit = pfit0; } else if (nmatch < 4) pfit = 12; else if (nmatch < 6) pfit = 123; else pfit = 12345; /* Get parameters to fit from digits of pfit */ sprintf (vpar, "%d", pfit); nfit = 0; vfit[0] = -1; for (i = 1; i < NPAR1; i++) { vc = i + 48; vi = strchr (vpar, vc); if (vi != NULL) { vfit[i] = vi - vpar; nfit++; } else vfit[i] = -1; } /* Set initial guesses for parameters which are being fit */ xref0 = wcs->xref; yref0 = wcs->yref; xinc0 = wcs->xinc; yinc0 = wcs->yinc; rot0 = wcs->rot; xrefpix0 = wcs->xrefpix; yrefpix0 = wcs->yrefpix; cd0[0] = wcs->cd[0]; cd0[1] = wcs->cd[1]; cd0[2] = wcs->cd[2]; cd0[3] = wcs->cd[3]; if (vfit[6] > -1) cdfit = 1; else cdfit = 0; /* Fit image star coordinates to reference star positions */ wcs_amoeba (wcs); if (debug) { fprintf (stderr,"\nAmoeba fit:\n"); ra2str (rastr, 31, xref0, 3); dec2str (decstr, 31, yref0, 2); fprintf (stderr," initial guess:\n"); if (vfit[6] > -1) fprintf (stderr," cra= %s cdec= %s cd = %9.7f,%9.7f,%9.7f,%9.7f ", rastr, decstr, cd0[0], cd0[1], cd0[2], cd0[3]); else fprintf (stderr," cra= %s cdec= %s del=%7.4f,%7.4f rot=%7.4f ", rastr, decstr, xinc0*3600.0, yinc0*3600.0, rot0); fprintf (stderr,"(%8.2f,%8.2f\n", xrefpix0, yrefpix0); ra2str (rastr, 31, wcs->xref, 3); dec2str (decstr, 31, wcs->yref, 2); fprintf (stderr,"\nfirst solution:\n"); if (vfit[6] > -1) fprintf (stderr," cra= %s cdec= %s cd = %9.7f,%9.7f,%9.7f,%9.7f ", rastr,decstr,wcs->cd[0],wcs->cd[1],wcs->cd[2],wcs->cd[3]); else fprintf (stderr," cra= %s cdec= %s del=%7.4f,%7.4f rot=%7.4f ", rastr,decstr,3600.0*wcs->xinc,3600.0*wcs->yinc,wcs->rot); fprintf (stderr,"(%8.2f,%8.2f)\n", wcs->xrefpix, wcs->yrefpix); } /* If we have extra bins, repeat with the best ones */ bestbin = nfit + 1; if (resid_refine && nmatch > bestbin) { double *resid = (double *) malloc (nmatch * sizeof(double)); double *xe = (double *) malloc (nmatch * sizeof(double)); double *ye = (double *) malloc (nmatch * sizeof(double)); int i, j; double xmean, ymean, rmean, xsumsq, ysumsq, diff; double mra, mdec, xsig, ysig, rsig, siglim; char wcstring[64]; double xsum = 0.0; double ysum = 0.0; double rsum = 0.0; double dmatch = (double)nmatch; double dmatch1 = (double)(nmatch - 1); /* Compute residuals at each star location */ for (i = 0; i < nmatch; i++) { pix2wcs (wcs, sbx[i], sby[i], &mra, &mdec); xe[i] = (mra - gbra[i]) * 3600.0; ye[i] = (mdec - gbdec[i]) * 3600.0; resid[i] = sqrt (xe[i]*xe[i] + ye[i]*ye[i]); if (debug) { pix2wcst (wcs, sbx[i], sby[i], wcstring, 64); fprintf (stderr,"%3d (%8.3f,%8.3f) -> %s %6.3f %6.3f %6.3f\n", i, sbx[i], sby[i], wcstring, xe[i], ye[i], resid[i]); } xsum = xsum + xe[i]; ysum = ysum + ye[i]; rsum = rsum + resid[i]; } /* Compute means and standard deviations */ xmean = xsum / dmatch; ymean = ysum / dmatch; rmean = rsum / dmatch; xsumsq = 0.0; ysumsq = 0.0; for (i = 0; i < nmatch; i++) { diff = xe[i] - xmean; xsumsq = xsumsq + (diff * diff); diff = ye[i] - ymean; ysumsq = ysumsq + (diff * diff); } xsig = sqrt (xsumsq / dmatch1); ysig = sqrt (ysumsq / dmatch1); rsig = sqrt ((xsumsq + ysumsq)/ dmatch1); siglim = 2.0 * rsig; if (debug) { fprintf (stderr,"Mean x: %6.3f/%6.3f y: %6.3f/%6.3f r: %6.3f/%6.3f\n", xmean, xsig, ymean, ysig, rmean, rsig); } /* sort by increasing total residual */ for (i = 0; i < nmatch-1; i++) { for (j = i+1; j < nmatch; j++) { if (resid[j] < resid[i]) { double tmp; tmp = sbx[i]; sbx[i] = sbx[j]; sbx[j] = tmp; tmp = sby[i]; sby[i] = sby[j]; sby[j] = tmp; tmp = gbra[i]; gbra[i] = gbra[j]; gbra[j] = tmp; tmp = gbdec[i]; gbdec[i] = gbdec[j]; gbdec[j] = tmp; tmp = resid[i]; resid[i] = resid[j]; resid[j] = tmp; } } } /* Cut off points at residual of two sigma */ for (i = 0; i < nmatch; i++) { if (resid[i] > siglim) { if (i > bestbin) bestbin = i - 1; break; } } xref_p = wcs->xref; if (xref_p < 0.0) xref_p = 360.0 + xref_p; yref_p = wcs->yref; xrefpix = wcs->xrefpix; yrefpix = wcs->yrefpix; nbin_p = bestbin; wcs_amoeba (wcs); if (debug) { ra2str (rastr, 31, wcs->xref, 3); dec2str (decstr, 31, wcs->yref, 2); fprintf (stderr,"\nresid solution:\n"); fprintf (stderr,"\n%d points < %.3f arcsec residuals refit\n", bestbin, siglim); fprintf (stderr," cra= %s cdec= %s del=%7.4f,%7.4f rot=%7.4f ", rastr, decstr, 3600.0*wcs->xinc, 3600.0*wcs->yinc, wcs->rot); fprintf (stderr,"(%8.2f,%8.2f)\n", wcs->xrefpix, wcs->yrefpix); } free (resid); free (xe); free (ye); } return (nmatch); } struct WorldCoor *wcsf; static double wcs_chisqr (); /* From Numerical Recipes */ void amoeba(); static double amotry(); /* Set up the necessary temp arrays and call the amoeba() multivariate solver */ static void wcs_amoeba (wcs0) struct WorldCoor *wcs0; { double *p[NPAR1]; /* used as p[NPAR1][NPAR] */ double vguess[NPAR], vp[NPAR], vdiff[NPAR]; double p0[NPAR], p1[NPAR], p2[NPAR], p3[NPAR], p4[NPAR], p5[NPAR], p6[NPAR], p7[NPAR], p8[NPAR]; /* used as px[0..NPAR-1] */ double y[NPAR1]; /* used as y[1..NPAR] */ double xinc1, yinc1, xrefpix1, yrefpix1, rot, cd[4]; double sumx, sumy, sumr; int iter; int i, j; int nfit1; char rastr[32],decstr[32]; int nitmax; nitmax = nitmax0; if (nfit > NPAR) nfit = NPAR; nfit1 = nfit + 1; wcsf = wcs0; /* Initialize guess and difference vectors to zero */ for (i = 0; i < NPAR; i++) { vguess[i] = 0.0; vdiff[i] = 0.0; } /* Optical axis center (RA and Dec degrees) */ if (vfit[1] > -1) { vguess[vfit[1]] = 0.0; vdiff[vfit[1]] = 5.0 * wcsf->xinc; } if (vfit[2] > -1) { vguess[vfit[2]] = 0.0; vdiff[vfit[2]] = 5.0 * wcsf->yinc; } /* Second rotation about optical axis (degrees) -> CD matrix */ if (vfit[6] > -1) { wcsf->rotmat = 1; vguess[vfit[3]] = wcsf->cd[0]; vdiff[vfit[3]] = wcsf->xinc * 0.03; vguess[vfit[4]] = wcsf->cd[1]; vdiff[vfit[4]] = wcsf->yinc * 0.03; vguess[vfit[5]] = wcsf->cd[2]; vdiff[vfit[5]] = wcsf->xinc * 0.03; vguess[vfit[6]] = wcsf->cd[3]; vdiff[vfit[6]] = wcsf->yinc * 0.03; } else { /* Plate scale at optical axis right ascension or both (degrees/pixel) */ if (vfit[3] > -1) { vguess[vfit[3]] = wcsf->xinc; vdiff[vfit[3]] = wcsf->xinc * 0.03; } /* Plate scale in declination at optical axis (degrees/pixel) */ if (vfit[4] > -1) { vguess[vfit[4]] = wcsf->yinc; vdiff[vfit[4]] = wcsf->yinc * 0.03; } /* Rotation about optical axis in degrees */ if (vfit[5] > -1) { vguess[vfit[5]] = wcsf->rot; vdiff[vfit[5]] = 0.5; } } /* Reference pixel (optical axis) */ if (vfit[7] > -1) { vguess[vfit[7]] = 0.0; vdiff[vfit[7]] = 10.0; } if (vfit[8] > -1) { vguess[vfit[8]] = 0.0; vdiff[vfit[8]] = 10.0; } /* Set up matrix of nfit+1 initial guesses. * The supplied guess, plus one for each parameter altered by a small amount */ p[0] = p0; if (nfit > 0) p[1] = p1; if (nfit > 1) p[2] = p2; if (nfit > 2) p[3] = p3; if (nfit > 3) p[4] = p4; if (nfit > 4) p[5] = p5; if (nfit > 5) p[6] = p6; if (nfit > 6) p[7] = p7; if (nfit > 7) p[8] = p8; for (i = 0; i <= nfit; i++) { for (j = 0; j < nfit; j++) p[i][j] = vguess[j]; if (i > 0 && i <= nfit) p[i][i-1] = vguess[i-1] + vdiff[i-1]; y[i] = wcs_chisqr (p[i], -i); } #define PDUMP #ifdef PDUMP fprintf (stderr,"Before:\n"); for (i = 0; i < nfit1; i++) { if (vfit[1] > -1) ra2str (rastr, 31, p[i][vfit[1]] + xref_p, 3); else ra2str (rastr, 31, wcsf->xref, 3); if (vfit[2] > -1) dec2str (decstr, 16, p[i][vfit[2]]+yref_p, 2); else dec2str (decstr, 16, wcsf->yref, 2); if (vfit[6] > -1) { cd[0] = p[i][vfit[3]]; cd[1] = p[i][vfit[4]]; cd[2] = p[i][vfit[5]]; cd[3] = p[i][vfit[6]]; fprintf (stderr,"%d: %s %s CD: %7.5f,%7.5f,%7.5f,%7.5f ", i, rastr, decstr, cd[0],cd[1],cd[2],cd[3]); } else { if (vfit[3] > -1) xinc1 = p[i][vfit[3]]; else xinc1 = wcsf->xinc; if (vfit[4] > -1) yinc1 = p[i][vfit[4]]; else if (vfit[3] > -1) { if (xinc1 < 0) yinc1 = -xinc1; else yinc1 = xinc1; } else yinc1 = wcsf->yinc; if (vfit[5] > -1) rot = p[i][vfit[5]]; else rot = wcsf->rot; fprintf (stderr,"%d: %s %s del=%6.4f,%6.4f rot=%5.3f ", i, rastr, decstr, 3600.0*xinc1, 3600.0*yinc1, rot); } if (vfit[7] > -1) xrefpix1 = xrefpix + p[i][vfit[7]]; else xrefpix1 = wcsf->xrefpix; if (vfit[8] > -1) yrefpix1 = yrefpix + p[i][vfit[8]]; else yrefpix1 = wcsf->yrefpix; fprintf (stderr,"(%8.2f,%8.2f) y=%g\n", xrefpix1, yrefpix1, y[i]); } #endif amoeba (p, y, nfit, FTOL, nitmax, wcs_chisqr, &iter); #define PDUMP #ifdef PDUMP fprintf (stderr,"\nAfter:\n"); for (i = 0; i < nfit1; i++) { if (vfit[1] > -1) ra2str (rastr, 31, p[i][vfit[1]] + xref_p, 3); else ra2str (rastr, 31, wcsf->xref, 3); if (vfit[2] > -1) dec2str (decstr, 31, p[i][vfit[2]]+yref_p, 2); else dec2str (decstr, 31, wcsf->yref, 2); if (vfit[6] > -1) { cd[0] = p[i][vfit[3]]; cd[1] = p[i][vfit[4]]; cd[2] = p[i][vfit[5]]; cd[3] = p[i][vfit[6]]; fprintf (stderr,"%d: %s %s CD: %7.5f,%7.5f,%7.5f,%7.5f ", i, rastr, decstr, cd[0],cd[1],cd[2],cd[3]); } else { if (vfit[3] > -1) xinc1 = p[i][vfit[3]]; else xinc1 = wcsf->xinc; if (vfit[4] > -1) yinc1 = p[i][vfit[4]]; else if (vfit[3] > -1) { if (xinc1 < 0) yinc1 = -xinc1; else yinc1 = xinc1; } else yinc1 = wcsf->yinc; if (vfit[5] > -1) rot = p[i][vfit[5]]; else rot = wcsf->rot; fprintf (stderr,"%d: %s %s del=%6.4f,%6.4f rot=%5.3f ", i,rastr,decstr, 3600.0*xinc1, 3600.0*yinc1, rot); } if (vfit[7] > -1) xrefpix1 = xrefpix + p[i][vfit[7]]; else xrefpix1 = wcsf->xrefpix; if (vfit[8] > -1) yrefpix1 = yrefpix + p[i][vfit[8]]; else yrefpix1 = wcsf->yrefpix; fprintf (stderr,"(%8.2f,%8.2f) y=%g\n", xrefpix1, yrefpix1, y[i]); } #endif /* On return, all entries in p[1..NPAR] are within FTOL; * Return the average, though you could just pick the first one */ for (j = 0; j < nfit; j++) { double sum = 0.0; for (i = 0; i < nfit1; i++) sum += p[i][j]; vp[j] = sum / (double)nfit1; } if (vfit[1] > -1) { wcsf->xref = xref_p + vp[vfit[1]]; if (wcsf->xref < 0.0) wcsf->xref = 360.0 + wcsf->xref; } if (vfit[2] > -1) wcsf->yref = yref_p + vp[vfit[2]]; if (vfit[6] > -1) { wcsf->cd[0] = vp[vfit[3]]; wcsf->cd[1] = vp[vfit[4]]; wcsf->cd[2] = vp[vfit[5]]; wcsf->cd[3] = vp[vfit[6]]; } else { if (vfit[3] > -1) wcsf->xinc = vp[vfit[3]]; if (vfit[4] > -1) wcsf->yinc = vp[vfit[4]]; else if (vfit[3] > -1) { if (wcsf->xinc < 0) wcsf->yinc = -wcsf->xinc; else wcsf->yinc = wcsf->xinc; } if (vfit[5] > -1) wcsf->rot = vp[vfit[5]]; } if (vfit[7] > -1) wcsf->xrefpix = xrefpix + vp[vfit[7]]; if (vfit[8] > -1) wcsf->yrefpix = yrefpix + vp[vfit[8]]; #define RESIDDUMP #ifdef RESIDDUMP ra2str (rastr, 31, wcsf->xref, 3); dec2str (decstr, 31, wcsf->yref, 2); if (vfit[6] > -1) fprintf (stderr,"iter=%d\n cra= %s cdec= %s CD=%9.7f,%9.7f,%9.7f,%9.7f ", iter, rastr, decstr, wcsf->cd[0], wcsf->cd[1], wcsf->cd[2], wcsf->cd[3]); else fprintf (stderr,"iter=%d\n cra= %s cdec= %s del=%7.4f,%7.4f rot=%7.4f ", iter, rastr, decstr, wcsf->xinc*3600.0, wcsf->yinc*3600.0, wcsf->rot); fprintf (stderr,"(%8.2f,%8.2f)\n", wcsf->xrefpix, wcsf->yrefpix); sumx = 0.0; sumy = 0.0; sumr = 0.0; for (i = 0; i < nbin_p; i++) { double mra, mdec, ex, ey, er; char rastr[32], decstr[32]; pix2wcs (wcsf, sx_p[i], sy_p[i], &mra, &mdec); ex = 3600.0 * (mra - gra_p[i]); ey = 3600.0 * (mdec - gdec_p[i]); er = sqrt (ex * ex + ey * ey); sumx = sumx + ex; sumy = sumy + ey; sumr = sumr + er; ra2str (rastr, 31, gra_p[i], 3); dec2str (decstr, 31, gdec_p[i], 2); fprintf (stderr,"%2d: c: %s %s ", i+1, rastr, decstr); ra2str (rastr, 31, mra, 3); dec2str (decstr, 31, mdec, 2); fprintf (stderr, "i: %s %s %6.3f %6.3f %6.3f\n", rastr, decstr, 3600.0*ex, 3600.0*ey, 3600.0*sqrt(ex*ex + ey*ey)); } sumx = sumx / (double)nbin_p; sumy = sumy / (double)nbin_p; sumr = sumr / (double)nbin_p; fprintf (stderr,"mean dra: %6.3f, ddec: %6.3f, dr = %6.3f\n", sumx, sumy, sumr); #endif } /* Compute the chisqr of the vector v, where * v[0]=cra, v[1]=cdec, v[2]=ra deg/pix, v[3]=dec deg/pix, * v[4]=rotation, v[5]=2nd rotation->CD matrix, v[6]=ref x, and v[7] = ref y * chisqr is in arcsec^2 */ static double wcs_chisqr (v, iter) double *v; /* Vector of parameter values */ int iter; /* Number of iterations */ { double chsq; char rastr[32],decstr[32]; double xmp, ymp, dx, dy, cd[4], *cdx; double crval1, crval2, cdelt1, cdelt2, crota, crpix1, crpix2; int i, offscale; /* Set WCS parameters from fit parameter vector */ /* Sky coordinates at optical axis (degrees) */ if (vfit[1] > -1) crval1 = xref_p + v[vfit[1]]; else crval1 = wcsf->xref; if (vfit[2] > -1) crval2 = yref_p + v[vfit[2]]; else crval2 = wcsf->yref; /* CD matrix */ if (vfit[6] > -1) { cdelt1 = 0.0; cdelt2 = 0.0; crota = 0.0; cd[0] = v[vfit[3]]; cd[1] = v[vfit[4]]; cd[2] = v[vfit[5]]; cd[3] = v[vfit[6]]; cdx = cd; } else { /* Plate scale (degrees/pixel) */ if (vfit[3] > -1) cdelt1 = v[vfit[3]]; else cdelt1 = wcsf->xinc; if (vfit[4] > -1) cdelt2 = v[vfit[4]]; else if (vfit[3] > -1) { if (cdelt1 < 0) cdelt2 = -cdelt1; else cdelt2 = cdelt1; } else cdelt2 = wcsf->yinc; /* Rotation angle (degrees) */ if (vfit[5] > -1) crota = v[vfit[5]]; else crota = wcsf->rot; cdx = NULL; } /* Optical axis pixel coordinates */ if (vfit[7] > -1) crpix1 = xrefpix + v[vfit[7]]; else crpix1 = wcsf->xrefpix; if (vfit[8] > -1) crpix2 = yrefpix + v[vfit[8]]; else crpix2 = wcsf->yrefpix; if (wcsreset (wcsf,crpix1,crpix2,crval1,crval2,cdelt1,cdelt2,crota,cdx)) { fprintf (stderr,"CHISQR: Cannot reset WCS!\n"); return (0.0); } /* Compute sum of squared residuals for these parameters */ chsq = 0.0; for (i = 0; i < nbin_p; i++) { wcs2pix (wcsf, gra_p[i], gdec_p[i], &xmp, &ymp, &offscale); /* if (!offscale) { */ dx = xmp - sx_p[i]; dy = ymp - sy_p[i]; chsq += dx*dx + dy*dy; /* } */ } #define TRACE_CHSQR #ifdef TRACE_CHSQR ra2str (rastr, 31, wcsf->xref, 3); dec2str (decstr, 31, wcsf->yref, 2); if (vfit[6] > -1) fprintf (stderr,"%4d: %s %s CD: %9.7f,%9.7f,%9.7f,%9.7f ", iter, rastr, decstr, wcsf->cd[0],wcsf->cd[1],wcsf->cd[2], wcsf->cd[3]); else fprintf (stderr,"%4d: %s %s %9.7f,%9.7f %8.5f ", iter, rastr, decstr, wcsf->xinc*3600.0, wcsf->yinc*3600.0, wcsf->rot); fprintf (stderr,"(%8.2f,%8.2f) -> %f\r", wcsf->xrefpix, wcsf->yrefpix, chsq); #endif return (chsq); } /* The following subroutines are based on those in Numerical Recipes in C */ /* amoeba.c */ #define ALPHA 1.0 #define BETA 0.5 #define GAMMA 2.0 void amoeba (p, y, ndim, ftol, itmax, funk, nfunk) double **p; double y[]; double ftol; int itmax; double (*funk)(); int ndim; int *nfunk; { int i,j,ilo,ihi,inhi,ndim1=ndim+1; double ytry,ysave,sum,rtol,*psum; psum = (double *) malloc ((unsigned)ndim * sizeof(double)); *nfunk = 0; for (j=0; j y[1]) { inhi = 1; ihi = 0; } else { inhi = 0; ihi = 1; } for (i = 0; i < ndim1; i++) { if (y[i] < y[ilo]) ilo=i; if (y[i] > y[ihi]) { inhi=ihi; ihi=i; } else if (y[i] > y[inhi]) if (i != ihi) inhi=i; } rtol = 2.0 * fabs(y[ihi]-y[ilo]) / (fabs(y[ihi]) + fabs(y[ilo])); if (rtol < ftol) break; if (*nfunk >= itmax) { fprintf (stderr,"Too many iterations in amoeba fit %d > %d",*nfunk,itmax); return; } ytry = amotry (p, y, psum, ndim, funk, ihi, nfunk, -ALPHA); if (ytry <= y[ilo]) ytry = amotry (p, y, psum, ndim, funk, ihi, nfunk, GAMMA); else if (ytry >= y[inhi]) { ysave = y[ihi]; ytry = amotry (p,y,psum,ndim,funk,ihi,nfunk,BETA); if (ytry >= ysave) { for (i = 0; i < ndim1; i++) { if (i != ilo) { for (j = 0; j < ndim; j++) { psum[j] = 0.5 * (p[i][j] + p[ilo][j]); p[i][j] = psum[j]; } y[i]=(*funk)(psum, *nfunk); } } *nfunk += ndim; for (j=0; j 40 * Oct 15 2001 Simplify error message * Oct 16 2001 Read minimum match to drop out of loop from lwcs.h * Oct 31 2001 Simplify innermost loop to try for more speed * Nov 1 2001 Add goff to StarMatch() arguments * Nov 5 2001 Use current WCS with no offset before trying offset matching * Nov 6 2001 Add setnitmax() to set maximum number of amoeba iterations * Nov 7 2001 Add setminbin to set minimum number of matches for fit * Nov 16 2001 Allocate slightly more than maxbin to handle dense fields * * Jul 31 2002 Add getnfit() to return current number of parameters being fit * Aug 30 2002 Fix WCSMatch() to set scale in arcsec, not degrees * * Jan 30 2003 Remove uninitialized variable in WCSMatch() * Mar 13 2003 Do not include malloc.h on Apples and Convexes * Apr 3 2003 Clean up code with lint * Nov 18 2003 Drop include of malloc.h; it is in stdlib.h * * Aug 30 2004 Declare void various external set*() calls * * Jun 19 2006 Initialize unitialized variables dxs and dys * Sep 26 2006 Increase length of rastr and destr from 16 to 32 * Oct 23 2006 Add bin array option to see if it works better * * Jan 8 2007 Drop unused variables; fix two format disagreements * Jan 11 2007 Include fitsfile.h * * Jul 20 2009 Fixed matched star wrap around RA = 0:00:00 * Jul 20 2009 Fixed matched star wrap for bad matches * * Dec 13 2009 In WCSMatch(), add last x,y,ra,dec so means are means of all * * Jun 9 2016 Fix isnum() tests for added coloned times and dashed dates */ wcstools-3.9.5/libwcs/matchstar1.c0000664000016200001660000014326311750060474016166 0ustar minkoirsys/*** File libwcs/matchstar.c *** June 19, 2006 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2006 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ /* StarMatch (ns, sx, sy, ng, gra, gdec, goff, gx, gy, tol, wcs, nfit, debug) * Find shift, scale, and rotation of image stars to best-match reference stars * * ReadMatch (filename, sx, sy, gra, gdec, debug) * Read in x, y, RA, and Dec of pre-match stars in image * * WCSMatch (nmatch, sbx, sby, gbra, gbdec, debug) * Find shift, scale, and rotation of image stars to best-match reference stars * * FitMatch (ns, sx, sy, ng, gra, gdec, gx, gy, tol, wcs, nfit, debug) * Fit shift, scale, and rotation of image stars to RA/Dec/X/Y matches * * wcs_amoeba (wcs0) Set up temp arrays and call multivariate solver * chisqr (v) Compute the chisqr of the vector v * amoeba (p, y, ndim, ftol, itmax, funk, nfunk) * Multivariate solver from Numerical Recipes */ #include #include #include #include #include "wcs.h" #include "lwcs.h" #include "wcscat.h" #define NPAR 8 #define NPAR1 9 #define ABS(a) ((a) < 0 ? (-(a)) : (a)) static void wcs_amoeba (); extern void setnofit(); extern int getfilelines(); /* Statics used by the chisqr evaluator */ static double *sx_p; static double *sy_p; static double *gra_p; static double *gdec_p; static double xref_p, yref_p; static double xrefpix, yrefpix; static int nbin_p; static int nfit; /* Number of parameters to fit */ static int pfit0 = 0; /* List of parameters to fit, 1 per digit */ static int cdfit = 0; /* 1 if CD matrix has been fit */ static int resid_refine = 0; static int minbin=2; /* Minimum number of coincidence hits needed */ static int minmatch0 = MINMATCH; /* matches to drop out of loop */ static int nitmax0 = NMAX; /* max iterations to stop fit */ static int vfit[NPAR1]; /* Parameters being fit: index to value vector 1= RA, 2= Dec, 3= X plate scale, 4= Y plate scale 5= rotation, 6= second rotation (skew), 7= optical axis X,8= optical axis Y */ /* Find shift, scale, and rotation of image stars to best-match reference stars * Get best match by finding which offsets between pairs of s's and g's * work for the most other pairs of s's and g's * N.B. we assume rotation will be "small enough" so that initial guesses can * be done using just shifts. * Return count of total coincidences found, else 0 if none or -1 if trouble. */ int StarMatch (ns,sx,sy,refcat,ng,gnum,gra,gdec,goff,gx,gy,tol,wcs,debug) int ns; /* Number of image stars */ double *sx; /* Image star X coordinates in pixels */ double *sy; /* Image star Y coordinates in pixels */ int refcat; /* Reference Catalog code */ int ng; /* Number of reference stars */ double *gnum; /* Reference star catalog numbers */ double *gra; /* Reference star right ascensions in degrees */ double *gdec; /* Reference star right ascensions in degrees */ int *goff; /* Reference star offscale flags */ double *gx; /* Reference star X coordinates in pixels */ double *gy; /* Reference star Y coordinates in pixels */ double tol; /* +/- this many pixels is a hit */ struct WorldCoor *wcs; /* World coordinate structure (fit returned) */ int debug; { double dx, bestdx, dxi; double dy, bestdy, dyi; double dx2, dy2, dxy, dxys, dxs, dys, dxsum, dysum; double *mx, *my, *mxy; int nmatch; int s, g, si, gi, igs; int nbin; double *sbx, *sby; /* malloced array of s stars in best bin */ double *gbra, *gbdec; /* malloced array of g stars in best bin */ int peaks[NPEAKS+1]; /* history of bin counts */ int dxpeaks[NPEAKS+1], dypeaks[NPEAKS+1]; /* history of dx/dy at peaks */ int npeaks; /* entries in use in peaks[] */ int maxnbin, i, nmatchd; int minmatch; int *is, *ig, *ibs, *ibg; char rastr[16], decstr[16], numstr[16]; double xref0, yref0, xinc0, yinc0, rot0, xrefpix0, yrefpix0, cd0[4]; int bestbin; /* Number of coincidences for refit */ int pfit; /* List of parameters to fit, 1 per digit */ char vpar[16]; /* List of parameters to fit */ char *vi; char vc; int ParamFit(); double tol2 = tol * tol; double maxnum; int nnfld = 0; /* Set minimum number of matches between image and reference stars to fit */ if (ns > ng) { minmatch = 0.5 * ng; if (minmatch > minmatch0) minmatch = 0.25 * ng; if (minmatch > minmatch0) minmatch = minmatch0; } else { minmatch = 0.5 * ns; if (minmatch > minmatch0) minmatch = 0.25 * ns; if (minmatch > minmatch0) minmatch = minmatch0; } /* Set format for numbers, if listed */ if (debug) { maxnum = gnum[0]; for (gi = 1; gi < ng; gi++) { if (gnum[gi] > maxnum) maxnum = gnum[gi]; } nnfld = CatNumLen (refcat, maxnum, 0); } /* Set maximum number of matches and allocate match indices */ if (ng > ns) maxnbin = (int) ((double) ng * 1.25); else maxnbin = (int) ((double) ns * 1.25); if (debug) fprintf (stderr,"Match history: nim=%d nref=%d tol=%3.0f minbin=%d minmatch=%d):\n", ns, ng, tol, minbin, minmatch); /* Allocate arrays in which to save match information */ mx = (double *) calloc (maxnbin, sizeof(double)); my = (double *) calloc (maxnbin, sizeof(double)); mxy = (double *) calloc (maxnbin, sizeof(double)); is = (int *) calloc (maxnbin, sizeof(int)); ig = (int *) calloc (maxnbin, sizeof(int)); ibs = (int *) calloc (maxnbin, sizeof(int)); ibg = (int *) calloc (maxnbin, sizeof(int)); /* Try matching stars using the current WCS first */ nmatch = 0; bestdx = 0.0; bestdy = 0.0; dxsum = 0.0; dysum = 0.0; dxs = 0.0; dys = 0.0; /* Loop through image stars */ nbx = nxpix / (int) tol; nby = nypix / (int) tol; dbin = calloc (4 * nbx * nby, sizeof(double)); for (s = 0; s < ns; s++) { /* Loop through reference catalog stars */ for (g = 0; g < ng; g++) { dx = gx[g] - sx[s]; dy = gy[g] - sy[s]; /* Add to number in this offset bin */ idx = (dx / tol) idy = (dy / tol) if ((idx > -nbx && idx < nbx && idy > -nby && idy < nby) dbin[((idy+nby) * nbx) + idx + nbx]++; } } /* Find offset bin with maximim number of entries idxmax = 0; idymax = 0; nmatch = 0; dbini = dbin for (idy = -nby; idy < nby; idy++) { for (idx = -nbx; idx < nbx; idx++) { if (*dbini > ndmax) { idxmax = idx; idymax - idy; nmatch = *dbini; } dbini++; } } bestdx = tol * (double) (idxmax + nbx); bestdy = tol * (double) (idymax + nby); /* If we found enough matches, we can proceed with this offset */ if (nmatch > minmatch) { if (debug) fprintf (stderr, "%d matches found at mean offset %6.3f %6.3f\n", nmatch, bestdx, bestdy); } /* Otherwise, look for a coarse alignment assuming no additional rotation. * This will collect a set of stars that correspond and * establish an initial guess of the solution. */ else { npeaks = 0; nmatch = 0; for (i = 0; i < NPEAKS; i++) { peaks[i] = 0; dxpeaks[i] = 0; dypeaks[i] = 0; } bestdx = 0.0; bestdy = 0.0; for (s = 0; s < ns; s++) { for (g = 0; g < ng; g++) { dx = gx[g] - sx[s]; dy = gy[g] - sy[s]; nbin = 0; for (gi = 0; gi < ng; gi++) { for (si = 0; si < ns; si++) { dxi = gx[gi] - sx[si] - dx; if (dxi < 0) dxi = -dxi; dyi = gy[gi] - sy[si] - dy; if (dyi < 0) dyi = -dyi; if (dxi <= tol && dyi <= tol) { /* if (debug) fprintf (stderr,"%d %d %d %d %5.1f %5.1f %5.1f %5.1f\n", g,s,gi,si,dx,dy,dxi,dyi); */ is[nbin] = si; ig[nbin] = gi; nbin++; } } } /* if (debug) fprintf (stderr,"%d %d %d %d %d\n", g,s,gi,si,nbin); */ if (nbin > 1 && nbin >= nmatch) { int i; nmatch = nbin; bestdx = (double) dx; bestdy = (double) dy; for (i = 0; i < nbin; i++) { ibs[i] = is[i]; ibg[i] = ig[i]; } /* keep last NPEAKS nmatchs, dx and dy; * put newest first in arrays */ if (npeaks > 0) { for (i = npeaks; i > 0; i--) { peaks[i] = peaks[i-1]; dxpeaks[i] = dxpeaks[i-1]; dypeaks[i] = dypeaks[i-1]; } } peaks[0] = nmatch; if (bestdx > 0.0) dxpeaks[0] = (int) (bestdx + 0.5); else dxpeaks[0] = (int) (bestdx - 0.5); if (bestdy > 0) dypeaks[0] = (int) (bestdy + 0.5); else dypeaks[0] = (int) (bestdy - 0.5); if (npeaks < NPEAKS) npeaks++; if (debug) fprintf (stderr,"%d: %d/%d matches at image %d cat %d: dx= %d dy= %d\n", npeaks, nmatch, minmatch, s, g, dxpeaks[0], dypeaks[0]); } if (nmatch > minmatch) break; } if (nmatch > minmatch) break; } /* if (debug) { int i; for (i = 0; i < npeaks; i++) fprintf (stderr," %d bins at dx=%d dy=%d\n", peaks[i], dxpeaks[i], dypeaks[i]); } */ /* peak is broad */ if (npeaks < 2 || peaks[1] == peaks[0]) { if (debug) fprintf (stderr," Broad peak of %d bins at dx=%.0f dy=%.0f\n", peaks[0], bestdx, bestdy); } } /* too few hits */ if (nmatch < minbin) return (nmatch); /* Get X and Y coordinates of matches from best binning */ nmatchd = nmatch * sizeof (double); if (!(sbx = (double *) malloc (nmatchd))) fprintf (stderr," Could not allocate %d bytes for SBX\n", nmatchd); if (!(sby = (double *) malloc (nmatchd))) fprintf (stderr," Could not allocate %d bytes for SBY\n", nmatchd); if (!(gbra = (double *) malloc (nmatchd))) fprintf (stderr," Could not allocate %d bytes for GBRA\n", nmatchd); if (!(gbdec = (double *) malloc (nmatchd))) fprintf (stderr," Could not allocate %d bytes for GBDEC\n", nmatchd); for (i = 0; i < nmatch; i++) { sbx[i] = sx[ibs[i]]; sby[i] = sy[ibs[i]]; gbra[i] = gra[ibg[i]]; gbdec[i] = gdec[ibg[i]]; } /* Reset image center based on star matching */ wcs->xref = wcs->xref + (bestdx * wcs->xinc); if (wcs->xref < 0.0) wcs->xref = 360.0 + wcs->xref; wcs->yref = wcs->yref + (bestdy * wcs->yinc); /* Fit WCS to matched stars */ /* Provide non-parametric access to the star lists */ sx_p = sbx; sy_p = sby; gra_p = gbra; gdec_p = gbdec; xref_p = wcs->xref; yref_p = wcs->yref; xrefpix = wcs->xrefpix; yrefpix = wcs->yrefpix; nbin_p = nmatch; /* Number of parameters to fit from command line or number of matches */ pfit = ParamFit (nmatch); /* Get parameters to fit from digits of pfit */ sprintf (vpar, "%d", pfit); nfit = 0; vfit[0] = -1; for (i = 1; i < NPAR1; i++) { vc = i + 48; vi = strchr (vpar, vc); if (vi != NULL) { vfit[i] = vi - vpar; nfit++; } else vfit[i] = -1; } /* Set initial guesses for parameters which are being fit */ xref0 = wcs->xref; yref0 = wcs->yref; xinc0 = wcs->xinc; yinc0 = wcs->yinc; rot0 = wcs->rot; xrefpix0 = wcs->xrefpix; yrefpix0 = wcs->yrefpix; cd0[0] = wcs->cd[0]; cd0[1] = wcs->cd[1]; cd0[2] = wcs->cd[2]; cd0[3] = wcs->cd[3]; if (vfit[6] > -1) cdfit = 1; else cdfit = 0; /* Fit image star coordinates to reference star positions */ wcs_amoeba (wcs); if (debug) { fprintf (stderr,"\nAmoeba fit:\n"); ra2str (rastr, 16, xref0, 3); dec2str (decstr, 16, yref0, 2); fprintf (stderr," initial guess:\n"); if (vfit[6] > -1) fprintf (stderr," cra= %s cdec= %s cd = %9.7f,%9.7f,%9.7f,%9.7f ", rastr, decstr, cd0[0], cd0[1], cd0[2], cd0[3]); else fprintf (stderr," cra= %s cdec= %s del=%7.4f,%7.4f rot=%7.4f ", rastr, decstr, xinc0*3600.0, yinc0*3600.0, rot0); fprintf (stderr,"(%8.2f,%8.2f\n", xrefpix0, yrefpix0); ra2str (rastr, 16, wcs->xref, 3); dec2str (decstr, 16, wcs->yref, 2); fprintf (stderr,"\nfirst solution:\n"); if (vfit[6] > -1) fprintf (stderr," cra= %s cdec= %s cd = %9.7f,%9.7f,%9.7f,%9.7f ", rastr,decstr,wcs->cd[0],wcs->cd[1],wcs->cd[2],wcs->cd[3]); else fprintf (stderr," cra= %s cdec= %s del=%7.4f,%7.4f rot=%7.4f ", rastr,decstr,3600.0*wcs->xinc,3600.0*wcs->yinc,wcs->rot); fprintf (stderr,"(%8.2f,%8.2f)\n", wcs->xrefpix, wcs->yrefpix); } /* If we have extra bins, repeat with the best ones */ bestbin = nfit + 1; if (resid_refine && nmatch > bestbin) { double *resid = (double *) malloc (nmatch * sizeof(double)); double *xe = (double *) malloc (nmatch * sizeof(double)); double *ye = (double *) malloc (nmatch * sizeof(double)); int i, j; double xmean, ymean, rmean, xsumsq, ysumsq, diff; double mx, my, xsig, ysig, rsig, siglim; char wcstring[64]; double xsum = 0.0; double ysum = 0.0; double rsum = 0.0; double dmatch = (double)nmatch; double dmatch1 = (double)(nmatch - 1); /* Compute residuals at each star location */ for (i = 0; i < nmatch; i++) { pix2wcs (wcs, sbx[i], sby[i], &mx, &my); xe[i] = (mx - gbra[i]) * 3600.0; ye[i] = (my - gbdec[i]) * 3600.0; resid[i] = sqrt (xe[i]*xe[i] + ye[i]*ye[i]); if (debug) { pix2wcst (wcs, sbx[i], sby[i], wcstring, 64); fprintf (stderr,"%3d (%8.3f,%8.3f) -> %s %6.3f %6.3f %6.3f\n", i, sbx[i], sby[i], wcstring, xe[i], ye[i], resid[i]); } xsum = xsum + xe[i]; ysum = ysum + ye[i]; rsum = rsum + resid[i]; } /* Compute means and standard deviations */ xmean = xsum / dmatch; ymean = ysum / dmatch; rmean = rsum / dmatch; xsumsq = 0.0; ysumsq = 0.0; for (i = 0; i < nmatch; i++) { diff = xe[i] - xmean; xsumsq = xsumsq + (diff * diff); diff = ye[i] - ymean; ysumsq = ysumsq + (diff * diff); } xsig = sqrt (xsumsq / dmatch1); ysig = sqrt (ysumsq / dmatch1); rsig = sqrt ((xsumsq + ysumsq)/ dmatch1); siglim = 2.0 * rsig; if (debug) { fprintf (stderr,"Mean x: %6.3f/%6.3f y: %6.3f/%6.3f r: %6.3f/%6.3f\n", xmean, xsig, ymean, ysig, rmean, rsig); } /* sort by increasing total residual */ for (i = 0; i < nmatch-1; i++) { for (j = i+1; j < nmatch; j++) { if (resid[j] < resid[i]) { double tmp; tmp = sbx[i]; sbx[i] = sbx[j]; sbx[j] = tmp; tmp = sby[i]; sby[i] = sby[j]; sby[j] = tmp; tmp = gbra[i]; gbra[i] = gbra[j]; gbra[j] = tmp; tmp = gbdec[i]; gbdec[i] = gbdec[j]; gbdec[j] = tmp; tmp = resid[i]; resid[i] = resid[j]; resid[j] = tmp; } } } /* Cut off points at residual of two sigma */ for (i = 0; i < nmatch; i++) { if (resid[i] > siglim) { if (i > bestbin) bestbin = i - 1; break; } } xref_p = wcs->xref; if (xref_p < 0.0) xref_p = 360.0 + xref_p; yref_p = wcs->yref; xrefpix = wcs->xrefpix; yrefpix = wcs->yrefpix; nbin_p = bestbin; wcs_amoeba (wcs); if (debug) { ra2str (rastr, 16, wcs->xref, 3); dec2str (decstr, 16, wcs->yref, 2); fprintf (stderr,"\nresid solution:\n"); fprintf (stderr,"\n%d points < %.3f arcsec residuals refit\n", bestbin, siglim); fprintf (stderr," cra= %s cdec= %s del=%7.4f,%7.4f rot=%7.4f ", rastr, decstr, 3600.0*wcs->xinc, 3600.0*wcs->yinc, wcs->rot); fprintf (stderr,"(%8.2f,%8.2f)\n", wcs->xrefpix, wcs->yrefpix); } free (resid); free (xe); free (ye); } free (sbx); free (sby); free (gbra); free (gbdec); free (is); free (ig); free (ibs); free (ibg); return (nmatch); } int ParamFit (nbin) int nbin; /* Number of point to be fit */ { int pfit; if (pfit0 != 0) { if (pfit0 < 3) pfit = 12; else if (pfit0 == 3) /* Fit center and plate scale */ pfit = 123; else if (pfit0 == 4) /* Fit center, plate scale, rotation */ pfit = 1235; else if (pfit0 == 5) /* Fit center, x&y plate scales, rotation */ pfit = 12345; else if (pfit0 == 6) /* Fit center, x&y plate scales, x&y rotations */ pfit = 123456; else if (pfit0 == 7) /* Fit center, x&y plate scales, rotation, refpix */ pfit = 1234578; else if (pfit0 == 8) /* Fit center, x&y plate scales, x&y rotation, refpix */ pfit = 12345678; else pfit = pfit0; } else if (nbin < 4) pfit = 12; else if (nbin < 6) pfit = 123; else pfit = 12345; return (pfit); } int NParamFit (nbin) int nbin; /* Number of point to be fit */ { int pfit; pfit = ParamFit (nbin); if (pfit < 1) return (0); else if (pfit < 10) return (1); else if (pfit < 100) return (2); else if (pfit < 1000) return (3); else if (pfit < 10000) return (4); else if (pfit < 100000) return (5); else if (pfit < 1000000) return (6); else if (pfit < 10000000) return (7); else return (8); } int ReadMatch (filename, sx, sy, sra, sdec, debug) char *filename; /* Name of file containing matches */ double **sx; /* Image star X coordinates in pixels */ double **sy; /* Image star Y coordinates in pixels */ double **sra; /* Probable image star right ascensions in degrees */ double **sdec; /* Probable image star declinations in degrees */ int debug; /* Printed debugging information if not zero */ { int nbytes, nread, ir, ntok, itok, iytok; double *tx, *ty, *tra, *tdec, ra, dec, x, y; int ndec; int nmatch = 0; /* Number of matches read from file */ char rastr[32], decstr[32]; /* If tab file, read from ra, dec, x, y columns */ if (istab (filename)) { } /* Otherwise, assume first 4 columns are x, y, ra, dec */ else { char line[1025]; char *nextline, *lastchar; FILE *fd; struct Tokens tokens; /* Token structure */ char *cwhite; /* additional whitespace characters */ char token[256]; cwhite = NULL; /* Open input file */ if (!strcmp (filename, "stdin")) { fd = stdin; nread = 1000; } else { nread = getfilelines (filename); if (!(fd = fopen (filename, "r"))) { fprintf (stderr, "SetWCSFITS: Match file %s could not be opened\n", filename); return (0); } } nbytes = nread * sizeof (double); if (!(tra = (double *) calloc (nread, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gra\n", nbytes); if (!(tdec = (double *) calloc (nread, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for gdec\n", nbytes); if (!(tx = (double *) calloc (nread, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for sx\n", nbytes); if (!(ty = (double *) calloc (nread, sizeof(double)))) fprintf (stderr, "Could not calloc %d bytes for sy\n", nbytes); *sra = tra; *sdec = tdec; *sx = tx; *sy = ty; nmatch = 0; nextline = line; for (ir = 0; ir < nread; ir++) { if (fgets (line, 1024, fd) == NULL) break; /* Skip lines with comments */ if (line[0] == '#') continue; /* Drop linefeeds */ lastchar = nextline + strlen(nextline) - 1; if (*lastchar < 32) *lastchar = (char) 0; /* Read X, Y, RA, and Dec from each line, skipping line if all four are not present and numbers */ ntok = setoken (&tokens, line, cwhite); if (ntok < 1) break; if (ntok < 4) continue; /* if (debug) fprintf (stderr, "%d: %s\n", nmatch, line); */ /* Image X coordinate or RA */ itok = 1; if (getoken(&tokens, itok, token, 256)) { /* Read RA, Dec, X, Y if first token has : in it */ if (strchr (token, ':') != NULL) { ra = str2ra (token); iytok = 4; if (getoken(&tokens, 2, token, 256)) dec = str2dec (token); if (getoken(&tokens, 3, token, 256)) { if (isnum (token)) x = atof (token); else { iytok = 5; if (getoken(&tokens, 4, token, 256)) { if (isnum (token)) x = atof (token); else continue; } } } if (getoken(&tokens, iytok, token, 256)) { if (isnum (token)) y = atof (token); else continue; } tx[nmatch] = x; ty[nmatch] = y; tra[nmatch] = ra; tdec[nmatch] = dec; nmatch++; continue; } if (isnum (token)) x = atof (token); else continue; } else continue; /* Image Y coordinate */ itok++; if (getoken(&tokens, itok, token, 256)) { if (isnum (token)) y = atof (token); else continue; } else continue; /* Right ascension */ itok++; if (getoken(&tokens, itok, token, 256)) { if (isnum (token) == 1) { ra = atof (token); itok++; if (getoken(&tokens, itok, token, 256)) { if (isnum (token) == 2) ra = ra + (atof (token) / 60.0); else if (isnum (token) == 1) { ra = ra + (atof (token) / 60.0); itok++; if (getoken(&tokens, itok, token, 256)) { if (isnum (token)) ra = ra + (atof (token) / 3600.0); } } } ra = ra * 15.0; } else ra = str2ra (token); } else continue; /* Declination */ itok++; if (getoken(&tokens, itok, token, 256)) { if (isnum (token) == 1) { dec = atof (token); itok++; if (strchr (token, '-') != NULL) ndec = 1; else ndec = 0; if (getoken(&tokens, itok, token, 256)) { if (isnum (token) == 2) { if (ndec) dec = dec - (atof (token) / 60.0); else dec = dec + (atof (token) / 60.0); } else if (isnum (token) == 1) { if (ndec) dec = dec - (atof (token) / 60.0); else dec = dec + (atof (token) / 60.0); itok++; if (getoken(&tokens, itok, token, 256)) { if (isnum (token)) { if (ndec) dec = dec - (atof (token) / 3600.0); else dec = dec + (atof (token) / 3600.0); } } } } } else dec = str2dec (token); } else continue; tx[nmatch] = x; ty[nmatch] = y; tra[nmatch] = ra; tdec[nmatch] = dec; if (debug) { ra2str (rastr, 32, tra[nmatch], 3); dec2str (decstr, 32, tdec[nmatch], 2); fprintf (stderr, "%d: %8.3f %8.3f %s %s\n", nmatch, tx[nmatch], ty[nmatch], rastr, decstr); } nmatch++; } } return (nmatch); } /* Find shift, scale, and rotation of image stars to best-match reference stars */ void WCSMatch (nmatch, sbx, sby, gbra, gbdec, debug) int nmatch; /* Number of matched stars */ double *sbx; /* Image star X coordinates in pixels */ double *sby; /* Image star Y coordinates in pixels */ double *gbra; /* Reference star right ascensions in degrees */ double *gbdec; /* Reference star right ascensions in degrees */ int debug; /* Printed debugging information if not zero */ { int i; double xdiff, ydiff; int nsc, j; double tx = 0.0; double ty = 0.0; double tra = 0.0; double tdec = 0.0; double tdiff = 0.0; double cra, cdec, cx, cy, scale; double dmatch; double skydiff, imdiff; extern double getsecpix(); extern void getcenter(),getrefpix(),setdcenter(),setrefpix(),setsecpix(); dmatch = (double) nmatch; if (debug) { fprintf (stderr,"%d matched stars:\n", nmatch); } /* too few hits */ if (nmatch < 2) return; /* Compute plate scale and center of stars */ nsc = 0; for (i = 0; i < nmatch; i++) { tx = tx + sbx[i]; ty = ty + sby[i]; tra = tra + gbra[i]; tdec = tdec + gbdec[i]; for (j = i+1; j < nmatch; j++) { skydiff = wcsdist (gbra[i], gbdec[i], gbra[j], gbdec[j]); xdiff = sbx[j] - sbx[i]; ydiff = sby[j] - sby[i]; imdiff = sqrt ((xdiff * xdiff) + (ydiff * ydiff)); scale = skydiff / imdiff; tdiff = tdiff + scale; nsc++; if (debug) { fprintf (stderr,"%d %d: sky: %8g, image: %8g, %8g deg/pix", i, j, skydiff, imdiff, scale); fprintf (stderr," = %8g arcsec/pix\n", scale * 3600.0); } } } /* Reset image center based on star matching */ getcenter (&cra, &cdec); if (cra == -99.0 && cdec == -99.0) { cra = tra / dmatch; cdec = tdec / dmatch; setdcenter (cra, cdec); } getrefpix (&cx, &cy); if (cx == -99999.0) { cx = tx / dmatch; cy = ty / dmatch; setrefpix (cx, cy); } scale = getsecpix(); if (scale == 0.0) { scale = tdiff / (double) nsc; setsecpix (3600.0 * scale); } if (debug) fprintf (stderr,"scale = %8g deg/pix = %8g arcsec/pix\n", scale, scale*3600.0); return; } /* Find shift, scale, and rotation of image stars to best-match reference stars * Return count of total coincidences found, else 0 if none or -1 if trouble. */ int FitMatch (nmatch, sbx, sby, gbra, gbdec, wcs, debug) int nmatch; /* Number of matched stars */ double *sbx; /* Image star X coordinates in pixels */ double *sby; /* Image star Y coordinates in pixels */ double *gbra; /* Reference star right ascensions in degrees */ double *gbdec; /* Reference star right ascensions in degrees */ struct WorldCoor *wcs; /* World coordinate structure (fit returned) */ int debug; /* Printed debugging information if not zero */ { int i; char rastr[16], decstr[16]; double xref0, yref0, xinc0, yinc0, rot0, xrefpix0, yrefpix0, cd0[4]; int bestbin; /* Number of coincidences for refit */ int pfit; /* List of parameters to fit, 1 per digit */ char vpar[16]; /* List of parameters to fit */ double xdiff, ydiff; char *vi; char vc; int nsc, j; /* double equinox = wcs->equinox; */ double tx = 0.0; double ty = 0.0; double tra = 0.0; double tdec = 0.0; double tdiff = 0.0; double scale; /* double dmatch; */ double skydiff, imdiff; /* dmatch = (double) nmatch; */ if (debug) { fprintf (stderr,"%d matched stars:\n", nmatch); } /* too few hits */ if (nmatch < minbin) return (nmatch); /* Compute plate scale and center of stars */ nsc = 0; for (i = 0; i < nmatch; i++) { tx = tx + sbx[i]; ty = ty + sby[i]; tra = tra + gbra[i]; tdec = tdec + gbdec[i]; for (j = i+1; j < nmatch; j++) { skydiff = wcsdist (gbra[i], gbdec[i], gbra[j], gbdec[j]); xdiff = sbx[j] - sbx[i]; ydiff = sby[j] - sby[i]; imdiff = sqrt ((xdiff * xdiff) + (ydiff * ydiff)); scale = skydiff / imdiff; tdiff = tdiff + scale; nsc++; if (debug) { fprintf (stderr,"%d %d: sky: %8g, image: %8g, %8g deg/pix", i, j, skydiff, imdiff, scale); fprintf (stderr," = %8g arcsec/pix\n", scale * 3600.0); } } } /* Reset image center in WCS data structure based on star matching */ /* cra = tra / dmatch; cdec = tdec / dmatch; cx = tx / dmatch; cy = ty / dmatch; scale = tdiff / (double) nsc; if (debug) fprintf (stderr,"scale = %8g deg/pix = %8g arcsec/pix\n", scale, scale*3600.0); wcsreset (wcs, cx, cy, cra, cdec, scale, 0.0, 0.0, NULL, equinox); */ /* Provide non-parametric access to the star lists */ sx_p = sbx; sy_p = sby; gra_p = gbra; gdec_p = gbdec; xref_p = wcs->xref; if (xref_p < 0.0) xref_p = 360.0 + xref_p; yref_p = wcs->yref; xrefpix = wcs->xrefpix; yrefpix = wcs->yrefpix; nbin_p = nmatch; /* Number of parameters to fit from command line or number of matches */ if (pfit0 != 0) { if (pfit0 < 3) pfit = 12; else if (pfit0 == 3) /* Fit center and plate scale */ pfit = 123; else if (pfit0 == 4) /* Fit center, plate scale, rotation */ pfit = 1235; else if (pfit0 == 5) /* Fit center, x&y plate scales, rotation */ pfit = 12345; else if (pfit0 == 6) /* Fit center, x&y plate scales, x&y rotations */ pfit = 123456; else if (pfit0 == 7) /* Fit center, x&y plate scales, rotation, refpix */ pfit = 1234578; else if (pfit0 == 8) /* Fit center, x&y plate scales, x&y rotation, refpix */ pfit = 12345678; else pfit = pfit0; } else if (nmatch < 4) pfit = 12; else if (nmatch < 6) pfit = 123; else pfit = 12345; /* Get parameters to fit from digits of pfit */ sprintf (vpar, "%d", pfit); nfit = 0; vfit[0] = -1; for (i = 1; i < NPAR1; i++) { vc = i + 48; vi = strchr (vpar, vc); if (vi != NULL) { vfit[i] = vi - vpar; nfit++; } else vfit[i] = -1; } /* Set initial guesses for parameters which are being fit */ xref0 = wcs->xref; yref0 = wcs->yref; xinc0 = wcs->xinc; yinc0 = wcs->yinc; rot0 = wcs->rot; xrefpix0 = wcs->xrefpix; yrefpix0 = wcs->yrefpix; cd0[0] = wcs->cd[0]; cd0[1] = wcs->cd[1]; cd0[2] = wcs->cd[2]; cd0[3] = wcs->cd[3]; if (vfit[6] > -1) cdfit = 1; else cdfit = 0; /* Fit image star coordinates to reference star positions */ wcs_amoeba (wcs); if (debug) { fprintf (stderr,"\nAmoeba fit:\n"); ra2str (rastr, 16, xref0, 3); dec2str (decstr, 16, yref0, 2); fprintf (stderr," initial guess:\n"); if (vfit[6] > -1) fprintf (stderr," cra= %s cdec= %s cd = %9.7f,%9.7f,%9.7f,%9.7f ", rastr, decstr, cd0[0], cd0[1], cd0[2], cd0[3]); else fprintf (stderr," cra= %s cdec= %s del=%7.4f,%7.4f rot=%7.4f ", rastr, decstr, xinc0*3600.0, yinc0*3600.0, rot0); fprintf (stderr,"(%8.2f,%8.2f\n", xrefpix0, yrefpix0); ra2str (rastr, 16, wcs->xref, 3); dec2str (decstr, 16, wcs->yref, 2); fprintf (stderr,"\nfirst solution:\n"); if (vfit[6] > -1) fprintf (stderr," cra= %s cdec= %s cd = %9.7f,%9.7f,%9.7f,%9.7f ", rastr,decstr,wcs->cd[0],wcs->cd[1],wcs->cd[2],wcs->cd[3]); else fprintf (stderr," cra= %s cdec= %s del=%7.4f,%7.4f rot=%7.4f ", rastr,decstr,3600.0*wcs->xinc,3600.0*wcs->yinc,wcs->rot); fprintf (stderr,"(%8.2f,%8.2f)\n", wcs->xrefpix, wcs->yrefpix); } /* If we have extra bins, repeat with the best ones */ bestbin = nfit + 1; if (resid_refine && nmatch > bestbin) { double *resid = (double *) malloc (nmatch * sizeof(double)); double *xe = (double *) malloc (nmatch * sizeof(double)); double *ye = (double *) malloc (nmatch * sizeof(double)); int i, j; double xmean, ymean, rmean, xsumsq, ysumsq, diff; double mra, mdec, xsig, ysig, rsig, siglim; char wcstring[64]; double xsum = 0.0; double ysum = 0.0; double rsum = 0.0; double dmatch = (double)nmatch; double dmatch1 = (double)(nmatch - 1); /* Compute residuals at each star location */ for (i = 0; i < nmatch; i++) { pix2wcs (wcs, sbx[i], sby[i], &mra, &mdec); xe[i] = (mra - gbra[i]) * 3600.0; ye[i] = (mdec - gbdec[i]) * 3600.0; resid[i] = sqrt (xe[i]*xe[i] + ye[i]*ye[i]); if (debug) { pix2wcst (wcs, sbx[i], sby[i], wcstring, 64); fprintf (stderr,"%3d (%8.3f,%8.3f) -> %s %6.3f %6.3f %6.3f\n", i, sbx[i], sby[i], wcstring, xe[i], ye[i], resid[i]); } xsum = xsum + xe[i]; ysum = ysum + ye[i]; rsum = rsum + resid[i]; } /* Compute means and standard deviations */ xmean = xsum / dmatch; ymean = ysum / dmatch; rmean = rsum / dmatch; xsumsq = 0.0; ysumsq = 0.0; for (i = 0; i < nmatch; i++) { diff = xe[i] - xmean; xsumsq = xsumsq + (diff * diff); diff = ye[i] - ymean; ysumsq = ysumsq + (diff * diff); } xsig = sqrt (xsumsq / dmatch1); ysig = sqrt (ysumsq / dmatch1); rsig = sqrt ((xsumsq + ysumsq)/ dmatch1); siglim = 2.0 * rsig; if (debug) { fprintf (stderr,"Mean x: %6.3f/%6.3f y: %6.3f/%6.3f r: %6.3f/%6.3f\n", xmean, xsig, ymean, ysig, rmean, rsig); } /* sort by increasing total residual */ for (i = 0; i < nmatch-1; i++) { for (j = i+1; j < nmatch; j++) { if (resid[j] < resid[i]) { double tmp; tmp = sbx[i]; sbx[i] = sbx[j]; sbx[j] = tmp; tmp = sby[i]; sby[i] = sby[j]; sby[j] = tmp; tmp = gbra[i]; gbra[i] = gbra[j]; gbra[j] = tmp; tmp = gbdec[i]; gbdec[i] = gbdec[j]; gbdec[j] = tmp; tmp = resid[i]; resid[i] = resid[j]; resid[j] = tmp; } } } /* Cut off points at residual of two sigma */ for (i = 0; i < nmatch; i++) { if (resid[i] > siglim) { if (i > bestbin) bestbin = i - 1; break; } } xref_p = wcs->xref; if (xref_p < 0.0) xref_p = 360.0 + xref_p; yref_p = wcs->yref; xrefpix = wcs->xrefpix; yrefpix = wcs->yrefpix; nbin_p = bestbin; wcs_amoeba (wcs); if (debug) { ra2str (rastr, 16, wcs->xref, 3); dec2str (decstr, 16, wcs->yref, 2); fprintf (stderr,"\nresid solution:\n"); fprintf (stderr,"\n%d points < %.3f arcsec residuals refit\n", bestbin, siglim); fprintf (stderr," cra= %s cdec= %s del=%7.4f,%7.4f rot=%7.4f ", rastr, decstr, 3600.0*wcs->xinc, 3600.0*wcs->yinc, wcs->rot); fprintf (stderr,"(%8.2f,%8.2f)\n", wcs->xrefpix, wcs->yrefpix); } free (resid); free (xe); free (ye); } return (nmatch); } struct WorldCoor *wcsf; static double wcs_chisqr (); /* From Numerical Recipes */ void amoeba(); static double amotry(); /* Set up the necessary temp arrays and call the amoeba() multivariate solver */ static void wcs_amoeba (wcs0) struct WorldCoor *wcs0; { double *p[NPAR1]; /* used as p[NPAR1][NPAR] */ double vguess[NPAR], vp[NPAR], vdiff[NPAR]; double p0[NPAR], p1[NPAR], p2[NPAR], p3[NPAR], p4[NPAR], p5[NPAR], p6[NPAR], p7[NPAR], p8[NPAR]; /* used as px[0..NPAR-1] */ double y[NPAR1]; /* used as y[1..NPAR] */ double xinc1, yinc1, xrefpix1, yrefpix1, rot, cd[4]; double sumx, sumy, sumr; int iter; int i, j; int nfit1; char rastr[16],decstr[16]; int nitmax; nitmax = nitmax0; if (nfit > NPAR) nfit = NPAR; nfit1 = nfit + 1; wcsf = wcs0; /* Initialize guess and difference vectors to zero */ for (i = 0; i < NPAR; i++) { vguess[i] = 0.0; vdiff[i] = 0.0; } /* Optical axis center (RA and Dec degrees) */ if (vfit[1] > -1) { vguess[vfit[1]] = 0.0; vdiff[vfit[1]] = 5.0 * wcsf->xinc; } if (vfit[2] > -1) { vguess[vfit[2]] = 0.0; vdiff[vfit[2]] = 5.0 * wcsf->yinc; } /* Second rotation about optical axis (degrees) -> CD matrix */ if (vfit[6] > -1) { wcsf->rotmat = 1; vguess[vfit[3]] = wcsf->cd[0]; vdiff[vfit[3]] = wcsf->xinc * 0.03; vguess[vfit[4]] = wcsf->cd[1]; vdiff[vfit[4]] = wcsf->yinc * 0.03; vguess[vfit[5]] = wcsf->cd[2]; vdiff[vfit[5]] = wcsf->xinc * 0.03; vguess[vfit[6]] = wcsf->cd[3]; vdiff[vfit[6]] = wcsf->yinc * 0.03; } else { /* Plate scale at optical axis right ascension or both (degrees/pixel) */ if (vfit[3] > -1) { vguess[vfit[3]] = wcsf->xinc; vdiff[vfit[3]] = wcsf->xinc * 0.03; } /* Plate scale in declination at optical axis (degrees/pixel) */ if (vfit[4] > -1) { vguess[vfit[4]] = wcsf->yinc; vdiff[vfit[4]] = wcsf->yinc * 0.03; } /* Rotation about optical axis in degrees */ if (vfit[5] > -1) { vguess[vfit[5]] = wcsf->rot; vdiff[vfit[5]] = 0.5; } } /* Reference pixel (optical axis) */ if (vfit[7] > -1) { vguess[vfit[7]] = 0.0; vdiff[vfit[7]] = 10.0; } if (vfit[8] > -1) { vguess[vfit[8]] = 0.0; vdiff[vfit[8]] = 10.0; } /* Set up matrix of nfit+1 initial guesses. * The supplied guess, plus one for each parameter altered by a small amount */ p[0] = p0; if (nfit > 0) p[1] = p1; if (nfit > 1) p[2] = p2; if (nfit > 2) p[3] = p3; if (nfit > 3) p[4] = p4; if (nfit > 4) p[5] = p5; if (nfit > 5) p[6] = p6; if (nfit > 6) p[7] = p7; if (nfit > 7) p[8] = p8; for (i = 0; i <= nfit; i++) { for (j = 0; j < nfit; j++) p[i][j] = vguess[j]; if (i > 0 && i <= nfit) p[i][i-1] = vguess[i-1] + vdiff[i-1]; y[i] = wcs_chisqr (p[i], -i); } #define PDUMP #ifdef PDUMP fprintf (stderr,"Before:\n"); for (i = 0; i < nfit1; i++) { if (vfit[1] > -1) ra2str (rastr, 16, p[i][vfit[1]] + xref_p, 3); else ra2str (rastr, 16, wcsf->xref, 3); if (vfit[2] > -1) dec2str (decstr, 16, p[i][vfit[2]]+yref_p, 2); else dec2str (decstr, 16, wcsf->yref, 2); if (vfit[6] > -1) { cd[0] = p[i][vfit[3]]; cd[1] = p[i][vfit[4]]; cd[2] = p[i][vfit[5]]; cd[3] = p[i][vfit[6]]; fprintf (stderr,"%d: %s %s CD: %7.5f,%7.5f,%7.5f,%7.5f ", i, rastr, decstr, cd[0],cd[1],cd[2],cd[3]); } else { if (vfit[3] > -1) xinc1 = p[i][vfit[3]]; else xinc1 = wcsf->xinc; if (vfit[4] > -1) yinc1 = p[i][vfit[4]]; else if (vfit[3] > -1) { if (xinc1 < 0) yinc1 = -xinc1; else yinc1 = xinc1; } else yinc1 = wcsf->yinc; if (vfit[5] > -1) rot = p[i][vfit[5]]; else rot = wcsf->rot; fprintf (stderr,"%d: %s %s del=%6.4f,%6.4f rot=%5.3f ", i, rastr, decstr, 3600.0*xinc1, 3600.0*yinc1, rot); } if (vfit[7] > -1) xrefpix1 = xrefpix + p[i][vfit[7]]; else xrefpix1 = wcsf->xrefpix; if (vfit[8] > -1) yrefpix1 = yrefpix + p[i][vfit[8]]; else yrefpix1 = wcsf->yrefpix; fprintf (stderr,"(%8.2f,%8.2f) y=%g\n", xrefpix1, yrefpix1, y[i]); } #endif amoeba (p, y, nfit, FTOL, nitmax, wcs_chisqr, &iter); #define PDUMP #ifdef PDUMP fprintf (stderr,"\nAfter:\n"); for (i = 0; i < nfit1; i++) { if (vfit[1] > -1) ra2str (rastr, 16, p[i][vfit[1]] + xref_p, 3); else ra2str (rastr, 16, wcsf->xref, 3); if (vfit[2] > -1) dec2str (decstr, 16, p[i][vfit[2]]+yref_p, 2); else dec2str (decstr, 16, wcsf->yref, 2); if (vfit[6] > -1) { cd[0] = p[i][vfit[3]]; cd[1] = p[i][vfit[4]]; cd[2] = p[i][vfit[5]]; cd[3] = p[i][vfit[6]]; fprintf (stderr,"%d: %s %s CD: %7.5f,%7.5f,%7.5f,%7.5f ", i, rastr, decstr, cd[0],cd[1],cd[2],cd[3]); } else { if (vfit[3] > -1) xinc1 = p[i][vfit[3]]; else xinc1 = wcsf->xinc; if (vfit[4] > -1) yinc1 = p[i][vfit[4]]; else if (vfit[3] > -1) { if (xinc1 < 0) yinc1 = -xinc1; else yinc1 = xinc1; } else yinc1 = wcsf->yinc; if (vfit[5] > -1) rot = p[i][vfit[5]]; else rot = wcsf->rot; fprintf (stderr,"%d: %s %s del=%6.4f,%6.4f rot=%5.3f ", i,rastr,decstr, 3600.0*xinc1, 3600.0*yinc1, rot); } if (vfit[7] > -1) xrefpix1 = xrefpix + p[i][vfit[7]]; else xrefpix1 = wcsf->xrefpix; if (vfit[8] > -1) yrefpix1 = yrefpix + p[i][vfit[8]]; else yrefpix1 = wcsf->yrefpix; fprintf (stderr,"(%8.2f,%8.2f) y=%g\n", xrefpix1, yrefpix1, y[i]); } #endif /* On return, all entries in p[1..NPAR] are within FTOL; * Return the average, though you could just pick the first one */ for (j = 0; j < nfit; j++) { double sum = 0.0; for (i = 0; i < nfit1; i++) sum += p[i][j]; vp[j] = sum / (double)nfit1; } if (vfit[1] > -1) { wcsf->xref = xref_p + vp[vfit[1]]; if (wcsf->xref < 0.0) wcsf->xref = 360.0 + wcsf->xref; } if (vfit[2] > -1) wcsf->yref = yref_p + vp[vfit[2]]; if (vfit[6] > -1) { wcsf->cd[0] = vp[vfit[3]]; wcsf->cd[1] = vp[vfit[4]]; wcsf->cd[2] = vp[vfit[5]]; wcsf->cd[3] = vp[vfit[6]]; } else { if (vfit[3] > -1) wcsf->xinc = vp[vfit[3]]; if (vfit[4] > -1) wcsf->yinc = vp[vfit[4]]; else if (vfit[3] > -1) { if (wcsf->xinc < 0) wcsf->yinc = -wcsf->xinc; else wcsf->yinc = wcsf->xinc; } if (vfit[5] > -1) wcsf->rot = vp[vfit[5]]; } if (vfit[7] > -1) wcsf->xrefpix = xrefpix + vp[vfit[7]]; if (vfit[8] > -1) wcsf->yrefpix = yrefpix + vp[vfit[8]]; #define RESIDDUMP #ifdef RESIDDUMP ra2str (rastr, 16, wcsf->xref, 3); dec2str (decstr, 16, wcsf->yref, 2); if (vfit[6] > -1) fprintf (stderr,"iter=%d\n cra= %s cdec= %s CD=%9.7f,%9.7f,%9.7f,%9.7f ", iter, rastr, decstr, wcsf->cd[0], wcsf->cd[1], wcsf->cd[2], wcsf->cd[3]); else fprintf (stderr,"iter=%d\n cra= %s cdec= %s del=%7.4f,%7.4f rot=%7.4f ", iter, rastr, decstr, wcsf->xinc*3600.0, wcsf->yinc*3600.0, wcsf->rot); fprintf (stderr,"(%8.2f,%8.2f)\n", wcsf->xrefpix, wcsf->yrefpix); sumx = 0.0; sumy = 0.0; sumr = 0.0; for (i = 0; i < nbin_p; i++) { double mra, mdec, ex, ey, er; char rastr[16], decstr[16]; pix2wcs (wcsf, sx_p[i], sy_p[i], &mra, &mdec); ex = 3600.0 * (mra - gra_p[i]); ey = 3600.0 * (mdec - gdec_p[i]); er = sqrt (ex * ex + ey * ey); sumx = sumx + ex; sumy = sumy + ey; sumr = sumr + er; ra2str (rastr, 16, gra_p[i], 3); dec2str (decstr, 16, gdec_p[i], 2); fprintf (stderr,"%2d: c: %s %s ", i+1, rastr, decstr); ra2str (rastr, 16, mra, 3); dec2str (decstr, 16, mdec, 2); fprintf (stderr, "i: %s %s %6.3f %6.3f %6.3f\n", rastr, decstr, 3600.0*ex, 3600.0*ey, 3600.0*sqrt(ex*ex + ey*ey)); } sumx = sumx / (double)nbin_p; sumy = sumy / (double)nbin_p; sumr = sumr / (double)nbin_p; fprintf (stderr,"mean dra: %6.3f, ddec: %6.3f, dr = %6.3f\n", sumx, sumy, sumr); #endif } /* Compute the chisqr of the vector v, where * v[0]=cra, v[1]=cdec, v[2]=ra deg/pix, v[3]=dec deg/pix, * v[4]=rotation, v[5]=2nd rotation->CD matrix, v[6]=ref x, and v[7] = ref y * chisqr is in arcsec^2 */ static double wcs_chisqr (v, iter) double *v; /* Vector of parameter values */ int iter; /* Number of iterations */ { double chsq; char rastr[16],decstr[16]; double xmp, ymp, dx, dy, cd[4], *cdx; double crval1, crval2, cdelt1, cdelt2, crota, crpix1, crpix2; int i, offscale; /* Set WCS parameters from fit parameter vector */ /* Sky coordinates at optical axis (degrees) */ if (vfit[1] > -1) crval1 = xref_p + v[vfit[1]]; else crval1 = wcsf->xref; if (vfit[2] > -1) crval2 = yref_p + v[vfit[2]]; else crval2 = wcsf->yref; /* CD matrix */ if (vfit[6] > -1) { cdelt1 = 0.0; cdelt2 = 0.0; crota = 0.0; cd[0] = v[vfit[3]]; cd[1] = v[vfit[4]]; cd[2] = v[vfit[5]]; cd[3] = v[vfit[6]]; cdx = cd; } else { /* Plate scale (degrees/pixel) */ if (vfit[3] > -1) cdelt1 = v[vfit[3]]; else cdelt1 = wcsf->xinc; if (vfit[4] > -1) cdelt2 = v[vfit[4]]; else if (vfit[3] > -1) { if (cdelt1 < 0) cdelt2 = -cdelt1; else cdelt2 = cdelt1; } else cdelt2 = wcsf->yinc; /* Rotation angle (degrees) */ if (vfit[5] > -1) crota = v[vfit[5]]; else crota = wcsf->rot; cdx = NULL; } /* Optical axis pixel coordinates */ if (vfit[7] > -1) crpix1 = xrefpix + v[vfit[7]]; else crpix1 = wcsf->xrefpix; if (vfit[8] > -1) crpix2 = yrefpix + v[vfit[8]]; else crpix2 = wcsf->yrefpix; if (wcsreset (wcsf,crpix1,crpix2,crval1,crval2,cdelt1,cdelt2,crota,cdx)) { fprintf (stderr,"CHISQR: Cannot reset WCS!\n"); return (0.0); } /* Compute sum of squared residuals for these parameters */ chsq = 0.0; for (i = 0; i < nbin_p; i++) { wcs2pix (wcsf, gra_p[i], gdec_p[i], &xmp, &ymp, &offscale); /* if (!offscale) { */ dx = xmp - sx_p[i]; dy = ymp - sy_p[i]; chsq += dx*dx + dy*dy; /* } */ } #define TRACE_CHSQR #ifdef TRACE_CHSQR ra2str (rastr, 16, wcsf->xref, 3); dec2str (decstr, 16, wcsf->yref, 2); if (vfit[6] > -1) fprintf (stderr,"%4d: %s %s CD: %9.7f,%9.7f,%9.7f,%9.7f ", iter, rastr, decstr, wcsf->cd[0],wcsf->cd[1],wcsf->cd[2], wcsf->cd[3]); else fprintf (stderr,"%4d: %s %s %9.7f,%9.7f %8.5f ", iter, rastr, decstr, wcsf->xinc*3600.0, wcsf->yinc*3600.0, wcsf->rot); fprintf (stderr,"(%8.2f,%8.2f) -> %f\r", wcsf->xrefpix, wcsf->yrefpix, chsq); #endif return (chsq); } /* The following subroutines are based on those in Numerical Recipes in C */ /* amoeba.c */ #define ALPHA 1.0 #define BETA 0.5 #define GAMMA 2.0 void amoeba (p, y, ndim, ftol, itmax, funk, nfunk) double **p; double y[]; double ftol; int itmax; double (*funk)(); int ndim; int *nfunk; { int i,j,ilo,ihi,inhi,ndim1=ndim+1; double ytry,ysave,sum,rtol,*psum; psum = (double *) malloc ((unsigned)ndim * sizeof(double)); *nfunk = 0; for (j=0; j y[1]) { inhi = 1; ihi = 0; } else { inhi = 0; ihi = 1; } for (i = 0; i < ndim1; i++) { if (y[i] < y[ilo]) ilo=i; if (y[i] > y[ihi]) { inhi=ihi; ihi=i; } else if (y[i] > y[inhi]) if (i != ihi) inhi=i; } rtol = 2.0 * fabs(y[ihi]-y[ilo]) / (fabs(y[ihi]) + fabs(y[ilo])); if (rtol < ftol) break; if (*nfunk >= itmax) { fprintf (stderr,"Too many iterations in amoeba fit %d > %d",*nfunk,itmax); return; } ytry = amotry (p, y, psum, ndim, funk, ihi, nfunk, -ALPHA); if (ytry <= y[ilo]) ytry = amotry (p, y, psum, ndim, funk, ihi, nfunk, GAMMA); else if (ytry >= y[inhi]) { ysave = y[ihi]; ytry = amotry (p,y,psum,ndim,funk,ihi,nfunk,BETA); if (ytry >= ysave) { for (i = 0; i < ndim1; i++) { if (i != ilo) { for (j = 0; j < ndim; j++) { psum[j] = 0.5 * (p[i][j] + p[ilo][j]); p[i][j] = psum[j]; } y[i]=(*funk)(psum, *nfunk); } } *nfunk += ndim; for (j=0; j 40 * Oct 15 2001 Simplify error message * Oct 16 2001 Read minimum match to drop out of loop from lwcs.h * Oct 31 2001 Simplify innermost loop to try for more speed * Nov 1 2001 Add goff to StarMatch() arguments * Nov 5 2001 Use current WCS with no offset before trying offset matching * Nov 6 2001 Add setnitmax() to set maximum number of amoeba iterations * Nov 7 2001 Add setminbin to set minimum number of matches for fit * Nov 16 2001 Allocate slightly more than maxbin to handle dense fields * * Jul 31 2002 Add getnfit() to return current number of parameters being fit * Aug 30 2002 Fix WCSMatch() to set scale in arcsec, not degrees * * Jan 30 2003 Remove uninitialized variable in WCSMatch() * Mar 13 2003 Do not include malloc.h on Apples and Convexes * Apr 3 2003 Clean up code with lint * Nov 18 2003 Drop include of malloc.h; it is in stdlib.h * * Aug 30 2004 Declare void various external set*() calls * * Jun 19 2006 Initialize unitialized variables dxs and dys */ wcstools-3.9.5/libwcs/platefit.c0000664000016200001660000001767311750060474015734 0ustar minkoirsys/*** File libwcs/platefit.c *** September 26, 2006 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1998-2006 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ /* Nonlinear least squares fitting program using data arrays starting * at x and y to fit array starting at z. * Contains convergence oscillation damping and optional normalization * Fits up to MAXPAR parameters */ #include #include #include #include "wcs.h" #include "lwcs.h" static void plate_amoeba(); static double plate_chisqr(); static int ncoeff=0; static double *sx_p; static double *sy_p; static double *gx_p; static double *gy_p; static int nbin_p; extern int SetPlate(); #define MAXPAR 26 #define MAXPAR1 27 #define NITMAX 2500 int FitPlate (wcs, x, y, x1, y1, np, ncoeff0, debug) struct WorldCoor *wcs; /* World coordinate system structure */ double *x, *y; /* Image WCS coordinates */ double *x1, *y1; /* Image pixel coordinates */ int np; /* Number of points to fit */ int ncoeff0; /* Order of polynomial terms in x and y */ int debug; { sx_p = x; sy_p = y; gx_p = x1; gy_p = y1; nbin_p = np; ncoeff = ncoeff0; /* Fit polynomials */ plate_amoeba (wcs); return (0); } static struct WorldCoor *wcsp; /* Set up the necessary temp arrays and call the amoeba() multivariate solver */ static void plate_amoeba (wcs0) struct WorldCoor *wcs0; { double *p[MAXPAR1]; /* used as p[NPAR1][NPAR] */ double vguess[MAXPAR], vp[MAXPAR], vdiff[MAXPAR]; double y[MAXPAR1]; /* used as y[1..NPAR] */ double sumx, sumy, sumr; int nbytes; int iter; int i, j; int nfit, nfit1; int nitmax; extern void amoeba(); /* Allocate memory for fit */ nfit = ncoeff * 2; nfit1 = nfit + 1; nbytes = nfit * sizeof (double); for (i = 0; i < nfit1; i++) p[i] = (double *) malloc (nbytes); nitmax = 6000; wcsp = wcs0; /* Zero guess and difference vectors */ for (i = 0; i < MAXPAR; i++) { vguess[i] = 0.0; vdiff[i] = 0.0; vp[i] = 0.0; } if (nfit > 0) { double dra = wcsp->cdelt[0]; double ddec = wcsp->cdelt[1]; vguess[0] = 0.0; vdiff[0] = 5.0 * dra; vguess[1] = wcsp->cd[0]; vdiff[1] = 0.05 * dra; vguess[2] = wcsp->cd[1]; vdiff[2] = 0.05 * ddec; vguess[3] = 0.0; vdiff[3] = 0.001 * dra; vguess[4] = 0.0; vdiff[4] = 0.001 * ddec; vguess[5] = 0.0; vdiff[5] = 0.001 * ddec; if (ncoeff > 6) { vguess[6] = 0.0; vdiff[6] = 0.001 * ddec; vguess[7] = 0.0; vdiff[7] = 0.001 * ddec; } vguess[ncoeff+0] = 0.0; vdiff[ncoeff+0] = 5.0 * ddec; vguess[ncoeff+1] = wcsp->cd[2]; vdiff[ncoeff+1] = 0.05 * ddec; vguess[ncoeff+2] = wcsp->cd[3]; vdiff[ncoeff+2] = 0.05 * dra; vguess[ncoeff+3] = 0.0; vdiff[ncoeff+3] = 0.001 * ddec; vguess[ncoeff+4] = 0.0; vdiff[ncoeff+4] = 0.001 * dra; vguess[ncoeff+5] = 0.0; vdiff[ncoeff+5] = 0.001 * ddec; if (ncoeff > 6) { vguess[ncoeff+6] = 0.0; vdiff[ncoeff+6] = 0.001 * dra; vguess[ncoeff+7] = 0.0; vdiff[ncoeff+7] = 0.001 * ddec; } } /* Set up matrix of nfit+1 initial guesses. * The supplied guess, plus one for each parameter altered by a small amount */ for (i = 0; i < nfit1; i++) { for (j = 0; j < nfit; j++) p[i][j] = vguess[j]; if (i > 0) p[i][i-1] = vguess[i-1] + vdiff[i-1]; y[i] = plate_chisqr (p[i], -i); } #define PDUMP #ifdef PDUMP fprintf (stderr,"Before:\n"); for (i = 0; i < nfit1; i++) { fprintf (stderr,"%3d: ", i); for (j = 0; j < ncoeff; j++) fprintf (stderr," %9.7f",p[i][j]); fprintf (stderr,"\n "); for (j = 0; j < ncoeff; j++) fprintf (stderr," %9.7f",p[i][ncoeff+j]); fprintf (stderr,"\n"); } #endif amoeba (p, y, nfit, FTOL, nitmax, plate_chisqr, &iter); #define PDUMP #ifdef PDUMP fprintf (stderr,"\nAfter:\n"); for (i = 0; i < nfit1; i++) { fprintf (stderr,"%3d: ", i); for (j = 0; j < ncoeff; j++) fprintf (stderr," %9.7f",p[i][j]); fprintf (stderr,"\n "); for (j = 0; j < ncoeff; j++) fprintf (stderr," %9.7f",p[i][ncoeff+j]); fprintf (stderr,"\n"); } #endif /* on return, all entries in p[1..NPAR] are within FTOL; average them */ for (j = 0; j < nfit; j++) { double sum = 0.0; for (i = 0; i < nfit1; i++) sum += p[i][j]; vp[j] = sum / (double)nfit1; } (void)SetPlate (wcsp, ncoeff, ncoeff, vp); #define RESIDDUMP #ifdef RESIDDUMP fprintf (stderr,"iter=%4d\n ", iter); for (j = 0; j < ncoeff; j++) fprintf (stderr," %9.7f",vp[j]); fprintf (stderr,"\n "); for (j = 0; j < ncoeff; j++) fprintf (stderr," %9.7f",vp[j+6]); fprintf (stderr,"\n"); sumx = 0.0; sumy = 0.0; sumr = 0.0; for (i = 0; i < nbin_p; i++) { double mx, my, ex, ey, er; char rastr[32], decstr[32]; pix2wcs (wcsp, sx_p[i], sy_p[i], &mx, &my); ex = 3600.0 * (mx - gx_p[i]); ey = 3600.0 * (my - gy_p[i]); er = sqrt (ex * ex + ey * ey); sumx = sumx + ex; sumy = sumy + ey; sumr = sumr + er; ra2str (rastr, 31, gx_p[i], 3); dec2str (decstr, 31, gy_p[i], 2); fprintf (stderr,"%2d: c: %s %s ", i+1, rastr, decstr); ra2str (rastr, 31, mx, 3); dec2str (decstr, 31, my, 2); fprintf (stderr,"i: %s %s %6.3f %6.3f %6.3f\n", rastr, decstr, 3600.0*ex, 3600.0*ey, 3600.0*sqrt(ex*ex + ey*ey)); } sumx = sumx / (double)nbin_p; sumy = sumy / (double)nbin_p; sumr = sumr / (double)nbin_p; fprintf (stderr,"mean dra: %6.3f, ddec: %6.3f, dr = %6.3f\n", sumx, sumy, sumr); #endif for (i = 0; i < nfit1; i++) free (p[i]); return; } /* Compute the chisqr of the vector v, where v[i]=plate fit coeffients * chisqr is in arcsec^2 */ static double plate_chisqr (v, iter) double *v; /* Vector of parameter values */ int iter; /* Number of iterations */ { double chsq; double xsp, ysp, dx, dy; int i, j; extern int SetPlate(); /* Set plate constants from fit parameter vector */ if (SetPlate (wcsp, ncoeff, ncoeff, v)) { fprintf (stderr,"CHISQR: Cannot reset WCS!\n"); return (0.0); } /* Compute sum of squared residuals for these parameters */ chsq = 0.0; for (i = 0; i < nbin_p; i++) { pix2wcs (wcsp, sx_p[i], sy_p[i], &xsp, &ysp); dx =3600.0 * (xsp - gx_p[i]); dy = 3600.0 * (ysp - gy_p[i]); chsq += dx*dx + dy*dy; } #define TRACE_CHSQR #ifdef TRACE_CHSQR fprintf (stderr,"%4d:", iter); for (j = 0; j < ncoeff; j++) fprintf (stderr," %9.4g",v[j]); for (j = 0; j < ncoeff; j++) fprintf (stderr," %9.4g",v[ncoeff+j]); fprintf (stderr," -> %f\r", chsq); #endif return (chsq); } /* Mar 30 1998 New subroutines * Apr 7 1998 Add x^3 and y^3 terms * Apr 10 1998 Add second number of coefficients * May 14 1998 include stdio.h for stderr * Jun 24 1998 Add string lengths to ra2str() and dec2str() calls * Oct 15 1999 Include stdlib.h for malloc() declaration * * Jan 11 2001 Print all messages to stderr * * Sep 26 2006 Increase length of rastr and destr from 16 to 32 */ wcstools-3.9.5/libwcs/platepos.c0000664000016200001660000002540011750060474015736 0ustar minkoirsys/*** File saoimage/wcslib/platepos.c *** February 29, 2000 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1998-2002 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: platepos.c (Plate solution WCS conversion * Purpose: Compute WCS from plate fit * Subroutine: platepos() converts from pixel location to RA,Dec * Subroutine: platepix() converts from RA,Dec to pixel location These functions are based on the astrmcal.c portion of GETIMAGE by J. Doggett and the documentation distributed with the Digital Sky Survey. */ #include #include #include #include "wcs.h" int platepos (xpix, ypix, wcs, xpos, ypos) /* Routine to determine accurate position for pixel coordinates */ /* returns 0 if successful otherwise 1 = angle too large for projection; */ /* based on amdpos() from getimage */ /* Input: */ double xpix; /* x pixel number (RA or long without rotation) */ double ypix; /* y pixel number (dec or lat without rotation) */ struct WorldCoor *wcs; /* WCS parameter structure */ /* Output: */ double *xpos; /* Right ascension or longitude in degrees */ double *ypos; /* Declination or latitude in degrees */ { double x, y, x2, y2, x3, y3, r2; double xi, xir, eta, etar, raoff, ra, dec, ra0, dec0; double twopi = 6.28318530717959; double ctan, ccos; int ncoeff1 = wcs->ncoeff1; int ncoeff2 = wcs->ncoeff2; /* Ignore magnitude and color terms double mag = 0.0; double color = 0.0; */ /* Convert from pixels to millimeters */ x = xpix - wcs->crpix[0]; y = ypix - wcs->crpix[1]; x2 = x * x; y2 = y * y; x3 = x * x2; y3 = y * y2; r2 = x2 + y2; /* Compute xi,eta coordinates in degrees from x,y and plate model */ xi = wcs->x_coeff[ 0] + wcs->x_coeff[ 1]*x + wcs->x_coeff[ 2]*y + wcs->x_coeff[ 3]*x2 + wcs->x_coeff[ 4]*y2 + wcs->x_coeff[ 5]*x*y; if (ncoeff1 > 6) xi = xi + wcs->x_coeff[ 6]*x3 + wcs->x_coeff[ 7]*y3; if (ncoeff1 > 8) { xi = xi + wcs->x_coeff[ 8]*x2*y + wcs->x_coeff[ 9]*x*y2 + wcs->x_coeff[10]*(r2) + wcs->x_coeff[11]*x*r2 + wcs->x_coeff[12]*y*r2; } eta = wcs->y_coeff[ 0] + wcs->y_coeff[ 1]*x + wcs->y_coeff[ 2]*y + wcs->y_coeff[ 3]*x2 + wcs->y_coeff[ 4]*y2 + wcs->y_coeff[ 5]*x*y; if (ncoeff2 > 6) eta = eta + wcs->y_coeff[ 6]*x3 + wcs->y_coeff[ 7]*y3; if (ncoeff2 > 8) { eta = eta + wcs->y_coeff[ 8]*x2*y + wcs->y_coeff[ 9]*y2*x + wcs->y_coeff[10]*r2 + wcs->y_coeff[11]*x*r2 + wcs->y_coeff[12]*y*r2; } /* Convert to radians */ xir = degrad (xi); etar = degrad (eta); /* Convert to RA and Dec */ ra0 = degrad (wcs->crval[0]); dec0 = degrad (wcs->crval[1]); ctan = tan (dec0); ccos = cos (dec0); raoff = atan2 (xir / ccos, 1.0 - etar * ctan); ra = raoff + ra0; if (ra < 0.0) ra = ra + twopi; *xpos = raddeg (ra); dec = atan (cos (raoff) / ((1.0 - (etar * ctan)) / (etar + ctan))); *ypos = raddeg (dec); return 0; } int platepix (xpos, ypos, wcs, xpix, ypix) /* Routine to determine pixel coordinates for sky position */ /* returns 0 if successful otherwise 1 = angle too large for projection; */ /* based on amdinv() from getimage */ /* Input: */ double xpos; /* Right ascension or longitude in degrees */ double ypos; /* Declination or latitude in degrees */ struct WorldCoor *wcs; /* WCS parameter structure */ /* Output: */ double *xpix; /* x pixel number (RA or long without rotation) */ double *ypix; /* y pixel number (dec or lat without rotation) */ { double xi,eta,x,y,xy,x2,y2,x2y,y2x,x3,y3,r2,dx,dy; double tdec,ctan,ccos,traoff, craoff, etar, xir; double f,fx,fy,g,gx,gy; double ra0, dec0, ra, dec; double tolerance = 0.0000005; int max_iterations = 50; int i; int ncoeff1 = wcs->ncoeff1; int ncoeff2 = wcs->ncoeff2; /* Convert RA and Dec in radians to standard coordinates on a plate */ ra = degrad (xpos); dec = degrad (ypos); tdec = tan (dec); ra0 = degrad (wcs->crval[0]); dec0 = degrad (wcs->crval[1]); ctan = tan (dec0); ccos = cos (dec0); traoff = tan (ra - ra0); craoff = cos (ra - ra0); etar = (1.0 - ctan * craoff / tdec) / (ctan + (craoff / tdec)); xir = traoff * ccos * (1.0 - (etar * ctan)); xi = raddeg (xir); eta = raddeg (etar); /* Set initial value for x,y */ x = xi * wcs->dc[0] + eta * wcs->dc[1]; y = xi * wcs->dc[2] + eta * wcs->dc[3]; /* if (wcs->x_coeff[1] == 0.0) x = xi - wcs->x_coeff[0]; else x = (xi - wcs->x_coeff[0]) / wcs->x_coeff[1]; if (wcs->y_coeff[2] == 0.0) y = eta - wcs->y_coeff[0]; else y = (eta - wcs->y_coeff[0]) / wcs->y_coeff[2]; */ /* Iterate by Newton's method */ for (i = 0; i < max_iterations; i++) { /* X plate model */ xy = x * y; x2 = x * x; y2 = y * y; x3 = x2 * x; y3 = y2 * y; x2y = x2 * y; y2x = y2 * x; r2 = x2 + y2; f = wcs->x_coeff[0] + wcs->x_coeff[1]*x + wcs->x_coeff[2]*y + wcs->x_coeff[3]*x2 + wcs->x_coeff[4]*y2 + wcs->x_coeff[5]*xy; /* Derivative of X model wrt x */ fx = wcs->x_coeff[1] + wcs->x_coeff[3]*2.0*x + wcs->x_coeff[5]*y; /* Derivative of X model wrt y */ fy = wcs->x_coeff[2] + wcs->x_coeff[4]*2.0*y + wcs->x_coeff[5]*x; if (ncoeff1 > 6) { f = f + wcs->x_coeff[6]*x3 + wcs->x_coeff[7]*y3; fx = fx + wcs->x_coeff[6]*3.0*x2; fy = fy + wcs->x_coeff[7]*3.0*y2; } if (ncoeff1 > 8) { f = f + wcs->x_coeff[8]*x2y + wcs->x_coeff[9]*y2x + wcs->x_coeff[10]*r2 + wcs->x_coeff[11]*x*r2 + wcs->x_coeff[12]*y*r2; fx = fx + wcs->x_coeff[8]*2.0*xy + wcs->x_coeff[9]*y2 + wcs->x_coeff[10]*2.0*x + wcs->x_coeff[11]*(3.0*x2+y2) + wcs->x_coeff[12]*2.0*xy; fy = fy + wcs->x_coeff[8]*x2 + wcs->x_coeff[9]*2.0*xy + wcs->x_coeff[10]*2.0*y + wcs->x_coeff[11]*2.0*xy + wcs->x_coeff[12]*(3.0*y2+x2); } /* Y plate model */ g = wcs->y_coeff[0] + wcs->y_coeff[1]*x + wcs->y_coeff[2]*y + wcs->y_coeff[3]*x2 + wcs->y_coeff[4]*y2 + wcs->y_coeff[5]*xy; /* Derivative of Y model wrt x */ gx = wcs->y_coeff[1] + wcs->y_coeff[3]*2.0*x + wcs->y_coeff[5]*y; /* Derivative of Y model wrt y */ gy = wcs->y_coeff[2] + wcs->y_coeff[4]*2.0*y + wcs->y_coeff[5]*x; if (ncoeff2 > 6) { g = g + wcs->y_coeff[6]*x3 + wcs->y_coeff[7]*y3; gx = gx + wcs->y_coeff[6]*3.0*x2; gy = gy + wcs->y_coeff[7]*3.0*y2; } if (ncoeff2 > 8) { g = g + wcs->y_coeff[8]*x2y + wcs->y_coeff[9]*y2x + wcs->y_coeff[10]*r2 + wcs->y_coeff[11]*x*r2 + wcs->y_coeff[12]*y*r2; gx = gx + wcs->y_coeff[8]*2.0*xy + wcs->y_coeff[9]*y2 + wcs->y_coeff[10]*2.0*x + wcs->y_coeff[11]*(3.0*x2+y2) + wcs->y_coeff[12]*2.0*xy; gy = gy + wcs->y_coeff[8]*x2 + wcs->y_coeff[9]*2.0*xy + wcs->y_coeff[10]*2.0*y + wcs->y_coeff[11]*2.0*xy + wcs->y_coeff[12]*(3.0*y2+x2); } f = f - xi; g = g - eta; dx = ((-f * gy) + (g * fy)) / ((fx * gy) - (fy * gx)); dy = ((-g * fx) + (f * gx)) / ((fx * gy) - (fy * gx)); x = x + dx; y = y + dy; if ((fabs(dx) < tolerance) && (fabs(dy) < tolerance)) break; } /* Convert from plate pixels to image pixels */ *xpix = x + wcs->crpix[0]; *ypix = y + wcs->crpix[1]; /* If position is off of the image, return offscale code */ if (*xpix < 0.5 || *xpix > wcs->nxpix+0.5) return -1; if (*ypix < 0.5 || *ypix > wcs->nypix+0.5) return -1; return 0; } /* Set plate fit coefficients in structure from arguments */ int SetPlate (wcs, ncoeff1, ncoeff2, coeff) struct WorldCoor *wcs; /* World coordinate system structure */ int ncoeff1; /* Number of coefficients for x */ int ncoeff2; /* Number of coefficients for y */ double *coeff; /* Plate fit coefficients */ { int i; if (nowcs (wcs) || (ncoeff1 < 1 && ncoeff2 < 1)) return 1; wcs->ncoeff1 = ncoeff1; wcs->ncoeff2 = ncoeff2; wcs->prjcode = WCS_PLT; for (i = 0; i < 20; i++) { if (i < ncoeff1) wcs->x_coeff[i] = coeff[i]; else wcs->x_coeff[i] = 0.0; } for (i = 0; i < 20; i++) { if (i < ncoeff2) wcs->y_coeff[i] = coeff[ncoeff1+i]; else wcs->y_coeff[i] = 0.0; } return 0; } /* Return plate fit coefficients from structure in arguments */ int GetPlate (wcs, ncoeff1, ncoeff2, coeff) struct WorldCoor *wcs; /* World coordinate system structure */ int *ncoeff1; /* Number of coefficients for x */ int *ncoeff2; /* Number of coefficients for y) */ double *coeff; /* Plate fit coefficients */ { int i; if (nowcs (wcs)) return 1; *ncoeff1 = wcs->ncoeff1; *ncoeff2 = wcs->ncoeff2; for (i = 0; i < *ncoeff1; i++) coeff[i] = wcs->x_coeff[i]; for (i = 0; i < *ncoeff2; i++) coeff[*ncoeff1+i] = wcs->y_coeff[i]; return 0; } /* Set FITS header plate fit coefficients from structure */ void SetFITSPlate (header, wcs) char *header; /* Image FITS header */ struct WorldCoor *wcs; /* WCS structure */ { char keyword[16]; int i; for (i = 0; i < wcs->ncoeff1; i++) { sprintf (keyword,"CO1_%d",i+1); hputnr8 (header, keyword, -15, wcs->x_coeff[i]); } for (i = 0; i < wcs->ncoeff2; i++) { sprintf (keyword,"CO2_%d",i+1); hputnr8 (header, keyword, -15, wcs->y_coeff[i]); } return; } /* Mar 27 1998 New subroutines for direct image pixel <-> sky polynomials * Apr 10 1998 Make terms identical for both x and y polynomials * Apr 10 1998 Allow different numbers of coefficients for x and y * Apr 16 1998 Drom NCOEFF header parameter * Apr 28 1998 Change projection flags to WCS_* * Sep 10 1998 Check for xc1 and yc2 divide by zero after Allen Harris, SAO * * Oct 21 1999 Drop unused variables after lint * * Feb 29 2000 Use inverse CD matrix to get initial X,Y in platepix() * as suggested by Paolo Montegriffo from Bologna Ast. Obs. */ wcstools-3.9.5/libwcs/polfit.c0000664000016200001660000001073412004315552015401 0ustar minkoirsys/*** File polfit.c *** July 26, 2012 *** By Jessica Mink, after Bevington, page 141 *--- Polynomial least squares fitting program, almost identical to the * one in Bevington, "Data Reduction and Error Analysis for the * Physical Sciences," page 141. The argument list was changed and * the weighting removed. * y = a(1) + a(2)*(x-x0) + a(3)*(x-x0)**2 + a(3)*(x-x0)**3 + . . . */ #include #include #include #include "wcscat.h" static double determ(); void polfit (x, y, x0, npts, nterms, a, stdev) double *x; /* Array of independent variable points */ double *y; /* Array of dependent variable points */ double x0; /* Offset to independent variable */ int npts; /* Number of data points to fit */ int nterms; /* Number of parameters to fit */ double *a; /* Vector containing current fit values */ double *stdev; /* Standard deviation of fit (returned) */ { double sigma2sum; double xterm,yterm,xi,yi; double *sumx, *sumy; double *array; int i,j,k,l,n,nmax; double delta; /* accumulate weighted sums */ nmax = 2 * nterms - 1; sumx = (double *) calloc (nmax, sizeof(double)); sumy = (double *) calloc (nterms, sizeof(double)); for (n = 0; n < nmax; n++) sumx[n] = 0.0; for (j = 0; j < nterms; j++) sumy[j] = 0.0; for (i = 0; i < npts; i++) { xi = x[i] - x0; yi = y[i]; xterm = 1.0; for (n = 0; n < nmax; n++) { sumx[n] = sumx[n] + xterm; xterm = xterm * xi; } yterm = yi; for (n = 0; n < nterms; n++) { sumy[n] = sumy[n] + yterm; yterm = yterm * xi; } } /* Construct matrices and calculate coeffients */ array = (double *) calloc (nterms*nterms, sizeof(double)); for (j = 0; j < nterms; j++) { for (k = 0; k < nterms; k++) { n = j + k; array[j+k*nterms] = sumx[n]; } } delta = determ (array, nterms); if (delta == 0.0) { *stdev = 0.; for (j = 0; j < nterms; j++) a[j] = 0. ; free (array); free (sumx); free (sumy); return; } for (l = 0; l < nterms; l++) { for (j = 0; j < nterms; j++) { for (k = 0; k < nterms; k++) { n = j + k; array[j+k*nterms] = sumx[n]; } array[j+l*nterms] = sumy[j]; } a[l] = determ (array, nterms) / delta; } /* Calculate sigma */ sigma2sum = 0.0; for (i = 0; i < npts; i++) { yi = polcomp (x[i], x0, nterms, a); sigma2sum = sigma2sum + ((y[i] - yi) * (y[i] - yi)); } *stdev = sqrt (sigma2sum / (double) (npts - 1)); free (array); free (sumx); free (sumy); return; } /*--- Calculate the determinant of a square matrix * This subprogram destroys the input matrix array * From Bevington, page 294. */ static double determ (array, norder) double *array; /* Input matrix array */ int norder; /* Order of determinant (degree of matrix) */ { double save, det; int i,j,k,k1, zero; det = 1.0; for (k = 0; k < norder; k++) { /* Interchange columns if diagonal element is zero */ if (array[k+k*norder] == 0) { zero = 1; for (j = k; j < norder; j++) { if (array[k+j*norder] != 0.0) zero = 0; } if (zero) return (0.0); for (i = k; i < norder; i++) { save = array[i+j*norder]; array[i+j*norder] = array[i+k*norder]; array[i+k*norder] = save ; } det = -det; } /* Subtract row k from lower rows to get diagonal matrix */ det = det * array[k+k*norder]; if (k < norder - 1) { k1 = k + 1; for (i = k1; i < norder; i++) { for (j = k1; j < norder; j++) { array[i+j*norder] = array[i+j*norder] - (array[i+k*norder] * array[k+j*norder] / array[k+k*norder]); } } } } return (det); } /* POLCOMP -- Polynomial evaluation * Y = A(1) + A(2)*X + A(3)*X**2 + A(3)*X**3 + . . . */ double polcomp (xi, x0, norder, a) double xi; /* Independent variable */ double x0; /* Offset to independent variable */ int norder; /* Number of coefficients */ double *a; /* Vector containing coeffiecients */ { double xterm, x, y; int iterm; /* Accumulate polynomial value */ x = xi - x0; y = 0.0; xterm = 1.0; for (iterm = 0; iterm < norder; iterm++) { y = y + a[iterm] * xterm; xterm = xterm * x; } return (y); } /* Sep 10 1987 Program written * * Mar 17 1993 Add x offset * * Feb 23 1998 Translate to C * * Jul 25 2001 Add polcomp to return computed values * * Apr 3 2003 Drop unused variable freedom in polfit() * * Jul 26 2012 Fix xterm computation in polcomp() from + to * * (found by Raymond Carlberg of U.Toronto) */ wcstools-3.9.5/libwcs/proj.c0000664000016200001660000030565311750060474015074 0ustar minkoirsys/*============================================================================ * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-2002, Mark Calabretta * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Correspondence concerning WCSLIB may be directed to: * Internet email: mcalabre@atnf.csiro.au * Postal address: Dr. Mark Calabretta, * Australia Telescope National Facility, * P.O. Box 76, * Epping, NSW, 2121, * AUSTRALIA * *============================================================================= * * C implementation of the spherical map projections recognized by the FITS * "World Coordinate System" (WCS) convention. * * Summary of routines * ------------------- * Each projection is implemented via separate functions for the forward, * *fwd(), and reverse, *rev(), transformation. * * Initialization routines, *set(), compute intermediate values from the * projection parameters but need not be called explicitly - see the * explanation of prj.flag below. * * prjset prjfwd prjrev Driver routines (see below). * * azpset azpfwd azprev AZP: zenithal/azimuthal perspective * szpset szpfwd szprev SZP: slant zenithal perspective * tanset tanfwd tanrev TAN: gnomonic * stgset stgfwd stgrev STG: stereographic * sinset sinfwd sinrev SIN: orthographic/synthesis * arcset arcfwd arcrev ARC: zenithal/azimuthal equidistant * zpnset zpnfwd zpnrev ZPN: zenithal/azimuthal polynomial * zeaset zeafwd zearev ZEA: zenithal/azimuthal equal area * airset airfwd airrev AIR: Airy * cypset cypfwd cyprev CYP: cylindrical perspective * ceaset ceafwd cearev CEA: cylindrical equal area * carset carfwd carrev CAR: Cartesian * merset merfwd merrev MER: Mercator * sflset sflfwd sflrev SFL: Sanson-Flamsteed * parset parfwd parrev PAR: parabolic * molset molfwd molrev MOL: Mollweide * aitset aitfwd aitrev AIT: Hammer-Aitoff * copset copfwd coprev COP: conic perspective * coeset coefwd coerev COE: conic equal area * codset codfwd codrev COD: conic equidistant * cooset coofwd coorev COO: conic orthomorphic * bonset bonfwd bonrev BON: Bonne * pcoset pcofwd pcorev PCO: polyconic * tscset tscfwd tscrev TSC: tangential spherical cube * cscset cscfwd cscrev CSC: COBE quadrilateralized spherical cube * qscset qscfwd qscrev QSC: quadrilateralized spherical cube * * * Driver routines; prjset(), prjfwd() & prjrev() * ---------------------------------------------- * A set of driver routines are available for use as a generic interface to * the specific projection routines. The interfaces to prjfwd() and prjrev() * are the same as those of the forward and reverse transformation routines * for the specific projections (see below). * * The interface to prjset() differs slightly from that of the initialization * routines for the specific projections and unlike them it must be invoked * explicitly to use prjfwd() and prjrev(). * * Given: * pcode[4] const char * WCS projection code. * * Given and/or returned: * prj prjprm* Projection parameters (see below). * * Function return value: * int Error status * 0: Success. * * * Initialization routine; *set() * ------------------------------ * Initializes members of a prjprm data structure which hold intermediate * values. Note that this routine need not be called directly; it will be * invoked by prjfwd() and prjrev() if the "flag" structure member is * anything other than a predefined magic value. * * Given and/or returned: * prj prjprm* Projection parameters (see below). * * Function return value: * int Error status * 0: Success. * 1: Invalid projection parameters. * * Forward transformation; *fwd() * ----------------------------- * Compute (x,y) coordinates in the plane of projection from native spherical * coordinates (phi,theta). * * Given: * phi, const double * theta Longitude and latitude of the projected point in * native spherical coordinates, in degrees. * * Given and returned: * prj prjprm* Projection parameters (see below). * * Returned: * x,y double* Projected coordinates. * * Function return value: * int Error status * 0: Success. * 1: Invalid projection parameters. * 2: Invalid value of (phi,theta). * * Reverse transformation; *rev() * ----------------------------- * Compute native spherical coordinates (phi,theta) from (x,y) coordinates in * the plane of projection. * * Given: * x,y const double * Projected coordinates. * * Given and returned: * prj prjprm* Projection parameters (see below). * * Returned: * phi, double* Longitude and latitude of the projected point in * theta native spherical coordinates, in degrees. * * Function return value: * int Error status * 0: Success. * 1: Invalid projection parameters. * 2: Invalid value of (x,y). * 1: Invalid projection parameters. * * Projection parameters * --------------------- * The prjprm struct consists of the following: * * int flag * This flag must be set to zero whenever any of p[10] or r0 are set * or changed. This signals the initialization routine to recompute * intermediaries. flag may also be set to -1 to disable strict bounds * checking for the AZP, SZP, TAN, SIN, ZPN, and COP projections. * * double r0 * r0; The radius of the generating sphere for the projection, a linear * scaling parameter. If this is zero, it will be reset to the default * value of 180/pi (the value for FITS WCS). * * double p[10] * The first 10 elements contain projection parameters which correspond * to the PROJPn keywords in FITS, so p[0] is PROJP0, and p[9] is * PROJP9. Many projections use p[1] (PROJP1) and some also use p[2] * (PROJP2). ZPN is the only projection which uses any of the others. * * The remaining members of the prjprm struct are maintained by the * initialization routines and should not be modified. This is done for the * sake of efficiency and to allow an arbitrary number of contexts to be * maintained simultaneously. * * char code[4] * Three-letter projection code. * * double phi0, theta0 * Native longitude and latitude of the reference point, in degrees. * * double w[10] * int n * Intermediate values derived from the projection parameters. * * int (*prjfwd)() * int (*prjrev)() * Pointers to the forward and reverse projection routines. * * Usage of the p[] array as it applies to each projection is described in * the prologue to each trio of projection routines. * * Argument checking * ----------------- * Forward routines: * * The values of phi and theta (the native longitude and latitude) * normally lie in the range [-180,180] for phi, and [-90,90] for theta. * However, all forward projections will accept any value of phi and will * not normalize it. * * The forward projection routines do not explicitly check that theta lies * within the range [-90,90]. They do check for any value of theta which * produces an invalid argument to the projection equations (e.g. leading * to division by zero). The forward routines for AZP, SZP, TAN, SIN, * ZPN, and COP also return error 2 if (phi,theta) corresponds to the * overlapped (far) side of the projection but also return the * corresponding value of (x,y). This strict bounds checking may be * relaxed by setting prj->flag to -1 (rather than 0) when these * projections are initialized. * * Reverse routines: * * Error checking on the projected coordinates (x,y) is limited to that * required to ascertain whether a solution exists. Where a solution does * exist no check is made that the value of phi and theta obtained lie * within the ranges [-180,180] for phi, and [-90,90] for theta. * * Accuracy * -------- * Closure to a precision of at least 1E-10 degree of longitude and latitude * has been verified for typical projection parameters on the 1 degree grid * of native longitude and latitude (to within 5 degrees of any latitude * where the projection may diverge). * * Author: Mark Calabretta, Australia Telescope National Facility * $Id: proj.c,v 2.20 2002/04/03 01:25:29 mcalabre Exp $ *===========================================================================*/ #include #include #include #include "wcslib.h" int npcode = 26; char pcodes[26][4] = {"AZP", "SZP", "TAN", "STG", "SIN", "ARC", "ZPN", "ZEA", "AIR", "CYP", "CEA", "CAR", "MER", "COP", "COE", "COD", "COO", "SFL", "PAR", "MOL", "AIT", "BON", "PCO", "TSC", "CSC", "QSC"}; const int AZP = 101; const int SZP = 102; const int TAN = 103; const int STG = 104; const int SIN = 105; const int ARC = 106; const int ZPN = 107; const int ZEA = 108; const int AIR = 109; const int CYP = 201; const int CEA = 202; const int CAR = 203; const int MER = 204; const int SFL = 301; const int PAR = 302; const int MOL = 303; const int AIT = 401; const int COP = 501; const int COE = 502; const int COD = 503; const int COO = 504; const int BON = 601; const int PCO = 602; const int TSC = 701; const int CSC = 702; const int QSC = 703; /* Map error number to error message for each function. */ const char *prjset_errmsg[] = { 0, "Invalid projection parameters"}; const char *prjfwd_errmsg[] = { 0, "Invalid projection parameters", "Invalid value of (phi,theta)"}; const char *prjrev_errmsg[] = { 0, "Invalid projection parameters", "Invalid value of (x,y)"}; #define copysgn(X, Y) ((Y) < 0.0 ? -fabs(X) : fabs(X)) #define copysgni(X, Y) ((Y) < 0 ? -abs(X) : abs(X)) /*==========================================================================*/ int prjset(pcode, prj) const char pcode[4]; struct prjprm *prj; { /* Set pointers to the forward and reverse projection routines. */ if (strcmp(pcode, "AZP") == 0) { azpset(prj); } else if (strcmp(pcode, "SZP") == 0) { szpset(prj); } else if (strcmp(pcode, "TAN") == 0) { tanset(prj); } else if (strcmp(pcode, "STG") == 0) { stgset(prj); } else if (strcmp(pcode, "SIN") == 0) { sinset(prj); } else if (strcmp(pcode, "ARC") == 0) { arcset(prj); } else if (strcmp(pcode, "ZPN") == 0) { zpnset(prj); } else if (strcmp(pcode, "ZEA") == 0) { zeaset(prj); } else if (strcmp(pcode, "AIR") == 0) { airset(prj); } else if (strcmp(pcode, "CYP") == 0) { cypset(prj); } else if (strcmp(pcode, "CEA") == 0) { ceaset(prj); } else if (strcmp(pcode, "CAR") == 0) { carset(prj); } else if (strcmp(pcode, "MER") == 0) { merset(prj); } else if (strcmp(pcode, "SFL") == 0) { sflset(prj); } else if (strcmp(pcode, "PAR") == 0) { parset(prj); } else if (strcmp(pcode, "MOL") == 0) { molset(prj); } else if (strcmp(pcode, "AIT") == 0) { aitset(prj); } else if (strcmp(pcode, "COP") == 0) { copset(prj); } else if (strcmp(pcode, "COE") == 0) { coeset(prj); } else if (strcmp(pcode, "COD") == 0) { codset(prj); } else if (strcmp(pcode, "COO") == 0) { cooset(prj); } else if (strcmp(pcode, "BON") == 0) { bonset(prj); } else if (strcmp(pcode, "PCO") == 0) { pcoset(prj); } else if (strcmp(pcode, "TSC") == 0) { tscset(prj); } else if (strcmp(pcode, "CSC") == 0) { cscset(prj); } else if (strcmp(pcode, "QSC") == 0) { qscset(prj); } else { /* Unrecognized projection code. */ return 1; } return 0; } /*--------------------------------------------------------------------------*/ int prjfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { return prj->prjfwd(phi, theta, prj, x, y); } /*--------------------------------------------------------------------------*/ int prjrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { return prj->prjrev(x, y, prj, phi, theta); } /*============================================================================ * AZP: zenithal/azimuthal perspective projection. * * Given: * prj->p[1] Distance parameter, mu in units of r0. * prj->p[2] Tilt angle, gamma in degrees. * * Given and/or returned: * prj->flag AZP, or -AZP if prj->flag is given < 0. * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "AZP" * prj->phi0 0.0 * prj->theta0 90.0 * prj->w[0] r0*(mu+1) * prj->w[1] tan(gamma) * prj->w[2] sec(gamma) * prj->w[3] cos(gamma) * prj->w[4] sin(gamma) * prj->w[5] asin(-1/mu) for |mu| >= 1, -90 otherwise * prj->w[6] mu*cos(gamma) * prj->w[7] 1 if |mu*cos(gamma)| < 1, 0 otherwise * prj->prjfwd Pointer to azpfwd(). * prj->prjrev Pointer to azprev(). *===========================================================================*/ int azpset(prj) struct prjprm *prj; { strcpy(prj->code, "AZP"); prj->flag = copysgni (AZP, prj->flag); prj->phi0 = 0.0; prj->theta0 = 90.0; if (prj->r0 == 0.0) prj->r0 = R2D; prj->w[0] = prj->r0*(prj->p[1] + 1.0); if (prj->w[0] == 0.0) { return 1; } prj->w[3] = cosdeg (prj->p[2]); if (prj->w[3] == 0.0) { return 1; } prj->w[2] = 1.0/prj->w[3]; prj->w[4] = sindeg (prj->p[2]); prj->w[1] = prj->w[4] / prj->w[3]; if (fabs(prj->p[1]) > 1.0) { prj->w[5] = asindeg (-1.0/prj->p[1]); } else { prj->w[5] = -90.0; } prj->w[6] = prj->p[1] * prj->w[3]; prj->w[7] = (fabs(prj->w[6]) < 1.0) ? 1.0 : 0.0; prj->prjfwd = azpfwd; prj->prjrev = azprev; return 0; } /*--------------------------------------------------------------------------*/ int azpfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double a, b, cphi, cthe, r, s, t; if (abs(prj->flag) != AZP) { if (azpset(prj)) return 1; } cphi = cosdeg (phi); cthe = cosdeg (theta); s = prj->w[1]*cphi; t = (prj->p[1] + sindeg (theta)) + cthe*s; if (t == 0.0) { return 2; } r = prj->w[0]*cthe/t; *x = r*sindeg (phi); *y = -r*cphi*prj->w[2]; /* Bounds checking. */ if (prj->flag > 0) { /* Overlap. */ if (theta < prj->w[5]) { return 2; } /* Divergence. */ if (prj->w[7] > 0.0) { t = prj->p[1] / sqrt(1.0 + s*s); if (fabs(t) <= 1.0) { s = atandeg (-s); t = asindeg (t); a = s - t; b = s + t + 180.0; if (a > 90.0) a -= 360.0; if (b > 90.0) b -= 360.0; if (theta < ((a > b) ? a : b)) { return 2; } } } } return 0; } /*--------------------------------------------------------------------------*/ int azprev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double a, b, r, s, t, ycosg; const double tol = 1.0e-13; if (abs(prj->flag) != AZP) { if (azpset(prj)) return 1; } ycosg = y*prj->w[3]; r = sqrt(x*x + ycosg*ycosg); if (r == 0.0) { *phi = 0.0; *theta = 90.0; } else { *phi = atan2deg (x, -ycosg); s = r / (prj->w[0] + y*prj->w[4]); t = s*prj->p[1]/sqrt(s*s + 1.0); s = atan2deg (1.0, s); if (fabs(t) > 1.0) { t = copysgn (90.0,t); if (fabs(t) > 1.0+tol) { return 2; } } else { t = asindeg (t); } a = s - t; b = s + t + 180.0; if (a > 90.0) a -= 360.0; if (b > 90.0) b -= 360.0; *theta = (a > b) ? a : b; } return 0; } /*============================================================================ * SZP: slant zenithal perspective projection. * * Given: * prj->p[1] Distance of the point of projection from the centre of the * generating sphere, mu in units of r0. * prj->p[2] Native longitude, phi_c, and ... * prj->p[3] Native latitude, theta_c, on the planewards side of the * intersection of the line through the point of projection * and the centre of the generating sphere, phi_c in degrees. * * Given and/or returned: * prj->flag SZP, or -SZP if prj->flag is given < 0. * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "SZP" * prj->phi0 0.0 * prj->theta0 90.0 * prj->w[0] 1/r0 * prj->w[1] xp = -mu*cos(theta_c)*sin(phi_c) * prj->w[2] yp = mu*cos(theta_c)*cos(phi_c) * prj->w[3] zp = mu*sin(theta_c) + 1 * prj->w[4] r0*xp * prj->w[5] r0*yp * prj->w[6] r0*zp * prj->w[7] (zp - 1)^2 * prj->w[8] asin(1-zp) if |1 - zp| < 1, -90 otherwise * prj->prjfwd Pointer to szpfwd(). * prj->prjrev Pointer to szprev(). *===========================================================================*/ int szpset(prj) struct prjprm *prj; { strcpy(prj->code, "SZP"); prj->flag = copysgni (SZP, prj->flag); prj->phi0 = 0.0; prj->theta0 = 90.0; if (prj->r0 == 0.0) prj->r0 = R2D; prj->w[0] = 1.0/prj->r0; prj->w[3] = prj->p[1] * sindeg (prj->p[3]) + 1.0; if (prj->w[3] == 0.0) { return 1; } prj->w[1] = -prj->p[1] * cosdeg (prj->p[3]) * sindeg (prj->p[2]); prj->w[2] = prj->p[1] * cosdeg (prj->p[3]) * cosdeg (prj->p[2]); prj->w[4] = prj->r0 * prj->w[1]; prj->w[5] = prj->r0 * prj->w[2]; prj->w[6] = prj->r0 * prj->w[3]; prj->w[7] = (prj->w[3] - 1.0) * prj->w[3] - 1.0; if (fabs(prj->w[3] - 1.0) < 1.0) { prj->w[8] = asindeg (1.0 - prj->w[3]); } else { prj->w[8] = -90.0; } prj->prjfwd = szpfwd; prj->prjrev = szprev; return 0; } /*--------------------------------------------------------------------------*/ int szpfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double a, b, cphi, cthe, s, sphi, t; if (abs(prj->flag) != SZP) { if (szpset(prj)) return 1; } cphi = cosdeg (phi); sphi = sindeg (phi); cthe = cosdeg (theta); s = 1.0 - sindeg (theta); t = prj->w[3] - s; if (t == 0.0) { return 2; } *x = (prj->w[6]*cthe*sphi - prj->w[4]*s)/t; *y = -(prj->w[6]*cthe*cphi + prj->w[5]*s)/t; /* Bounds checking. */ if (prj->flag > 0) { /* Divergence. */ if (theta < prj->w[8]) { return 2; } /* Overlap. */ if (fabs(prj->p[1]) > 1.0) { s = prj->w[1]*sphi - prj->w[2]*cphi; t = 1.0/sqrt(prj->w[7] + s*s); if (fabs(t) <= 1.0) { s = atan2deg (s, prj->w[3] - 1.0); t = asindeg (t); a = s - t; b = s + t + 180.0; if (a > 90.0) a -= 360.0; if (b > 90.0) b -= 360.0; if (theta < ((a > b) ? a : b)) { return 2; } } } } return 0; } /*--------------------------------------------------------------------------*/ int szprev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double a, b, c, d, r2, sth1, sth2, sthe, sxy, t, x1, xp, y1, yp, z; const double tol = 1.0e-13; if (abs(prj->flag) != SZP) { if (szpset(prj)) return 1; } xp = x*prj->w[0]; yp = y*prj->w[0]; r2 = xp*xp + yp*yp; x1 = (xp - prj->w[1])/prj->w[3]; y1 = (yp - prj->w[2])/prj->w[3]; sxy = xp*x1 + yp*y1; if (r2 < 1.0e-10) { /* Use small angle formula. */ z = r2/2.0; *theta = 90.0 - R2D*sqrt(r2/(1.0 + sxy)); } else { t = x1*x1 + y1*y1; a = t + 1.0; b = sxy - t; c = r2 - sxy - sxy + t - 1.0; d = b*b - a*c; /* Check for a solution. */ if (d < 0.0) { return 2; } d = sqrt(d); /* Choose solution closest to pole. */ sth1 = (-b + d)/a; sth2 = (-b - d)/a; sthe = (sth1 > sth2) ? sth1 : sth2; if (sthe > 1.0) { if (sthe-1.0 < tol) { sthe = 1.0; } else { sthe = (sth1 < sth2) ? sth1 : sth2; } } if (sthe < -1.0) { if (sthe+1.0 > -tol) { sthe = -1.0; } } if (sthe > 1.0 || sthe < -1.0) { return 2; } *theta = asindeg (sthe); z = 1.0 - sthe; } *phi = atan2deg (xp - x1*z, -(yp - y1*z)); return 0; } /*============================================================================ * TAN: gnomonic projection. * * Given and/or returned: * prj->flag TAN, or -TAN if prj->flag is given < 0. * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "TAN" * prj->phi0 0.0 * prj->theta0 90.0 * prj->prjfwd Pointer to tanfwd(). * prj->prjrev Pointer to tanrev(). *===========================================================================*/ int tanset(prj) struct prjprm *prj; { int k; strcpy(prj->code, "TAN"); prj->flag = copysgni (TAN, prj->flag); prj->phi0 = 0.0; prj->theta0 = 90.0; if (prj->r0 == 0.0) prj->r0 = R2D; prj->prjfwd = tanfwd; prj->prjrev = tanrev; for (k = (MAXPV-1); k >= 0 && prj->ppv[k] == 0.0 && prj->ppv[k+MAXPV] == 0.0; k--); if (k < 0) k = 0; prj->npv = k; return 0; } /*--------------------------------------------------------------------------*/ int tanfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double r, s; double xp[2]; if (abs(prj->flag) != TAN) { if(tanset(prj)) return 1; } s = sindeg (theta); if (s <= 0.0) { return 2; } r = prj->r0*cosdeg (theta)/s; xp[0] = r*sindeg (phi); xp[1] = -r*cosdeg (phi); *x = prj->inv_x? poly_func(prj->inv_x, xp) : xp[0]; *y = prj->inv_y? poly_func(prj->inv_y, xp) : xp[1]; if (prj->flag > 0 && s < 0.0) { return 2; } return 0; } /*--------------------------------------------------------------------------*/ int tanrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double r; double xp; double yp; if (abs(prj->flag) != TAN) { if (tanset(prj)) return 1; } if (prj->npv) { raw_to_pv(prj, x,y, &xp, &yp); } else { xp = x; yp = y; } r = sqrt(xp*xp + yp*yp); if (r == 0.0) { *phi = 0.0; } else { *phi = atan2deg (xp, -yp); } *theta = atan2deg (prj->r0, r); return 0; } /*============================================================================ * STG: stereographic projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "STG" * prj->flag STG * prj->phi0 0.0 * prj->theta0 90.0 * prj->w[0] 2*r0 * prj->w[1] 1/(2*r0) * prj->prjfwd Pointer to stgfwd(). * prj->prjrev Pointer to stgrev(). *===========================================================================*/ int stgset(prj) struct prjprm *prj; { strcpy(prj->code, "STG"); prj->flag = STG; prj->phi0 = 0.0; prj->theta0 = 90.0; if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[0] = 360.0/PI; prj->w[1] = PI/360.0; } else { prj->w[0] = 2.0*prj->r0; prj->w[1] = 1.0/prj->w[0]; } prj->prjfwd = stgfwd; prj->prjrev = stgrev; return 0; } /*--------------------------------------------------------------------------*/ int stgfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double r, s; if (prj->flag != STG) { if (stgset(prj)) return 1; } s = 1.0 + sindeg (theta); if (s == 0.0) { return 2; } r = prj->w[0]*cosdeg (theta)/s; *x = r*sindeg (phi); *y = -r*cosdeg (phi); return 0; } /*--------------------------------------------------------------------------*/ int stgrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double r; if (prj->flag != STG) { if (stgset(prj)) return 1; } r = sqrt(x*x + y*y); if (r == 0.0) { *phi = 0.0; } else { *phi = atan2deg (x, -y); } *theta = 90.0 - 2.0*atandeg (r*prj->w[1]); return 0; } /*============================================================================ * SIN: orthographic/synthesis projection. * * Given: * prj->p[1:2] Obliqueness parameters, xi and eta. * * Given and/or returned: * prj->flag SIN, or -SIN if prj->flag is given < 0. * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "SIN" * prj->phi0 0.0 * prj->theta0 90.0 * prj->w[0] 1/r0 * prj->w[1] xi**2 + eta**2 * prj->w[2] xi**2 + eta**2 + 1 * prj->w[3] xi**2 + eta**2 - 1 * prj->prjfwd Pointer to sinfwd(). * prj->prjrev Pointer to sinrev(). *===========================================================================*/ int sinset(prj) struct prjprm *prj; { strcpy(prj->code, "SIN"); prj->flag = copysgni (SIN, prj->flag); prj->phi0 = 0.0; prj->theta0 = 90.0; if (prj->r0 == 0.0) prj->r0 = R2D; prj->w[0] = 1.0/prj->r0; prj->w[1] = prj->p[1]*prj->p[1] + prj->p[2]*prj->p[2]; prj->w[2] = prj->w[1] + 1.0; prj->w[3] = prj->w[1] - 1.0; prj->prjfwd = sinfwd; prj->prjrev = sinrev; return 0; } /*--------------------------------------------------------------------------*/ int sinfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double cphi, cthe, sphi, t, z; if (abs(prj->flag) != SIN) { if (sinset(prj)) return 1; } t = (90.0 - fabs(theta))*D2R; if (t < 1.0e-5) { if (theta > 0.0) { z = t*t/2.0; } else { z = 2.0 - t*t/2.0; } cthe = t; } else { z = 1.0 - sindeg (theta); cthe = cosdeg (theta); } cphi = cosdeg (phi); sphi = sindeg (phi); *x = prj->r0*(cthe*sphi + prj->p[1]*z); *y = -prj->r0*(cthe*cphi - prj->p[2]*z); /* Validate this solution. */ if (prj->flag > 0) { if (prj->w[1] == 0.0) { /* Orthographic projection. */ if (theta < 0.0) { return 2; } } else { /* "Synthesis" projection. */ t = -atandeg (prj->p[1]*sphi - prj->p[2]*cphi); if (theta < t) { return 2; } } } return 0; } /*--------------------------------------------------------------------------*/ int sinrev (x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { const double tol = 1.0e-13; double a, b, c, d, r2, sth1, sth2, sthe, sxy, x0, x1, xp, y0, y1, yp, z; if (abs(prj->flag) != SIN) { if (sinset(prj)) return 1; } /* Compute intermediaries. */ x0 = x*prj->w[0]; y0 = y*prj->w[0]; r2 = x0*x0 + y0*y0; if (prj->w[1] == 0.0) { /* Orthographic projection. */ if (r2 != 0.0) { *phi = atan2deg (x0, -y0); } else { *phi = 0.0; } if (r2 < 0.5) { *theta = acosdeg (sqrt(r2)); } else if (r2 <= 1.0) { *theta = asindeg (sqrt(1.0 - r2)); } else { return 2; } } else { /* "Synthesis" projection. */ x1 = prj->p[1]; y1 = prj->p[2]; sxy = x0*x1 + y0*y1; if (r2 < 1.0e-10) { /* Use small angle formula. */ z = r2/2.0; *theta = 90.0 - R2D*sqrt(r2/(1.0 + sxy)); } else { a = prj->w[2]; b = sxy - prj->w[1]; c = r2 - sxy - sxy + prj->w[3]; d = b*b - a*c; /* Check for a solution. */ if (d < 0.0) { return 2; } d = sqrt(d); /* Choose solution closest to pole. */ sth1 = (-b + d)/a; sth2 = (-b - d)/a; sthe = (sth1 > sth2) ? sth1 : sth2; if (sthe > 1.0) { if (sthe-1.0 < tol) { sthe = 1.0; } else { sthe = (sth1 < sth2) ? sth1 : sth2; } } if (sthe < -1.0) { if (sthe+1.0 > -tol) { sthe = -1.0; } } if (sthe > 1.0 || sthe < -1.0) { return 2; } *theta = asindeg (sthe); z = 1.0 - sthe; } xp = -y0 + prj->p[2]*z; yp = x0 - prj->p[1]*z; if (xp == 0.0 && yp == 0.0) { *phi = 0.0; } else { *phi = atan2deg (yp,xp); } } return 0; } /*============================================================================ * ARC: zenithal/azimuthal equidistant projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "ARC" * prj->flag ARC * prj->phi0 0.0 * prj->theta0 90.0 * prj->w[0] r0*(pi/180) * prj->w[1] (180/pi)/r0 * prj->prjfwd Pointer to arcfwd(). * prj->prjrev Pointer to arcrev(). *===========================================================================*/ int arcset(prj) struct prjprm *prj; { strcpy(prj->code, "ARC"); prj->flag = ARC; prj->phi0 = 0.0; prj->theta0 = 90.0; if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[0] = 1.0; prj->w[1] = 1.0; } else { prj->w[0] = prj->r0*D2R; prj->w[1] = 1.0/prj->w[0]; } prj->prjfwd = arcfwd; prj->prjrev = arcrev; return 0; } /*--------------------------------------------------------------------------*/ int arcfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double r; if (prj->flag != ARC) { if (arcset(prj)) return 1; } r = prj->w[0]*(90.0 - theta); *x = r*sindeg (phi); *y = -r*cosdeg (phi); return 0; } /*--------------------------------------------------------------------------*/ int arcrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double r; if (prj->flag != ARC) { if (arcset(prj)) return 1; } r = sqrt(x*x + y*y); if (r == 0.0) { *phi = 0.0; } else { *phi = atan2deg (x, -y); } *theta = 90.0 - r*prj->w[1]; return 0; } /*============================================================================ * ZPN: zenithal/azimuthal polynomial projection. * * Given: * prj->p[0:9] Polynomial coefficients. * * Given and/or returned: * prj->flag ZPN, or -ZPN if prj->flag is given < 0. * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "ZPN" * prj->phi0 0.0 * prj->theta0 90.0 * prj->n Degree of the polynomial, N. * prj->w[0] Co-latitude of the first point of inflection (N > 2). * prj->w[1] Radius of the first point of inflection (N > 2). * prj->prjfwd Pointer to zpnfwd(). * prj->prjrev Pointer to zpnrev(). *===========================================================================*/ int zpnset(prj) struct prjprm *prj; { int i, j, k; double d, d1, d2, r, zd, zd1, zd2; const double tol = 1.0e-13; strcpy(prj->code, "ZPN"); prj->flag = copysgni (ZPN, prj->flag); prj->phi0 = 0.0; prj->theta0 = 90.0; if (prj->r0 == 0.0) prj->r0 = R2D; /* Find the highest non-zero coefficient. */ for (k = 9; k >= 0 && prj->p[k] == 0.0; k--){ i = 0; } /* if (k < 0) return 1; */ /* if (k < 0 switch to ARC projection */ if (k < 0) { return (arcset (prj)); } prj->n = k; /* No negative derivative -> no point of inflection. */ zd = PI; /* Processing subroutines */ prj->prjfwd = zpnfwd; prj->prjrev = zpnrev; if (k >= 3) { /* Find the point of inflection closest to the pole. */ zd1 = 0.0; d1 = prj->p[1]; if (d1 <= 0.0) { return 1; } /* Find the point where the derivative first goes negative. */ for (i = 0; i < 180; i++) { zd2 = i*D2R; d2 = 0.0; for (j = k; j > 0; j--) { d2 = d2*zd2 + j*prj->p[j]; } if (d2 <= 0.0) break; zd1 = zd2; d1 = d2; } if (i == 180) { /* No negative derivative -> no point of inflection. */ zd = PI; } else { /* Find where the derivative is zero. */ for (i = 1; i <= 10; i++) { zd = zd1 - d1*(zd2-zd1)/(d2-d1); d = 0.0; for (j = k; j > 0; j--) { d = d*zd + j*prj->p[j]; } if (fabs(d) < tol) break; if (d < 0.0) { zd2 = zd; d2 = d; } else { zd1 = zd; d1 = d; } } } r = 0.0; for (j = k; j >= 0; j--) { r = r*zd + prj->p[j]; } prj->w[0] = zd; prj->w[1] = r; } return 0; } /*--------------------------------------------------------------------------*/ int zpnfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { int j; double r, s; if (abs(prj->flag) != ZPN) { if (zpnset(prj)) return 1; } s = (90.0 - theta)*D2R; r = 0.0; for (j = 9; j >= 0; j--) { r = r*s + prj->p[j]; } r = prj->r0*r; *x = r*sindeg (phi); *y = -r*cosdeg (phi); if (prj->flag > 0 && s > prj->w[0]) { return 2; } return 0; } /*--------------------------------------------------------------------------*/ int zpnrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { int i, j, k; double a, b, c, d, lambda, r, r1, r2, rt, zd, zd1, zd2; const double tol = 1.0e-13; if (abs(prj->flag) != ZPN) { if (zpnset(prj)) return 1; } k = prj->n; r = sqrt(x*x + y*y)/prj->r0; if (k < 1) { /* Constant - no solution. */ return 1; } else if (k == 1) { /* Linear. */ zd = (r - prj->p[0])/prj->p[1]; } else if (k == 2) { /* Quadratic. */ a = prj->p[2]; b = prj->p[1]; c = prj->p[0] - r; d = b*b - 4.0*a*c; if (d < 0.0) { return 2; } d = sqrt(d); /* Choose solution closest to pole. */ zd1 = (-b + d)/(2.0*a); zd2 = (-b - d)/(2.0*a); zd = (zd1zd2) ? zd1 : zd2; if (zd < 0.0) { if (zd < -tol) { return 2; } zd = 0.0; } else if (zd > PI) { if (zd > PI+tol) { return 2; } zd = PI; } } else { /* Higher order - solve iteratively. */ zd1 = 0.0; r1 = prj->p[0]; zd2 = prj->w[0]; r2 = prj->w[1]; if (r < r1) { if (r < r1-tol) { return 2; } zd = zd1; } else if (r > r2) { if (r > r2+tol) { return 2; } zd = zd2; } else { /* Disect the interval. */ for (j = 0; j < 100; j++) { lambda = (r2 - r)/(r2 - r1); if (lambda < 0.1) { lambda = 0.1; } else if (lambda > 0.9) { lambda = 0.9; } zd = zd2 - lambda*(zd2 - zd1); rt = 0.0; for (i = k; i >= 0; i--) { rt = (rt * zd) + prj->p[i]; } if (rt < r) { if (r-rt < tol) break; r1 = rt; zd1 = zd; } else { if (rt-r < tol) break; r2 = rt; zd2 = zd; } if (fabs(zd2-zd1) < tol) break; } } } if (r == 0.0) { *phi = 0.0; } else { *phi = atan2deg (x, -y); } *theta = 90.0 - zd*R2D; return 0; } /*============================================================================ * ZEA: zenithal/azimuthal equal area projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "ZEA" * prj->flag ZEA * prj->phi0 0.0 * prj->theta0 90.0 * prj->w[0] 2*r0 * prj->w[1] 1/(2*r0) * prj->prjfwd Pointer to zeafwd(). * prj->prjrev Pointer to zearev(). *===========================================================================*/ int zeaset(prj) struct prjprm *prj; { strcpy(prj->code, "ZEA"); prj->flag = ZEA; prj->phi0 = 0.0; prj->theta0 = 90.0; if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[0] = 360.0/PI; prj->w[1] = PI/360.0; } else { prj->w[0] = 2.0*prj->r0; prj->w[1] = 1.0/prj->w[0]; } prj->prjfwd = zeafwd; prj->prjrev = zearev; return 0; } /*--------------------------------------------------------------------------*/ int zeafwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double r; if (prj->flag != ZEA) { if (zeaset(prj)) return 1; } r = prj->w[0]*sindeg ((90.0 - theta)/2.0); *x = r*sindeg (phi); *y = -r*cosdeg (phi); return 0; } /*--------------------------------------------------------------------------*/ int zearev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double r, s; const double tol = 1.0e-12; if (prj->flag != ZEA) { if (zeaset(prj)) return 1; } r = sqrt(x*x + y*y); if (r == 0.0) { *phi = 0.0; } else { *phi = atan2deg (x, -y); } s = r*prj->w[1]; if (fabs(s) > 1.0) { if (fabs(r - prj->w[0]) < tol) { *theta = -90.0; } else { return 2; } } else { *theta = 90.0 - 2.0*asindeg (s); } return 0; } /*============================================================================ * AIR: Airy's projection. * * Given: * prj->p[1] Latitude theta_b within which the error is minimized, in * degrees. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "AIR" * prj->flag AIR * prj->phi0 0.0 * prj->theta0 90.0 * prj->w[0] 2*r0 * prj->w[1] ln(cos(xi_b))/tan(xi_b)**2, where xi_b = (90-theta_b)/2 * prj->w[2] 1/2 - prj->w[1] * prj->w[3] 2*r0*prj->w[2] * prj->w[4] tol, cutoff for using small angle approximation, in * radians. * prj->w[5] prj->w[2]*tol * prj->w[6] (180/pi)/prj->w[2] * prj->prjfwd Pointer to airfwd(). * prj->prjrev Pointer to airrev(). *===========================================================================*/ int airset(prj) struct prjprm *prj; { const double tol = 1.0e-4; double cxi; strcpy(prj->code, "AIR"); prj->flag = AIR; prj->phi0 = 0.0; prj->theta0 = 90.0; if (prj->r0 == 0.0) prj->r0 = R2D; prj->w[0] = 2.0*prj->r0; if (prj->p[1] == 90.0) { prj->w[1] = -0.5; prj->w[2] = 1.0; } else if (prj->p[1] > -90.0) { cxi = cosdeg ((90.0 - prj->p[1])/2.0); prj->w[1] = log(cxi)*(cxi*cxi)/(1.0-cxi*cxi); prj->w[2] = 0.5 - prj->w[1]; } else { return 1; } prj->w[3] = prj->w[0] * prj->w[2]; prj->w[4] = tol; prj->w[5] = prj->w[2]*tol; prj->w[6] = R2D/prj->w[2]; prj->prjfwd = airfwd; prj->prjrev = airrev; return 0; } /*--------------------------------------------------------------------------*/ int airfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double cxi, r, txi, xi; if (prj->flag != AIR) { if (airset(prj)) return 1; } if (theta == 90.0) { r = 0.0; } else if (theta > -90.0) { xi = D2R*(90.0 - theta)/2.0; if (xi < prj->w[4]) { r = xi*prj->w[3]; } else { cxi = cosdeg ((90.0 - theta)/2.0); txi = sqrt(1.0-cxi*cxi)/cxi; r = -prj->w[0]*(log(cxi)/txi + prj->w[1]*txi); } } else { return 2; } *x = r*sindeg (phi); *y = -r*cosdeg (phi); return 0; } /*--------------------------------------------------------------------------*/ int airrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { int j; double cxi, lambda, r, r1, r2, rt, txi, x1, x2, xi; const double tol = 1.0e-12; if (prj->flag != AIR) { if (airset(prj)) return 1; } r = sqrt(x*x + y*y)/prj->w[0]; if (r == 0.0) { xi = 0.0; } else if (r < prj->w[5]) { xi = r*prj->w[6]; } else { /* Find a solution interval. */ x1 = 1.0; r1 = 0.0; for (j = 0; j < 30; j++) { x2 = x1/2.0; txi = sqrt(1.0-x2*x2)/x2; r2 = -(log(x2)/txi + prj->w[1]*txi); if (r2 >= r) break; x1 = x2; r1 = r2; } if (j == 30) return 2; for (j = 0; j < 100; j++) { /* Weighted division of the interval. */ lambda = (r2-r)/(r2-r1); if (lambda < 0.1) { lambda = 0.1; } else if (lambda > 0.9) { lambda = 0.9; } cxi = x2 - lambda*(x2-x1); txi = sqrt(1.0-cxi*cxi)/cxi; rt = -(log(cxi)/txi + prj->w[1]*txi); if (rt < r) { if (r-rt < tol) break; r1 = rt; x1 = cxi; } else { if (rt-r < tol) break; r2 = rt; x2 = cxi; } } if (j == 100) return 2; xi = acosdeg (cxi); } if (r == 0.0) { *phi = 0.0; } else { *phi = atan2deg (x, -y); } *theta = 90.0 - 2.0*xi; return 0; } /*============================================================================ * CYP: cylindrical perspective projection. * * Given: * prj->p[1] Distance of point of projection from the centre of the * generating sphere, mu, in units of r0. * prj->p[2] Radius of the cylinder of projection, lambda, in units of * r0. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "CYP" * prj->flag CYP * prj->phi0 0.0 * prj->theta0 0.0 * prj->w[0] r0*lambda*(pi/180) * prj->w[1] (180/pi)/(r0*lambda) * prj->w[2] r0*(mu + lambda) * prj->w[3] 1/(r0*(mu + lambda)) * prj->prjfwd Pointer to cypfwd(). * prj->prjrev Pointer to cyprev(). *===========================================================================*/ int cypset(prj) struct prjprm *prj; { strcpy(prj->code, "CYP"); prj->flag = CYP; prj->phi0 = 0.0; prj->theta0 = 0.0; if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[0] = prj->p[2]; if (prj->w[0] == 0.0) { return 1; } prj->w[1] = 1.0/prj->w[0]; prj->w[2] = R2D*(prj->p[1] + prj->p[2]); if (prj->w[2] == 0.0) { return 1; } prj->w[3] = 1.0/prj->w[2]; } else { prj->w[0] = prj->r0*prj->p[2]*D2R; if (prj->w[0] == 0.0) { return 1; } prj->w[1] = 1.0/prj->w[0]; prj->w[2] = prj->r0*(prj->p[1] + prj->p[2]); if (prj->w[2] == 0.0) { return 1; } prj->w[3] = 1.0/prj->w[2]; } prj->prjfwd = cypfwd; prj->prjrev = cyprev; return 0; } /*--------------------------------------------------------------------------*/ int cypfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double s; if (prj->flag != CYP) { if (cypset(prj)) return 1; } s = prj->p[1] + cosdeg (theta); if (s == 0.0) { return 2; } *x = prj->w[0]*phi; *y = prj->w[2]*sindeg (theta)/s; return 0; } /*--------------------------------------------------------------------------*/ int cyprev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double eta; if (prj->flag != CYP) { if (cypset(prj)) return 1; } *phi = x*prj->w[1]; eta = y*prj->w[3]; *theta = atan2deg (eta,1.0) + asindeg (eta*prj->p[1]/sqrt(eta*eta+1.0)); return 0; } /*============================================================================ * CEA: cylindrical equal area projection. * * Given: * prj->p[1] Square of the cosine of the latitude at which the * projection is conformal, lambda. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "CEA" * prj->flag CEA * prj->phi0 0.0 * prj->theta0 0.0 * prj->w[0] r0*(pi/180) * prj->w[1] (180/pi)/r0 * prj->w[2] r0/lambda * prj->w[3] lambda/r0 * prj->prjfwd Pointer to ceafwd(). * prj->prjrev Pointer to cearev(). *===========================================================================*/ int ceaset(prj) struct prjprm *prj; { strcpy(prj->code, "CEA"); prj->flag = CEA; prj->phi0 = 0.0; prj->theta0 = 0.0; if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[0] = 1.0; prj->w[1] = 1.0; if (prj->p[1] <= 0.0 || prj->p[1] > 1.0) { return 1; } prj->w[2] = prj->r0/prj->p[1]; prj->w[3] = prj->p[1]/prj->r0; } else { prj->w[0] = prj->r0*D2R; prj->w[1] = R2D/prj->r0; if (prj->p[1] <= 0.0 || prj->p[1] > 1.0) { return 1; } prj->w[2] = prj->r0/prj->p[1]; prj->w[3] = prj->p[1]/prj->r0; } prj->prjfwd = ceafwd; prj->prjrev = cearev; return 0; } /*--------------------------------------------------------------------------*/ int ceafwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { if (prj->flag != CEA) { if (ceaset(prj)) return 1; } *x = prj->w[0]*phi; *y = prj->w[2]*sindeg (theta); return 0; } /*--------------------------------------------------------------------------*/ int cearev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double s; const double tol = 1.0e-13; if (prj->flag != CEA) { if (ceaset(prj)) return 1; } s = y*prj->w[3]; if (fabs(s) > 1.0) { if (fabs(s) > 1.0+tol) { return 2; } s = copysgn (1.0,s); } *phi = x*prj->w[1]; *theta = asindeg (s); return 0; } /*============================================================================ * CAR: Cartesian projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "CAR" * prj->flag CAR * prj->phi0 0.0 * prj->theta0 0.0 * prj->w[0] r0*(pi/180) * prj->w[1] (180/pi)/r0 * prj->prjfwd Pointer to carfwd(). * prj->prjrev Pointer to carrev(). *===========================================================================*/ int carset(prj) struct prjprm *prj; { strcpy(prj->code, "CAR"); prj->flag = CAR; prj->phi0 = 0.0; prj->theta0 = 0.0; if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[0] = 1.0; prj->w[1] = 1.0; } else { prj->w[0] = prj->r0*D2R; prj->w[1] = 1.0/prj->w[0]; } prj->prjfwd = carfwd; prj->prjrev = carrev; return 0; } /*--------------------------------------------------------------------------*/ int carfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { if (prj->flag != CAR) { if (carset(prj)) return 1; } *x = prj->w[0]*phi; *y = prj->w[0]*theta; return 0; } /*--------------------------------------------------------------------------*/ int carrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { if (prj->flag != CAR) { if (carset(prj)) return 1; } *phi = prj->w[1]*x; *theta = prj->w[1]*y; return 0; } /*============================================================================ * MER: Mercator's projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "MER" * prj->flag MER * prj->phi0 0.0 * prj->theta0 0.0 * prj->w[0] r0*(pi/180) * prj->w[1] (180/pi)/r0 * prj->prjfwd Pointer to merfwd(). * prj->prjrev Pointer to merrev(). *===========================================================================*/ int merset(prj) struct prjprm *prj; { strcpy(prj->code, "MER"); prj->flag = MER; prj->phi0 = 0.0; prj->theta0 = 0.0; if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[0] = 1.0; prj->w[1] = 1.0; } else { prj->w[0] = prj->r0*D2R; prj->w[1] = 1.0/prj->w[0]; } prj->prjfwd = merfwd; prj->prjrev = merrev; return 0; } /*--------------------------------------------------------------------------*/ int merfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { if (prj->flag != MER) { if (merset(prj)) return 1; } if (theta <= -90.0 || theta >= 90.0) { return 2; } *x = prj->w[0]*phi; *y = prj->r0*log(tandeg ((90.0+theta)/2.0)); return 0; } /*--------------------------------------------------------------------------*/ int merrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { if (prj->flag != MER) { if (merset(prj)) return 1; } *phi = x*prj->w[1]; *theta = 2.0*atandeg (exp(y/prj->r0)) - 90.0; return 0; } /*============================================================================ * SFL: Sanson-Flamsteed ("global sinusoid") projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "SFL" * prj->flag SFL * prj->phi0 0.0 * prj->theta0 0.0 * prj->w[0] r0*(pi/180) * prj->w[1] (180/pi)/r0 * prj->prjfwd Pointer to sflfwd(). * prj->prjrev Pointer to sflrev(). *===========================================================================*/ int sflset(prj) struct prjprm *prj; { strcpy(prj->code, "SFL"); prj->flag = SFL; prj->phi0 = 0.0; prj->theta0 = 0.0; if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[0] = 1.0; prj->w[1] = 1.0; } else { prj->w[0] = prj->r0*D2R; prj->w[1] = 1.0/prj->w[0]; } prj->prjfwd = sflfwd; prj->prjrev = sflrev; return 0; } /*--------------------------------------------------------------------------*/ int sflfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { if (prj->flag != SFL) { if (sflset(prj)) return 1; } *x = prj->w[0]*phi*cosdeg (theta); *y = prj->w[0]*theta; return 0; } /*--------------------------------------------------------------------------*/ int sflrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double w; if (prj->flag != SFL) { if (sflset(prj)) return 1; } w = cos(y/prj->r0); if (w == 0.0) { *phi = 0.0; } else { *phi = x*prj->w[1]/cos(y/prj->r0); } *theta = y*prj->w[1]; return 0; } /*============================================================================ * PAR: parabolic projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "PAR" * prj->flag PAR * prj->phi0 0.0 * prj->theta0 0.0 * prj->w[0] r0*(pi/180) * prj->w[1] (180/pi)/r0 * prj->w[2] pi*r0 * prj->w[3] 1/(pi*r0) * prj->prjfwd Pointer to parfwd(). * prj->prjrev Pointer to parrev(). *===========================================================================*/ int parset(prj) struct prjprm *prj; { strcpy(prj->code, "PAR"); prj->flag = PAR; prj->phi0 = 0.0; prj->theta0 = 0.0; if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[0] = 1.0; prj->w[1] = 1.0; prj->w[2] = 180.0; prj->w[3] = 1.0/prj->w[2]; } else { prj->w[0] = prj->r0*D2R; prj->w[1] = 1.0/prj->w[0]; prj->w[2] = PI*prj->r0; prj->w[3] = 1.0/prj->w[2]; } prj->prjfwd = parfwd; prj->prjrev = parrev; return 0; } /*--------------------------------------------------------------------------*/ int parfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double s; if (prj->flag != PAR) { if (parset(prj)) return 1; } s = sindeg (theta/3.0); *x = prj->w[0]*phi*(1.0 - 4.0*s*s); *y = prj->w[2]*s; return 0; } /*--------------------------------------------------------------------------*/ int parrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double s, t; if (prj->flag != PAR) { if (parset(prj)) return 1; } s = y*prj->w[3]; if (s > 1.0 || s < -1.0) { return 2; } t = 1.0 - 4.0*s*s; if (t == 0.0) { if (x == 0.0) { *phi = 0.0; } else { return 2; } } else { *phi = prj->w[1]*x/t; } *theta = 3.0*asindeg (s); return 0; } /*============================================================================ * MOL: Mollweide's projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "MOL" * prj->flag MOL * prj->phi0 0.0 * prj->theta0 0.0 * prj->w[0] sqrt(2)*r0 * prj->w[1] sqrt(2)*r0/90 * prj->w[2] 1/(sqrt(2)*r0) * prj->w[3] 90/r0 * prj->prjfwd Pointer to molfwd(). * prj->prjrev Pointer to molrev(). *===========================================================================*/ int molset(prj) struct prjprm *prj; { strcpy(prj->code, "MOL"); prj->flag = MOL; prj->phi0 = 0.0; prj->theta0 = 0.0; if (prj->r0 == 0.0) prj->r0 = R2D; prj->w[0] = SQRT2*prj->r0; prj->w[1] = prj->w[0]/90.0; prj->w[2] = 1.0/prj->w[0]; prj->w[3] = 90.0/prj->r0; prj->w[4] = 2.0/PI; prj->prjfwd = molfwd; prj->prjrev = molrev; return 0; } /*--------------------------------------------------------------------------*/ int molfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { int j; double gamma, resid, u, v, v0, v1; const double tol = 1.0e-13; if (prj->flag != MOL) { if (molset(prj)) return 1; } if (fabs(theta) == 90.0) { *x = 0.0; *y = copysgn (prj->w[0],theta); } else if (theta == 0.0) { *x = prj->w[1]*phi; *y = 0.0; } else { u = PI*sindeg (theta); v0 = -PI; v1 = PI; v = u; for (j = 0; j < 100; j++) { resid = (v - u) + sin(v); if (resid < 0.0) { if (resid > -tol) break; v0 = v; } else { if (resid < tol) break; v1 = v; } v = (v0 + v1)/2.0; } gamma = v/2.0; *x = prj->w[1]*phi*cos(gamma); *y = prj->w[0]*sin(gamma); } return 0; } /*--------------------------------------------------------------------------*/ int molrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double s, y0, z; const double tol = 1.0e-12; if (prj->flag != MOL) { if (molset(prj)) return 1; } y0 = y/prj->r0; s = 2.0 - y0*y0; if (s <= tol) { if (s < -tol) { return 2; } s = 0.0; if (fabs(x) > tol) { return 2; } *phi = 0.0; } else { s = sqrt(s); *phi = prj->w[3]*x/s; } z = y*prj->w[2]; if (fabs(z) > 1.0) { if (fabs(z) > 1.0+tol) { return 2; } z = copysgn (1.0,z) + y0*s/PI; } else { z = asin(z)*prj->w[4] + y0*s/PI; } if (fabs(z) > 1.0) { if (fabs(z) > 1.0+tol) { return 2; } z = copysgn (1.0,z); } *theta = asindeg (z); return 0; } /*============================================================================ * AIT: Hammer-Aitoff projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "AIT" * prj->flag AIT * prj->phi0 0.0 * prj->theta0 0.0 * prj->w[0] 2*r0**2 * prj->w[1] 1/(2*r0)**2 * prj->w[2] 1/(4*r0)**2 * prj->w[3] 1/(2*r0) * prj->prjfwd Pointer to aitfwd(). * prj->prjrev Pointer to aitrev(). *===========================================================================*/ int aitset(prj) struct prjprm *prj; { strcpy(prj->code, "AIT"); prj->flag = AIT; prj->phi0 = 0.0; prj->theta0 = 0.0; if (prj->r0 == 0.0) prj->r0 = R2D; prj->w[0] = 2.0*prj->r0*prj->r0; prj->w[1] = 1.0/(2.0*prj->w[0]); prj->w[2] = prj->w[1]/4.0; prj->w[3] = 1.0/(2.0*prj->r0); prj->prjfwd = aitfwd; prj->prjrev = aitrev; return 0; } /*--------------------------------------------------------------------------*/ int aitfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double cthe, w; if (prj->flag != AIT) { if (aitset(prj)) return 1; } cthe = cosdeg (theta); w = sqrt(prj->w[0]/(1.0 + cthe*cosdeg (phi/2.0))); *x = 2.0*w*cthe*sindeg (phi/2.0); *y = w*sindeg (theta); return 0; } /*--------------------------------------------------------------------------*/ int aitrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double s, u, xp, yp, z; const double tol = 1.0e-13; if (prj->flag != AIT) { if (aitset(prj)) return 1; } u = 1.0 - x*x*prj->w[2] - y*y*prj->w[1]; if (u < 0.0) { if (u < -tol) { return 2; } u = 0.0; } z = sqrt(u); s = z*y/prj->r0; if (fabs(s) > 1.0) { if (fabs(s) > 1.0+tol) { return 2; } s = copysgn (1.0,s); } xp = 2.0*z*z - 1.0; yp = z*x*prj->w[3]; if (xp == 0.0 && yp == 0.0) { *phi = 0.0; } else { *phi = 2.0*atan2deg (yp, xp); } *theta = asindeg (s); return 0; } /*============================================================================ * COP: conic perspective projection. * * Given: * prj->p[1] sigma = (theta2+theta1)/2 * prj->p[2] delta = (theta2-theta1)/2, where theta1 and theta2 are the * latitudes of the standard parallels, in degrees. * * Given and/or returned: * prj->flag COP, or -COP if prj->flag is given < 0. * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "COP" * prj->phi0 0.0 * prj->theta0 sigma * prj->w[0] C = sin(sigma) * prj->w[1] 1/C * prj->w[2] Y0 = r0*cos(delta)*cot(sigma) * prj->w[3] r0*cos(delta) * prj->w[4] 1/(r0*cos(delta) * prj->w[5] cot(sigma) * prj->prjfwd Pointer to copfwd(). * prj->prjrev Pointer to coprev(). *===========================================================================*/ int copset(prj) struct prjprm *prj; { strcpy(prj->code, "COP"); prj->flag = copysgni (COP, prj->flag); prj->phi0 = 0.0; prj->theta0 = prj->p[1]; if (prj->r0 == 0.0) prj->r0 = R2D; prj->w[0] = sindeg (prj->p[1]); if (prj->w[0] == 0.0) { return 1; } prj->w[1] = 1.0/prj->w[0]; prj->w[3] = prj->r0*cosdeg (prj->p[2]); if (prj->w[3] == 0.0) { return 1; } prj->w[4] = 1.0/prj->w[3]; prj->w[5] = 1.0/tandeg (prj->p[1]); prj->w[2] = prj->w[3]*prj->w[5]; prj->prjfwd = copfwd; prj->prjrev = coprev; return 0; } /*--------------------------------------------------------------------------*/ int copfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double a, r, s, t; if (abs(prj->flag) != COP) { if (copset(prj)) return 1; } t = theta - prj->p[1]; s = cosdeg (t); if (s == 0.0) { return 2; } a = prj->w[0]*phi; r = prj->w[2] - prj->w[3]*sindeg (t)/s; *x = r*sindeg (a); *y = prj->w[2] - r*cosdeg (a); if (prj->flag > 0 && r*prj->w[0] < 0.0) { return 2; } return 0; } /*--------------------------------------------------------------------------*/ int coprev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double a, dy, r; if (abs(prj->flag) != COP) { if (copset(prj)) return 1; } dy = prj->w[2] - y; r = sqrt(x*x + dy*dy); if (prj->p[1] < 0.0) r = -r; if (r == 0.0) { a = 0.0; } else { a = atan2deg (x/r, dy/r); } *phi = a*prj->w[1]; *theta = prj->p[1] + atandeg (prj->w[5] - r*prj->w[4]); return 0; } /*============================================================================ * COE: conic equal area projection. * * Given: * prj->p[1] sigma = (theta2+theta1)/2 * prj->p[2] delta = (theta2-theta1)/2, where theta1 and theta2 are the * latitudes of the standard parallels, in degrees. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "COE" * prj->flag COE * prj->phi0 0.0 * prj->theta0 sigma * prj->w[0] C = (sin(theta1) + sin(theta2))/2 * prj->w[1] 1/C * prj->w[2] Y0 = chi*sqrt(psi - 2C*sindeg (sigma)) * prj->w[3] chi = r0/C * prj->w[4] psi = 1 + sin(theta1)*sin(theta2) * prj->w[5] 2C * prj->w[6] (1 + sin(theta1)*sin(theta2))*(r0/C)**2 * prj->w[7] C/(2*r0**2) * prj->w[8] chi*sqrt(psi + 2C) * prj->prjfwd Pointer to coefwd(). * prj->prjrev Pointer to coerev(). *===========================================================================*/ int coeset(prj) struct prjprm *prj; { double theta1, theta2; strcpy(prj->code, "COE"); prj->flag = COE; prj->phi0 = 0.0; prj->theta0 = prj->p[1]; if (prj->r0 == 0.0) prj->r0 = R2D; theta1 = prj->p[1] - prj->p[2]; theta2 = prj->p[1] + prj->p[2]; prj->w[0] = (sindeg (theta1) + sindeg (theta2))/2.0; if (prj->w[0] == 0.0) { return 1; } prj->w[1] = 1.0/prj->w[0]; prj->w[3] = prj->r0/prj->w[0]; prj->w[4] = 1.0 + sindeg (theta1)*sindeg (theta2); prj->w[5] = 2.0*prj->w[0]; prj->w[6] = prj->w[3]*prj->w[3]*prj->w[4]; prj->w[7] = 1.0/(2.0*prj->r0*prj->w[3]); prj->w[8] = prj->w[3]*sqrt(prj->w[4] + prj->w[5]); prj->w[2] = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sindeg (prj->p[1])); prj->prjfwd = coefwd; prj->prjrev = coerev; return 0; } /*--------------------------------------------------------------------------*/ int coefwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double a, r; if (prj->flag != COE) { if (coeset(prj)) return 1; } a = phi*prj->w[0]; if (theta == -90.0) { r = prj->w[8]; } else { r = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sindeg (theta)); } *x = r*sindeg (a); *y = prj->w[2] - r*cosdeg (a); return 0; } /*--------------------------------------------------------------------------*/ int coerev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double a, dy, r, w; const double tol = 1.0e-12; if (prj->flag != COE) { if (coeset(prj)) return 1; } dy = prj->w[2] - y; r = sqrt(x*x + dy*dy); if (prj->p[1] < 0.0) r = -r; if (r == 0.0) { a = 0.0; } else { a = atan2deg (x/r, dy/r); } *phi = a*prj->w[1]; if (fabs(r - prj->w[8]) < tol) { *theta = -90.0; } else { w = (prj->w[6] - r*r)*prj->w[7]; if (fabs(w) > 1.0) { if (fabs(w-1.0) < tol) { *theta = 90.0; } else if (fabs(w+1.0) < tol) { *theta = -90.0; } else { return 2; } } else { *theta = asindeg (w); } } return 0; } /*============================================================================ * COD: conic equidistant projection. * * Given: * prj->p[1] sigma = (theta2+theta1)/2 * prj->p[2] delta = (theta2-theta1)/2, where theta1 and theta2 are the * latitudes of the standard parallels, in degrees. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "COD" * prj->flag COD * prj->phi0 0.0 * prj->theta0 sigma * prj->w[0] C = r0*sin(sigma)*sin(delta)/delta * prj->w[1] 1/C * prj->w[2] Y0 = delta*cot(delta)*cot(sigma) * prj->w[3] Y0 + sigma * prj->prjfwd Pointer to codfwd(). * prj->prjrev Pointer to codrev(). *===========================================================================*/ int codset(prj) struct prjprm *prj; { strcpy(prj->code, "COD"); prj->flag = COD; prj->phi0 = 0.0; prj->theta0 = prj->p[1]; if (prj->r0 == 0.0) prj->r0 = R2D; if (prj->p[2] == 0.0) { prj->w[0] = prj->r0*sindeg (prj->p[1])*D2R; } else { prj->w[0] = prj->r0*sindeg (prj->p[1])*sindeg (prj->p[2])/prj->p[2]; } if (prj->w[0] == 0.0) { return 1; } prj->w[1] = 1.0/prj->w[0]; prj->w[2] = prj->r0*cosdeg (prj->p[2])*cosdeg (prj->p[1])/prj->w[0]; prj->w[3] = prj->w[2] + prj->p[1]; prj->prjfwd = codfwd; prj->prjrev = codrev; return 0; } /*--------------------------------------------------------------------------*/ int codfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double a, r; if (prj->flag != COD) { if (codset(prj)) return 1; } a = prj->w[0]*phi; r = prj->w[3] - theta; *x = r*sindeg (a); *y = prj->w[2] - r*cosdeg (a); return 0; } /*--------------------------------------------------------------------------*/ int codrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double a, dy, r; if (prj->flag != COD) { if (codset(prj)) return 1; } dy = prj->w[2] - y; r = sqrt(x*x + dy*dy); if (prj->p[1] < 0.0) r = -r; if (r == 0.0) { a = 0.0; } else { a = atan2deg (x/r, dy/r); } *phi = a*prj->w[1]; *theta = prj->w[3] - r; return 0; } /*============================================================================ * COO: conic orthomorphic projection. * * Given: * prj->p[1] sigma = (theta2+theta1)/2 * prj->p[2] delta = (theta2-theta1)/2, where theta1 and theta2 are the * latitudes of the standard parallels, in degrees. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "COO" * prj->flag COO * prj->phi0 0.0 * prj->theta0 sigma * prj->w[0] C = ln(cos(theta2)/cos(theta1))/ln(tan(tau2)/tan(tau1)) * where tau1 = (90 - theta1)/2 * tau2 = (90 - theta2)/2 * prj->w[1] 1/C * prj->w[2] Y0 = psi*tan((90-sigma)/2)**C * prj->w[3] psi = (r0*cos(theta1)/C)/tan(tau1)**C * prj->w[4] 1/psi * prj->prjfwd Pointer to coofwd(). * prj->prjrev Pointer to coorev(). *===========================================================================*/ int cooset(prj) struct prjprm *prj; { double cos1, cos2, tan1, tan2, theta1, theta2; strcpy(prj->code, "COO"); prj->flag = COO; prj->phi0 = 0.0; prj->theta0 = prj->p[1]; if (prj->r0 == 0.0) prj->r0 = R2D; theta1 = prj->p[1] - prj->p[2]; theta2 = prj->p[1] + prj->p[2]; tan1 = tandeg ((90.0 - theta1)/2.0); cos1 = cosdeg (theta1); if (theta1 == theta2) { prj->w[0] = sindeg (theta1); } else { tan2 = tandeg ((90.0 - theta2)/2.0); cos2 = cosdeg (theta2); prj->w[0] = log(cos2/cos1)/log(tan2/tan1); } if (prj->w[0] == 0.0) { return 1; } prj->w[1] = 1.0/prj->w[0]; prj->w[3] = prj->r0*(cos1/prj->w[0])/pow(tan1,prj->w[0]); if (prj->w[3] == 0.0) { return 1; } prj->w[2] = prj->w[3]*pow(tandeg ((90.0 - prj->p[1])/2.0),prj->w[0]); prj->w[4] = 1.0/prj->w[3]; prj->prjfwd = coofwd; prj->prjrev = coorev; return 0; } /*--------------------------------------------------------------------------*/ int coofwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double a, r; if (prj->flag != COO) { if (cooset(prj)) return 1; } a = prj->w[0]*phi; if (theta == -90.0) { if (prj->w[0] < 0.0) { r = 0.0; } else { return 2; } } else { r = prj->w[3]*pow(tandeg ((90.0 - theta)/2.0),prj->w[0]); } *x = r*sindeg (a); *y = prj->w[2] - r*cosdeg (a); return 0; } /*--------------------------------------------------------------------------*/ int coorev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double a, dy, r; if (prj->flag != COO) { if (cooset(prj)) return 1; } dy = prj->w[2] - y; r = sqrt(x*x + dy*dy); if (prj->p[1] < 0.0) r = -r; if (r == 0.0) { a = 0.0; } else { a = atan2deg (x/r, dy/r); } *phi = a*prj->w[1]; if (r == 0.0) { if (prj->w[0] < 0.0) { *theta = -90.0; } else { return 2; } } else { *theta = 90.0 - 2.0*atandeg (pow(r*prj->w[4],prj->w[1])); } return 0; } /*============================================================================ * BON: Bonne's projection. * * Given: * prj->p[1] Bonne conformal latitude, theta1, in degrees. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "BON" * prj->flag BON * prj->phi0 0.0 * prj->theta0 0.0 * prj->w[1] r0*pi/180 * prj->w[2] Y0 = r0*(cot(theta1) + theta1*pi/180) * prj->prjfwd Pointer to bonfwd(). * prj->prjrev Pointer to bonrev(). *===========================================================================*/ int bonset(prj) struct prjprm *prj; { strcpy(prj->code, "BON"); prj->flag = BON; prj->phi0 = 0.0; prj->theta0 = 0.0; if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[1] = 1.0; prj->w[2] = prj->r0*cosdeg (prj->p[1])/sindeg (prj->p[1]) + prj->p[1]; } else { prj->w[1] = prj->r0*D2R; prj->w[2] = prj->r0*(cosdeg (prj->p[1])/sindeg (prj->p[1]) + prj->p[1]*D2R); } prj->prjfwd = bonfwd; prj->prjrev = bonrev; return 0; } /*--------------------------------------------------------------------------*/ int bonfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double a, r; if (prj->p[1] == 0.0) { /* Sanson-Flamsteed. */ return sflfwd(phi, theta, prj, x, y); } if (prj->flag != BON) { if (bonset(prj)) return 1; } r = prj->w[2] - theta*prj->w[1]; a = prj->r0*phi*cosdeg (theta)/r; *x = r*sindeg (a); *y = prj->w[2] - r*cosdeg (a); return 0; } /*--------------------------------------------------------------------------*/ int bonrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double a, cthe, dy, r; if (prj->p[1] == 0.0) { /* Sanson-Flamsteed. */ return sflrev(x, y, prj, phi, theta); } if (prj->flag != BON) { if (bonset(prj)) return 1; } dy = prj->w[2] - y; r = sqrt(x*x + dy*dy); if (prj->p[1] < 0.0) r = -r; if (r == 0.0) { a = 0.0; } else { a = atan2deg (x/r, dy/r); } *theta = (prj->w[2] - r)/prj->w[1]; cthe = cosdeg (*theta); if (cthe == 0.0) { *phi = 0.0; } else { *phi = a*(r/prj->r0)/cthe; } return 0; } /*============================================================================ * PCO: polyconic projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "PCO" * prj->flag PCO * prj->phi0 0.0 * prj->theta0 0.0 * prj->w[0] r0*(pi/180) * prj->w[1] 1/r0 * prj->w[2] 2*r0 * prj->prjfwd Pointer to pcofwd(). * prj->prjrev Pointer to pcorev(). *===========================================================================*/ int pcoset(prj) struct prjprm *prj; { strcpy(prj->code, "PCO"); prj->flag = PCO; prj->phi0 = 0.0; prj->theta0 = 0.0; if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[0] = 1.0; prj->w[1] = 1.0; prj->w[2] = 360.0/PI; } else { prj->w[0] = prj->r0*D2R; prj->w[1] = 1.0/prj->w[0]; prj->w[2] = 2.0*prj->r0; } prj->prjfwd = pcofwd; prj->prjrev = pcorev; return 0; } /*--------------------------------------------------------------------------*/ int pcofwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double a, cthe, cotthe, sthe; if (prj->flag != PCO) { if (pcoset(prj)) return 1; } cthe = cosdeg (theta); sthe = sindeg (theta); a = phi*sthe; if (sthe == 0.0) { *x = prj->w[0]*phi; *y = 0.0; } else { cotthe = cthe/sthe; *x = prj->r0*cotthe*sindeg (a); *y = prj->r0*(cotthe*(1.0 - cosdeg (a)) + theta*D2R); } return 0; } /*--------------------------------------------------------------------------*/ int pcorev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { int j; double f, fneg, fpos, lambda, tanthe, theneg, thepos, w, xp, xx, ymthe, yp; const double tol = 1.0e-12; if (prj->flag != PCO) { if (pcoset(prj)) return 1; } w = fabs(y*prj->w[1]); if (w < tol) { *phi = x*prj->w[1]; *theta = 0.0; } else if (fabs(w-90.0) < tol) { *phi = 0.0; *theta = copysgni (90.0,y); } else { /* Iterative solution using weighted division of the interval. */ if (y > 0.0) { thepos = 90.0; } else { thepos = -90.0; } theneg = 0.0; xx = x*x; ymthe = y - prj->w[0]*thepos; fpos = xx + ymthe*ymthe; fneg = -999.0; for (j = 0; j < 64; j++) { if (fneg < -100.0) { /* Equal division of the interval. */ *theta = (thepos+theneg)/2.0; } else { /* Weighted division of the interval. */ lambda = fpos/(fpos-fneg); if (lambda < 0.1) { lambda = 0.1; } else if (lambda > 0.9) { lambda = 0.9; } *theta = thepos - lambda*(thepos-theneg); } /* Compute the residue. */ ymthe = y - prj->w[0]*(*theta); tanthe = tandeg (*theta); f = xx + ymthe*(ymthe - prj->w[2]/tanthe); /* Check for convergence. */ if (fabs(f) < tol) break; if (fabs(thepos-theneg) < tol) break; /* Redefine the interval. */ if (f > 0.0) { thepos = *theta; fpos = f; } else { theneg = *theta; fneg = f; } } xp = prj->r0 - ymthe*tanthe; yp = x*tanthe; if (xp == 0.0 && yp == 0.0) { *phi = 0.0; } else { *phi = atan2deg (yp, xp)/sindeg (*theta); } } return 0; } /*============================================================================ * TSC: tangential spherical cube projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "TSC" * prj->flag TSC * prj->phi0 0.0 * prj->theta0 0.0 * prj->w[0] r0*(pi/4) * prj->w[1] (4/pi)/r0 * prj->prjfwd Pointer to tscfwd(). * prj->prjrev Pointer to tscrev(). *===========================================================================*/ int tscset(prj) struct prjprm *prj; { strcpy(prj->code, "TSC"); prj->flag = TSC; prj->phi0 = 0.0; prj->theta0 = 0.0; if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[0] = 45.0; prj->w[1] = 1.0/45.0; } else { prj->w[0] = prj->r0*PI/4.0; prj->w[1] = 1.0/prj->w[0]; } prj->prjfwd = tscfwd; prj->prjrev = tscrev; return 0; } /*--------------------------------------------------------------------------*/ int tscfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { int face; double cthe, l, m, n, rho; double x0 = 0.0; double y0 = 0.0; double xf = 0.0; double yf = 0.0; const double tol = 1.0e-12; if (prj->flag != TSC) { if (tscset(prj)) return 1; } cthe = cosdeg (theta); l = cthe*cosdeg (phi); m = cthe*sindeg (phi); n = sindeg (theta); face = 0; rho = n; if (l > rho) { face = 1; rho = l; } if (m > rho) { face = 2; rho = m; } if (-l > rho) { face = 3; rho = -l; } if (-m > rho) { face = 4; rho = -m; } if (-n > rho) { face = 5; rho = -n; } if (face == 0) { xf = m/rho; yf = -l/rho; x0 = 0.0; y0 = 2.0; } else if (face == 1) { xf = m/rho; yf = n/rho; x0 = 0.0; y0 = 0.0; } else if (face == 2) { xf = -l/rho; yf = n/rho; x0 = 2.0; y0 = 0.0; } else if (face == 3) { xf = -m/rho; yf = n/rho; x0 = 4.0; y0 = 0.0; } else if (face == 4) { xf = l/rho; yf = n/rho; x0 = 6.0; y0 = 0.0; } else if (face == 5) { xf = m/rho; yf = l/rho; x0 = 0.0; y0 = -2.0; } if (fabs(xf) > 1.0) { if (fabs(xf) > 1.0+tol) { return 2; } xf = copysgn (1.0,xf); } if (fabs(yf) > 1.0) { if (fabs(yf) > 1.0+tol) { return 2; } yf = copysgn (1.0,yf); } *x = prj->w[0]*(xf + x0); *y = prj->w[0]*(yf + y0); return 0; } /*--------------------------------------------------------------------------*/ int tscrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double l, m, n, xf, yf; if (prj->flag != TSC) { if (tscset(prj)) return 1; } xf = x*prj->w[1]; yf = y*prj->w[1]; /* Check bounds. */ if (fabs(xf) <= 1.0) { if (fabs(yf) > 3.0) return 2; } else { if (fabs(xf) > 7.0) return 2; if (fabs(yf) > 1.0) return 2; } /* Map negative faces to the other side. */ if (xf < -1.0) xf += 8.0; /* Determine the face. */ if (xf > 5.0) { /* face = 4 */ xf = xf - 6.0; m = -1.0/sqrt(1.0 + xf*xf + yf*yf); l = -m*xf; n = -m*yf; } else if (xf > 3.0) { /* face = 3 */ xf = xf - 4.0; l = -1.0/sqrt(1.0 + xf*xf + yf*yf); m = l*xf; n = -l*yf; } else if (xf > 1.0) { /* face = 2 */ xf = xf - 2.0; m = 1.0/sqrt(1.0 + xf*xf + yf*yf); l = -m*xf; n = m*yf; } else if (yf > 1.0) { /* face = 0 */ yf = yf - 2.0; n = 1.0/sqrt(1.0 + xf*xf + yf*yf); l = -n*yf; m = n*xf; } else if (yf < -1.0) { /* face = 5 */ yf = yf + 2.0; n = -1.0/sqrt(1.0 + xf*xf + yf*yf); l = -n*yf; m = -n*xf; } else { /* face = 1 */ l = 1.0/sqrt(1.0 + xf*xf + yf*yf); m = l*xf; n = l*yf; } if (l == 0.0 && m == 0.0) { *phi = 0.0; } else { *phi = atan2deg (m, l); } *theta = asindeg (n); return 0; } /*============================================================================ * CSC: COBE quadrilateralized spherical cube projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "CSC" * prj->flag CSC * prj->phi0 0.0 * prj->theta0 0.0 * prj->w[0] r0*(pi/4) * prj->w[1] (4/pi)/r0 * prj->prjfwd Pointer to cscfwd(). * prj->prjrev Pointer to cscrev(). *===========================================================================*/ int cscset(prj) struct prjprm *prj; { strcpy(prj->code, "CSC"); prj->flag = CSC; prj->phi0 = 0.0; prj->theta0 = 0.0; if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[0] = 45.0; prj->w[1] = 1.0/45.0; } else { prj->w[0] = prj->r0*PI/4.0; prj->w[1] = 1.0/prj->w[0]; } prj->prjfwd = cscfwd; prj->prjrev = cscrev; return 0; } /*--------------------------------------------------------------------------*/ int cscfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { int face; double cthe, eta, l, m, n, rho, xi; const float tol = 1.0e-7; float a, a2, a2b2, a4, ab, b, b2, b4, ca2, cb2; float x0 = 0.0; float y0 = 0.0; float xf = 0.0; float yf = 0.0; const float gstar = 1.37484847732; const float mm = 0.004869491981; const float gamma = -0.13161671474; const float omega1 = -0.159596235474; const float d0 = 0.0759196200467; const float d1 = -0.0217762490699; const float c00 = 0.141189631152; const float c10 = 0.0809701286525; const float c01 = -0.281528535557; const float c11 = 0.15384112876; const float c20 = -0.178251207466; const float c02 = 0.106959469314; if (prj->flag != CSC) { if (cscset(prj)) return 1; } cthe = cosdeg (theta); l = cthe*cosdeg (phi); m = cthe*sindeg (phi); n = sindeg (theta); face = 0; rho = n; if (l > rho) { face = 1; rho = l; } if (m > rho) { face = 2; rho = m; } if (-l > rho) { face = 3; rho = -l; } if (-m > rho) { face = 4; rho = -m; } if (-n > rho) { face = 5; rho = -n; } if (face == 0) { xi = m; eta = -l; x0 = 0.0; y0 = 2.0; } else if (face == 1) { xi = m; eta = n; x0 = 0.0; y0 = 0.0; } else if (face == 2) { xi = -l; eta = n; x0 = 2.0; y0 = 0.0; } else if (face == 3) { xi = -m; eta = n; x0 = 4.0; y0 = 0.0; } else if (face == 4) { xi = l; eta = n; x0 = 6.0; y0 = 0.0; } else if (face == 5) { xi = m; eta = l; x0 = 0.0; y0 = -2.0; } a = xi/rho; b = eta/rho; a2 = a*a; b2 = b*b; ca2 = 1.0 - a2; cb2 = 1.0 - b2; /* Avoid floating underflows. */ ab = fabs(a*b); a4 = (a2 > 1.0e-16) ? a2*a2 : 0.0; b4 = (b2 > 1.0e-16) ? b2*b2 : 0.0; a2b2 = (ab > 1.0e-16) ? a2*b2 : 0.0; xf = a*(a2 + ca2*(gstar + b2*(gamma*ca2 + mm*a2 + cb2*(c00 + c10*a2 + c01*b2 + c11*a2b2 + c20*a4 + c02*b4)) + a2*(omega1 - ca2*(d0 + d1*a2)))); yf = b*(b2 + cb2*(gstar + a2*(gamma*cb2 + mm*b2 + ca2*(c00 + c10*b2 + c01*a2 + c11*a2b2 + c20*b4 + c02*a4)) + b2*(omega1 - cb2*(d0 + d1*b2)))); if (fabs(xf) > 1.0) { if (fabs(xf) > 1.0+tol) { return 2; } xf = copysgn (1.0,xf); } if (fabs(yf) > 1.0) { if (fabs(yf) > 1.0+tol) { return 2; } yf = copysgn (1.0,yf); } *x = prj->w[0]*(x0 + xf); *y = prj->w[0]*(y0 + yf); return 0; } /*--------------------------------------------------------------------------*/ int cscrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { int face; double l = 0.0; double m = 0.0; double n = 0.0; float a, b, xf, xx, yf, yy, z0, z1, z2, z3, z4, z5, z6; const float p00 = -0.27292696; const float p10 = -0.07629969; const float p20 = -0.22797056; const float p30 = 0.54852384; const float p40 = -0.62930065; const float p50 = 0.25795794; const float p60 = 0.02584375; const float p01 = -0.02819452; const float p11 = -0.01471565; const float p21 = 0.48051509; const float p31 = -1.74114454; const float p41 = 1.71547508; const float p51 = -0.53022337; const float p02 = 0.27058160; const float p12 = -0.56800938; const float p22 = 0.30803317; const float p32 = 0.98938102; const float p42 = -0.83180469; const float p03 = -0.60441560; const float p13 = 1.50880086; const float p23 = -0.93678576; const float p33 = 0.08693841; const float p04 = 0.93412077; const float p14 = -1.41601920; const float p24 = 0.33887446; const float p05 = -0.63915306; const float p15 = 0.52032238; const float p06 = 0.14381585; if (prj->flag != CSC) { if (cscset(prj)) return 1; } xf = x*prj->w[1]; yf = y*prj->w[1]; /* Check bounds. */ if (fabs(xf) <= 1.0) { if (fabs(yf) > 3.0) return 2; } else { if (fabs(xf) > 7.0) return 2; if (fabs(yf) > 1.0) return 2; } /* Map negative faces to the other side. */ if (xf < -1.0) xf += 8.0; /* Determine the face. */ if (xf > 5.0) { face = 4; xf = xf - 6.0; } else if (xf > 3.0) { face = 3; xf = xf - 4.0; } else if (xf > 1.0) { face = 2; xf = xf - 2.0; } else if (yf > 1.0) { face = 0; yf = yf - 2.0; } else if (yf < -1.0) { face = 5; yf = yf + 2.0; } else { face = 1; } xx = xf*xf; yy = yf*yf; z0 = p00 + xx*(p10 + xx*(p20 + xx*(p30 + xx*(p40 + xx*(p50 + xx*(p60)))))); z1 = p01 + xx*(p11 + xx*(p21 + xx*(p31 + xx*(p41 + xx*(p51))))); z2 = p02 + xx*(p12 + xx*(p22 + xx*(p32 + xx*(p42)))); z3 = p03 + xx*(p13 + xx*(p23 + xx*(p33))); z4 = p04 + xx*(p14 + xx*(p24)); z5 = p05 + xx*(p15); z6 = p06; a = z0 + yy*(z1 + yy*(z2 + yy*(z3 + yy*(z4 + yy*(z5 + yy*z6))))); a = xf + xf*(1.0 - xx)*a; z0 = p00 + yy*(p10 + yy*(p20 + yy*(p30 + yy*(p40 + yy*(p50 + yy*(p60)))))); z1 = p01 + yy*(p11 + yy*(p21 + yy*(p31 + yy*(p41 + yy*(p51))))); z2 = p02 + yy*(p12 + yy*(p22 + yy*(p32 + yy*(p42)))); z3 = p03 + yy*(p13 + yy*(p23 + yy*(p33))); z4 = p04 + yy*(p14 + yy*(p24)); z5 = p05 + yy*(p15); z6 = p06; b = z0 + xx*(z1 + xx*(z2 + xx*(z3 + xx*(z4 + xx*(z5 + xx*z6))))); b = yf + yf*(1.0 - yy)*b; if (face == 0) { n = 1.0/sqrt(a*a + b*b + 1.0); l = -b*n; m = a*n; } else if (face == 1) { l = 1.0/sqrt(a*a + b*b + 1.0); m = a*l; n = b*l; } else if (face == 2) { m = 1.0/sqrt(a*a + b*b + 1.0); l = -a*m; n = b*m; } else if (face == 3) { l = -1.0/sqrt(a*a + b*b + 1.0); m = a*l; n = -b*l; } else if (face == 4) { m = -1.0/sqrt(a*a + b*b + 1.0); l = -a*m; n = -b*m; } else if (face == 5) { n = -1.0/sqrt(a*a + b*b + 1.0); l = -b*n; m = -a*n; } if (l == 0.0 && m == 0.0) { *phi = 0.0; } else { *phi = atan2deg (m, l); } *theta = asindeg (n); return 0; } /*============================================================================ * QSC: quadrilaterilized spherical cube projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * * Returned: * prj->code "QSC" * prj->flag QSC * prj->phi0 0.0 * prj->theta0 0.0 * prj->w[0] r0*(pi/4) * prj->w[1] (4/pi)/r0 * prj->prjfwd Pointer to qscfwd(). * prj->prjrev Pointer to qscrev(). *===========================================================================*/ int qscset(prj) struct prjprm *prj; { strcpy(prj->code, "QSC"); prj->flag = QSC; prj->phi0 = 0.0; prj->theta0 = 0.0; if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[0] = 45.0; prj->w[1] = 1.0/45.0; } else { prj->w[0] = prj->r0*PI/4.0; prj->w[1] = 1.0/prj->w[0]; } prj->prjfwd = qscfwd; prj->prjrev = qscrev; return 0; } /*--------------------------------------------------------------------------*/ int qscfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { int face; double cthe, l, m, n, omega, p, rho, rhu, t, tau; double xi = 0.0; double eta = 0.0; double x0 = 0.0; double y0 = 0.0; double xf = 0.0; double yf = 0.0; const double tol = 1.0e-12; if (prj->flag != QSC) { if (qscset(prj)) return 1; } if (fabs(theta) == 90.0) { *x = 0.0; *y = copysgn (2.0*prj->w[0],theta); return 0; } cthe = cosdeg (theta); l = cthe*cosdeg (phi); m = cthe*sindeg (phi); n = sindeg (theta); face = 0; rho = n; if (l > rho) { face = 1; rho = l; } if (m > rho) { face = 2; rho = m; } if (-l > rho) { face = 3; rho = -l; } if (-m > rho) { face = 4; rho = -m; } if (-n > rho) { face = 5; rho = -n; } rhu = 1.0 - rho; if (face == 0) { xi = m; eta = -l; if (rhu < 1.0e-8) { /* Small angle formula. */ t = (90.0 - theta)*D2R; rhu = t*t/2.0; } x0 = 0.0; y0 = 2.0; } else if (face == 1) { xi = m; eta = n; if (rhu < 1.0e-8) { /* Small angle formula. */ t = theta*D2R; p = fmod(phi,360.0); if (p < -180.0) p += 360.0; if (p > 180.0) p -= 360.0; p *= D2R; rhu = (p*p + t*t)/2.0; } x0 = 0.0; y0 = 0.0; } else if (face == 2) { xi = -l; eta = n; if (rhu < 1.0e-8) { /* Small angle formula. */ t = theta*D2R; p = fmod(phi,360.0); if (p < -180.0) p += 360.0; p = (90.0 - p)*D2R; rhu = (p*p + t*t)/2.0; } x0 = 2.0; y0 = 0.0; } else if (face == 3) { xi = -m; eta = n; if (rhu < 1.0e-8) { /* Small angle formula. */ t = theta*D2R; p = fmod(phi,360.0); if (p < 0.0) p += 360.0; p = (180.0 - p)*D2R; rhu = (p*p + t*t)/2.0; } x0 = 4.0; y0 = 0.0; } else if (face == 4) { xi = l; eta = n; if (rhu < 1.0e-8) { /* Small angle formula. */ t = theta*D2R; p = fmod(phi,360.0); if (p > 180.0) p -= 360.0; p *= (90.0 + p)*D2R; rhu = (p*p + t*t)/2.0; } x0 = 6; y0 = 0.0; } else if (face == 5) { xi = m; eta = l; if (rhu < 1.0e-8) { /* Small angle formula. */ t = (90.0 + theta)*D2R; rhu = t*t/2.0; } x0 = 0.0; y0 = -2; } if (xi == 0.0 && eta == 0.0) { xf = 0.0; yf = 0.0; } else if (-xi >= fabs(eta)) { omega = eta/xi; tau = 1.0 + omega*omega; xf = -sqrt(rhu/(1.0-1.0/sqrt(1.0+tau))); yf = (xf/15.0)*(atandeg (omega) - asindeg (omega/sqrt(tau+tau))); } else if (xi >= fabs(eta)) { omega = eta/xi; tau = 1.0 + omega*omega; xf = sqrt(rhu/(1.0-1.0/sqrt(1.0+tau))); yf = (xf/15.0)*(atandeg (omega) - asindeg (omega/sqrt(tau+tau))); } else if (-eta > fabs(xi)) { omega = xi/eta; tau = 1.0 + omega*omega; yf = -sqrt(rhu/(1.0-1.0/sqrt(1.0+tau))); xf = (yf/15.0)*(atandeg (omega) - asindeg (omega/sqrt(tau+tau))); } else if (eta > fabs(xi)) { omega = xi/eta; tau = 1.0 + omega*omega; yf = sqrt(rhu/(1.0-1.0/sqrt(1.0+tau))); xf = (yf/15.0)*(atandeg (omega) - asindeg (omega/sqrt(tau+tau))); } if (fabs(xf) > 1.0) { if (fabs(xf) > 1.0+tol) { return 2; } xf = copysgn (1.0,xf); } if (fabs(yf) > 1.0) { if (fabs(yf) > 1.0+tol) { return 2; } yf = copysgn (1.0,yf); } *x = prj->w[0]*(xf + x0); *y = prj->w[0]*(yf + y0); return 0; } /*--------------------------------------------------------------------------*/ int qscrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { int direct, face; double omega, rho, rhu, tau, xf, yf, w; double l = 0.0; double m = 0.0; double n = 0.0; const double tol = 1.0e-12; if (prj->flag != QSC) { if (qscset(prj)) return 1; } xf = x*prj->w[1]; yf = y*prj->w[1]; /* Check bounds. */ if (fabs(xf) <= 1.0) { if (fabs(yf) > 3.0) return 2; } else { if (fabs(xf) > 7.0) return 2; if (fabs(yf) > 1.0) return 2; } /* Map negative faces to the other side. */ if (xf < -1.0) xf += 8.0; /* Determine the face. */ if (xf > 5.0) { face = 4; xf = xf - 6.0; } else if (xf > 3.0) { face = 3; xf = xf - 4.0; } else if (xf > 1.0) { face = 2; xf = xf - 2.0; } else if (yf > 1.0) { face = 0; yf = yf - 2.0; } else if (yf < -1.0) { face = 5; yf = yf + 2.0; } else { face = 1; } direct = (fabs(xf) > fabs(yf)); if (direct) { if (xf == 0.0) { omega = 0.0; tau = 1.0; rho = 1.0; rhu = 0.0; } else { w = 15.0*yf/xf; omega = sindeg (w)/(cosdeg (w) - SQRT2INV); tau = 1.0 + omega*omega; rhu = xf*xf*(1.0 - 1.0/sqrt(1.0 + tau)); rho = 1.0 - rhu; } } else { if (yf == 0.0) { omega = 0.0; tau = 1.0; rho = 1.0; rhu = 0.0; } else { w = 15.0*xf/yf; omega = sindeg (w)/(cosdeg (w) - SQRT2INV); tau = 1.0 + omega*omega; rhu = yf*yf*(1.0 - 1.0/sqrt(1.0 + tau)); rho = 1.0 - rhu; } } if (rho < -1.0) { if (rho < -1.0-tol) { return 2; } rho = -1.0; rhu = 2.0; w = 0.0; } else { w = sqrt(rhu*(2.0-rhu)/tau); } if (face == 0) { n = rho; if (direct) { m = w; if (xf < 0.0) m = -m; l = -m*omega; } else { l = w; if (yf > 0.0) l = -l; m = -l*omega; } } else if (face == 1) { l = rho; if (direct) { m = w; if (xf < 0.0) m = -m; n = m*omega; } else { n = w; if (yf < 0.0) n = -n; m = n*omega; } } else if (face == 2) { m = rho; if (direct) { l = w; if (xf > 0.0) l = -l; n = -l*omega; } else { n = w; if (yf < 0.0) n = -n; l = -n*omega; } } else if (face == 3) { l = -rho; if (direct) { m = w; if (xf > 0.0) m = -m; n = -m*omega; } else { n = w; if (yf < 0.0) n = -n; m = -n*omega; } } else if (face == 4) { m = -rho; if (direct) { l = w; if (xf < 0.0) l = -l; n = l*omega; } else { n = w; if (yf < 0.0) n = -n; l = n*omega; } } else if (face == 5) { n = -rho; if (direct) { m = w; if (xf < 0.0) m = -m; l = m*omega; } else { l = w; if (yf < 0.0) l = -l; m = l*omega; } } if (l == 0.0 && m == 0.0) { *phi = 0.0; } else { *phi = atan2deg (m, l); } *theta = asindeg (n); return 0; } /* This routine comes from E. Bertin sextractor-2.8.6 */ int raw_to_pv(struct prjprm *prj, double x, double y, double *xo, double *yo) { int k; double *a,*b, r,r3,r5,r7,xy,x2,x3,x4,x5,x6,x7,y2,y3,y4,y5,y6,y7,xp,yp; k=prj->npv; a = prj->ppv+MAXPV; /* Latitude comes first for compatibility */ b = prj->ppv; /* Longitude */ xp = *(a++); xp += *(a++)*x; yp = *(b++); yp += *(b++)*y; if (!--k) goto poly_end; xp += *(a++)*y; yp += *(b++)*x; if (!--k) goto poly_end; r = sqrt(x*x + y*y); xp += *(a++)*r; yp += *(b++)*r; if (!--k) goto poly_end; xp += *(a++)*(x2=x*x); yp += *(b++)*(y2=y*y); if (!--k) goto poly_end; xp += *(a++)*(xy=x*y); yp += *(b++)*xy; if (!--k) goto poly_end; xp += *(a++)*y2; yp += *(b++)*x2; if (!--k) goto poly_end; xp += *(a++)*(x3=x*x2); yp += *(b++)*(y3=y*y2); if (!--k) goto poly_end; xp += *(a++)*x2*y; yp += *(b++)*y2*x; if (!--k) goto poly_end; xp += *(a++)*x*y2; yp += *(b++)*y*x2; if (!--k) goto poly_end; xp += *(a++)*y3; yp += *(b++)*x3; if (!--k) goto poly_end; xp += *(a++)*(r3=r*r*r); yp += *(b++)*r3; if (!--k) goto poly_end; xp += *(a++)*(x4=x2*x2); yp += *(b++)*(y4=y2*y2); if (!--k) goto poly_end; xp += *(a++)*x3*y; yp += *(b++)*y3*x; if (!--k) goto poly_end; xp += *(a++)*x2*y2; yp += *(b++)*x2*y2; if (!--k) goto poly_end; xp += *(a++)*x*y3; yp += *(b++)*y*x3; if (!--k) goto poly_end; xp += *(a++)*y4; yp += *(b++)*x4; if (!--k) goto poly_end; xp += *(a++)*(x5=x4*x); yp += *(b++)*(y5=y4*y); if (!--k) goto poly_end; xp += *(a++)*x4*y; yp += *(b++)*y4*x; if (!--k) goto poly_end; xp += *(a++)*x3*y2; yp += *(b++)*y3*x2; if (!--k) goto poly_end; xp += *(a++)*x2*y3; yp += *(b++)*y2*x3; if (!--k) goto poly_end; xp += *(a++)*x*y4; yp += *(b++)*y*x4; if (!--k) goto poly_end; xp += *(a++)*y5; yp += *(b++)*x5; if (!--k) goto poly_end; xp += *(a++)*(r5=r3*r*r); yp += *(b++)*r5; if (!--k) goto poly_end; xp += *(a++)*(x6=x5*x); yp += *(b++)*(y6=y5*y); if (!--k) goto poly_end; xp += *(a++)*x5*y; yp += *(b++)*y5*x; if (!--k) goto poly_end; xp += *(a++)*x4*y2; yp += *(b++)*y4*x2; if (!--k) goto poly_end; xp += *(a++)*x3*y3; yp += *(b++)*y3*x3; if (!--k) goto poly_end; xp += *(a++)*x2*y4; yp += *(b++)*y2*x4; if (!--k) goto poly_end; xp += *(a++)*x*y5; yp += *(b++)*y*x5; if (!--k) goto poly_end; xp += *(a++)*y6; yp += *(b++)*x6; if (!--k) goto poly_end; xp += *(a++)*(x7=x6*x); yp += *(b++)*(y7=y6*y); if (!--k) goto poly_end; xp += *(a++)*x6*y; yp += *(b++)*y6*x; if (!--k) goto poly_end; xp += *(a++)*x5*y2; yp += *(b++)*y5*x2; if (!--k) goto poly_end; xp += *(a++)*x4*y3; yp += *(b++)*y4*x3; if (!--k) goto poly_end; xp += *(a++)*x3*y4; yp += *(b++)*y3*x4; if (!--k) goto poly_end; xp += *(a++)*x2*y5; yp += *(b++)*y2*x5; if (!--k) goto poly_end; xp += *(a++)*x*y6; yp += *(b++)*y*x6; if (!--k) goto poly_end; xp += *(a++)*y7; yp += *(b++)*x7; if (!--k) goto poly_end; xp += *a*(r7=r5*r*r); yp += *b*r7; poly_end: *xo = xp; *yo = yp; return 0; } /* Dec 20 1999 Doug Mink - Change cosd() and sind() to cosdeg() and sindeg() * Dec 20 1999 Doug Mink - Include wcslib.h, which includes proj.h, wcsmath.h * Dec 20 1999 Doug Mink - Define copysign only if it is not defined * Dec 20 1999 Doug Mink - tanfwd() returns error if s<=0.0, not only if s==0.0 * * Jun 2 2000 Doug Mink - include stdlib.h to get abs() * * Feb 15 2001 Doug Mink - update zearev() for WCSLIB 2.6 * Sep 19 2001 Doug Mink - Make above changes for WCSLIB 2.7 * * Mar 15 2002 Doug Mink - Make above changes for WCSLIB 2.8.2 * * Feb 3 2003 Doug Mink - Use locally defined copysgn() and copysgni(), * not copysign() * Apr 1 2003 Doug Mink - include string.h for strcpy() and strcmp() * * Mar 14 2011 Doug Mink - If no coefficients in ZPN, make ARC * Mar 14 2011 Doug Mink - Add Emmanuel Bertin's TAN polynomial from Ed Los */ wcstools-3.9.5/libwcs/sdssread.c0000664000016200001660000002207512455251342015723 0ustar minkoirsys/*** File libwcs/sdssread.c *** September 16, 2013 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 2004-2013 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include #include #include #include "fitsfile.h" #include "wcs.h" #include "wcscat.h" #define ABS(a) ((a) < 0 ? (-(a)) : (a)) #define LINE 1024 /* SDSS DR1 search engine URL char sdssrurl[64]="http://skyserver.sdss.org/cas/en/tools/search/x_radial.asp"; char sdssburl[64]="http://skyserver.sdss.org/cas/en/tools/search/x_rect.asp"; */ /* SDSS DR4 search engine URL char sdssrurl[64]="http://cas.sdss.org/dr4/en/tools/search/x_radial.asp"; char sdssburl[64]="http://cas.sdss.org/dr4/en/tools/search/x_rect.asp"; */ /* SDSS DR5 search engine URL char sdssrurl[64]="http://cas.sdss.org/dr5/en/tools/search/x_radial.asp"; char sdssburl[64]="http://cas.sdss.org/dr5/en/tools/search/x_rect.asp"; */ /* SDSS DR6 search engine URL char sdssrurl[64]="http://cas.sdss.org/dr6/en/tools/search/x_radial.asp"; char sdssburl[64]="http://cas.sdss.org/dr6/en/tools/search/x_rect.asp"; */ /* SDSS DR7 search engine US URL */ char sdssrurl[64]="http://skyserver.sdss.org/dr7/en/tools/search/x_radial.asp"; char sdssburl[64]="http://skyserver.sdss.org/dr7/en/tools/search/x_rect.asp"; /* SDSS DR7 search engine former main server URL */ /* char sdssrurl[64]="http://cas.sdss.org/dr7/en/tools/search/x_radial.asp"; char sdssburl[64]="http://cas.sdss.org/dr7/en/tools/search/x_rect.asp"; */ /* SDSS DR7 search engine UK alternate URL */ /* char sdssrurl[64]="http://www.sdss.org.uk/dr7/en/tools/search/x_radial.asp"; char sdssburl[64]="http://www.sdss.org.uk/dr7/en/tools/search/x_rect.asp"; */ /* SDSS magnitudes */ char sdssmag[6]="ugriz"; /* SDSSREAD -- Read Sloan Digital Sky Survey catalog stars over the web */ int sdssread (cra,cdec,dra,ddec,drad,dradi,distsort,sysout,eqout,epout, mag1,mag2,sortmag,nstarmax,gnum,gobj,gra,gdec,gmag,gtype,nlog) double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ double dradi; /* Inner edge of annulus in degrees (ignore if 0) */ int distsort; /* 1 to sort stars by distance from center */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 to nmag) */ int nstarmax; /* Maximum number of stars to be returned */ double *gnum; /* Array of catalog numbers (returned) */ char **gobj; /* Array of object IDs (too long for integer*4) */ double *gra; /* Array of right ascensions (returned) */ double *gdec; /* Array of declinations (returned) */ double **gmag; /* 2-D array of magnitudes (returned) */ int *gtype; /* Array of object classes (returned) */ int nlog; /* 1 for diagnostics */ { char srchurl[LINE]; char temp[64]; char cmag; struct TabTable *tabtable; double dtemp; double *gpra, *gpdec; struct StarCat *starcat; int nstar, nlog0; double ra, dec, mag; char rastr[32], decstr[32]; char *sdssurl; gpra = NULL; gpdec = NULL; nlog0 = nlog; if (nstarmax < 1) nlog = -1; /* make mag1 always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } if (mag1 < 0) mag1 = 0.0; /* Set up query for STScI GSC II server */ ra = cra; dec = cdec; if (sysout != WCS_J2000) wcscon (sysout, WCS_J2000, eqout, 2000.0, &ra, &dec, epout); sdssurl = sdssrurl; deg2str (rastr, 32, ra, 5); deg2str (decstr, 32, dec, 5); /* Radius or box size */ if (drad != 0.0) { dtemp = drad * 60.0; sprintf (srchurl, "?ra=%.5f&dec=%.5f&radius=%.3f", ra, dec, dtemp); } else { dtemp = sqrt (dra*dra + ddec*ddec) * 60.0; sprintf (srchurl, "?ra=%.5f&dec=%.5f&radius=%.3f", ra, dec, dtemp); } /* Magnitude limit, if any */ if (sortmag < 1) cmag = 'g'; else cmag = sdssmag[sortmag - 1]; if (mag1 < mag2) { sprintf (temp, "&check_%c=%c&min_%c=%.2f&max_%c=%.2f", cmag, cmag, cmag, mag1, cmag, mag2); strcat (srchurl, temp); } nstar = 50000; sprintf (temp, "&entries=top&topnum=%d&format=csv",nstar); strcat (srchurl, temp); if (nlog0 > 0) fprintf (stderr,"%s%s\n", sdssurl, srchurl); /* Run search across the web */ if ((tabtable = webopen (sdssurl, srchurl, nlog)) == NULL) { if (nlog > 0) fprintf (stderr, "WEBREAD: %s failed\n", srchurl); return (0); } /* Return if no data */ if (tabtable->tabdata == NULL || strlen (tabtable->tabdata) == 0 || !strncasecmp (tabtable->tabdata, "[EOD]", 5)) { if (nlog > 0) fprintf (stderr, "WEBRNUM: No data returned\n"); return (0); } /* Dump returned file and stop */ if (nlog < 0) { (void) fwrite (tabtable->tabbuff, tabtable->lbuff, 1, stdout); exit (0); } /* Open returned Starbase table as a catalog */ if ((starcat = tabcatopen (sdssurl, tabtable,0)) == NULL) { if (nlog > 0) fprintf (stderr, "WEBREAD: Could not open Starbase table as catalog\n"); return (0); } /* Set reference frame, epoch, and equinox of catalog */ starcat->coorsys = WCS_J2000; starcat->epoch = 2000.0; starcat->equinox = 2000.0; starcat->nmag = 5; /* Extract desired sources from catalog and return them */ nstar = tabread (sdssurl,distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nstarmax,&starcat, gnum,gra,gdec,gpra,gpdec,gmag,gtype,gobj,nlog); tabcatclose (starcat); starcat = NULL; return (nstar); } char * sdssc2t (csvbuff) char *csvbuff; /* Input comma-separated table */ { char colhead[180]="objID run rerun camcol field obj type ra dec umag gmag rmag imag zmag uerr gerr rerr ierr zerr \n"; char colsep[180]="------------------ --- ----- ------ ----- --- ---- ---------- --------- ------ ------ ------ ------ ------ -------- ------ -------- -------- -------\n"; char *tabbuff; /* Output tab-separated table */ char *databuff; char *lastbuff; int lbuff, i; char ctab = (char) 9; char ccom = ','; /* Skip first line of returned header */ databuff = strchr (csvbuff, '\n') + 1; /* Drop extraneous data after last linefeed */ lbuff = strlen (databuff); lastbuff = strrchr (databuff, '\n'); if (lastbuff - databuff < lbuff) *(lastbuff+1) = (char) 0; /* Convert commas in table to tabs */ lbuff = strlen (databuff); for (i = 0; i < lbuff; i++) { if (databuff[i] == ccom) databuff[i] = ctab; } /* Allocate buffer for tab-separated table with header */ lbuff = strlen (databuff) + strlen (colhead) + strlen (colsep); tabbuff = (char *) calloc (lbuff, 1); /* Copy column headings, separator, and data to output buffer */ strcpy (tabbuff, colhead); strcat (tabbuff, colsep); strcat (tabbuff, databuff); return (tabbuff); } /* Jan 5 2004 New program * * Apr 6 2006 Use different server to get DR4 data * Jun 20 2006 Drop unused variables * Jul 11 2006 Change path to Data Release 5 * Oct 30 2006 Print URL in verbose mode when printing web-returned sources * Oct 30 2006 Fix bug in buffer length when setting up tab table * Nov 3 2006 Drop extra characters from end of data returned from SDSS * Nov 6 2006 Pass SDSS ID as character string because it is too long integer * * Jan 8 2007 Drop unused variables * Jan 9 2007 Drop refcatname from argument list; it is not used * Jan 10 2007 Drop gnum argument from sdssread(); gobj replaced it * Oct 22 2007 Change path to Data Release 6 * * May 01 2012 Change path to Data Release 7 * * Sep 16 2013 Add alternate servers for SDSS * * Jan 13 2015 Add new main server for SDSS DR7 */ wcstools-3.9.5/libwcs/shrink.c0000664000016200001660000000747311750060474015417 0ustar minkoirsys/* File libwcs/shrink.c * January 24, 2006 * By Jessica Mink, Harvard-Smithsonian Center for Astrophysics */ /* Return image buffer reduced by a given factor */ #include /* NULL, strlen, strstr, strcpy */ #include #include #include "fitshead.h" char * ShrinkFITSImage (header, image, factor, floor, bitpix, nlog) char *header; /* Image header */ char *image; /* Image bytes to be filtered */ int factor; /* Factor by which to reduce size of image */ int floor; /* Subtract this number from every value */ int bitpix; /* Number of bits per output pixel (neg=f.p.) */ int nlog; /* Logging interval in lines */ { char *image1; int nx,ny; /* Number of columns and rows in input image */ int nx1,ny1; /* Number of columns and rows in input image */ int ix,iy; /* Output pixel coordinates */ int jx,jy; /* Input pixel coordinates */ int npix; /* Number of pixels in input image */ int npix1; /* Number of pixels in output image */ int bitsin; /* Number of bits per input pixel (<0=floating point) */ int bytesin; /* Number of bytes per input pixel */ int naxes; double pixij; /* Summed value of rebinned pixel */ double bzero, bscale; double pixval, pixij, dnp; short *buffi2; int *buffi4; float *buffr4; double *buffr8; hgeti4 (header, "BITPIX", &bitsin); bytesin = bitsin / 8; if (bytesin < 0) bytesin = -bytesin; hgeti4 (header, "NAXIS", &naxes); hgeti4 (header, "NAXIS1", &nx); if (naxes > 1) hgeti4 (header, "NAXIS2", &ny); else ny = 1; bzero = 0.0; hgetr8 (header, "BZERO", &bzero); bscale = 1.0; hgetr8 (header, "BSCALE", &bscale); npix = nx * ny; nx1 = nx1 / factor; ny1 = ny / factor; npix1 = nx1 * ny1; image1 = NULL; if (bitpix == 16) { image1 = (char *) calloc (npix1, sizeof (short)); buffi2 = (short *) image1; } else if (bitpix == 32) { image1 = (char *) calloc (npix1, sizeof (int)); buffi4 = (int *) image1; } else if (bitpix == -32) { image1 = (char *) calloc (npix1, sizeof (float)); buffr4 = (float *) image1; } else if (bitpix == -64) { image1 = (char *) calloc (npix1, sizeof (double)); buffr8 = (double *) image1; } if (mean) *buffout++ = (short) (pixij / dnp); else { if (pixij < 32768.0) *buffout++ = (short) pixij; else *buffout++ = 32767; } } if ((jy+1)%nlog == 0) fprintf (stderr,"SHRINK: %d lines created\r", jy+1); } if (nlog > 0) fprintf (stderr,"\n"); } for (jy = 0; jy < ny1; jy++) { for (jx = 0; jx < nx1; jx++) { pixij = 0.0; ky = (jy * factor); if (ky + factor > ny) nyf = ny - ky + 1; else nyf = factor; dnp = 0.0; for (iy = 0; iy < nyf; iy++) { kx = (jx * factor); if (kx + factor > nx) nxf = nx - kx + 1; else nxf = factor; for (ix = 0; ix < nxf; ix++) { pixval = getpix (image, bitsin, nx,ny,bzero,bscale,kx++,ky); pixfal = pixval - floor; if (pixval < 0.0) pixval = 0.0; pixij = pixij + pixval; dnp++; } ky++; } if (mean) { switch (bitpix) { case 16: *buffi2++ = (short) (pixij / dnp); break; case 32: *buffi4++ = (int) (pixij / dnp); break; case -32: *buffr4++ = (float) (pixij / dnp); break; case -64: *buffr8++ = (pixij / dnp); break; } } else { switch (bitpix) { case 16: if (pixij < 32768.0) *buffi2++ = (short) pixij; else *buffi2++ = 32767; break; case 32: *buffi4++ = (int) pixij; break; case -32: *buffr4++ = (float) pixij; break; case -64: *buffr8++ = pixij; break; } } } if ((jy+1)%nlog == 0) fprintf (stderr,"SHRINK: %d lines created\r", jy+1); } if (nlog > 0) fprintf (stderr,"\n"); return (image1); } /* Jan 25 2006 New subroutine based on libwcs/filter.c */ wcstools-3.9.5/libwcs/sortstar.c0000664000016200001660000006470612733325642016007 0ustar minkoirsys/*** File libwcs/sortstar.c *** June 24, 2016 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2016 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ /* void FluxSortStars() Sort star list based on brightness * int StarFluxSort() Return brightest of two stars based on flux * void MagSortStars() Sort stars list based on magnitude * int StarMagSort() Return brightest of two stars based on mag. * void RASortStars() Sort stars based on right ascension * int StarRASort() Return star with lowest right ascension * void DecSortStars() Sort stars based on declination * int StarDecSort() Return star with lowest declination * void IDSortStars() Sort stars based on ID number * int StarIDSort() Return star with lowest ID number * void XSortStars() Sort stars based on X coordinate in image * int StarXSort() Return star with lowest X coordinate * void YSortStars() Sort stars based on Y coordinate in image * int StarYSort() Return star with lowest Y coordinate * int MergeStars() Merge multiple entries within given radius * int StarMerge() Merge stars, called by MergeStars() */ #include #include #include #include "wcs.h" #include "fitsfile.h" #include "wcscat.h" /* structure for star lists needed for sorting */ typedef struct { double n; /* Identifying number */ double ra; /* Right Ascension */ double dec; /* Declination */ double pra; /* Right Ascension proper motion */ double pdec; /* Declination proper motion */ double m[MAXNMAG+1]; /* Magnitude */ double b; /* flux */ double x; /* Image X coordinate */ double y; /* Image Y coordinate */ int c; /* Other 4-byte information */ char *obj; /* Object name */ } StarInfo; /* Sort image stars by decreasing flux */ void FluxSortStars (sx, sy, sb, sc, ns) double *sx; double *sy; double *sb; int *sc; int ns; { StarInfo *stars; int StarFluxSort (); int i; stars = (StarInfo *) calloc ((unsigned int)ns, sizeof(StarInfo)); for (i = 0; i < ns; i++) { stars[i].x = sx[i]; stars[i].y = sy[i]; stars[i].b = sb[i]; stars[i].c = sc[i]; } qsort ((char *)stars, ns, sizeof(StarInfo), StarFluxSort); for (i = 0; i < ns; i++) { sx[i] = stars[i].x; sy[i] = stars[i].y; sb[i] = stars[i].b; sc[i] = stars[i].c; } free ((char *)stars); return; } /* StarFluxSort -- Order stars in decreasing flux called by qsort */ int StarFluxSort (ssp1, ssp2) void *ssp1, *ssp2; { double b1 = ((StarInfo *)ssp1)->b; double b2 = ((StarInfo *)ssp2)->b; if (b2 > b1) return (1); else if (b2 < b1) return (-1); else return (0); } /* MagSortStars -- Sort image stars by increasing magnitude */ static int magsort = 0; void MagSortStars (sn, sra, sdec, spra, spdec, sx, sy, sm, sc, sobj, ns, nm, ms) double *sn; /* Identifying number */ double *sra; /* Right Ascension */ double *sdec; /* Declination */ double *spra; /* Right Ascension proper motion */ double *spdec; /* Declination proper motion */ double *sx; /* Image X coordinate */ double *sy; /* Image Y coordinate */ double **sm; /* Magnitudes */ int *sc; /* Other 4-byte information */ char **sobj; /* Object name */ int ns; /* Number of stars to sort */ int nm; /* Number of magnitudes per star */ int ms; /* Magnitude by which to sort (1 to nmag) */ { StarInfo *stars; int i, j, hasnum, haspos, hasobj, haspm, hasxy; int StarMagSort(); stars = (StarInfo *) calloc ((unsigned int)ns, sizeof(StarInfo)); if (ms > 0 && ms <= nm) magsort = ms - 1; if (sn == NULL) hasnum = 0; else hasnum = 1; if (sra != NULL && sdec != NULL) haspos = 1; else haspos = 0; if (spra != NULL && spdec != NULL) haspm = 1; else haspm = 0; if (sx != NULL && sy != NULL) hasxy = 1; else hasxy = 0; if (sobj == NULL) hasobj = 0; else hasobj = 1; for (i = 0; i < ns; i++) { if (hasnum) stars[i].n = sn[i]; if (haspos) { stars[i].ra = sra[i]; stars[i].dec = sdec[i]; } if (haspm) { stars[i].pra = spra[i]; stars[i].pdec = spdec[i]; } if (hasxy) { stars[i].x = sx[i]; stars[i].y = sy[i]; } for (j = 0; j < nm; j++) stars[i].m[j] = sm[j][i]; stars[i].c = sc[i]; if (hasobj) stars[i].obj = sobj[i]; } qsort ((char *)stars, ns, sizeof(StarInfo), StarMagSort); for (i = 0; i < ns; i++) { if (hasnum) sn[i] = stars[i].n; if (haspos) { sra[i] = stars[i].ra; sdec[i] = stars[i].dec; } if (haspm) { spra[i] = stars[i].pra; spdec[i] = stars[i].pdec; } if (hasxy) { sx[i] = stars[i].x; sy[i] = stars[i].y; } for (j = 0; j < nm; j++) sm[j][i] = stars[i].m[j]; sc[i] = stars[i].c; if (hasobj) sobj[i] = stars[i].obj; } free ((char *)stars); return; } /* StarMagSort -- Order stars in decreasing flux called by qsort */ int StarMagSort (ssp1, ssp2) void *ssp1, *ssp2; { double b1 = ((StarInfo *)ssp1)->m[magsort]; double b2 = ((StarInfo *)ssp2)->m[magsort]; /* If sort magnitude is not set, check the others until one is found */ if (b1 > 100.0) b1 = b1 - 100.0; if (b1 == 99.90) b1 = ((StarInfo *)ssp1)->m[0]; if (b1 == 99.90) b1 = ((StarInfo *)ssp1)->m[1]; if (b1 == 99.90) b1 = ((StarInfo *)ssp1)->m[2]; if (b1 == 99.90) b1 = ((StarInfo *)ssp1)->m[3]; /* If sort magnitude is not set, check the others until one is found */ if (b2 > 100.0) b2 = b2 - 100.0; if (b2 == 99.90) b2 = ((StarInfo *)ssp2)->m[0]; if (b2 == 99.90) b2 = ((StarInfo *)ssp2)->m[1]; if (b2 == 99.90) b2 = ((StarInfo *)ssp2)->m[2]; if (b2 == 99.90) b2 = ((StarInfo *)ssp2)->m[3]; if (b2 < b1) return (1); else if (b2 > b1) return (-1); else return (0); } /* IDSortStars -- Sort image stars by increasing ID Number value */ void IDSortStars (sn, sra, sdec, spra, spdec, sx, sy, sm, sc, sobj, ns, nm) double *sn; /* Identifying number */ double *sra; /* Right Ascension */ double *sdec; /* Declination */ double *spra; /* Right Ascension proper motion */ double *spdec; /* Declination proper motion */ double *sx; /* Image X coordinate */ double *sy; /* Image Y coordinate */ double **sm; /* Magnitudes */ int *sc; /* Other 4-byte information */ char **sobj; /* Object name */ int ns; /* Number of stars to sort */ int nm; /* Number of magnitudes per star */ { StarInfo *stars; int i, j, hasnum, hasobj, haspos, haspm, hasxy; int StarIDSort (); stars = (StarInfo *) calloc ((unsigned int)ns, sizeof(StarInfo)); if (sn == NULL) return; else hasnum = 1; if (sra != NULL && sdec != NULL) haspos = 1; else haspos = 0; if (spra != NULL && spdec != NULL) haspm = 1; else haspm = 0; if (sobj == NULL) hasobj = 0; else hasobj = 1; if (sx != NULL && sy != NULL) hasxy = 1; else hasxy = 0; for (i = 0; i < ns; i++) { if (hasnum) stars[i].n = sn[i]; if (haspos) { stars[i].ra = sra[i]; stars[i].dec = sdec[i]; } if (haspm) { stars[i].pra = spra[i]; stars[i].pdec = spdec[i]; } if (hasxy) { stars[i].x = sx[i]; stars[i].y = sy[i]; } for (j = 0; j < nm; j++) stars[i].m[j] = sm[j][i]; stars[i].c = sc[i]; if (hasobj) stars[i].obj = sobj[i]; } qsort ((char *)stars, ns, sizeof(StarInfo), StarIDSort); for (i = 0; i < ns; i++) { if (hasnum) sn[i] = stars[i].n; if (haspos) { sra[i] = stars[i].ra; sdec[i] = stars[i].dec; } if (haspm) { spra[i] = stars[i].pra; spdec[i] = stars[i].pdec; } if (hasxy) { sx[i] = stars[i].x; sy[i] = stars[i].y; } for (j = 0; j < nm; j++) sm[j][i] = stars[i].m[j]; sc[i] = stars[i].c; if (hasobj) sobj[i] = stars[i].obj; } free ((char *)stars); return; } /* StarIDSort -- Order stars in increasing ID value called by qsort */ int StarIDSort (ssp1, ssp2) void *ssp1, *ssp2; { double n1 = ((StarInfo *)ssp1)->n; double n2 = ((StarInfo *)ssp2)->n; if (n2 < n1) return (1); else if (n2 > n1) return (-1); else return (0); } /* Sort image stars by increasing right ascension */ void RASortStars (sn, sra, sdec, spra, spdec, sx, sy, sm, sc, sobj, ns, nm) double *sn; /* Identifying number */ double *sra; /* Right Ascension */ double *sdec; /* Declination */ double *spra; /* Right Ascension proper motion */ double *spdec; /* Declination proper motion */ double *sx; /* Image X coordinate */ double *sy; /* Image Y coordinate */ double **sm; /* Magnitudes */ int *sc; /* Other 4-byte information */ char **sobj; /* Object name */ int ns; /* Number of stars to sort */ int nm; /* Number of magnitudes per star */ { StarInfo *stars; int i, j, hasnum, hasobj, haspm, hasxy; int StarRASort(); stars = (StarInfo *) calloc ((unsigned int)ns, sizeof(StarInfo)); if (sn == NULL) hasnum = 0; else hasnum = 1; if (spra != NULL && spdec != NULL) haspm = 1; else haspm = 0; if (sx != NULL && sy != NULL) hasxy = 1; else hasxy = 0; if (sobj == NULL) hasobj = 0; else hasobj = 1; for (i = 0; i < ns; i++) { if (hasnum) stars[i].n = sn[i]; stars[i].ra = sra[i]; stars[i].dec = sdec[i]; if (haspm) { stars[i].pra = spra[i]; stars[i].pdec = spdec[i]; } if (hasxy) { stars[i].x = sx[i]; stars[i].y = sy[i]; } for (j = 0; j < nm; j++) stars[i].m[j] = sm[j][i]; stars[i].c = sc[i]; if (hasobj) stars[i].obj = sobj[i]; } qsort ((char *)stars, ns, sizeof(StarInfo), StarRASort); for (i = 0; i < ns; i++) { if (hasnum) sn[i] = stars[i].n; sra[i] = stars[i].ra; sdec[i] = stars[i].dec; if (haspm) { spra[i] = stars[i].pra; spdec[i] = stars[i].pdec; } if (hasxy) { sx[i] = stars[i].x; sy[i] = stars[i].y; } for (j = 0; j < nm; j++) sm[j][i] = stars[i].m[j]; sc[i] = stars[i].c; if (hasobj) sobj[i] = stars[i].obj; } free ((char *)stars); return; } /* Order stars in increasing right ascension (called by qsort) */ int StarRASort (ssp1, ssp2) const void *ssp1, *ssp2; { double ra1 = ((StarInfo *)ssp1)->ra; double ra2 = ((StarInfo *)ssp2)->ra; if (ra2 > ra1) return (-1); else if (ra2 < ra1) return (1); else return (0); } /* Sort image stars by increasing declination */ void DecSortStars (sn, sra, sdec, spra, spdec, sx, sy, sm, sc, sobj, ns, nm) double *sn; /* Identifying number */ double *sra; /* Right Ascension */ double *sdec; /* Declination */ double *spra; /* Right Ascension proper motion */ double *spdec; /* Declination proper motion */ double *sx; /* Image X coordinate */ double *sy; /* Image Y coordinate */ double **sm; /* Magnitudes */ int *sc; /* Other 4-byte information */ char **sobj; /* Object name */ int ns; /* Number of stars to sort */ int nm; /* Number of magnitudes per star */ { StarInfo *stars; int i, j, hasnum, hasobj, haspm, hasxy; int StarDecSort (); stars = (StarInfo *) calloc ((unsigned int)ns, sizeof(StarInfo)); if (sn == NULL) hasnum = 0; else hasnum = 1; if (spra != NULL && spdec != NULL) haspm = 1; else haspm = 0; if (sx != NULL && sy != NULL) hasxy = 1; else hasxy = 0; if (sobj == NULL) hasobj = 0; else hasobj = 1; for (i = 0; i < ns; i++) { if (hasnum) stars[i].n = sn[i]; stars[i].ra = sra[i]; stars[i].dec = sdec[i]; if (haspm) { stars[i].pra = spra[i]; stars[i].pdec = spdec[i]; } if (hasxy) { stars[i].x = sx[i]; stars[i].y = sy[i]; } for (j = 0; j < nm; j++) stars[i].m[j] = sm[j][i]; stars[i].c = sc[i]; if (hasobj) stars[i].obj = sobj[i]; } qsort ((char *)stars, ns, sizeof(StarInfo), StarDecSort); for (i = 0; i < ns; i++) { if (hasnum) sn[i] = stars[i].n; sra[i] = stars[i].ra; sdec[i] = stars[i].dec; if (haspm) { spra[i] = stars[i].pra; spdec[i] = stars[i].pdec; } if (hasxy) { sx[i] = stars[i].x; sy[i] = stars[i].y; } for (j = 0; j < nm; j++) sm[j][i] = stars[i].m[j]; sc[i] = stars[i].c; if (hasobj) sobj[i] = stars[i].obj; } free ((char *)stars); return; } /* Order stars in increasing declination (called by qsort) */ int StarDecSort (ssp1, ssp2) void *ssp1, *ssp2; { double dec1 = ((StarInfo *)ssp1)->dec; double dec2 = ((StarInfo *)ssp2)->dec; if (dec2 > dec1) return (-1); else if (dec2 < dec1) return (1); else return (0); } /* XSortStars -- Sort image stars by increasing X value */ void XSortStars (sn, sra, sdec, spra, spdec, sx, sy, sm, sc, sobj, ns, nm) double *sn; /* Identifying number */ double *sra; /* Right Ascension */ double *sdec; /* Declination */ double *spra; /* Right Ascension proper motion */ double *spdec; /* Declination proper motion */ double *sx; /* Image X coordinate */ double *sy; /* Image Y coordinate */ double **sm; /* Magnitudes */ int *sc; /* Other 4-byte information */ char **sobj; /* Object name */ int ns; /* Number of stars to sort */ int nm; /* Number of magnitudes per star */ { StarInfo *stars; int i, j, hasnum, hasobj, haspos, haspm; int StarXSort (); stars = (StarInfo *) calloc ((unsigned int)ns, sizeof(StarInfo)); if (sn == NULL) hasnum = 0; else hasnum = 1; if (sra != NULL && sdec != NULL) haspos = 1; else haspos = 0; if (spra != NULL && spdec != NULL) haspm = 1; else haspm = 0; if (sobj == NULL) hasobj = 0; else hasobj = 1; for (i = 0; i < ns; i++) { if (hasnum) stars[i].n = sn[i]; if (haspos) { stars[i].ra = sra[i]; stars[i].dec = sdec[i]; } if (haspm) { stars[i].pra = spra[i]; stars[i].pdec = spdec[i]; } stars[i].x = sx[i]; stars[i].y = sy[i]; for (j = 0; j < nm; j++) stars[i].m[j] = sm[j][i]; stars[i].c = sc[i]; if (hasobj) stars[i].obj = sobj[i]; } qsort ((char *)stars, ns, sizeof(StarInfo), StarXSort); for (i = 0; i < ns; i++) { if (hasnum) sn[i] = stars[i].n; if (haspos) { sra[i] = stars[i].ra; sdec[i] = stars[i].dec; } if (haspm) { spra[i] = stars[i].pra; spdec[i] = stars[i].pdec; } sx[i] = stars[i].x; sy[i] = stars[i].y; for (j = 0; j < nm; j++) sm[j][i] = stars[i].m[j]; sc[i] = stars[i].c; if (hasobj) sobj[i] = stars[i].obj; } free ((char *)stars); return; } /* StarXSort -- Order stars in decreasing X value called by qsort */ int StarXSort (ssp1, ssp2) void *ssp1, *ssp2; { double x1 = ((StarInfo *)ssp1)->x; double x2 = ((StarInfo *)ssp2)->x; if (x2 < x1) return (1); else if (x2 > x1) return (-1); else return (0); } /* YSortStars -- Sort image stars by increasing Y value */ void YSortStars (sn, sra, sdec, spra, spdec, sx, sy, sm, sc, sobj, ns, nm) double *sn; /* Identifying number */ double *sra; /* Right Ascension */ double *sdec; /* Declination */ double *spra; /* Right Ascension proper motion */ double *spdec; /* Declination proper motion */ double *sx; /* Image X coordinate */ double *sy; /* Image Y coordinate */ double **sm; /* Magnitudes */ int *sc; /* Other 4-byte information */ char **sobj; /* Object name */ int ns; /* Number of stars to sort */ int nm; /* Number of magnitudes per star */ { StarInfo *stars; int i, j, hasnum, hasobj, haspm, haspos; int StarYSort (); stars = (StarInfo *) calloc ((unsigned int)ns, sizeof(StarInfo)); if (sn == NULL) hasnum = 0; else hasnum = 1; if (sra != NULL && sdec != NULL) haspos = 1; else haspos = 0; if (spra != NULL && spdec != NULL) haspm = 1; else haspm = 0; if (sobj == NULL) hasobj = 0; else hasobj = 1; for (i = 0; i < ns; i++) { if (hasnum) stars[i].n = sn[i]; if (haspos) { stars[i].ra = sra[i]; stars[i].dec = sdec[i]; } if (haspm) { stars[i].pra = spra[i]; stars[i].pdec = spdec[i]; } stars[i].x = sx[i]; stars[i].y = sy[i]; for (j = 0; j < nm; j++) stars[i].m[j] = sm[j][i]; stars[i].c = sc[i]; if (hasobj) stars[i].obj = sobj[i]; } qsort ((char *)stars, ns, sizeof(StarInfo), StarYSort); for (i = 0; i < ns; i++) { if (hasnum) sn[i] = stars[i].n; if (haspos) { sra[i] = stars[i].ra; sdec[i] = stars[i].dec; } if (haspm) { spra[i] = stars[i].pra; spdec[i] = stars[i].pdec; } sx[i] = stars[i].x; sy[i] = stars[i].y; for (j = 0; j < nm; j++) sm[j][i] = stars[i].m[j]; sc[i] = stars[i].c; if (hasobj) sobj[i] = stars[i].obj; } free ((char *)stars); return; } /* StarYSort -- Order stars in decreasing Y value called by qsort */ int StarYSort (ssp1, ssp2) void *ssp1, *ssp2; { double y1 = ((StarInfo *)ssp1)->y; double y2 = ((StarInfo *)ssp2)->y; if (y2 < y1) return (1); else if (y2 > y1) return (-1); else return (0); } static int logmerge = 0; /* MergeStars -- Merge multiple entries within given radius */ /* return mean ra, dec, proper motion, and magnitude(s) */ int MergeStars (sn,sra,sdec,spra,spdec,sx,sy,sm,sc,sobj,ns,nm,rad,log) double *sn; /* Identifying number */ double *sra; /* Right Ascension */ double *sdec; /* Declination */ double *spra; /* Right Ascension proper motion */ double *spdec; /* Declination proper motion */ double *sx; /* Image X coordinate */ double *sy; /* Image Y coordinate */ double **sm; /* Magnitudes */ int *sc; /* Other 4-byte information */ char **sobj; /* Object name */ int ns; /* Number of stars to sort */ int nm; /* Number of magnitudes per star */ double rad; /* Maximum separation in arcseconds to merge */ int log; /* If >0, log progress every time mod number written */ { StarInfo *stars; int i, j, hasnum, hasobj, haspm, hasxy; int StarMerge(); int nns; /* Number of stars in merged catalog (returned) */ double drad; /* Maximum separation in degrees to merge */ int StarRASort(); stars = (StarInfo *) calloc ((unsigned int)ns, sizeof(StarInfo)); drad = rad / 3600.0; logmerge = log; if (sn == NULL) hasnum = 0; else hasnum = 1; if (spra != NULL && spdec != NULL) haspm = 1; if (sx != NULL && sy != NULL) hasxy = 1; else hasxy = 0; if (sobj == NULL) hasobj = 0; else hasobj = 1; for (i = 0; i < ns; i++) { if (hasnum) stars[i].n = sn[i]; else stars[i].n = (double) i; stars[i].ra = sra[i]; stars[i].dec = sdec[i]; if (haspm) { stars[i].pra = spra[i]; stars[i].pdec = spdec[i]; } else { stars[i].pra = 0.0; stars[i].pdec = 0.0; } if (hasxy) { stars[i].x = sx[i]; stars[i].y = sy[i]; } else { stars[i].x = 0.0; stars[i].y = 0.0; } for (j = 0; j < nm; j++) stars[i].m[j] = sm[j][i]; stars[i].c = sc[i]; if (hasobj) stars[i].obj = sobj[i]; } /* Sort stars by right ascension */ if (logmerge) fprintf (stderr, "MergeStars: Sorting %d stars\n", ns); qsort ((char *)stars, ns, sizeof(StarInfo), StarRASort); /* Merge RA-sorted catalogued stars within drad arcseconds of each other */ /* (array stars is replaced by shorter array) */ if (logmerge) fprintf (stderr, "MergeStars: Merging %d stars\n", ns); nns = StarMerge (ns, nm, &stars, drad); /* Re-sort stars by right ascension */ if (logmerge) fprintf (stderr, "MergeStars: Sorting %d stars\n", nns); qsort ((char *)stars, nns, sizeof(StarInfo), StarRASort); for (i = 0; i < nns; i++) { if (hasnum) sn[i] = stars[i].n; sra[i] = stars[i].ra; sdec[i] = stars[i].dec; if (haspm) { spra[i] = stars[i].pra; spdec[i] = stars[i].pdec; } if (hasxy) { sx[i] = stars[i].x; sy[i] = stars[i].y; } for (j = 0; j < nm; j++) sm[j][i] = stars[i].m[j]; sc[i] = stars[i].c; if (hasobj) sobj[i] = stars[i].obj; } free ((char *)stars); return (nns); } #define MAXMERGE 32 /* StarMerge -- Merge stars, called by MergeStars() */ int StarMerge (ns, nm, stars0, rad) int ns; /* Number of stars to merge */ int nm; /* Number of magnitudes per star */ StarInfo **stars0; double rad; /* Maximum separation in arcseconds to merge */ { StarInfo *stars, *newstars; double ra, dec, rsec, dsec, pra, pdec, mag[11]; double rai, deci, dn, dmax; int i, is, js, nthis, im, no, nums[MAXMERGE]; stars = *stars0; newstars = (StarInfo *) calloc ((unsigned int)ns, sizeof(StarInfo)); dmax = rad + 1.0; /* Loop through stars in input catalog */ no = 0; for (is = 1; is < ns; is++) { /* Ignore star if has already been used */ if (stars[is].y == -999.0) continue; /* Initialize position to that of current star */ nthis = 1; ra = stars[is].ra; dec = stars[is].dec; /* Find all stars within rad arcseconds of current input star */ /* Search forward (upward in RA) */ for (js = is; js < ns; js++) { dsec = (stars[js].ra - stars[is].ra) * 3600.0; if (dsec > dmax) break; if (is != js && stars[js].y != -999.0) { rsec = wcsdist (stars[is].ra, stars[is].dec, stars[js].ra, stars[js].dec); if (rsec <= rad) { nthis = nthis + 1; ra = ra + stars[js].ra; dec = dec + stars[js].dec; } } } /* Search backward (downward in RA) */ for (js = is; js > 0; js--) { dsec = (stars[is].ra - stars[js].ra) * 3600.0; if (dsec > dmax) break; if (is != js && stars[js].y != -999.0) { rsec = wcsdist (stars[is].ra, stars[is].dec, stars[js].ra, stars[js].dec); if (rsec <= rad) { nthis = nthis + 1; ra = ra + stars[js].ra; dec = dec + stars[js].dec; } } } /* Compute mean position for this star */ rai = ra / (double) nthis; deci = dec / (double) nthis; /* if (nthis > 1) printf ("StarMerge: Merging %d stars at %d\n", nthis, is); */ /* Initialize output star parameters */ ra = 0.0; dec = 0.0; pra = 0.0; pdec = 0.0; for (im = 0; im < nm; im++) mag[im] = 0.0; nthis = 0; for (i = 0; i < MAXMERGE; i++) nums[i] = 0; /* Find all stars within rad arcseconds of current mean position */ i = 0; dmax = rad + 2.0; /* Search forward (upward in RA) */ for (js = is; js < ns; js++) { dsec = (stars[js].ra - rai) * 3600.0; if (dsec > dmax) break; if (stars[js].y != -999.0) { rsec = wcsdist (rai, deci, stars[js].ra, stars[js].dec); if (rsec <= rad) { nthis = nthis + 1; ra = ra + stars[js].ra; dec = dec + stars[js].dec; pra = pra + stars[js].pra; pdec = pdec + stars[js].pdec; for (im = 0; im < nm; im++) mag[im] = mag[im] + stars[js].m[im]; stars[js].y = -999.0; nums[i++] = js; } } } /* Search backward (downward in RA) */ for (js = is; js > -1; js--) { dsec = (rai - stars[js].ra) * 3600.0; if (dsec > dmax) break; if (stars[js].y != -999.0) { rsec = wcsdist (rai, deci, stars[js].ra, stars[js].dec); if (rsec <= rad) { nthis = nthis + 1; ra = ra + stars[js].ra; dec = dec + stars[js].dec; pra = pra + stars[js].pra; pdec = pdec + stars[js].pdec; for (im = 0; im < nm; im++) mag[im] = mag[im] + stars[js].m[im]; stars[js].y = -999.0; nums[i++] = js; } } } if (nthis > 0) { dn = (double) nthis; newstars[no].ra = ra / dn; newstars[no].dec = dec / dn; newstars[no].pra = pra / dn; newstars[no].pdec = pdec / dn; for (im = 0; im < nm; im++) newstars[no].m[im] = mag[im] / dn; newstars[no].x = dn; newstars[no].y = dn; no = no + 1; } if (logmerge && no%logmerge == 0) fprintf (stderr, "Merged %6d from %6d stars\r", no, is); } /* Free input star entries */ free (stars); fprintf (stderr, "\n"); /* Reset input pointer to merged entries */ *stars0 = newstars; return (no); } /* Jun 13 1996 New program * Oct 18 1996 Add sorting by X value * Nov 13 1996 Add second magnitude * Jan 10 1997 Fix bug in RASortStars to return correct red magnitude * * Mar 2 1998 Make number and second magnitude optional * Oct 21 1998 Add RefCat() to set reference catalog code * Oct 26 1998 Include object names in star catalog entry structure * Oct 29 1998 Return coordinate system and title from RefCat * Nov 20 1998 Add USNO A-2.0 catalog and return different code * Dec 9 1998 Add Hipparcos and Tycho catalogs * * Jan 26 1999 Add subroutines to deal with ranges of numbers * Feb 8 1999 Fix bug initializing ACT catalog * Feb 11 1999 Change starcat.insys to starcat.coorsys * May 19 1999 Move catalog subroutines to catutil() * Aug 26 1999 Compare pointers to NULL, not 0 * * Mar 14 2000 Add proper motions * * May 22 2001 Add sort by declination * Jun 28 2001 In MagSort, if b mag is 99.9, try r mag * Jul 20 2001 In MagSort, allow for absence of ra and dec * Sep 12 2001 Allow up to 11 magnitudes; add nm and magsort * Sep 13 2001 Add YSortStars() to sort by Y coordinate * Sep 18 2001 Subtract 100 in MagSort if magnitude is greater than 100 * Nov 6 2001 Allow missing x and y in MagSort, RASort, and DecSort * Nov 6 2001 Allow missing ra and dec in XSort and YSort * * Apr 8 2002 Drop static subroutine declarations * * Sep 23 2003 Add MergeStars() and StarMerge() to merge input catalog * * Mar 4 2004 Fix rad in MergeStars() * Mar 17 2004 RA-sort before and after merging catalog in MergeStars() * Mar 17 2004 Rewrite StarMerge() to merge RA-sorted catalog quickly * Mar 18 2004 Add logging to StarMerge() * Aug 30 2004 Fix bad declaration * * Apr 13 2006 Add sort by ID number * * Jan 11 2007 Include fitsfile.h * * Nov 6 2009 Set number of magnitudes from MAXNMAG parameter in wcscat.h * * Jun 24 2016 Always initialize haspm in RASortStars() (from Ole Streicher) */ wcstools-3.9.5/libwcs/sph.c0000664000016200001660000001643111750060474014705 0ustar minkoirsys/*============================================================================ * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-2002, Mark Calabretta * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Correspondence concerning WCSLIB may be directed to: * Internet email: mcalabre@atnf.csiro.au * Postal address: Dr. Mark Calabretta, * Australia Telescope National Facility, * P.O. Box 76, * Epping, NSW, 2121, * AUSTRALIA * *============================================================================= * * C routines for the spherical coordinate transformations used by the FITS * "World Coordinate System" (WCS) convention. * * Summary of routines * ------------------- * The spherical coordinate transformations are implemented via separate * functions for the transformation in each direction. * * Forward transformation; sphfwd() * -------------------------------- * Transform celestial coordinates to the native coordinates of a projection. * * Given: * lng,lat double Celestial longitude and latitude, in degrees. * eul[5] double Euler angles for the transformation: * 0: Celestial longitude of the native pole, in * degrees. * 1: Celestial colatitude of the native pole, or * native colatitude of the celestial pole, in * degrees. * 2: Native longitude of the celestial pole, in * degrees. * 3: cos(eul[1]) * 4: sin(eul[1]) * * Returned: * phi, double Longitude and latitude in the native coordinate * theta system of the projection, in degrees. * * Function return value: * int Error status * 0: Success. * * Reverse transformation; sphrev() * -------------------------------- * Transform native coordinates of a projection to celestial coordinates. * * Given: * phi, double Longitude and latitude in the native coordinate * theta system of the projection, in degrees. * eul[5] double Euler angles for the transformation: * 0: Celestial longitude of the native pole, in * degrees. * 1: Celestial colatitude of the native pole, or * native colatitude of the celestial pole, in * degrees. * 2: Native longitude of the celestial pole, in * degrees. * 3: cos(eul[1]) * 4: sin(eul[1]) * * Returned: * lng,lat double Celestial longitude and latitude, in degrees. * * Function return value: * int Error status * 0: Success. * * Author: Mark Calabretta, Australia Telescope National Facility * $Id: sph.c,v 2.7 2002/04/03 01:25:29 mcalabre Exp $ *===========================================================================*/ #include #include "wcslib.h" #ifndef __STDC__ #ifndef const #define const #endif #endif const double tol = 1.0e-5; int sphfwd (lng, lat, eul, phi, theta) const double lat, lng, eul[5]; double *phi, *theta; { double coslat, coslng, dlng, dphi, sinlat, sinlng, x, y, z; coslat = cosdeg (lat); sinlat = sindeg (lat); dlng = lng - eul[0]; coslng = cosdeg (dlng); sinlng = sindeg (dlng); /* Compute the native longitude. */ x = sinlat*eul[4] - coslat*eul[3]*coslng; if (fabs(x) < tol) { /* Rearrange formula to reduce roundoff errors. */ x = -cosdeg (lat+eul[1]) + coslat*eul[3]*(1.0 - coslng); } y = -coslat*sinlng; if (x != 0.0 || y != 0.0) { dphi = atan2deg (y, x); } else { /* Change of origin of longitude. */ dphi = dlng - 180.0; } *phi = eul[2] + dphi; /* Normalize the native longitude. */ if (*phi > 180.0) { *phi -= 360.0; } else if (*phi < -180.0) { *phi += 360.0; } /* Compute the native latitude. */ if (fmod(dlng,180.0) == 0.0) { *theta = lat + coslng*eul[1]; if (*theta > 90.0) *theta = 180.0 - *theta; if (*theta < -90.0) *theta = -180.0 - *theta; } else { z = sinlat*eul[3] + coslat*eul[4]*coslng; /* Use an alternative formula for greater numerical accuracy. */ if (fabs(z) > 0.99) { if (z < 0) *theta = -acosdeg (sqrt(x*x+y*y)); else *theta = acosdeg (sqrt(x*x+y*y)); } else { *theta = asindeg (z); } } return 0; } /*-----------------------------------------------------------------------*/ int sphrev (phi, theta, eul, lng, lat) const double phi, theta, eul[5]; double *lng, *lat; { double cosphi, costhe, dlng, dphi, sinphi, sinthe, x, y, z; costhe = cosdeg (theta); sinthe = sindeg (theta); dphi = phi - eul[2]; cosphi = cosdeg (dphi); sinphi = sindeg (dphi); /* Compute the celestial longitude. */ x = sinthe*eul[4] - costhe*eul[3]*cosphi; if (fabs(x) < tol) { /* Rearrange formula to reduce roundoff errors. */ x = -cosdeg (theta+eul[1]) + costhe*eul[3]*(1.0 - cosphi); } y = -costhe*sinphi; if (x != 0.0 || y != 0.0) { dlng = atan2deg (y, x); } else { /* Change of origin of longitude. */ dlng = dphi + 180.0; } *lng = eul[0] + dlng; /* Normalize the celestial longitude. */ if (eul[0] >= 0.0) { if (*lng < 0.0) *lng += 360.0; } else { if (*lng > 0.0) *lng -= 360.0; } if (*lng > 360.0) { *lng -= 360.0; } else if (*lng < -360.0) { *lng += 360.0; } /* Compute the celestial latitude. */ if (fmod(dphi,180.0) == 0.0) { *lat = theta + cosphi*eul[1]; if (*lat > 90.0) *lat = 180.0 - *lat; if (*lat < -90.0) *lat = -180.0 - *lat; } else { z = sinthe*eul[3] + costhe*eul[4]*cosphi; /* Use an alternative formula for greater numerical accuracy. */ if (fabs(z) > 0.99) { if (z < 0) *lat = -acosdeg (sqrt(x*x+y*y)); else *lat = acosdeg (sqrt(x*x+y*y)); } else { *lat = asindeg (z); } } return 0; } /* Dec 20 1999 Doug Mink - Change cosd() and sind() to cosdeg() and sindeg() * Dec 20 1999 Doug Mink - Include wcslib.h, which includes wcstrig.h, sph.h * Dec 20 1999 Doug Mink - Define copysign only if it is not already defined * * Jan 5 2000 Doug Mink - Drop copysign * * Sep 19 2001 Doug Mink - No change for WCSLIB 2.7 */ wcstools-3.9.5/libwcs/tabread.c0000664000016200001660000024556712400203477015526 0ustar minkoirsys/*** File libwcs/tabread.c *** August 29, 2014 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2014 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ /* int tabread() Read tab table stars in specified region * int tabrnum() Read tab table stars with specified numbers * int tabbin () Bin tab table stars in specified region into an image * int tabxyread() Read x, y, and magnitude from tab table star list * int tabrkey() Read single keyword from specified tab table stars * struct StarCat tabcatopen() Open tab table catalog, return number of entries * struct TabTable *tabopen() Open tab table, returning number of entries * char *tabline() Get tab table entry for one line * double tabgetra() Return double right ascension in degrees * double tabgetdec() Return double declination in degrees * double tabgetr8() Return 8-byte floating point number from tab table line * int tabgeti4() Return 4-byte integer from tab table line * int tabgetk() Return character entry from tab table line for column * int tabgetc() Return n'th character entry from tab table line * int tabhgetr8() Return 8-byte floating point keyword value from header * int tabhgeti4() Return 4-byte integer keyword value from header * int tabhgetc() Return character keyword value from header * int tabparse() Make a table of column headings * int tabcol() Find entry in a table of column headings (case-dependent) * int tabccol() Find entry in a table of column headings (case-independent) * int tabsize() Return length of file in bytes * int istab() Return 1 if first line of file contains a tab, else 0 */ #include #include #include #include #include #include #include "wcs.h" #include "fitsfile.h" #include "wcscat.h" #define ABS(a) ((a) < 0 ? (-(a)) : (a)) static int tabhgetr8(); static int tabhgeti4(); static int tabhgetc(); static int tabcont(); static int tabccont(); static int tabsize(); static int nndec = 0; static int verbose = 0; static char *taberr; static struct Tokens startok; char *gettaberr () { return (taberr); } int gettabndec() { return (nndec); } static char *kwo = NULL; /* Keyword returned by tabread(), tabrnum() */ void settabkey (keyword0) char *keyword0; { kwo = keyword0; return; } /* TABREAD -- Read tab table stars in specified region */ int tabread (tabcatname,distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nstarmax,starcat, tnum,tra,tdec,tpra,tpdec,tmag,tpeak,tkey,nlog) char *tabcatname; /* Name of reference star catalog file */ int distsort; /* 1 to sort stars by distance from center */ double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ double dradi; /* Inner edge of annulus in degrees (ignore if 0) */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 to nmag) */ int nstarmax; /* Maximum number of stars to be returned */ struct StarCat **starcat; /* Star catalog data structure */ double *tnum; /* Array of UJ numbers (returned) */ double *tra; /* Array of right ascensions (returned) */ double *tdec; /* Array of declinations (returned) */ double *tpra; /* Array of right ascension proper motions (returned) */ double *tpdec; /* Array of declination proper motions (returned) */ double **tmag; /* 2-D Array of magnitudes (returned) */ int *tpeak; /* Array of peak counts (returned) */ char **tkey; /* Array of values of additional keyword */ int nlog; { double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ double rra1,rra2; /* Catalog coordinate limiting right ascension (deg) */ double rdec1,rdec2; /* Catalog coordinate limiting declination (deg) */ double dist = 0.0; /* Distance from search center in degrees */ double faintmag=0.0; /* Faintest magnitude */ double maxdist=0.0; /* Largest distance */ int faintstar=0; /* Faintest star */ int farstar=0; /* Most distant star */ double *tdist; /* Array of distances to stars */ int sysref; /* Catalog coordinate system */ double eqref; /* Catalog equinox */ double epref; /* Catalog epoch */ double secmarg = 0.0; /* Arcsec/century margin for proper motion */ double magt; double rdist, ddist; int pass; char cstr[32]; struct Star *star; struct StarCat *sc; /* Star catalog data structure */ int wrap; int jstar; int magsort; int nstar; char *objname; int lname; int imag; double ra,dec, rapm, decpm; double mag, parallax, rv; double num; int peak, i; int istar, nstars, lstar; sc = *starcat; if (nlog > 0) verbose = 1; else verbose = 0; SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* mag1 is always the smallest magnitude limit */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } /* Logging interval */ nstar = 0; tdist = (double *) calloc (nstarmax, sizeof (double)); lstar = sizeof (struct Star); star = (struct Star *) calloc (1, lstar); if (sc == NULL) sc = tabcatopen (tabcatname, NULL, 0); *starcat = sc; if (sc == NULL || sc->nstars <= 0) { if (taberr != NULL) fprintf (stderr,"%s\n", taberr); fprintf (stderr,"TABREAD: Cannot read catalog %s\n", tabcatname); free (star); sc = NULL; return (0); } nstars = sc->nstars; jstar = 0; if (sortmag > 0 && sortmag <= sc->nmag) magsort = sortmag - 1; else magsort = 0; /* Set catalog coordinate system */ if (sc->equinox != 0.0) eqref = sc->equinox; else eqref = eqout; if (sc->epoch != 0.0) epref = sc->epoch; else epref = epout; if (sc->coorsys) sysref = sc->coorsys; else sysref = sysout; wcscstr (cstr, sysout, eqout, epout); rra1 = ra1; rra2 = ra2; rdec1 = dec1; rdec2 = dec2; if (sc->mprop > 0) secmarg = 60.0; RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref,secmarg, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); /* Loop through catalog */ for (istar = 1; istar <= nstars; istar++) { /* Read position of next star */ if (tabstar (istar, sc, star, verbose)) { if (verbose) fprintf (stderr,"TABREAD: Cannot read star %d\n", istar); break; } /* Set magnitude to test */ if (sc->nmag > 0) { magt = star->xmag[magsort]; if (sortmag < 1) { imag = 0; while (magt == 99.90 && imag < sc->nmag) magt = star->xmag[imag++]; if (magt > 100.0) magt = magt - 100.0; } } else magt = mag1; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (magt < mag1 || magt > mag2)) pass = 0; /* Check rough position limits */ ra = star->ra; dec = star->dec; if ((!wrap && (ra < rra1 || ra > rra2)) || (wrap && (ra < rra1 && ra > rra2)) || dec < rdec1 || dec > rdec2) pass = 0; /* Convert coordinate system for this star and test it*/ if (pass) { sysref = star->coorsys; eqref = star->equinox; epref = star->epoch; /* Extract selected fields */ num = star->num; rapm = star->rapm; decpm = star->decpm; parallax = star->parallax; rv = star->radvel; /* Convert from catalog to search coordinate system */ if (sc->entpx || sc->entrv) wcsconv (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm, ¶llax, &rv); else if (sc->mprop == 1) wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); else wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); if (sc->sptype) peak = (1000 * (int) star->isp[0]) + (int)star->isp[1]; else peak = star->peak; /* Compute distance from search center */ if (drad > 0 || distsort) dist = wcsdist (cra,cdec,ra,dec); else dist = 0.0; /* Check radial distance to search center */ if (drad > 0) { if (dist > drad) pass = 0; if (dradi > 0.0 && dist < dradi) pass = 0; } /* Check distance along RA and Dec axes */ else { ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } } /* Add this star's information to the list if still OK */ if (pass) { /* Save star position and magnitude in table */ if (nstar < nstarmax) { tnum[nstar] = num; tra[nstar] = ra; tdec[nstar] = dec; if (sc->mprop == 1) { tpra[nstar] = rapm; tpdec[nstar] = decpm; } for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][nstar] = star->xmag[imag]; } if (tpeak) tpeak[nstar] = peak; tdist[nstar] = dist; lname = strlen (star->objname); if (lname > 0) { objname = (char *)calloc (lname+1, 1); strcpy (objname, star->objname); if (tkey[nstar]) free(tkey[nstar]); tkey[nstar] = objname; } if (dist > maxdist) { maxdist = dist; farstar = nstar; } if (sc->nmag > 0 && magt > faintmag) { faintmag = magt; faintstar = nstar; } } /* If radial search & too many stars, replace furthest star */ else if (distsort) { if (dist < maxdist) { tnum[farstar] = num; tra[farstar] = ra; tdec[farstar] = dec; if (sc->mprop == 1) { tpra[farstar] = rapm; tpdec[farstar] = decpm; } for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][farstar] = star->xmag[imag]; } tpeak[farstar] = peak; tdist[farstar] = dist; lname = strlen (star->objname); if (lname > 0) { objname = (char *)calloc (lname+1, 1); strcpy (objname, star->objname); if (tkey[farstar]) free(tkey[farstar]); tkey[farstar] = objname; } /* Find new farthest star */ maxdist = 0.0; for (i = 0; i < nstarmax; i++) { if (tdist[i] > maxdist) { maxdist = tdist[i]; farstar = i; } } } } /* Otherwise if too many stars, replace faintest star */ else if (sc->nmag > 0 && magt < faintmag) { tnum[faintstar] = num; tra[faintstar] = ra; tdec[faintstar] = dec; if (sc->mprop == 1) { tpra[faintstar] = rapm; tpdec[faintstar] = decpm; } for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][faintstar] = star->xmag[imag]; } tpeak[faintstar] = peak; tdist[faintstar] = dist; lname = strlen (star->objname); if (lname > 0) { objname = (char *)calloc (lname+1, 1); strcpy (objname, star->objname); if (tkey[faintstar]) free(tkey[faintstar]); tkey[faintstar] = objname; } faintmag = 0.0; /* Find new faintest star */ for (i = 0; i < nstarmax; i++) { magt = tmag[magsort][i]; imag = 0; while (magt == 99.90 && imag < sc->nmag) magt = tmag[imag++][i]; if (magt > 100.0) magt = magt - 100.0; if (magt > faintmag) { faintmag = magt; faintstar = i; } } } nstar++; jstar++; if (nlog == 1) fprintf (stderr,"TABREAD: %11.6f: %9.5f %9.5f %s %5.2f %d \n", num,ra,dec,cstr,magt,peak); /* End of accepted star processing */ } /* Log operation */ if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"TABREAD: %5d / %5d / %5d sources catalog %s\r", jstar,istar,nstars,tabcatname); /* End of star loop */ } /* Summarize search */ if (nlog > 0) { fprintf (stderr,"TABREAD: Catalog %s : %d / %d / %d found\n",tabcatname, jstar,istar,nstars); if (nstar > nstarmax) fprintf (stderr,"TABREAD: %d stars found; only %d returned\n", nstar,nstarmax); } free ((char *) tdist); free ((char *) star); return (nstar); } /* TABRNUM -- Read tab table stars with specified numbers */ int tabrnum (tabcatname, nnum, sysout, eqout, epout, starcat, match, tnum,tra,tdec,tpra,tpdec,tmag,tpeak,tkey,nlog) char *tabcatname; /* Name of reference star catalog file */ int nnum; /* Number of stars to look for */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ struct StarCat **starcat; /* Star catalog data structure */ int match; /* 1 to match star number exactly, else sequence num.*/ double *tnum; /* Array of star numbers to look for */ double *tra; /* Array of right ascensions (returned) */ double *tdec; /* Array of declinations (returned) */ double *tpra; /* Array of right ascension proper motions (returned) */ double *tpdec; /* Array of declination proper motions (returned) */ double **tmag; /* 2-D array of magnitudes (returned) */ int *tpeak; /* Array of peak counts (returned) */ char **tkey; /* Array of additional keyword values */ int nlog; { int jnum; int nstar; double ra,dec, rapm, decpm; double mag, parallax, rv; double num; int peak; int istar, istar0, nstars; int imag; char *line; char numstr[32]; /* Catalog number */ int sysref; /* Catalog coordinate system */ double eqref; /* Catalog equinox */ double epref; /* Catalog epoch */ char cstr[32]; char str[32]; char *objname; char *datestring; int lname, lstar; int ireg, inum, nnfld, i; char rastr[32], decstr[32]; struct TabTable *startab; struct StarCat *sc; struct Star *star; line = NULL; nnfld = 0; nstar = 0; nndec = 0; /* Allocate catalog entry buffer */ lstar = sizeof (struct Star); star = (struct Star *) calloc (1, lstar); /* Open star catalog */ sc = *starcat; if (sc == NULL) sc = tabcatopen (tabcatname, NULL, 0); *starcat = sc; if (sc == NULL || sc->nstars <= 0) { if (taberr != NULL) fprintf (stderr,"%s\n", taberr); fprintf (stderr,"TABRNUM: Cannot read catalog %s\n", tabcatname); free (star); return (0); } startab = sc->startab; nstars = sc->nstars; /* Set catalog coordinate system */ if (sc->equinox != 0.0) eqref = sc->equinox; else eqref = eqout; if (sc->epoch != 0.0) epref = sc->epoch; else epref = epout; if (sc->coorsys) sysref = sc->coorsys; else sysref = sysout; wcscstr (cstr, sysout, eqout, epout); /* Write header if printing star entries as found */ if (nlog < 0) { char *revmessage; revmessage = getrevmsg(); printf ("catalog %s\n", tabcatname); printf ("radecsys %s\n", cstr); printf ("equinox %.3f\n", eqout); printf ("epoch %.3f\n", epout); printf ("program scat %s\n", revmessage); if (sc->nnfld > 0) nnfld = sc->nnfld; else nnfld = CatNumLen (TABCAT, tnum[nnum-1], sc->nndec); printf ("id ra dec "); for (i = 1; i < sc->nmag+1; i++) { if (i == sc->nmag && sc->entepoch) printf (" epoch "); else printf (" %s", sc->keymag[i-1]); } if (kwo != NULL) printf (" %s\n", kwo); else printf ("\n"); printf ("----- ------------ ------------"); for (i = 1; i < sc->nmag+1; i++) { if (i == sc->nmag && sc->entepoch) printf (" --------"); else printf (" -----"); } if (kwo != NULL) printf (" ---------\n"); else printf ("\n"); } star->num = 0.0; istar0 = 0; num = 0.0; /* Loop through star list */ line = startab->tabdata; for (jnum = 0; jnum < nnum; jnum++) { /* Read forward from the last star if possible */ inum = (int) (tnum[jnum] + 0.5); if ((double)inum != tnum[jnum] || inum < istar0 || istar0 == 0) { istar0 = 1; } /* Loop through catalog to star */ for (istar = istar0; istar <= nstars; istar++) { if (!match && istar == inum) break; if (num < tnum[jnum]) { if ((line = gettabline (startab, istar)) == NULL) { if (nlog) fprintf (stderr,"TABRNUM: Cannot read star %d\n", istar); break; } } /* Check ID number first */ (void) setoken (&startok, line, "tab"); if (!strcmp (sc->isfil,"gsc-server")) { if (tabgetc (&startok, sc->entid, str, 24)) num = 0.0; else { num = atof (str+3) * 0.00001; ireg = (int) num; inum = (int) (((num - (double)ireg) * 100000.0) + 0.5); num = (double) ireg + 0.0001 * (double) inum; } } else num = tabgetr8 (&startok,sc->entid); if (num == 0.0) num = (double) istar; if (num > tnum[jnum]) { break; } if (num == tnum[jnum]) break; } /* If star has been found in table, read rest of entry */ if ((match && num == tnum[jnum]) || (!match && inum == istar)) { istar0 = istar; sc->istar = startab->iline; if (tabstar (istar, sc, star, nlog)) fprintf (stderr,"TABRNUM: Cannot read star %d\n", istar); /* If star entry has been read successfully */ else { /* Set coordinate system for this star */ sysref = star->coorsys; eqref = star->equinox; /* Extract selected fields */ num = star->num; ra = star->ra; dec = star->dec; rapm = star->rapm; decpm = star->decpm; parallax = star->parallax; rv = star->radvel; if (sc->entrv > 0) star->xmag[sc->nmag-1] = rv; if (sc->entpx || sc->entrv) wcsconv (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm, ¶llax, &rv); else if (sc->mprop == 1) wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); else wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); if (sc->nmag > 0) mag = star->xmag[0]; else mag = 99.99; if (sc->sptype) peak = (1000 * (int) star->isp[0]) + (int)star->isp[1]; else peak = star->peak; if (nlog < 0) { CatNum (TABCAT, -nnfld, sc->nndec, num, numstr); ra2str (rastr, 31, ra, 3); dec2str (decstr, 31, dec, 2); printf ("%s %s %s", numstr,rastr,decstr); for (imag = 0; imag < sc->nmag; imag++) if (imag == sc->nmag-1 && sc->entepoch) { datestring = DateString (star->xmag[imag], 1); printf ("%s", datestring); free (datestring); } else printf (" %.2f", star->xmag[imag]); if (kwo != NULL) printf (" %s\n", star->objname); else printf ("\n"); continue; } /* Save star position and magnitude in table */ tnum[jnum] = num; tra[jnum] = ra; tdec[jnum] = dec; if (sc->mprop == 1) { tpra[jnum] = rapm; tpdec[jnum] = decpm; } for (imag = 0; imag < sc->nmag; imag++) { if (tmag[imag] != NULL) tmag[imag][jnum] = star->xmag[imag]; } tpeak[jnum] = peak; lname = strlen (star->objname); if (lname > 0) { objname = (char *)calloc (lname+1, 1); strcpy (objname, star->objname); if (tkey[jnum]) free(tkey[jnum]); tkey[jnum] = objname; } nstar++; if (nlog == 1) fprintf (stderr,"TABRNUM: %11.6f: %9.5f %9.5f %s %5.2f %d \n", num,ra,dec,cstr,mag,peak); /* End of accepted star processing */ } } else { nstar++; istar0 = istar; if (nlog < 0) { CatNum (TABCAT, -nnfld, sc->nndec, tnum[jnum], numstr); ra = 0.0; ra2str (rastr, 31, ra, 3); dec = 0.0; dec2str (decstr, 31, dec, 2); printf ("%s %s %s", numstr,rastr,decstr); for (imag = 0; imag < sc->nmag; imag++) printf (" 99.0"); printf ("\n"); } } /* Log operation */ if (nlog > 0 && jnum%nlog == 0) fprintf (stderr,"TABRNUM: %5d / %5d / %5d sources catalog %s\r", nstar,jnum,nstars,tabcatname); /* End of star loop */ } /* Summarize search */ if (nlog > 0) fprintf (stderr,"TABRNUM: Catalog %s : %d / %d found\n", tabcatname,nstar,nstars); free ((char *) star); return (nstar); } /* TABBIN -- Bin tab table stars in specified region into an image */ int tabbin (tabcatname, wcs, header, image, mag1, mag2, sortmag, magscale, nlog) char *tabcatname; /* Name of reference star catalog file */ struct WorldCoor *wcs; /* World coordinate system for image */ char *header; /* FITS header for output image */ char *image; /* Output FITS image */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 to nmag) */ double magscale; /* Scaling factor for magnitude to pixel flux * (number of catalog objects per bin if 0) */ int nlog; { double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ double rra1,rra2; /* Catalog coordinate limiting right ascension (deg) */ double rdec1,rdec2; /* Catalog coordinate limiting declination (deg) */ int sysref; /* Catalog coordinate system */ double eqref; /* Catalog equinox */ double epref; /* Catalog epoch */ double secmarg = 0.0; /* Arcsec/century margin for proper motion */ double magt; double rdist, ddist; int ix, iy; int pass; char cstr[32]; struct Star *star; struct StarCat *sc; /* Star catalog data structure */ int wrap; int jstar; int magsort; int nstar; int imag; double ra,dec, rapm, decpm; double mag, parallax, rv; double num; int peak; int istar, nstars, lstar; double xpix, ypix, flux; int offscl; int bitpix, w, h; /* Image bits/pixel and pixel width and height */ double logt = log(10.0); if (nlog > 0) verbose = 1; else verbose = 0; /* Set image parameters */ bitpix = 0; (void)hgeti4 (header, "BITPIX", &bitpix); w = 0; (void)hgeti4 (header, "NAXIS1", &w); h = 0; (void)hgeti4 (header, "NAXIS2", &h); /* Set catalog search limits from image WCS information */ sysout = wcs->syswcs; eqout = wcs->equinox; epout = wcs->epoch; wcscstr (cstr, sysout, eqout, epout); wcssize (wcs, &cra, &cdec, &dra, &ddec); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* mag1 is always the smallest magnitude limit */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } /* Logging interval */ nstar = 0; lstar = sizeof (struct Star); star = (struct Star *) calloc (1, lstar); sc = tabcatopen (tabcatname, NULL, 0); if (sc == NULL || sc->nstars <= 0) { if (taberr != NULL) fprintf (stderr,"%s\n", taberr); fprintf (stderr,"TABBIN: Cannot read catalog %s\n", tabcatname); free (star); sc = NULL; return (0); } nstars = sc->nstars; jstar = 0; if (sortmag > 0 && sortmag <= sc->nmag) magsort = sortmag - 1; else magsort = 0; /* Set catalog coordinate system */ if (sc->equinox != 0.0) eqref = sc->equinox; else eqref = eqout; if (sc->epoch != 0.0) epref = sc->epoch; else epref = epout; if (sc->coorsys) sysref = sc->coorsys; else sysref = sysout; wcscstr (cstr, sysout, eqout, epout); rra1 = ra1; rra2 = ra2; rdec1 = dec1; rdec2 = dec2; if (sc->mprop > 0) secmarg = 60.0; RefLim(cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref,secmarg, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); /* If RA range includes zero, split it in two */ if (rra1 > rra2) wrap = 1; else wrap = 0; /* Loop through catalog */ for (istar = 1; istar <= nstars; istar++) { /* Read position of next star */ if (tabstar (istar, sc, star, verbose)) { if (verbose) fprintf (stderr,"TABBIN: Cannot read star %d\n", istar); break; } /* Set magnitude to test */ if (sc->nmag > 0) { magt = star->xmag[magsort]; imag = 0; while (magt == 99.90 && imag < sc->nmag) magt = star->xmag[imag++]; if (magt > 100.0) magt = magt - 100.0; } else magt = mag1; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (magt < mag1 || magt > mag2)) pass = 0; /* Check rough position limits */ ra = star->ra; dec = star->dec; if ((!wrap && (ra < rra1 || ra > rra2)) || (wrap && (ra < rra1 && ra > rra2)) || dec < rdec1 || dec > rdec2) pass = 0; /* Convert coordinate system for this star and test it*/ if (pass) { sysref = star->coorsys; eqref = star->equinox; epref = star->epoch; /* Extract selected fields */ num = star->num; rapm = star->rapm; decpm = star->decpm; parallax = star->parallax; rv = star->radvel; /* Convert from catalog to search coordinate system */ if (sc->entpx || sc->entrv) wcsconv (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm, ¶llax, &rv); else if (sc->mprop == 1) wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); else wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); if (sc->sptype) peak = (1000 * (int) star->isp[0]) + (int)star->isp[1]; else peak = star->peak; /* Check distance along RA and Dec axes */ ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } /* Save star in FITS image */ if (pass) { wcs2pix (wcs, ra, dec, &xpix, &ypix, &offscl); if (!offscl) { if (magscale > 0.0) flux = magscale * exp (logt * (-magt / 2.5)); else flux = 1.0; ix = (int) (xpix + 0.5); iy = (int) (ypix + 0.5); addpix1 (image, bitpix, w,h, 0.0,1.0, xpix,ypix, flux); nstar++; jstar++; } else { ix = 0; iy = 0; } if (nlog == 1) { fprintf (stderr,"TABBIN: %11.6f: %9.5f %9.5f %s", num,ra,dec,cstr); if (magscale > 0.0) fprintf (stderr, " %5.2f", mag); if (!offscl) flux = getpix1 (image, bitpix, w, h, 0.0, 1.0, ix, iy); else flux = 0.0; fprintf (stderr," (%d,%d): %f\n", ix, iy, flux); } /* End of accepted star processing */ } /* Log operation */ if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"TABBIN: %5d / %5d / %5d sources catalog %s\r", jstar,istar,nstars,tabcatname); /* End of star loop */ } /* Summarize search */ if (nlog > 0) { fprintf (stderr,"TABBIN: Catalog %s : %d / %d / %d found\n",tabcatname, jstar,istar,nstars); } return (nstar); } /* TABXYREAD -- Read X, Y, and magnitude of tab table stars */ int tabxyread (tabcatname, xa, ya, ba, pa, nlog) char *tabcatname; /* Name of reference star catalog file */ double **xa; /* Array of x coordinates (returned) */ double **ya; /* Array of y coordinates (returned) */ double **ba; /* Array of magnitudes (returned) */ int **pa; /* Array of fluxes (returned) */ int nlog; { double xi, yi, magi, flux; char *line; int istar, nstars; struct TabTable *startab; int entx, enty, entmag; /* Open tab table file */ nndec = 0; startab = tabopen (tabcatname, 0); if (startab == NULL || startab->nlines <= 0) { fprintf (stderr,"TABXYREAD: Cannot read catalog %s\n", tabcatname); return (0); } /* Find columns for X and Y */ entx = tabccol (startab, "x"); enty = tabccol (startab, "y"); /* Find column for magnitude */ if (!(entmag = tabccol (startab, "mag"))) { if (!(entmag = tabccol (startab, "magv"))) { if (!(entmag = tabccol (startab, "magj"))) entmag = tabccol (startab, "magr"); } } /* Allocate vectors for x, y, magnitude, and flux */ nstars = startab->nlines; *xa = (double *) realloc(*xa, nstars*sizeof(double)); if (*xa == NULL) { fprintf (stderr,"TABXYREAD: Cannot allocate memory for x\n"); return (0); } *ya = (double *) realloc(*ya, nstars*sizeof(double)); if (*ya == NULL) { fprintf (stderr,"TABXYREAD: Cannot allocate memory for y\n"); return (0); } *ba = (double *) realloc(*ba, nstars*sizeof(double)); if (*ba == NULL) { fprintf (stderr,"TABXYREAD: Cannot allocate memory for mag\n"); return (0); } *pa = (int *) realloc(*pa, nstars*sizeof(int)); if (*pa == NULL) { fprintf (stderr,"TABXYREAD: Cannot allocate memory for flux\n"); return (0); } /* Loop through catalog */ for (istar = 0; istar < nstars; istar++) { /* Read line for next star */ if ((line = gettabline (startab, istar+1)) == NULL) { fprintf (stderr,"TABXYREAD: Cannot read star %d\n", istar); break; } /* Extract x, y, and magnitude */ (void) setoken (&startok, line, "tab"); xi = tabgetr8 (&startok, entx); yi = tabgetr8 (&startok, enty); magi = tabgetr8 (&startok, entmag); (*xa)[istar] = xi; (*ya)[istar] = yi; (*ba)[istar] = magi; flux = 1000000000.0 * pow (10.0, (-magi / 2.5)); (*pa)[istar] = (int) flux; if (nlog == 1) fprintf (stderr,"DAOREAD: %6d/%6d: %9.5f %9.5f %6.2f %15.4f\n", istar,nstars,xi,yi,magi,flux); /* Log operation */ if (nlog > 1 && istar%nlog == 0) fprintf (stderr,"TABXYREAD: %5d / %5d sources catalog %s\r", istar,nstars,tabcatname); /* End of star loop */ } /* Summarize search */ if (nlog > 0) fprintf (stderr,"TABXYREAD: Catalog %s : %d / %d found\n",tabcatname, istar,nstars); /* Free table */ tabclose (startab); if (istar < nstars-1) return (istar + 1); else return (nstars); } #define TABMAX 64 /* TABRKEY -- Read single keyword from tab table stars with specified numbers */ int tabrkey (tabcatname, starcat, nnum, tnum, keyword, tval) char *tabcatname; /* Name of reference star catalog file */ struct StarCat **starcat; /* Star catalog data structure */ int nnum; /* Number of stars to look for */ double *tnum; /* Array of star numbers to look for */ char *keyword; /* Keyword for which to return values */ char **tval; /* Returned values for specified keyword */ { int jnum, lval; int nstar; int istar, nstars; double num; char *line; char *tvalue; char value[TABMAX]; struct TabTable *startab; struct StarCat *sc; /* Star catalog data structure */ nstar = 0; /* Open star catalog */ sc = *starcat; if (sc == NULL) sc = tabcatopen (tabcatname, NULL, 0); *starcat = sc; if (sc == NULL || sc->nstars <= 0) { if (taberr != NULL) fprintf (stderr,"%s\n", taberr); fprintf (stderr,"TABRKEY: Cannot read catalog %s\n", tabcatname); return (0); } startab = sc->startab; if (startab == NULL || startab->nlines <= 0) { fprintf (stderr,"TABRKEY: Cannot read catalog %s\n", tabcatname); return (0); } /* Loop through star list */ nstars = startab->nlines; for (jnum = 0; jnum < nnum; jnum++) { /* Loop through catalog to star */ for (istar = 1; istar <= nstars; istar++) { if ((line = gettabline (startab, istar)) == NULL) { fprintf (stderr,"TABRKEY: Cannot read star %d\n", istar); num = 0.0; break; } /* Check ID number */ (void) setoken (&startok, line, "tab"); if ((num = tabgetr8 (&startok,sc->entid)) == 0.0) num = (double) istar; if (num == tnum[jnum]) break; } /* If star has been found in table */ if (num == tnum[jnum]) { nstar++; /* Extract selected field */ (void) tabgetk (startab, &startok, keyword, value, TABMAX); lval = strlen (value); if (lval > 0) { tvalue = (char *) calloc (1, lval+1); strcpy (tvalue, value); } else tvalue = NULL; if (tval[jnum]) free(tval[jnum]); tval[jnum] = tvalue; } } return (nstars); } static char newline = 10; static char tab = 9; /* TABCATOPEN -- Open tab table catalog, returning number of entries */ struct StarCat * tabcatopen (tabpath, tabtable, nbbuff) char *tabpath; /* Tab table catalog file pathname */ struct TabTable *tabtable; int nbbuff; /* Number of bytes in buffer; 0=read whole file */ { char cstr[32]; char keyword[16]; char *tabname; struct TabTable *startab; struct StarCat *sc; int i, lnum, ndec, istar, nbsc, icol, j, nnfld; int entpmq, entnid; char *line; double dnum; /* Open the tab table file */ if (tabtable != NULL) startab = tabtable; else if ((startab = tabopen (tabpath, nbbuff)) == NULL) return (NULL); /* Allocate catalog data structure */ nbsc = sizeof (struct StarCat); sc = (struct StarCat *) calloc (1, nbsc); sc->startab = startab; /* Save name of catalog */ tabname = strrchr (tabpath, '/'); if (tabname) tabname = tabname + 1; else tabname = tabpath; if (strlen (tabname) < 24) strcpy (sc->isfil, tabname); else { strncpy (sc->isfil, tabname, 23); sc->isfil[23] = (char) 0; } /* Find column and name of object identifier */ sc->entid = -1; sc->keyid[0] = (char) 0; if ((sc->entid = tabccol (startab, "id"))) { i = sc->entid - 1; strncpy (sc->keyid, startab->colname[i], startab->lcol[i]); } else if ((sc->entid = tabccont (startab, "_id"))) { i = sc->entid - 1; strncpy (sc->keyid, startab->colname[i], startab->lcol[i]); } else if ((sc->entid = tabccont (startab, "id"))) { i = sc->entid - 1; strncpy (sc->keyid, startab->colname[i], startab->lcol[i]); } else if ((sc->entid = tabccont (startab, "num"))) { i = sc->entid - 1; strncpy (sc->keyid, startab->colname[i], startab->lcol[i]); } else if ((sc->entid = tabccont (startab, "name"))) { i = sc->entid - 1; strncpy (sc->keyid, startab->colname[i], startab->lcol[i]); } else if ((sc->entid = tabccont (startab, "obj"))) { i = sc->entid - 1; strncpy (sc->keyid, startab->colname[i], startab->lcol[i]); } sc->nndec = nndec; /* Figure out what the coordinate system is */ if (tabhgetc (startab, "radecsys", cstr)) { if (!strcmp (cstr, "galactic")) sc->coorsys = WCS_GALACTIC; else if (!strcmp (cstr, "ecliptic")) sc->coorsys = WCS_ECLIPTIC; else if (!strcmp (cstr, "fk4")) sc->coorsys = WCS_B1950; else sc->coorsys = WCS_J2000; } else sc->coorsys = WCS_J2000; /* Find column and name of object right ascension */ sc->entra = -1; sc->keyra[0] = (char) 0; if (sc->coorsys == WCS_GALACTIC) { if ((sc->entra = tabccol (startab, "long_gal"))) strcpy (sc->keyra, "long_gal"); else if ((sc->entra = tabccol (startab, "long"))) strcpy (sc->keyra, "long_gal"); else if ((sc->entra = tabccont (startab, "long"))) { i = sc->entra - 1; strncpy (sc->keyra, startab->colname[i], startab->lcol[i]); } } else if (sc->coorsys == WCS_ECLIPTIC) { if ((sc->entra = tabccol (startab, "long_ecl"))) strcpy (sc->keyra, "long_ecl"); else if ((sc->entra = tabccol (startab, "long"))) strcpy (sc->keyra, "long_ecl"); else if ((sc->entra = tabccont (startab, "long"))) { i = sc->entra - 1; strncpy (sc->keyra, startab->colname[i], startab->lcol[i]); } } else { if ((sc->entra = tabccol (startab, "ra"))) { i = sc->entra - 1; strncpy (sc->keyra, startab->colname[i], startab->lcol[i]); } else if ((sc->entra = tabccont (startab, "ra"))) { i = sc->entra - 1; strncpy (sc->keyra, startab->colname[i], startab->lcol[i]); } } /* Find column and name of object declination */ sc->entdec = -1; sc->keydec[0] = (char) 0; if (sc->coorsys == WCS_GALACTIC) { if ((sc->entdec = tabccol (startab, "lat_gal"))) strcpy (sc->keydec, "lat_gal"); else if ((sc->entdec = tabccol (startab, "lat"))) strcpy (sc->keydec, "lat_gal"); else if ((sc->entdec = tabccont (startab, "lat"))) { i = sc->entdec - 1; strncpy (sc->keydec, startab->colname[i], startab->lcol[i]); } } else if (sc->coorsys == WCS_ECLIPTIC) { if ((sc->entdec = tabccol (startab, "lat_ecl"))) strcpy (sc->keydec, "lat_ecl"); else if ((sc->entdec = tabccol (startab, "lat"))) strcpy (sc->keydec, "lat_ecl"); else if ((sc->entdec = tabccont (startab, "lat"))) { i = sc->entdec - 1; strncpy (sc->keydec, startab->colname[i], startab->lcol[i]); } } else { if ((sc->entdec = tabccol (startab, "de(deg)"))) { i = sc->entdec - 1; strcpy (sc->keydec, "dec"); } else if ((sc->entdec = tabccol (startab, "dec"))) { i = sc->entdec - 1; strncpy (sc->keydec, startab->colname[i], startab->lcol[i]); } else if ((sc->entdec = tabccont (startab, "dec"))) { i = sc->entdec - 1; strncpy (sc->keydec, startab->colname[i], startab->lcol[i]); } } /* Check columns for magnitudes and save columns and names */ sc->nmag = 0; icol = 0; for (i = 0; i < startab->ncols; i++) { icol = icol + 1; if (icol == sc->entid) continue; if (icol == sc->entra) continue; if (icol == sc->entdec) continue; for (j = 0; j < 16; j++) keyword[j] = (char)0; if (startab->lcol[i] < 16) strncpy (keyword, startab->colname[i], startab->lcol[i]); else strncpy (keyword, startab->colname[i], 15); if (strcsrch (keyword, "mag") && !strcsrch (keyword, "err") && !strcsrch (keyword, "code")) { strcpy (sc->keymag[sc->nmag], keyword); sc->entmag[sc->nmag] = icol; sc->nmag++; } else if (strcsrch (keyword, "exp")) { strcpy (sc->keymag[sc->nmag], keyword); sc->entmag[sc->nmag] = icol; sc->nmag++; } else if (strcsrch (keyword, "dist")) { strcpy (sc->keymag[sc->nmag], keyword); sc->entmag[sc->nmag] = icol; sc->nmag++; } else if ((keyword[0] == 'M' || keyword[0] == 'm') && !strcsrch (keyword, "err") && !strcsrch (keyword, "code") && !strcsrch (keyword, "flag")) { strcpy (sc->keymag[sc->nmag], keyword); sc->entmag[sc->nmag] = icol; sc->nmag++; } } /* Find column and name of object right ascension proper motion */ sc->entrpm = -1; sc->keyrpm[0] = (char) 0; if ((sc->entrpm = tabccol (startab, "ura"))) strcpy (sc->keyrpm, "ura"); else if ((sc->entrpm = tabccol (startab, "rapm"))) strcpy (sc->keyrpm, "rapm"); else if ((sc->entrpm = tabccol (startab, "pmra"))) strcpy (sc->keyrpm, "pmra"); else if ((sc->entrpm = tabccol (startab, "dra"))) strcpy (sc->keyrpm, "dra"); else if ((sc->entrpm = tabccol (startab, "ux"))) strcpy (sc->keyrpm, "ux"); /* Find column and name of object declination proper motion */ sc->entdpm = -1; sc->keydpm[0] = (char) 0; if ((sc->entdpm = tabccol (startab, "udec"))) strcpy (sc->keydpm, "udec"); else if ((sc->entdpm = tabccol (startab, "decpm"))) strcpy (sc->keydpm, "decpm"); else if ((sc->entdpm = tabccol (startab, "pmdec"))) strcpy (sc->keydpm, "pmdec"); else if ((sc->entrpm = tabccol (startab, "ddec"))) strcpy (sc->keyrpm, "ddec"); else if ((sc->entdpm = tabccol (startab, "uy"))) strcpy (sc->keydpm, "uy"); /* Find units for RA proper motion */ sc->mprop = 0; cstr[0] = 0; if (!tabhgetc (startab,"RPMUNIT", cstr)) { if (!tabhgetc (startab,"rpmunit", cstr)) { if (!tabhgetc (startab,"pmunit", cstr)) { if (sc->entdpm > 0 && sc->entrpm > 0) strcpy (cstr,"mas/yr"); } } } if (strlen (cstr) > 0) { sc->mprop = 1; if (!strcmp (cstr, "mas/yr") || !strcmp (cstr, "mas/year")) sc->rpmunit = PM_MASYR; else if (!strcmp (cstr, "ms/yr") || !strcmp (cstr, "millisec/year")) sc->rpmunit = PM_MTSYR; else if (!strcmp (cstr, "arcsec/yr") || !strcmp (cstr, "arcsec/year")) sc->rpmunit = PM_ARCSECYR; else if (!strcmp (cstr, "arcsec/hr") || !strcmp (cstr, "arcsec/hour")) sc->rpmunit = PM_ARCSECHR; else if (!strcmp (cstr, "arcsec/cen") || !strcmp (cstr, "arcsec/century")) sc->rpmunit = PM_ARCSECCEN; else if (!strcmp (cstr, "rad/yr") || !strcmp (cstr, "rad/year")) sc->rpmunit = PM_RADYR; else if (!strcmp (cstr, "sec/yr") || !strcmp (cstr, "sec/year")) sc->rpmunit = PM_TSECYR; else if (!strcmp (cstr, "tsec/yr") || !strcmp (cstr, "tsec/year")) sc->rpmunit = PM_TSECYR; else if (!strcmp (cstr, "tsec/cen") || !strcmp (cstr, "tsec/century")) sc->rpmunit = PM_TSECCEN; else sc->rpmunit = PM_DEGYR; } else if (sc->entrpm > 0) sc->rpmunit = PM_TSECCEN; /* Find units for Dec proper motion */ cstr[0] = 0; if (!tabhgetc (startab,"DPMUNIT", cstr)) { if (!tabhgetc (startab,"dpmunit", cstr)) { if (!tabhgetc (startab,"pmunit", cstr)) tabhgetc (startab,"pmunit", cstr); } } if (strlen (cstr) > 0) { sc->mprop = 1; if (!strcmp (cstr, "mas/yr") || !strcmp (cstr, "mas/year")) sc->dpmunit = PM_MASYR; else if (!strcmp (cstr, "sec/yr") || !strcmp (cstr, "sec/year")) sc->dpmunit = PM_ARCSECYR; else if (!strcmp (cstr, "tsec/yr") || !strcmp (cstr, "tsec/year")) sc->dpmunit = PM_ARCSECYR; else if (!strcmp (cstr, "arcsec/hr") || !strcmp (cstr, "arcsec/hour")) sc->dpmunit = PM_ARCSECHR; else if (!strcmp (cstr, "arcsec/cen") || !strcmp (cstr, "arcsec/century")) sc->dpmunit = PM_ARCSECCEN; else if (!strcmp (cstr, "arcsec/yr") || !strcmp (cstr, "arcsec/year")) sc->dpmunit = PM_ARCSECYR; else if (!strcmp (cstr, "rad/yr") || !strcmp (cstr, "rad/year")) sc->dpmunit = PM_RADYR; else sc->dpmunit = PM_DEGYR; } else if (sc->entdpm > 0) sc->dpmunit = PM_ARCSECCEN; /* Find column for parallax */ sc->entpx = 0; sc->entpx = tabccol (startab, "px"); /* Find column for parallax error */ sc->entpxe = 0; sc->entpxe = tabccol (startab, "pxerr"); /* Find column for radial velocity */ sc->entrv = 0; sc->keyrv[0] = (char) 0; if ((sc->entrv = tabccol (startab, "rv"))) strcpy (sc->keyrv, "rv"); else if ((sc->entrv = tabccol (startab, "cz"))) strcpy (sc->keyrv, "cz"); if (sc->entrv > 0 && sc->nmag < 10) { strcpy (sc->keymag[sc->nmag], sc->keyrv); sc->entmag[sc->nmag] = sc->entrv; sc->nmag++; } /* Find column for epoch */ sc->entepoch = 0; sc->keyepoch[0] = (char) 0; if ((sc->entepoch = tabccol (startab, "epoch"))) strcpy (sc->keyepoch, "epoch"); else if ((sc->entepoch = tabccol (startab, "ep"))) strcpy (sc->keyepoch, "ep"); if (sc->entepoch > 0 && sc->nmag < 10) { strcpy (sc->keymag[sc->nmag], sc->keyepoch); sc->entmag[sc->nmag] = sc->entepoch; sc->nmag++; sc->nepoch = 1; } /* Find column for date (in FITS format as epoch alternate) */ sc->entdate = 0; sc->entdate = tabccol (startab, "date"); /* Find column and name of object peak or plate number */ sc->entpeak = -1; sc->keypeak[0] = (char) 0; if ((sc->entpeak = tabccol (startab, "PEAK"))) strcpy (sc->keypeak, "PEAK"); else if ((sc->entpeak = tabccol (startab, "peak"))) strcpy (sc->keypeak, "peak"); else if ((sc->entpeak = tabccol (startab, "plate"))) { strcpy (sc->keypeak, "plate"); sc->plate = 1; } else if ((sc->entpeak = tabccol (startab, "field"))) { strcpy (sc->keypeak, "field"); sc->plate = 1; } else if ((sc->entpeak = tabccol (startab, "Class"))) { strcpy (sc->keypeak, "class"); sc->plate = 1; } else if ((sc->entpeak = tabcol (startab, "c"))) { strcpy (sc->keypeak, "class"); sc->plate = 1; } else if ((entpmq = tabccol (startab, "pm")) > 0 && (entnid = tabccol (startab, "ni")) > 0) { sc->entpeak = (entpmq * 100) + entnid; } /* Find column and name of object spectral type */ sc->enttype = 0; sc->keytype[0] = (char) 0; if ((sc->enttype = tabccol (startab, "SpT"))) strcpy (sc->keytype, "spt"); else if ((sc->enttype = tabccol (startab, "TYPE"))) strcpy (sc->keytype, "type"); else if ((sc->enttype = tabccont (startab, "typ"))) { i = sc->enttype - 1; strncpy (sc->keytype, startab->colname[i], startab->lcol[i]); } if (sc->enttype > 0) sc->sptype = 1; sc->entadd = -1; sc->keyadd[0] = (char) 0; if (kwo != NULL) { sc->entadd = tabccol (startab, kwo); strcpy (sc->keyadd, kwo); } /* Set catalog coordinate system */ sc->coorsys = 0; sc->equinox = 0.0; sc->epoch = 0.0; if (tabhgetc (startab,"RADECSYS", cstr)) { sc->coorsys = wcscsys (cstr); if (!tabhgetr8 (startab,"EQUINOX", &sc->equinox)) sc->equinox = wcsceq (cstr); if (!tabhgetr8 (startab,"EPOCH",&sc->epoch)) sc->epoch = sc->equinox; } if (tabhgetc (startab,"radecsys", cstr)) { sc->coorsys = wcscsys (cstr); if (!tabhgetr8 (startab,"equinox", &sc->equinox)) sc->equinox = wcsceq (cstr); if (!tabhgetr8 (startab,"epoch",&sc->epoch)) sc->epoch = sc->equinox; } else if (tabhgetr8 (startab,"EQUINOX", &sc->equinox)) { if (!tabhgetr8 (startab,"EPOCH",&sc->epoch)) sc->epoch = sc->equinox; if (sc->equinox == 1950.0) sc->coorsys = WCS_B1950; else sc->coorsys = WCS_J2000; } else if (tabhgetr8 (startab,"equinox", &sc->equinox)) { if (!tabhgetr8 (startab,"epoch",&sc->epoch)) sc->epoch = sc->equinox; if (sc->equinox == 1950.0) sc->coorsys = WCS_B1950; else sc->coorsys = WCS_J2000; } else if (tabhgetr8 (startab,"EPOCH", &sc->epoch)) { sc->equinox = sc->epoch; if (sc->equinox == 1950.0) sc->coorsys = WCS_B1950; else sc->coorsys = WCS_J2000; } else if (tabhgetr8 (startab,"epoch", &sc->epoch)) { sc->equinox = sc->epoch; if (sc->equinox == 1950.0) sc->coorsys = WCS_B1950; else sc->coorsys = WCS_J2000; } /* Check whether catalog is sorted by right ascension */ if (tabhgetc (startab, "rasort", cstr)) sc->rasorted = 1; else sc->rasorted = 0; /* Set other stuff */ sc->nstars = startab->nlines; if (sc->entid) sc->stnum = 1; else sc->stnum = 0; /* Find out if ID is number, and if so, how many decimal places it has */ if (sc->entid) { istar = 1; if ((line = gettabline (startab, istar)) == NULL) { fprintf (stderr,"TABCATOPEN: Cannot read first star\n"); tabcatclose (sc); return (NULL); } if (setoken (&startok, line, "tab") < 2) { fprintf (stderr,"TABCATOPEN: First star has too few columns\n"); tabcatclose (sc); return (NULL); } tabgetc (&startok, sc->entid, cstr, 32); /* Find length of identifier */ if (tabhgeti4 (startab,"nfield", &nnfld)) sc->nnfld = nnfld; else sc->nnfld = strlen (cstr); /* Find number of decimal places in identifier */ if (tabhgeti4 (startab, "ndec", &nndec)) { sc->nndec = nndec; if (!isnum (cstr)) sc->stnum = -nndec; } else if (isnum (cstr)) { dnum = tabgetr8 (&startok,sc->entid); sprintf (cstr,"%.0f", (dnum * 100000000.0) + 0.1); lnum = strlen (cstr); for (i = 0; i < 8; i++) { if (cstr[lnum-i-1] != '0') { ndec = 8 - i; if (ndec > nndec) { nndec = ndec; sc->nndec = nndec; } break; } } sc->nndec = nndec; } else { sc->stnum = -strlen (cstr); sc->nndec = nndec; } } sc->refcat = TABCAT; return (sc); } /* TABCATCLOSE -- Close tab table catalog and free associated data structures */ void tabcatclose (sc) struct StarCat *sc; { tabclose (sc->startab); free (sc); return; } /* TABSTAR -- Get tab table catalog entry for one star; return 0 if successful, else -1 */ int tabstar (istar, sc, st, verbose) int istar; /* Star sequence number in tab table catalog */ struct StarCat *sc; /* Star catalog data structure */ struct Star *st; /* Star data structure, updated on return */ int verbose; /* 1 to print error messages */ { struct TabTable *startab = sc->startab; char *line; char *uscore; char cnum[64]; char temp[64]; double ydate; char *cn; int ndec, i, imag, ltok; int lnum, ireg, inum; int pmq, nid; int lcn; char str[24]; if ((line = gettabline (startab, istar)) == NULL) { if (verbose) fprintf (stderr,"TABSTAR: Cannot read star %d\n", istar); return (-1); } /* Parse line for rapid field extraction */ if (setoken (&startok, line, "tab") < 2) { fprintf (stderr,"TABSTAR: Star %d entry too short\n", istar); return (-1); } /* Extract ID */ st->objname[0] = (char) 0; if (sc->entid) { tabgetc (&startok, sc->entid, cnum, 64); if (!strcmp (sc->isfil,"usnoa-server")) { if ((uscore = strchr (cnum, '_')) != NULL) *uscore = '.'; cn = cnum + 1; } else if (!strcmp (sc->isfil,"gsc-server")) cn = cnum + 3; else cn = cnum; lcn = strlen (cn); /* if (lcn < 16 && (isnum (cn) || isnum (cn+1))) { */ if (lcn < 16 && isnum (cn)) { if (isnum(cnum)) { lcn = strlen (cn); if (lcn > 15) st->num = atof (cn + lcn - 15); else st->num = atof (cn); } else { if (cnum[0] == 'S') st->num = -atof (cn+1); else st->num = atof (cn+1); } if (!strcmp (sc->isfil,"gsc-server")) { ireg = atoi (cn) / 100000; inum = atoi (cn) % 100000; st->num = (double) ireg + 0.0001 * (double) inum; } /* Find field length of identifier */ sc->nnfld = strlen (cn); /* Find number of decimal places in identifier */ if (strchr (cn,'.') == NULL) { nndec = 0; sc->nndec = nndec; } else { sprintf (cn,"%.0f", (st->num * 100000000.0) + 0.1); lnum = strlen (cnum); for (i = 0; i < 8; i++) { if (cn[lnum-i-1] != '0') { ndec = 8 - i; if (ndec > nndec) { nndec = ndec; sc->nndec = nndec; } break; } } } } else { strcpy (st->objname, cnum); st->num = st->num + 1.0; } } else { st->num = (double) istar; nndec = 0; sc->nndec = nndec; } /* Right ascension */ st->ra = tabgetra (&startok, sc->entra); /* Declination */ st->dec = tabgetdec (&startok, sc->entdec); /* Magnitudes */ for (imag = 0; imag < sc->nmag; imag++) { if (sc->entmag[imag]) { if (tabgetc (&startok, sc->entmag[imag], str, 24)) return (0); ltok = strlen (str); if (str[ltok-1] == 'L') { str[ltok-1] = (char) 0; if (isnum (str)) st->xmag[imag] = 100.0 + atof (str); else st->xmag[imag] = 0.0; } else st->xmag[imag] = tabgetr8 (&startok, sc->entmag[imag]); } else st->xmag[imag] = 0.0; } /* Convert right ascension proper motion to degrees/year */ st->rapm = tabgetr8 (&startok, sc->entrpm); if (sc->rpmunit == PM_MASYR) st->rapm = (st->rapm / 3600000.0) / cosdeg(st->dec); else if (sc->rpmunit == PM_MTSYR) st->rapm = st->rapm / 240000.0; else if (sc->rpmunit == PM_ARCSECYR) st->rapm = (st->rapm / 3600.0) / cosdeg (st->dec); else if (sc->rpmunit == PM_ARCSECCEN) st->rapm = (st->rapm / 360000.0) / cosdeg (st->dec); else if (sc->rpmunit == PM_TSECYR) st->rapm = st->rapm / 240.0; else if (sc->rpmunit == PM_TSECCEN) st->rapm = st->rapm / 24000.0; else if (sc->rpmunit == PM_RADYR) st->rapm = raddeg (st->rapm); else st->rapm = 0.0; /* Convert declination proper motion to degrees/year */ st->decpm = tabgetr8 (&startok, sc->entdpm); if (sc->dpmunit == PM_MASYR) st->decpm = st->decpm / 3600000.0; else if (sc->dpmunit == PM_ARCSECYR) st->decpm = st->decpm / 3600.0; else if (sc->dpmunit == PM_ARCSECCEN) st->decpm = st->decpm / 360000.0; else if (sc->dpmunit == PM_RADYR) st->decpm = raddeg (st->decpm); else st->decpm = 0.0; /* Parallax */ if (sc->entpx) st->parallax = tabgetr8 (&startok, sc->entpx); else st->parallax = 0.0; /* Radial velocity */ if (sc->entrv) st->radvel = tabgetr8 (&startok, sc->entrv); else st->radvel = 0.0; /* Epoch */ if (sc->entepoch) { tabgetc (&startok, sc->entepoch, temp, 10); if (temp[0] == '_') { if (sc->entdate > 0) { tabgetc (&startok, sc->entdate, temp, 10); st->epoch = fd2ep (temp); } else st->epoch = sc->epoch; } else if (strchr (temp, '-') != NULL) st->epoch = fd2ep (temp); else { ydate = tabgetr8 (&startok, sc->entepoch); if (ydate < 3000.0 && ydate > 0.0) st->epoch = dt2ep (ydate, 12.0); else if (ydate < 100000.0) st->epoch = mjd2ep (ydate); else st->epoch = jd2ep (ydate); if (st->epoch > 2005.000) printf ("TABSTAR: %s = %.5f -> %.5f\n", temp, ydate, st->epoch); } st->xmag[sc->nmag-1] = st->epoch; } else st->epoch = sc->epoch; /* Peak counts */ if (sc->entpeak > 100) { pmq = tabgeti4 (&startok, sc->entpeak/100); nid = tabgeti4 (&startok, sc->entpeak%100); st->peak = (pmq * 100) + nid; } else if (sc->entpeak > 0) st->peak = tabgeti4 (&startok, sc->entpeak); else st->peak = 0; /* Spectral type */ if (sc->enttype > 0) { strcpy (st->isp, "__"); tabgetc (&startok, sc->enttype, st->isp, 24); } /* Extract selected field */ if (kwo != NULL) (void) tabgetk (startab, &startok, kwo, st->objname, 79); st->coorsys = sc->coorsys; st->equinox = sc->equinox; return (0); } /* TABOPEN -- Open tab table file, returning number of entries */ struct TabTable * tabopen (tabfile, nbbuff) char *tabfile; /* Tab table catalog file name */ int nbbuff; /* Number of bytes in buffer; 0=read whole file */ { FILE *fcat; int nr, lfile, lname, lline; char *tabnew, *tabline, *lastline; char *tabcomma, *nextline; char *thisname, *tabname; char tabcstr[4]; int thistab, itab, nchar, nbtab; int formfeed = (char) 12; struct TabTable *tabtable; tabcomma = NULL; if (taberr != NULL) { free (taberr); taberr = NULL; } tabname = NULL; if (!strcmp (tabfile, "stdin")) { lfile = 100000; fcat = stdin; } else { /* Separate table name from file name, if necessary */ if ((tabcomma = strchr (tabfile, ',')) != NULL) { tabname = (char *) calloc (1,64); strcpy (tabname, tabcomma+1); *tabcomma = (char) 0; } /* Find length of tab table catalog */ lfile = tabsize (tabfile); if (nbbuff > 1 && nbbuff < lfile) lfile = nbbuff; else if (nbbuff == 1 && lfile > 10000) lfile = 10000; if (lfile < 1) { taberr = (char *) calloc (64 + strlen (tabfile), 1); sprintf (taberr,"TABOPEN: Tab table file %s has no entries", tabfile); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } /* Open tab table catalog */ if (!(fcat = fopen (tabfile, "r"))) { taberr = (char *) calloc (64 + strlen (tabfile), 1); sprintf (taberr,"TABOPEN: Tab table file %s cannot be read", tabfile); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } else if (verbose) { fprintf (stderr,"TABOPEN: tab table %s opened", tabfile); } } /* Allocate tab table structure */ nbtab = sizeof(struct TabTable); if ((tabtable=(struct TabTable *) calloc(1,nbtab)) == NULL){ taberr = (char *) calloc (64 + strlen (tabfile), 1); sprintf (taberr,"TABOPEN: cannot allocate %d bytes for tab table structure for %s", nbtab, tabfile); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } else if (verbose) { fprintf (stderr,"TABOPEN: allocated %d bytes for tab table structure for %s", nbtab, tabfile); } tabtable->tabname = tabname; /* Allocate space in structure for filename and save it */ lname = strlen (tabfile) + 2; if ((tabtable->filename = (char *)calloc (1, lname)) == NULL) { taberr = (char *) calloc (64 + strlen (tabfile), 1); sprintf (taberr,"TABOPEN: cannot allocate filename %s in structure", tabfile); (void) fclose (fcat); tabclose (tabtable); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } strcpy (tabtable->filename, tabfile); /* Allocate buffer to hold entire catalog (or buffer length) and read it */ if ((tabtable->tabbuff = (char *) calloc (1, lfile+2)) == NULL) { taberr = (char *) calloc (64 + strlen (tabfile), 1); sprintf (taberr,"TABOPEN: cannot allocate buffer for tab table %s", tabfile); (void) fclose (fcat); tabclose (tabtable); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } else { if (verbose) { fprintf (stderr,"TABOPEN: allocated %d bytes for tab table for %s", lfile+2, tabfile); } nr = fread (tabtable->tabbuff, 1, lfile, fcat); if (fcat != stdin && nr < lfile) { fprintf (stderr,"TABOPEN: read only %d / %d bytes of file %s\n", nr, lfile, tabfile); (void) fclose (fcat); tabclose (tabtable); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } else if (verbose) { fprintf (stderr,"TABOPEN: read %d byte tab table from %s", lfile, tabfile); } tabtable->tabbuff[lfile] = (char) 0; /* Check for named table within a file */ if (tabname != NULL) { if (isnum (tabname)) { itab = atoi (tabname); thisname = tabtable->tabbuff; thistab = 1; if (itab > 1) { while (thistab < itab && thisname != NULL) { thisname = strchr (thisname, formfeed); if (thisname != NULL) thisname++; thistab++; } } if (thisname == NULL) { fprintf (stderr, "GETTAB: There are < %d tables in %s\n", itab, tabfile); return (NULL); } while (*thisname==' ' || *thisname==newline || *thisname==formfeed || *thisname==(char)13) thisname++; tabline = strchr (thisname, newline); if (tabline != NULL) { nchar = tabline - thisname; if (strchr (thisname, tab) > tabline) strncpy (tabtable->tabname, thisname, nchar); } } else { lname = strlen (tabname); thisname = tabtable->tabbuff; while (*thisname != (char) 0) { while (*thisname==' ' || *thisname==newline || *thisname==formfeed || *thisname==(char)13) thisname++; if (!strncmp (tabname, thisname, lname)) break; else thisname = strchr (thisname, formfeed); } } if (thisname == NULL) { fprintf (stderr, "TABOPEN: table %s in file %s not found\n", tabname, tabfile); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } else tabtable->tabheader = strchr (thisname, newline) + 1; } else tabtable->tabheader = tabtable->tabbuff; tabline = tabtable->tabheader; lastline = NULL; while (*tabline!='-' && tabline!=NULL && tabline < tabtable->tabbuff+lfile) { lastline = tabline; if ((tabline = strchr (lastline,newline)) != NULL) tabline++; else break; } if (tabline == NULL || *tabline != '-') { taberr = (char *) calloc (64 + strlen (tabfile), 1); sprintf (taberr,"TABOPEN: No - line in tab table %s",tabfile); (void) fclose (fcat); tabclose (tabtable); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } tabcstr[0] = tabline[1]; tabcstr[1] = (char) 0; if ( tabline[1] != '-' && tabline[1] != (char)9 ) { sprintf (taberr,"TABOPEN: No - line in tab table %s",tabfile); return (NULL); } tabtable->tabhead = lastline; tabtable->tabdash = tabline; tabtable->tabdata = strchr (tabline, newline) + 1; /* Extract positions of keywords we will want to use */ if (!tabparse (tabtable)) { fprintf (stderr,"TABOPEN: No columns in tab table %s\n",tabfile); (void) fclose (fcat); tabclose (tabtable); if (tabcomma != NULL) *tabcomma = ','; return (NULL); } else if (verbose) { fprintf (stderr,"TABOPEN: tab table %s header parsed", tabfile); } /* Enumerate entries in tab table catalog by counting newlines */ if (nbbuff > 0) tabtable->nlines = 10000000; else { tabnew = tabtable->tabdata; tabtable->nlines = 0; while ((tabnew = strchr (tabnew, newline)) != NULL) { tabnew = tabnew + 1; tabtable->nlines = tabtable->nlines + 1; if (*tabnew == formfeed) break; } } if (verbose) { fprintf (stderr,"TABOPEN: %d lines in tab table %s", tabtable->nlines, tabfile); } } /* Set up line buffer, and put first line in it */ if (nbbuff > 0) { tabtable->lhead = tabtable->tabdata - tabtable->tabheader; tabtable->tcat = fcat; nextline = strchr (tabtable->tabdata, newline) + 1; tabtable->lline = (nextline - tabtable->tabdata) * 2; tabtable->tabline = (char *) calloc (tabtable->lline, 1); fseek (tabtable->tcat, (long) tabtable->lhead, SEEK_SET); (void) fgets (tabtable->tabline, tabtable->lline, tabtable->tcat); lline = strlen (tabtable->tabline); if (tabtable->tabline[lline-1] < 32) tabtable->tabline[lline-1] = (char) 0; tabtable->tabdata = tabtable->tabline; } /* Close catalog file if not reading one line at a time */ else { tabtable->lhead = 0; (void) fclose (fcat); tabtable->tcat = NULL; } tabtable->tabline = tabtable->tabdata; tabtable->iline = 1; if (tabcomma != NULL) *tabcomma = ','; return (tabtable); } void tabclose (tabtable) struct TabTable *tabtable; { if (tabtable != NULL) { if (tabtable->filename != NULL) free (tabtable->filename); if (tabtable->tabname != NULL) free (tabtable->tabname); if (tabtable->tabbuff != NULL) free (tabtable->tabbuff); if (tabtable->colname != NULL) free (tabtable->colname); if (tabtable->lcol != NULL) free (tabtable->lcol); if (tabtable->lcfld != NULL) free (tabtable->lcfld); if (tabtable->tcat != NULL) fclose (tabtable->tcat); free (tabtable); } return; } /* TABLINE -- Get tab table entry for one line; return NULL if unsuccessful */ char * gettabline (tabtable, iline) struct TabTable *tabtable; /* Tab table structure */ int iline; /* Line sequence number in tab table */ { char *nextline = tabtable->tabline; char *next; int lline, i; /* Return NULL if tab table has not been opened */ if (tabtable == NULL) return (NULL); /* Read one line at a time if file is still open */ if (tabtable->tcat != NULL) { /* Return current line from buffer */ if (iline == tabtable->iline) return (tabtable->tabline); /* Read next line from file */ if (iline < 1 || iline > tabtable->iline) { for (i = tabtable->iline; i < iline; i++) { next = fgets (tabtable->tabline, tabtable->lline, tabtable->tcat); if (next == NULL || *next == EOF) return (NULL); tabtable->iline++; } lline = strlen (tabtable->tabline); if (lline < 2) return (NULL); if (tabtable->tabline[lline-1] < 32) tabtable->tabline[lline-1] = (char) 0; } else if (iline < tabtable->iline) { fseek (tabtable->tcat, (long) tabtable->lhead, SEEK_SET); tabtable->iline = 0; for (i = tabtable->iline; i < iline; i++) { (void) fgets (tabtable->tabline, tabtable->lline, tabtable->tcat); tabtable->iline++; } lline = strlen (tabtable->tabline); if (tabtable->tabline[lline-1] < 32) tabtable->tabline[lline-1] = (char) 0; } return (tabtable->tabline); } /* Return NULL if trying to read past last line */ if (iline > tabtable->nlines) { fprintf (stderr, "TABLINE: line %d is not in table\n",iline); return (NULL); } /* If iline is 0 or less, just read next line from table */ else if (iline < 1 && nextline) { tabtable->iline++; if (tabtable->iline > tabtable->nlines) { fprintf (stderr, "TABLINE: line %d is not in table\n",iline); return (NULL); } nextline = strchr (nextline, newline) + 1; } /* If iline is before current line, read from start of file */ else if (iline < tabtable->iline) { tabtable->iline = 1; tabtable->tabline = tabtable->tabdata; while (tabtable->iline < iline) { tabtable->tabline = strchr (tabtable->tabline, newline) + 1; tabtable->iline ++; } } /* If iline is after current line, read forward */ else if (iline > tabtable->iline) { while (tabtable->iline < iline) { tabtable->tabline = strchr (tabtable->tabline, newline) + 1; tabtable->iline ++; } } return (tabtable->tabline); } /* TABGETRA -- returns double right ascension in degrees */ double tabgetra (tabtok, ientry) struct Tokens *tabtok; /* Line token structure */ int ientry; /* sequence of entry on line */ { char str[24]; strcpy (str, "0.0"); if (tabgetc (tabtok, ientry, str, 24)) return (0.0); else return (str2ra (str)); } /* TABGETDEC -- returns double declination in degrees */ double tabgetdec (tabtok, ientry) struct Tokens *tabtok; /* Line token structure */ int ientry; /* sequence of entry on line */ { char str[24]; strcpy (str, "0.0"); if (tabgetc (tabtok, ientry, str, 24)) return (0.0); else return (str2dec (str)); } /* TABGETR8 -- returns 8-byte floating point number from tab table line */ double tabgetr8 (tabtok, ientry) struct Tokens *tabtok; /* Line token structure */ int ientry; /* sequence of entry on line */ { char str[24]; strcpy (str, "0.0"); if (tabgetc (tabtok, ientry, str, 24)) return (0.0); else if (isnum (str)) return (atof (str)); else return (0.0); } /* TABGETI4 -- returns a 4-byte integer from tab table line */ int tabgeti4 (tabtok, ientry) struct Tokens *tabtok; /* Line token structure */ int ientry; /* sequence of entry on line */ { char str[24]; strcpy (str, "0"); if (tabgetc (tabtok, ientry, str, 24)) return (0); else if (isnum (str)) return ((int) atof (str)); else return (0); } /* TABGETK -- returns a character entry from tab table line for named column */ int tabgetk (tabtable, tabtok, keyword, string, maxchar) struct TabTable *tabtable; /* Tab table structure */ struct Tokens *tabtok; /* Line token structure */ char *keyword; /* column header of desired value */ char *string; /* character string (returned) */ int maxchar; /* Maximum number of characters in returned string */ { int ientry = tabccol (tabtable, keyword); return (tabgetc (tabtok, ientry, string, maxchar)); } /* TABGETC -- returns n'th entry from tab table line as character string */ int tabgetc (tabtok, ientry, string, maxchar) struct Tokens *tabtok; /* Line token structure */ int ientry; /* Sequence of entry on line (1-ncol) */ char *string; /* Character string (returned) */ int maxchar; /* Maximum number of characters in returned string */ { if (ientry > tabtok->ntok) return (0); else if (getoken (tabtok, ientry, string, maxchar)) return (0); else return (-1); } /* TABHGETR8 -- read an 8-byte floating point number from a tab table header */ static int tabhgetr8 (tabtable, keyword, result) struct TabTable *tabtable; /* Tab table structure */ char *keyword; /* sequence of entry on line */ double *result; { char value[24]; if (tabhgetc (tabtable, keyword, value)) { *result = atof (value); return (1); } else return (0); } /* TABHGETI4 -- read a 4-byte integer from a tab table header */ static int tabhgeti4 (tabtable, keyword, result) struct TabTable *tabtable; /* Tab table structure */ char *keyword; /* sequence of entry on line */ int *result; { char value[24]; if (tabhgetc (tabtable, keyword, value)) { *result = (int) atof (value); return (1); } else return (0); } /* TABHGETC -- read a string from a tab table header */ static int tabhgetc (tabtable, keyword, result) struct TabTable *tabtable; /* Tab table structure */ char *keyword; /* sequence of entry on line */ char *result; { char *str0, *str1, *line, *head, keylow[24], keyup[24]; int ncstr, lkey, i; head = tabtable->tabbuff; str0 = 0; /* Make all-upper-case and all-lower-case versions of keyword */ lkey = strlen (keyword); if (lkey > 24) lkey = 24; for (i = 0; i < lkey; i++) { if (keyword[i] > 96 && keyword[i] < 123) keyup[i] = keyword[i] - 32; else keyup[i] = keyword[i]; if (keyword[i] > 64 && keyword[i] < 91) keylow[i] = keyword[i] + 32; else keylow[i] = keyword[i]; } keyup[lkey] = (char) 0; keylow[lkey] = (char) 0; /* Find keyword or all-upper-case or all-lower-case version in header */ while (head < tabtable->tabhead) { line = strsrch (head, keyword); if (line == NULL) line = strsrch (head, keylow); if (line == NULL) line = strsrch (head, keyup); if (line == NULL) break; if (line == tabtable->tabbuff || line[-1] == newline) { str0 = strchr (line, tab) + 1; str1 = strchr (str0, newline); break; } else head = line + 1; } /* Return value as a character string and 1 if found */ if (str0) { ncstr = str1 - str0; strncpy (result, str0, ncstr); result[ncstr] = (char)0; return (1); } else return (0); } /* TABPARSE -- Make a table of column headings */ int tabparse (tabtable) struct TabTable *tabtable; /* Tab table structure */ { char *colhead; /* Column heading first character */ char *endcol; /* Column heading last character */ char *headlast; char *hyphens; char *hyphlast; char *nextab; int icol; int nbytes, nba; /* Return if no column names in header */ if (tabtable->tabhead == NULL) return (0); headlast = strchr (tabtable->tabhead, newline); if (headlast == tabtable->tabhead) return (0); /* Count columns in table header */ tabtable->ncols = 1; for (colhead = tabtable->tabhead; colhead < headlast; colhead++) { if (*colhead == tab) tabtable->ncols++; } /* Tabulate column names */ nbytes = tabtable->ncols * sizeof (char *); nba = nbytes / 64; if (nbytes > nba * 64) nba = (nba + 1) * 64; else nba = nba * 64; tabtable->colname = (char **)calloc (tabtable->ncols, sizeof (char *)); tabtable->lcol = (int *) calloc (tabtable->ncols, sizeof (int)); colhead = tabtable->tabhead; for (icol = 0; icol < tabtable->ncols; icol++) { nextab = strchr (colhead, tab); if (nextab < headlast) endcol = nextab - 1; else endcol = headlast - 1; while (*endcol == ' ') endcol = endcol - 1; tabtable->lcol[icol] = (int) (endcol - colhead) + 1; tabtable->colname[icol] = colhead; colhead = nextab + 1; if (colhead > headlast) break; } /* Tabulate field widths */ hyphens = headlast + 1; hyphlast = strchr (hyphens, newline); if (hyphlast == hyphens) return (0); tabtable->lcfld = (int *) calloc (tabtable->ncols, sizeof (int)); colhead = hyphens; for (icol = 0; icol < tabtable->ncols; icol++) { if ((nextab = strchr (colhead, tab)) == NULL) endcol = hyphlast - 1; else endcol = nextab - 1; tabtable->lcfld[icol] = (int) (endcol - colhead) + 1; if (nextab != NULL) colhead = nextab + 1; else break; } return (tabtable->ncols); } /* Search table of column headings for a particlar entry (case-dependent) */ int tabcol (tabtable, keyword) struct TabTable *tabtable; /* Tab table structure */ char *keyword; /* Column heading to find */ { int i, lkey, lcol; lkey = strlen (keyword); for (i = 0; i < tabtable->ncols; i++) { lcol = tabtable->lcol[i]; if (lcol == lkey && !strncmp (keyword, tabtable->colname[i], lcol)) { return (i + 1); } } return (0); } /* Search table of column headings for a particlar entry (case-independent) */ int tabccol (tabtable, keyword) struct TabTable *tabtable; /* Tab table structure */ char *keyword; /* Column heading to find */ { int i, lkey, lcol; lkey = strlen (keyword); for (i = 0; i < tabtable->ncols; i++) { lcol = tabtable->lcol[i]; if (lcol == lkey && !strncasecmp (keyword, tabtable->colname[i], lcol)) { return (i + 1); } } return (0); } /* Search table of column headings for first with string (case-dependent) */ static int tabcont (tabtable, keyword) struct TabTable *tabtable; /* Tab table structure */ char *keyword; /* Part of column heading to find */ { int i; for (i = 0; i < tabtable->ncols; i++) { if (strnsrch (tabtable->colname[i], keyword, tabtable->lcol[i])) { return (i + 1); } } return (0); } /* Search table of column headings for first with string (case-independent) */ static int tabccont (tabtable, keyword) struct TabTable *tabtable; /* Tab table structure */ char *keyword; /* Part of column heading to find */ { int i; for (i = 0; i < tabtable->ncols; i++) { if (strncsrch (tabtable->colname[i], keyword, tabtable->lcol[i])) { return (i + 1); } } return (0); } /* TABSIZE -- return size of file in bytes */ static int tabsize (filename) char *filename; /* Name of file for which to find size */ { FILE *diskfile; long filesize; /* Open file */ if ((diskfile = fopen (filename, "r")) == NULL) return (-1); /* Move to end of the file */ if (fseek (diskfile, 0, 2) == 0) /* Position is the size of the file */ filesize = ftell (diskfile); else filesize = -1; fclose (diskfile); return (filesize); } /* ISTAB -- Return 1 if tab table file, else 0 */ int istab (filename) char *filename; /* Name of file to check */ { FILE *diskfile; char *line; int ncmax=63; /* First check file extension */ if (strsrch (filename, ".tab")) return (1); /* If no .tab file extension, look for tab on first line */ else { /* Open file */ if ((diskfile = fopen (filename, "r")) == NULL) return (0); /* Allocate buffer for first line of file */ line = (char *)calloc (1, 63); /* Return 0 if no characters in first line */ if (!next_line (diskfile, ncmax, line)) { fclose (diskfile); free (line); return (0); } /* Return 0 if there is a tab in the first line */ if (strchr (line, (char)9)) { fclose (diskfile); free (line); return (1); } /* Otherwise, return 0 */ else { fclose (diskfile); free (line); return (0); } } } /* Jul 18 1996 New subroutines * Aug 6 1996 Remove unused variables after lint * Aug 8 1996 Fix bugs in entry reading and logging * Oct 15 1996 Add comparison when testing an assignment * Nov 5 1996 Drop unnecessary static declarations * Nov 13 1996 Return no more than maximum star number * Nov 13 1996 Write all error messages to stderr with subroutine names * Nov 15 1996 Implement search radius; change input arguments * Nov 19 1996 Allow lower case column headings * Dec 18 1996 Add UJCRNUM to read specified catalog entries * Dec 18 1996 Keep closest stars, not brightest, if searching within radius * * Mar 20 1997 Clean up code in TABRNUM * May 7 1997 Set entry number to zero if column not found * May 29 1997 Add TABPARSE and TABCOL to more easily extract specific columns * May 29 1997 Add TABCLOSE to free memory from outside this file * Jun 4 1997 Set ID to sequence number in table if no ID/id entry present * * Jun 2 1998 Fix bug parsing last column of header * Jun 24 1998 Add string lengths to ra2str() and dec2str() calls * Sep 16 1998 Use limiting radius correctly * Sep 22 1998 Convert to output coordinate system * Oct 15 1998 Add tabsize() and istab() * Oct 21 1998 Add tabrkey() to read values of keyword for list of stars * Oct 29 1998 Correctly assign numbers when too many stars are found * Oct 30 1998 Fix istab() to check only first line of file * Dec 8 1998 Do not declare tabsize() static * Jan 20 1999 Add tabcatopen() and keep table info in structure, not global * Jan 25 1999 Add lcfld to structure to keep track of field widths * Jan 29 1999 Add current line number and pointer to table structure * Feb 2 1999 Allow for equinox other than 2000.0 in tab table header * Feb 2 1999 Add tabhgetc() to read char string values from tab table header * Feb 17 1999 Increase maximum line in istab() from 80 to 1024 * Mar 2 1999 Fix bugs calling tabhgetx() * Mar 2 1999 Rewrite tabhgetx() to use tabhgetc() for all header reading * May 28 1999 Add tabcatopen() and tabstar() and use them * Jun 3 1999 Fix bug so header parameters are read correctly * Jun 16 1999 Use SearchLim() * Aug 16 1999 Fix bug to fix failure to search across 0:00 RA * Aug 25 1999 Return real number of stars from tabread() * Sep 10 1999 Fix bug setting equinox and coordinate system in tabcatopen() * Sep 10 1999 Set additional keyword selection with subroutine * Sep 13 1999 Fix comment for tabstar() * Sep 16 1999 Fix bug which didn't always return closest stars * Sep 16 1999 Add distsort argument so brightest stars in circle works, too * Oct 21 1999 Clean up code after lint * Oct 25 1999 Fix subroutine declaration inconsistency * Oct 25 1999 Replace malloc() calls with calloc() * Oct 29 1999 Add tabxyread() for image catalogs * Nov 23 1999 Improve error checking on Starbase tables; istab() opens file * Nov 30 1999 Fix bugs found when compiling under SunOS 4.1.3 * * Jan 4 2000 Always close file and print error message on tabopen() failures * Jan 6 2000 If "id" not found, try heading with "_id" to catch scat output * Jan 10 2000 Add second magnitude; save column headers in catalog structure * Feb 10 2000 Implement proper motion in source catalogs * Feb 10 2000 Accept first mag-containing column as first magnitude * Feb 10 2000 Clean up id reading: no. decimals, non-numeric id * Feb 14 2000 Save table opening errors in string * Feb 16 2000 Lengthen short calloc() lengths * Feb 16 2000 Pad tabbuff with 2 nulls so end can be found * Mar 10 2000 Return proper motions from tabread() and tabrnum() * Mar 13 2000 Do not free tabtable structure if it is null * Mar 27 2000 Clean up code after lint * May 26 2000 Add ability to read named tables in a multi-table file * Jun 26 2000 Add coordinate system to SearchLim() arguments * Jul 5 2000 Check for additional column heading variations * Jul 10 2000 Deal with number of decimal places and name/number in tabcatopen() * Jul 12 2000 Add star catalog data structure to tabread() argument list * Jul 13 2000 Use nndec header parameter to optionally set decimal places * Jul 25 2000 Pass star catalog address of data structure address * Aug 3 2000 Skip first character of ID if rest is number * Aug 3 2000 If no decimal point in numeric ID, set ndec to zero * Sep 27 2000 Use first column with name if no id column is found * Oct 26 2000 Add proper motion in seconds and arcseconds per century * Oct 31 2000 Add proper motion in milliseconds of time per year * Nov 22 2000 Add tabtable argument to tabcatopen() for URL search returns * Nov 28 2000 Add starcat as argument to tabrnum() as well as tabread() * Nov 29 2000 Do not set tmagb if it is null; set type if present * Nov 30 2000 Add spectral type as possible column * Dec 1 2000 Add field as synonym for plate * Dec 18 2000 Clean up after lint * Dec 29 2000 Clean up after lint * * May 29 2001 Save length of identifier in catalog structure * May 30 2001 Rewrite to deal with up to 3 magnitudes * Jun 11 2001 Add one-line-at-a-time catalog reading from tabcatopen() * Jun 14 2001 In tabopen(), use actual file size if less than buffer size * Jun 14 2001 In tabcol() make sure lengths are equal, too * Jun 18 2001 Fix bug finding of length of token string extracted * Jun 19 2001 Use setoken() to parse each catalog line * Jun 20 2001 Add fourth magnitude for GSC II * Jun 25 2001 Check fgets() return in gettabline() * Jun 25 2001 Print star read errors only in verbose mode * Jun 28 2001 If no proper motion unit is set, set proper motion to 0.0 * Jun 28 2001 If first magnitude is 99.90, sort by second magnitude * Jun 28 2001 Up default line limit from 1 million to 10 million * Jul 2 2001 Fix order of 3rd and 4th magnitudes * Jul 20 2001 Return magnitude as well as flux from tabxyread() * Aug 8 2001 Return radial velocity as additional magnitude * Aug 17 2001 Fix bug reading radial velocity * Aug 21 2001 Check numbers using isnum() in tabgetr8() and tabgeti4() * Aug 21 2001 Add starcat to tabrkey() argument list * Aug 21 2001 Read object name into tkey if it is present * Sep 11 2001 Allow an arbitrary number of magnitudes * Sep 11 2001 Add sort magnitude argument to tabread() * Sep 19 2001 Drop fitshead.h; it is in wcs.h * Sep 20 2001 Clean up pointers for Alpha and Linux; drop tabgetpm() * Sep 20 2001 Change _ to . in ESO server USNO-A2.0 numbers * Sep 21 2001 Rearrange ESO server GSC numbers * Oct 12 2001 Check for additional column names for magnitude * Oct 15 2001 Read first star only once, compute relative flux in tabxyread() (bug fix) * Oct 16 2001 Add pointer to line of dashes to table structure * Dec 3 2001 Initialize keyword search variables in tabhgetc() * * May 6 2002 Allow object names to be up to 79 characters long * Aug 5 2002 Deal correctly with magnitude-less catalogs * Aug 5 2002 Add magu, magb, magv for UBV magnitudes * Aug 6 2002 Pass through magnitude keywords * Aug 6 2002 Return initial string if token not found by tabgetc() * Oct 30 2002 Add code to pass epoch as a final magnitude (but not RV, yet) * * Jan 26 2003 Add code to pass USNO-B1.0 pm quality and no. of ids * Jan 28 2003 Improve spatial position test * Feb 4 2003 Compare character to 0, not NULL * Mar 11 2003 Fix limit setting * Apr 3 2003 Drop unused variables after lint * May 28 2003 Read long and lat if radecsys is "galactic" or "ecliptic" * Jun 2 003 Divide by cos(dec) for arcsec and mas RA proper motions * Aug 22 2003 Add radi argument for inner edge of search annulus * Sep 25 2003 Add tabbin() to fill an image with sources * Oct 6 2003 Update tabread() and tabbin() for improved RefLim() * Nov 18 2003 Initialize image size and bits/pixel from header in tabbin() * Nov 22 2003 Add GSC II object class (c) as possible content for tpeak * Dec 4 2003 Add default of arcsec/century as proper motion unit * Dec 10 2003 If magnitude ends in L and is a number, add 100.0 * Dec 12 2003 Fix bug in wcs2pix() call in tabbin() * * Jan 5 2004 If more than 15 digits in numberic ID, drop excess off front * Mar 16 2004 Be more clever about reading by number * Mar 19 2004 Make verbose flag global * Nov 17 2004 Accept SpT and spt before type for spectral type * * May 12 2005 Add "num" as a possible substring to identify an ID column * Jul 26 2005 Fix bug to set magnitudes and keywords correctly in tabrnum() * Aug 3 2005 If nlog < 0 in tabrnum(), print objects as found * Aug 10 2005 Add "exp" as possible "magnitude" column heading * Aug 11 2005 Do not re-read lines if missing object numbers in tabrnum() * Aug 17 2005 If nmax is -1, print magnitude keywords from file * Sep 29 2005 Read first 10000 characters for istab() to capture long heads * Sep 29 2005 Add rasort header flag if catalog is sorted by RA * * Jun 15 2006 Read ID field length from header, if present * Jun 20 2006 Drop unused variables; initialize uninitialized variables * Jun 30 2006 Add match argument to tabrnum() to add sequential read option * * Jan 11 2007 Switch order of wcscat.h and fitsfile.h includes * Mar 13 2007 Return object name if first character of ID is non-numeric * Mar 13 2007 Check for "Class" for GSC2 object class * Jul 9 2007 Reject mflag as a magnitude * Jul 9 2007 Sort by designated magnitude only unless sort mag is 0 * Jul 18 2007 Add tabccol() and tabccont() case-insensitive header searches * Jul 19 2007 Add proper motion in arsec/hour for solar system objects * Jul 23 2007 Add ...obj... as possible identifier * Jul 23 2007 Add ...dist... as possible "magnitude" * * Aug 17 2009 Fix columns for declination column name * Sep 25 2009 Fix memory leaks found by Jessicalas Burke * Sep 30 2009 Fix bugs freeing object names for first pass and farthest star * * Sep 22 2010 Fix bug when checking file which is not tab table * * Jun 20 2014 Not a tab table if no tab in first line * Aug 28 2014 Fix istab() and tabread() * Aug 29 2014 Exclude "code" from magnitude keywords */ wcstools-3.9.5/libwcs/COPYING0000644000016200001660000005775207466274233015024 0ustar minkoirsys GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS wcstools-3.9.5/libwcs/tabsort.c0000664000016200001660000000440711750060474015571 0ustar minkoirsys/* void TabSort() Sort table based on possible sexigesimal entry * int SortTab() Return lowest of two entries */ /* Sort catalog by increasing angle, returning sorted buffer */ /* Structure for sorting lines */ typedef struct { double ang; /* Selected angle */ char *entry; /* Entire entry */ } TabInfo; char * SortTab (buffer, isort); char *buffer; /* White-space separated table */ int isort; /* Column by which to sort */ { TabInfo *table; char line[500]; char token[32]; char *bufline; char *buffout; char newline = 10; char czero; char *cwhite; int TabSort (); int nlines = 0; int i; int ntok; struct Tokens tokens; /* Token structure */ if (buffer == NULL) return; cwhite = NULL; czero = (char) 0; /* Count lines in file */ bufline = buffer; nlines = 0; while ((bufline = strchr (bufline, newline)) != NULL) { bufline = bufline + 1; nlines++; } /* Allocate array for lines of table */ table = (TabInfo *) calloc ((unsigned int)nlines, sizeof(TabInfo)); /* Fill out data structure of lines and indices */ line1 = buffer; for (i = 0; i < 500; i++) line[i] = czero; i = 0; while ((line2 = strchr (bufline, newline)) != NULL) { nchar = line2 - line1 + 1; table[i]->entry = (char *)calloc (1, nchar); line = table[i]->entry; strncpy (line, line1, nchar); line[nchar] = czero; ntok = setoken (&tokens, line, cwhite); if (getoken(&tokens, itok, token, 32)) { if (strchr (token, ':') table[i]->ang = str2dec (token); else table[i]->ang = atof (token); i++; } qsort ((char *)table, nlines, sizeof(TabInfo), TabSort); /* Allocate output buffer the same size as input buffer */ lbuff = strlen (buffer) + 1; buffout = (char *) calloc (lbuff, 1); strcpy (buffout, table[0]->entry); for (i = 1; i < nlines; i++) strcat (buffout, table[i]->entry); free (table[i]->entry); } free (table); return (buffout); } /* TabSort -- Order stars in decreasing flux called by qsort */ int TabSort (ssp1, ssp2) void *ssp1, *ssp2; { double b1 = ((TabInfo *)ssp1)->ang; double b2 = ((TabInfo *)ssp2)->ang; if (b2 > b1) return (1); else if (b2 < b1) return (-1); else return (0); } wcstools-3.9.5/libwcs/tmcread.c0000664000016200001660000012245011750060474015531 0ustar minkoirsys/*** File libwcs/tmcread.c *** September 23, 2010 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 2001-2010 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include #include #include #include "fitsfile.h" #include "wcs.h" #include "wcscat.h" #define MAXREG 1800 #define MINRA 1 #define MAXRA 2 #define ABS(a) ((a) < 0 ? (-(a)) : (a)) /* pathname of 2MASS point source catalog root directory or catalog search engine URL */ char tmc2path[64]="/data/astrocat/2MASS"; char tmcapath[64]="/data/astrocat/tmc"; char tmcepath[64]="/data/astrocat2/tmce"; char tmxpath[64]="/data/astrocat/tmx"; char *tmcpath; static double *gdist; /* Array of distances to stars */ static int ndist = 0; static int linedump = 0; static char *catfile = NULL; static int tmcreg(); struct StarCat *tmcopen(); void tmcclose(); static int tmcstar(); static int tmcsdec(); static int tmcsra(); /* TMCREAD -- Read 2MASS catalog stars from disk files */ int tmcread (refcat,cra,cdec,dra,ddec,drad,dradi,distsort,sysout,eqout,epout, mag1,mag2,sortmag,nstarmax,gnum,gra,gdec,gmag,gtype,nlog) int refcat; /* Code for catalog file from wcscat.h */ double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ double dradi; /* Inner edge of annulus in degrees (ignore if 0) */ int distsort; /* 1 to sort stars by distance from center */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 to nmag) */ int nstarmax; /* Maximum number of stars to be returned */ double *gnum; /* Array of catalog numbers (returned) */ double *gra; /* Array of right ascensions (returned) */ double *gdec; /* Array of declinations (returned) */ double **gmag; /* Array of visual magnitudes (returned) */ int *gtype; /* Array of object types (returned) */ int nlog; /* 1 for diagnostics */ { double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ double dist = 0.0; /* Distance from search center in degrees */ double faintmag=0.0; /* Faintest magnitude */ double maxdist=0.0; /* Largest distance */ int faintstar=0; /* Faintest star */ int farstar=0; /* Most distant star */ int nreg = 0; /* Number of 2MASS point source regions in search */ int rlist[MAXREG]; /* List of regions */ char inpath[128]; /* Pathname for input region file */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ double size = 0.0; /* Semi-major axis of extended source */ struct StarCat *starcat; struct Star *star; int verbose; int wrap; int pass; int ireg; int imag, nmag; int jstar, iw; int zone; int magsort; int nrmax = MAXREG; int nstar,i, ntot; int istar, istar1, istar2; double num, ra, dec, mag; double rra1, rra2, rra2a, rdec1, rdec2; double rdist, ddist; char cstr[32], rastr[32], decstr[32], numstr[32]; char *str; char tmcenv[16]; /* Choose appropriate catalog to read */ if (refcat == TMIDR2) { tmcpath = tmc2path; strcpy (tmcenv, "TMCIDR2_PATH"); nmag = 3; } else if (refcat == TMXSC) { tmcpath = tmxpath; strcpy (tmcenv, "TMX_PATH"); nmag = 3; } else if (refcat == TMPSCE) { tmcpath = tmcepath; strcpy (tmcenv, "TMCE_PATH"); nmag = 6; } else { tmcpath = tmcapath; strcpy (tmcenv, "TMC_PATH"); nmag = 3; } ntot = 0; if (nlog > 0) verbose = 1; else if (nlog < 0) { linedump = 0; verbose = 0; } else verbose = 0; /* If pathname is set in environment, override local value */ if ((str = getenv(tmcenv)) != NULL ) tmcpath = str; /* If pathname is a URL, search and return */ if (!strncmp (tmcpath, "http:",5)) { if (catfile == NULL) catfile = (char *) calloc (8, 1); if (refcat == TMPSC) strcpy (catfile, "tmc"); else if (refcat == TMPSCE) strcpy (catfile, "tmce"); else if (refcat == TMXSC) strcpy (catfile, "tmx"); else if (refcat == TMIDR2) strcpy (catfile, "tmidr2"); return (webread (str,catfile,distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nstarmax, gnum,gra,gdec,NULL,NULL,gmag,gtype,nlog)); } wcscstr (cstr, sysout, eqout, epout); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* If RA range includes zero, split it in two */ wrap = 0; if (ra1 > ra2) wrap = 1; else wrap = 0; /* make mag1 always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } /* Allocate table for distances of stars from search center */ if (nstarmax > ndist) { if (ndist > 0) free ((void *)gdist); gdist = (double *) malloc (nstarmax * sizeof (double)); if (gdist == NULL) { fprintf (stderr,"TMCREAD: cannot allocate separation array\n"); return (0); } ndist = nstarmax; } /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; nstar = 0; jstar = 0; if (sortmag > 0 && sortmag < 4) magsort = sortmag - 1; else magsort = 0; rra1 = ra1; rra2 = ra2; rdec1 = dec1; rdec2 = dec2; RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref,0.0, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); if (wrap) { rra2a = rra2; rra2 = 360.0; } else rra2a = 0.0; /* Write header if printing star entries as found */ if (nstarmax < 1) { char *revmessage; revmessage = getrevmsg(); if (refcat == TMXSC) printf ("catalog 2MASS Extended Source Catalog\n"); else printf ("catalog 2MASS Point Source Catalog\n"); ra2str (rastr, 31, cra, 3); printf ("ra %s\n", rastr); dec2str (decstr, 31, cdec, 2); printf ("dec %s\n", decstr); if (drad != 0.0) { printf ("radmin %.1f\n", drad*60.0); if (dradi > 0) printf ("radimin %.1f\n", dradi*60.0); } else { printf ("dramin %.1f\n", dra*60.0* cosdeg (cdec)); printf ("ddecmin %.1f\n", ddec*60.0); } printf ("radecsys %s\n", cstr); printf ("equinox %.3f\n", eqout); printf ("epoch %.3f\n", epout); if (refcat == TMXSC) printf ("program stmx %s\n", revmessage); else printf ("program stmc %s\n", revmessage); if (refcat == TMXSC) printf ("2mx_id ra dec "); else printf ("2mass_id ra dec "); printf ("magj magh magk "); if (refcat == TMPSCE) printf ("magje maghe magke "); if (refcat == TMXSC) printf (" size "); printf (" arcmin\n"); printf ("---------- ------------ ------------ "); printf ("------ ------ ------"); if (refcat == TMPSCE) printf ("------ ------ ------"); if (refcat == TMXSC) printf (" ------"); printf (" ------\n"); } /* If searching through RA = 0:00, split search in two */ for (iw = 0; iw <= wrap; iw++) { /* Find 2MASS Point Source Catalog regions in which to search */ nreg = tmcreg (refcat, rra1,rra2,rdec1,rdec2,nrmax,rlist,verbose); if (nreg <= 0) { fprintf (stderr,"TMCREAD: no 2MASS regions found\n"); return (0); } /* Loop through zone or region list */ for (ireg = 0; ireg < nreg; ireg++) { /* Open file for this region of 2MASS point source catalog */ zone = rlist[ireg]; starcat = tmcopen (refcat, zone); if (starcat == NULL) { fprintf (stderr,"TMCREAD: File %s not found\n",inpath); return (0); } /* Find first and last stars in this region */ if (refcat == TMPSC || refcat == TMPSCE) { istar1 = tmcsra (starcat, star, zone, rra1, MINRA); istar2 = tmcsra (starcat, star, zone, rra2, MAXRA); } else if (refcat == TMXSC) { istar1 = tmcsra (starcat, star, zone, rra1, MINRA); istar2 = tmcsra (starcat, star, zone, rra2, MAXRA); /* istar1 = 1; istar2 = starcat->nstars; */ } else { istar1 = tmcsdec (starcat, star, zone, rdec1); istar2 = tmcsdec (starcat, star, zone, rdec2); } if (verbose) fprintf (stderr,"TMCREAD: Searching stars %d through %d in region %d\n", istar1, istar2-1, zone); /* Loop through catalog for this region */ for (istar = istar1; istar <= istar2; istar++) { if (tmcstar (starcat, star, zone, istar)) { fprintf (stderr,"TMCREAD: Cannot read star %d\n", istar); break; } /* ID number */ num = star->num; /* Magnitude */ mag = star->xmag[0]; /* Semi-major axis of extended source */ if (refcat == TMXSC) size = star->size; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; if (pass) { /* Get position in output coordinate system */ ra = star->ra; dec = star->dec; wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); /* Compute distance from search center */ if (drad > 0 || distsort) dist = wcsdist (cra,cdec,ra,dec); else dist = 0.0; /* Check radial distance to search center */ if (drad > 0) { if (dist > drad) pass = 0; if (dradi > 0.0 && dist < dradi) pass = 0; } /* Check distance along RA and Dec axes */ else { ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } } if (pass) { /* Write star position and magnitudes to stdout */ if (nstarmax < 1) { CatNum (TMPSC, -10, 0, num, numstr); ra2str (rastr, 31, ra, 3); dec2str (decstr, 31, dec, 2); dist = wcsdist (cra,cdec,ra,dec) * 60.0; printf ("%s %s %s", numstr,rastr,decstr); for (imag = 0; imag < 3; imag++) { if (star->xmag[imag] > 100.0) printf (" %.3fL", star->xmag[imag]-100.0); else printf (" %.3f ", star->xmag[imag]); } if (refcat == TMPSCE) { for (imag = 3; imag < 6; imag++) { printf (" %.3f ", star->xmag[imag]); } } if (refcat == TMXSC) printf (" %.1f", size); printf (" %.2f\n", dist); } /* Save star position and magnitudes in table */ else if (nstar < nstarmax) { gnum[nstar] = num; gra[nstar] = ra; gdec[nstar] = dec; for (imag = 0; imag < nmag; imag++) { if (gmag[imag] != NULL) gmag[imag][nstar] = star->xmag[imag]; } if (refcat == TMXSC) gtype[nstar] = (int) ((size + 0.05) * 10.0); else gtype[nstar] = 0; gdist[nstar] = dist; if (dist > maxdist) { maxdist = dist; farstar = nstar; } if (mag > faintmag) { faintmag = mag; faintstar = nstar; } } /* If too many stars and distance sorting, replace farthest star */ else if (distsort) { if (dist < maxdist) { gnum[farstar] = num; gra[farstar] = ra; gdec[farstar] = dec; for (imag = 0; imag < nmag; imag++) { if (gmag[imag] != NULL) gmag[imag][farstar] = star->xmag[imag]; } if (refcat == TMXSC) gtype[farstar] = (int) ((size + 0.05) * 10.0); else gtype[farstar] = 0; gdist[farstar] = dist; /* Find new farthest star */ maxdist = 0.0; for (i = 0; i < nstarmax; i++) { if (gdist[i] > maxdist) { maxdist = gdist[i]; farstar = i; } } } } /* Else if too many stars, replace faintest star */ else if (mag < faintmag) { gnum[faintstar] = num; gra[faintstar] = ra; gdec[faintstar] = dec; for (imag = 0; imag < nmag; imag++) { if (gmag[imag] != NULL) gmag[imag][faintstar] = star->xmag[imag]; } if (refcat == TMXSC) gtype[faintstar] = (int) ((size + 0.05) * 10.0); else gtype[faintstar] = 0; gdist[faintstar] = dist; faintmag = 0.0; /* Find new faintest star */ for (i = 0; i < nstarmax; i++) { if (gmag[magsort][i] > faintmag) { faintmag = gmag[magsort][i]; faintstar = i; } } } nstar++; if (nlog == 1) fprintf (stderr,"TMCREAD: %11.6f: %9.5f %9.5f %5.2f %5.2f %5.2f\n", num,ra,dec,star->xmag[0],star->xmag[1],star->xmag[2]); /* End of accepted star processing */ } /* Log operation */ jstar++; if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"TMCREAD: %5d / %5d / %5d sources\r", nstar,jstar,starcat->nstars); /* End of star loop */ } ntot = ntot + starcat->nstars; if (nlog > 0) fprintf (stderr,"TMCREAD: %4d / %4d: %5d / %5d / %5d sources from region %4d \n", ireg+1,nreg,nstar,jstar,starcat->nstars,zone); /* Close region input file */ tmcclose (starcat); } rra1 = 0.0; rra2 = rra2a; } /* close output file and summarize transfer */ if (nlog > 0) { if (nreg > 1) fprintf (stderr,"TMCREAD: %d regions: %d / %d found\n",nreg,nstar,ntot); else fprintf (stderr,"TMCREAD: 1 region: %d / %d found\n",nstar,ntot); if (nstar > nstarmax) fprintf (stderr,"TMCREAD: %d stars found; only %d returned\n", nstar,nstarmax); } return (nstar); } /* TMCRNUM -- Read HST Guide Star Catalog stars from CDROM */ int tmcrnum (refcat,nstars,sysout,eqout,epout,gnum,gra,gdec,gmag,gtype,nlog) int refcat; /* Code for catalog file from wcscat.h */ int nstars; /* Number of stars to find */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double *gnum; /* Array of source numbers for which to search */ double *gra; /* Array of right ascensions (returned) */ double *gdec; /* Array of declinations (returned) */ double **gmag; /* 2-D array of magnitudes (returned) */ int *gtype; /* Array of object types (returned) */ int nlog; /* 1 for diagnostics */ { char inpath[128]; /* Pathname for input region file */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ struct StarCat *starcat; struct Star *star; char *str; int rnum; int jstar; int imag, nmag; int istar, nstar; double num, ra, dec, rapm, decpm, dstar; char tmcenv[16]; /* Choose appropriate catalog */ if (refcat == TMIDR2) { tmcpath = tmc2path; strcpy (tmcenv, "TMCIDR2_PATH"); nmag = 3; } else if (refcat == TMXSC) { tmcpath = tmxpath; strcpy (tmcenv, "TMX_PATH"); nmag = 3; } else if (refcat == TMPSCE) { tmcpath = tmcepath; strcpy (tmcenv, "TMCE_PATH"); nmag = 6; } else { tmcpath = tmcapath; strcpy (tmcenv, "TMC_PATH"); nmag = 3; } if (nlog < 0) linedump = 1; /* If pathname is set in environment, override local value */ if ((str = getenv(tmcenv)) != NULL ) tmcpath = str; /* If pathname is a URL, search and return */ if (!strncmp (tmcpath, "http:",5)) return (webrnum (tmcpath,"tmc",nstars,sysout,eqout,epout,1, gnum,gra,gdec,NULL,NULL,gmag,gtype,nlog)); /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; nstar = 0; /* Loop through star list */ for (jstar = 0; jstar < nstars; jstar++) { rnum = (int) (gnum[jstar] + 0.0000000001); starcat = tmcopen (refcat, rnum); if (starcat == NULL) { fprintf (stderr,"TMCRNUM: File %s not found\n",inpath); return (0); } if (refcat == TMIDR2) dstar = (gnum[jstar] - (double)rnum) * 10000000.0; else dstar = (gnum[jstar] - (double)rnum) * 1000000.0; istar = (int) (dstar + 0.5); if (tmcstar (starcat, star, rnum, istar)) { fprintf (stderr,"TMCRNUM: Cannot read star %d\n", istar); gra[jstar] = 0.0; gdec[jstar] = 0.0; for (imag = 0; imag < nmag; imag++) { gmag[imag][jstar] = 0.0; } gtype[jstar] = 0; continue; } /* If star has been found in catalog */ /* ID number */ num = star->num; /* Position in degrees at designated epoch */ ra = star->ra; dec = star->dec; rapm = star->rapm; decpm = star->decpm; wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); /* Save star position and magnitude in table */ gnum[jstar] = num; gra[jstar] = ra; gdec[jstar] = dec; for (imag = 0; imag < nmag; imag++) { gmag[imag][jstar] = star->xmag[imag]; } if (refcat == TMXSC) gtype[jstar] = (int) ((star->size * 10.0) + 0.5); else gtype[jstar] = 0; if (nlog == 1) { fprintf (stderr,"TMCRNUM: %11.6f: %9.5f %9.5f %5.2f %5.2f %5.2f", num, ra, dec, star->xmag[0],star->xmag[1],star->xmag[2]); if (nmag > 3) { fprintf (stderr," %5.2f %5.2f %5.2f", star->xmag[3],star->xmag[4],star->xmag[5]); } fprintf (stderr, "\n"); } /* End of star loop */ } /* Summarize search */ if (nlog > 0) fprintf (stderr,"TMCRNUM: %d / %d found\n",nstar, nstars); tmcclose (starcat); return (nstars); } /* TMCBIN -- Fill FITS WCS image with 2MASS point source catalog objects */ int tmcbin (refcat, wcs, header, image, mag1, mag2, sortmag, magscale, nlog) int refcat; /* Code for catalog file from wcscat.h */ struct WorldCoor *wcs; /* World coordinate system for image */ char *header; /* FITS header for output image */ char *image; /* Output FITS image */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 to nmag) */ double magscale; /* Scaling factor for magnitude to pixel flux * (number of catalog objects per bin if 0) */ int nlog; /* 1 for diagnostics */ { double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ int nreg = 0; /* Number of 2MASS point source regions in search */ int rlist[MAXREG]; /* List of regions */ char inpath[128]; /* Pathname for input region file */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ struct StarCat *starcat; struct Star *star; int verbose; int wrap; int pass; int ireg; int jstar, iw; int zone; int magsort; int nrmax = MAXREG; int nstar, ntot; int istar, istar1, istar2; double num, ra, dec, mag; double rra1, rra2, rra2a, rdec1, rdec2; double rdist, ddist; char cstr[32]; char *str; char tmcenv[16]; double xpix, ypix, flux; int offscl; int ix, iy; int bitpix, w, h; /* Image bits/pixel and pixel width and height */ double logt = log(10.0); /* Choose appropriate catalog */ if (refcat == TMIDR2) { tmcpath = tmc2path; strcpy (tmcenv, "TMCIDR2_PATH"); } else if (refcat == TMXSC) { tmcpath = tmxpath; strcpy (tmcenv, "TMX_PATH"); } else if (refcat == TMPSCE) { tmcpath = tmcepath; strcpy (tmcenv, "TMCE_PATH"); } else { tmcpath = tmcapath; strcpy (tmcenv, "TMC_PATH"); } ntot = 0; if (nlog > 0) verbose = 1; else if (nlog < 0) { linedump = 0; verbose = 0; } else verbose = 0; /* Set image parameters */ bitpix = 0; (void)hgeti4 (header, "BITPIX", &bitpix); w = 0; (void)hgeti4 (header, "NAXIS1", &w); h = 0; (void)hgeti4 (header, "NAXIS2", &h); /* If pathname is set in environment, override local value */ if ((str = getenv(tmcenv)) != NULL ) tmcpath = str; /* Set catalog search limits from image WCS information */ sysout = wcs->syswcs; eqout = wcs->equinox; epout = wcs->epoch; wcscstr (cstr, sysout, eqout, epout); wcssize (wcs, &cra, &cdec, &dra, &ddec); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* If RA range includes zero, split it in two */ wrap = 0; if (ra1 > ra2) wrap = 1; else wrap = 0; /* make mag1 always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; nstar = 0; jstar = 0; if (sortmag > 0 && sortmag < 4) magsort = sortmag - 1; else magsort = 0; rra1 = ra1; rra2 = ra2; rdec1 = dec1; rdec2 = dec2; RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref,0.0, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); if (wrap) { rra2a = rra2; rra2 = 360.0; } else rra2a = 0.0; /* If searching through RA = 0:00, split search in two */ for (iw = 0; iw <= wrap; iw++) { /* Find 2MASS Point Source Catalog regions in which to search */ nreg = tmcreg (refcat, rra1,rra2,rdec1,rdec2,nrmax,rlist,verbose); if (nreg <= 0) { fprintf (stderr,"TMCBIN: no 2MASS regions found\n"); return (0); } /* Loop through zone or region list */ for (ireg = 0; ireg < nreg; ireg++) { /* Open file for this region of 2MASS point source catalog */ zone = rlist[ireg]; starcat = tmcopen (refcat, zone); if (starcat == NULL) { fprintf (stderr,"TMCBIN: File %s not found\n",inpath); return (0); } /* Find first and last stars in this region */ if (refcat == TMPSC || refcat == TMPSCE || refcat == TMXSC) { istar1 = tmcsra (starcat, star, zone, rra1, MINRA); istar2 = tmcsra (starcat, star, zone, rra2, MAXRA); } else { istar1 = tmcsdec (starcat, star, zone, rdec1); istar2 = tmcsdec (starcat, star, zone, rdec2); } if (verbose) fprintf (stderr,"TMCBIN: Searching stars %d through %d\n", istar1, istar2-1); /* Loop through catalog for this region */ for (istar = istar1; istar < istar2; istar++) { if (tmcstar (starcat, star, zone, istar)) { fprintf (stderr,"TMCBIN: Cannot read star %d\n", istar); break; } /* ID number */ num = star->num; /* Magnitude */ mag = star->xmag[0]; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; if (pass) { /* Get position in output coordinate system */ ra = star->ra; dec = star->dec; wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); /* Check distance along RA and Dec axes */ ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } /* Save star in FITS image */ if (pass) { wcs2pix (wcs, ra, dec,&xpix,&ypix,&offscl); if (!offscl) { if (magscale > 0.0) flux = magscale * exp (logt * (-mag / 2.5)); else flux = 1.0; ix = (int) (xpix + 0.5); iy = (int) (ypix + 0.5); addpix1 (image, bitpix, w,h, 0.0,1.0, xpix,ypix, flux); nstar++; jstar++; } else { ix = 0; iy = 0; } if (nlog == 1) { fprintf (stderr,"TMCBIN: %11.6f: %9.5f %9.5f %s", num,ra,dec,cstr); if (magscale > 0.0) fprintf (stderr, " %5.2f", mag); if (!offscl) flux = getpix1 (image, bitpix, w, h, 0.0, 1.0, ix, iy); else flux = 0.0; fprintf (stderr," (%d,%d): %f\n", ix, iy, flux); } /* End of accepted star processing */ } /* Log operation */ jstar++; if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"TMCBIN: %5d / %5d / %5d sources\r", nstar,jstar,starcat->nstars); /* End of star loop */ } ntot = ntot + starcat->nstars; if (nlog > 0) fprintf (stderr,"TMCBIN: %4d / %4d: %5d / %5d / %5d sources from region %4d \n", ireg+1,nreg,nstar,jstar,starcat->nstars,zone); /* Close region input file */ tmcclose (starcat); } rra1 = 0.0; rra2 = rra2a; } /* close output file and summarize transfer */ if (nlog > 0) { if (nreg > 1) fprintf (stderr,"TMCBIN: %d regions: %d / %d found\n",nreg,nstar,ntot); else fprintf (stderr,"TMCBIN: 1 region: %d / %d found\n",nstar,ntot); } return (nstar); } char rdir[50][4]={"0", "1", "2", "3", "4", "5a", "5b", "6a", "6b", "6c", "6d", "7a", "7b", "7c", "7d", "8a", "8b", "9", "10", "11", "12", "13", "14", "15", "16a", "16b", "17a", "17b", "17c", "17d", "17e", "17f", "17g", "17h", "18a", "18b", "18c", "18d", "19a", "19b", "19c", "19d", "20a", "20b", "20c", "20d", "21", "22", "23", ""}; double zmax[50]={00.000, 01.000, 02.000, 03.000, 04.000, 05.000, 05.500, 06.000, 06.250, 06.500, 06.750, 07.000, 07.250, 07.500, 07.750, 08.000, 08.500, 09.000, 10.000, 11.000, 12.000, 13.000, 14.000, 15.000, 16.000, 16.500, 17.000, 17.125, 17.250, 17.375, 17.500, 17.625, 17.750, 17.875, 18.000, 18.250, 18.500, 18.750, 19.000, 19.250, 19.500, 19.750, 20.000, 20.250, 20.500, 20.750, 21.000, 22.000, 23.000, 24.000}; /* TMCREG -- find the regions contained by the given RA/Dec limits * Build lists containing the first star and number of stars for each range. */ static int tmcreg (refcat, ra1, ra2, dec1, dec2, nrmax, regions, verbose) int refcat; /* Code for catalog file from wcscat.h */ double ra1, ra2; /* Right ascension limits in degrees */ double dec1, dec2; /* Declination limits in degrees */ int nrmax; /* Maximum number of regions to find */ int *regions; /* Region numbers to search (returned)*/ int verbose; /* 1 for diagnostics */ { int nrgn; /* Number of regions found (returned) */ int ir; int iz1 = 0; int iz2 = 0; int ir1,ir2,jr1,jr2,i; int ispd1, ispd2, ispd; int nsrch; double rah1,rah2, spd1, spd2; nrgn = 0; /* Find region range to search based on right ascension */ if (refcat == TMIDR2) { rah1 = ra1 / 15.0; for (i = 1; i < 50; i++) { if (rah1 < zmax[i]) { iz1 = i - 1; break; } } rah2 = ra2 / 15.0; for (i = 1; i < 50; i++) { if (rah2 < zmax[i]) { iz2 = i - 1; break; } } if (iz2 >= iz1) { ir1 = iz1; ir2 = iz2; jr1 = 0; jr2 = 0; nsrch = iz2 - iz1 + 1; } else { ir1 = iz1; ir2 = 48; jr1 = 0; jr2 = iz2; nsrch = 48 - iz1 + 1 + iz2 + 1; } /* Search region northern hemisphere or only one region */ if (verbose) { fprintf(stderr,"TMCREG: RA: %.5f - %.5f, Dec: %.5f - %.5f\n", ra1,ra2,dec1,dec2); if (nsrch == 1) fprintf (stderr,"TMCREG: searching region %d", ir1); else fprintf (stderr,"TMCREG: searching %d regions: %d - %d", nsrch, ir1, ir2); if (jr1 > 0 && jr2 > 0) fprintf (stderr,", %d - %d", jr1, jr2); fprintf (stderr,"\n"); } /* Loop through first section of sky */ nrgn = 0; for (ir = ir1; ir <= ir2; ir++) { if (verbose) fprintf (stderr,"TMCREG: Region %d (%s) added to search\n", ir, rdir[ir]); /* Add this region to list, if there is space */ if (nrgn < nrmax) { regions[nrgn] = ir; nrgn++; } } /* Loop through second section of sky */ for (ir = jr1; ir < jr2; ir++) { if (verbose) fprintf (stderr,"TMCREG: Region %d %s) added to search\n", ir, rdir[ir]); /* Add this region to list, if there is space */ if (nrgn < nrmax) { regions[nrgn] = ir; nrgn++; } } } /* Compute SPD regions for all-sky release of point source catalog */ else { if (dec1 < dec2) { spd1 = dec1 + 90.0; spd2 = dec2 + 90.0; } else { spd1 = dec2 + 90.0; spd2 = dec1 + 90.0; } ispd1 = (int) (spd1 * 10.0); ispd2 = (int) (spd2 * 10.0); if (ispd2 > 1799) ispd2 = 1799; for (ispd = ispd1; ispd <= ispd2; ispd++) { /* Add this region to list, if there is space */ if (nrgn < nrmax) { regions[nrgn] = ispd; nrgn++; } } } return (nrgn); } /* TMCOPEN -- Open 2MASS point source catalog file, returning catalog structure */ struct StarCat * tmcopen (refcat, zone) int refcat; /* Code for catalog file from wcscat.h */ int zone; /* RA zone (hours) to read */ { FILE *fcat; struct StarCat *sc; int lfile, lpath, izone, ireg; char *zonefile; char *zonepath; /* Full pathname for catalog file */ /* Set path to 2MASS Point Source Catalog zone */ if (refcat == TMPSC || refcat == TMPSCE || refcat == TMXSC) { izone = zone / 10; ireg = zone % 10; lpath = strlen (tmcpath) + 18; zonepath = (char *) malloc (lpath); sprintf (zonepath, "%s/%03d/t%04d.cat", tmcpath, izone, ireg); } else { lpath = strlen (tmcpath) + 18; zonepath = (char *) malloc (lpath); sprintf (zonepath, "%s/idr2psc%s.tbl", tmcpath, rdir[zone]); } /* Find length of 2MASS catalog file */ lfile = getfilesize (zonepath); /* Check for existence of catalog */ if (lfile < 2) { fprintf (stderr,"TMCOPEN: Binary catalog %s has no entries\n",zonepath); free (zonepath); return (NULL); } /* Open 2MASS point source catalog zone file */ if (!(fcat = fopen (zonepath, "r"))) { fprintf (stderr,"TMCOPEN: 2MASS PSC file %s cannot be read\n",zonepath); free (zonepath); return (0); } /* Set 2MASS PSC catalog header information */ sc = (struct StarCat *) calloc (1, sizeof (struct StarCat)); sc->byteswapped = 0; sc->refcat = refcat; if (refcat == TMPSC) { sc->entra = 0; sc->entdec = 10; sc->entname = 0; sc->entmag[0] = 39; sc->entmag[1] = 46; sc->entmag[2] = 53; sc->entadd = 61; sc->nbent = 69; } else if (refcat == TMPSCE) { sc->entra = 0; sc->entdec = 10; sc->entname = 0; sc->entmag[0] = 39; sc->entmag[1] = 46; sc->entmag[2] = 53; sc->entmag[3] = 60; sc->entmag[4] = 66; sc->entmag[5] = 72; sc->entadd = 79; sc->nbent = 87; } else if (refcat == TMXSC) { sc->entra = 0; sc->entdec = 10; sc->entname = 0; sc->entmag[0] = 39; sc->entmag[1] = 46; sc->entmag[2] = 53; sc->entsize = 60; sc->nbent = 68; } else { sc->entra = 0; sc->entdec = 10; sc->entmag[0] = 53; sc->entmag[1] = 72; sc->entmag[2] = 91; sc->entadd = 110; sc->nbent = 302; } sc->nstars = lfile / sc->nbent; /* Separate filename from pathname and save in structure */ zonefile = strrchr (zonepath,'/'); if (zonefile) zonefile = zonefile + 1; else zonefile = zonepath; if (strlen (zonefile) < 24) strcpy (sc->isfil, zonefile); else strncpy (sc->isfil, zonefile, 23); /* Set other catalog information in structure */ sc->inform = 'J'; sc->coorsys = WCS_J2000; sc->epoch = 2000.0; sc->equinox = 2000.0; sc->ifcat = fcat; sc->sptype = 2; /* All-sky release 2MASS catalogs are RA-sorted within Dec zones */ if (refcat == TMPSC || refcat == TMPSCE) sc->rasorted = 1; /* Pre-release 2MASS catalogs were Dec-sorted within RA zones */ else sc->rasorted = 0; free (zonepath); return (sc); } void tmcclose (sc) struct StarCat *sc; /* Star catalog descriptor */ { fclose (sc->ifcat); if (sc->catdata != NULL) free (sc->catdata); free (sc); return; } /* TMCSDEC -- Find 2MASS star closest to specified declination */ static int tmcsdec (starcat, star, zone, decx0) struct StarCat *starcat; /* Star catalog descriptor */ struct Star *star; /* Current star entry */ int zone; /* RA zone in which search is occuring */ double decx0; /* Declination in degrees for which to search */ { int istar, istar1, istar2, nrep; double decx, dec1, dec, rdiff, rdiff1, rdiff2, sdiff; char decstrx[32]; int debug = 0; decx = decx0; if (debug) dec2str (decstrx, 31, decx, 3); istar1 = 1; if (tmcstar (starcat, star, zone, istar1)) return (0); dec1 = star->dec; istar = starcat->nstars; nrep = 0; while (istar != istar1 && nrep < 20) { if (tmcstar (starcat, star, zone, istar)) break; else { dec = star->dec; if (dec == dec1) break; if (debug) { char decstr[32]; dec2str (decstr, 31, dec, 3); fprintf (stderr,"TMCSRA %d %d: %s (%s)\n", nrep,istar,decstr,decstrx); } rdiff = dec1 - dec; rdiff1 = dec1 - decx; rdiff2 = dec - decx; if (nrep > 20 && ABS(rdiff2) > ABS(rdiff1)) { istar = istar1; break; } nrep++; sdiff = (double)(istar - istar1) * rdiff1 / rdiff; istar2 = istar1 + (int) (sdiff + 0.5); dec1 = dec; istar1 = istar; istar = istar2; if (debug) { fprintf (stderr," dec1= %.5f dec= %.5f decx= %.5f\n", dec1,dec,decx); fprintf (stderr," rdiff= %.5f rdiff1= %.5f rdiff2= %.5f\n", rdiff,rdiff1,rdiff2); fprintf (stderr," istar1= %d istar= %d istar1= %d\n", istar1,istar,istar2); } if (istar < 1) istar = 1; if (istar > starcat->nstars) istar = starcat->nstars; if (istar == istar1) break; } } return (istar); } /* TMCSRA -- Find 2MASS star closest to specified right ascension */ static int tmcsra (starcat, star, zone, rax0, minmax) struct StarCat *starcat; /* Star catalog descriptor */ struct Star *star; /* Current star entry */ int zone; /* Declination zone in which search is occurring */ double rax0; /* Right ascension in degrees for which to search */ int minmax; /* Flag to say whether this is a min or max RA */ { int istar, istar0, istar1, nrep, i; double rax, ra0, ra1, ra, sdiff; char rastrx[32]; char rastr[32]; int debug = 0; rax = rax0; ra0 = -1.0; ra1 = star->ra; if (debug) { ra2str (rastrx, 31, rax, 3); ra2str (rastr, 31, ra1, 3); nrep = -1; istar = (int) star->num; fprintf (stderr,"TMCSRA %d %d: %s (%s)\n", nrep,istar,rastr,rastrx); } istar0 = 1; if (tmcstar (starcat, star, zone, istar0)) return (0); ra0 = star->ra; istar1 = starcat->nstars; if (tmcstar (starcat, star, zone, istar1)) return (0); ra1 = star->ra; istar = starcat->nstars / 2; if (tmcstar (starcat, star, zone, istar)) return (0); ra = star->ra; nrep = 0; while (istar != istar1 && nrep < 20) { if (ra < rax) { sdiff = 0.5 * (double) (istar1 - istar); if (sdiff < 1.0) break; istar0 = istar; istar = istar + (int) (sdiff + 0.5); } else if (ra > rax) { sdiff = 0.5 * (double) (istar - istar0); if (sdiff < 1.0) break; istar1 = istar; istar = istar - (int) (sdiff + 0.5); } else break; if (debug) { fprintf (stderr," istar0= %d istar1= %d istar= %d\n", istar0, istar1,istar); fprintf (stderr," ra1= %.5f ra= %.5f rax= %.5f\n", ra0,ra,rax); } if (istar == 1 || istar == istar1) break; if (tmcstar (starcat, star, zone, istar)) break; ra = star->ra; nrep++; } /* For small catalogs, linear projection of RA's doesn't work */ /* Check lower numbers if low end of range is being set */ if (minmax == MINRA) { for (i = 1; i < 5; i++) { istar0 = istar - 1; if (istar0 < 1) break; if (tmcstar (starcat, star, zone, istar0)) break; if (star->ra < rax) break; else istar = istar0; } } /* Check higher numbers if top end of range is being set */ else { for (i = 1; i < 5; i++) { istar0 = istar + 1; if (istar0 > starcat->nstars) break; if (tmcstar (starcat, star, zone, istar0)) break; if (star->ra > rax) break; else istar = istar0; } } return (istar); } /* TMCSTAR -- Get 2MASS Point Source Catalog entry for one star; return 0 if successful */ static int tmcstar (sc, st, zone, istar) struct StarCat *sc; /* Star catalog descriptor */ struct Star *st; /* Current star entry */ int zone; /* Zone catalog number (1-49) */ int istar; /* Star sequence in 2MASS zone file */ { char line[500]; int nbskip, nbr, iflag; /* Drop out if catalog pointer is not set */ if (sc == NULL) return (1); /* Drop out if catalog is not open */ if (sc->ifcat == NULL) return (2); /* Drop out if star number is too large */ if (istar > sc->nstars) { fprintf (stderr, "TMCSTAR: %d > %d is not in catalog\n", istar, sc->nstars); return (3); } /* Read entry for one star */ nbskip = sc->nbent * (istar - 1); if (fseek (sc->ifcat,nbskip,SEEK_SET)) return (-1); nbr = fread (line, sc->nbent, 1, sc->ifcat) * sc->nbent; if (nbr < sc->nbent) { fprintf (stderr, "tmcstar %d / %d bytes read\n",nbr, sc->nbent); return (-2); } /* Make up source number from zone number and star number */ if (sc->refcat == TMIDR2) st->num = zone + (0.0000001 * (double) istar); else st->num = zone + (0.000001 * (double) istar); /* Read position in degrees */ st->ra = atof (line); st->dec = atof (line+sc->entdec); /* No proper motion */ st->rapm = 0.0; st->decpm = 0.0; /* Set J magnitude */ st->xmag[0] = atof (line+sc->entmag[0]); /* Set H magnitude */ st->xmag[1] = atof (line+sc->entmag[1]); /* Set K magnitude */ st->xmag[2] = atof (line+sc->entmag[2]); /* Add J, H, K errors if needed */ if (sc->refcat == TMPSCE) { st->xmag[3] = atof (line+sc->entmag[3]); st->xmag[4] = atof (line+sc->entmag[4]); st->xmag[5] = atof (line+sc->entmag[5]); } /* Add 100 to magnitude if it isn't a good one */ if (sc->refcat == TMPSC || sc->refcat == TMPSCE || sc->refcat == TMXSC) { if (line[sc->entadd] == 'U') st->xmag[0] = st->xmag[0] + 100.0; if (line[sc->entadd + 1] == 'U') st->xmag[1] = st->xmag[1] + 100.0; if (line[sc->entadd + 2] == 'U') st->xmag[2] = st->xmag[2] + 100.0; } /* Preliminary data release data quality flag */ else { iflag = ((int) line[sc->entadd]) - 48; if (iflag < 1 || iflag == 3 || iflag > 4) st->xmag[0] = st->xmag[0] + 100.0; iflag = ((int) line[sc->entadd + 1]) - 48; if (iflag < 1 || iflag == 3 || iflag > 4) st->xmag[1] = st->xmag[1] + 100.0; iflag = ((int) line[sc->entadd + 2]) - 48; if (iflag < 1 || iflag == 3 || iflag > 4) st->xmag[2] = st->xmag[2] + 100.0; } if (sc->refcat == TMXSC) st->size = atof (line+sc->entsize); else st->size = 0.0; if (linedump) printf ("%s\n",line); return (0); } /* May 29 2001 New program, based on ty2read.c and uacread.c * May 30 2001 Round K magnitude to nearest 1000th * Jun 13 2001 Round star number up to avoid truncation problem * Jun 27 2001 Add code to print one entry at time if nstars < 1 * Jun 27 2001 Allocate gdist only if larger array is needed * Sep 11 2001 Return all three magnitudes * Sep 17 2001 Print line from catalog if nlog is < 0 * Sep 17 2001 Flag bad magnitudes by adding 100 to them * Sep 18 2001 Fix bug in magnitudes returned if not distance sorted * Nov 20 2001 Change cos(degrad()) to cosdeg() * Nov 29 2001 Declare undeclared subroutine tmcsdec * Dec 3 2001 Change default catalog directory to /data/astrocat/2MASS * * Feb 13 2002 Fix catalog name in web access * Oct 3 2002 Use global variable for scat version * * Apr 3 2003 Drop unused variables after lint * Apr 14 2003 Explicitly get revision date if nstarmax < 1 * May 19 2003 Add code to read dec-zoned, ra-sorted All-Sky release * May 21 2003 Add catfile argument to read both IDR2 and All-Sky releases * May 27 2003 Allow IDR2 and Allsky release to be set by catalog name * May 28 2003 Star ID numbers from All-Sky release have 6 decimal places * Jul 2 2003 Fix limiting magnitude for All-Sky Release * Aug 22 2003 Add radi argument for inner edge of search annulus * Sep 25 2003 Add tmcbin() to fill an image with sources * Oct 6 2003 Update tmcread() and tmcbin() for improved RefLim() * Nov 18 2003 Initialize image size and bits/pixel from header in tmcbin() * * Jan 13 2004 Add support for 2MASS Extended Source Catalog * Jan 14 2004 Add code to fix convergence in tmcsra() * Jan 23 2004 Fix search algorith in tmcsra() * Nov 10 2004 Fix region computation at north pole * * Aug 5 2005 Add JHK errors as additional option * Aug 5 2005 Avoid extra work by passing refcat catalog code * * Jun 20 2006 Initialize uninitialized variables * Sep 26 2006 Increase length of rastr and destr from 16 to 32 * Nov 15 2006 Fix binning * * Jan 8 2007 Drop unused variables * Jan 9 2007 Relabel number arrays * Jan 10 2007 Add match=1 argument to webrnum() * Oct 31 2007 Properly return magnitude errors from tmcrnum(), if present * Nov 20 2007 Fix bug which offset limit flag by one (found by Gus Muensch) * * Sep 28 2009 Print correct heading for n<0 Extended Source tab table * * Sep 23 2010 Add last star to search loop to fix bug */ wcstools-3.9.5/libwcs/tnxpos.c0000664000016200001660000010050011750060474015435 0ustar minkoirsys/*** File wcslib/tnxpos.c *** September 17, 2008 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** After IRAF mwcs/wftnx.x and mwcs/wfgsurfit.x *** Copyright (C) 1998-2008 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include "wcs.h" #define SPHTOL 0.00001 #define BADCVAL 0.0 #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) /* wftnx -- wcs function driver for the gnomonic projection with correction. * tnxinit (header, wcs) * tnxclose (wcs) * tnxfwd (xpix, ypix, wcs, xpos, ypos) Pixels to WCS * tnxrev (xpos, ypos, wcs, xpix, ypix) WCS to pixels */ #define max_niter 500 #define SZ_ATSTRING 2000 static void wf_gsclose(); static void wf_gsb1pol(); static void wf_gsb1leg(); static void wf_gsb1cheb(); /* tnxinit -- initialize the gnomonic forward or inverse transform. * initialization for this transformation consists of, determining which * axis is ra / lon and which is dec / lat, computing the celestial longitude * and colatitude of the native pole, reading in the the native longitude * of the pole of the celestial coordinate system longpole from the attribute * list, precomputing euler angles and various intermediaries derived from the * coordinate reference values, and reading in the projection parameter ro * from the attribute list. if longpole is undefined then a value of 180.0 * degrees is assumed. if ro is undefined a value of 180.0 / pi is assumed. * the tan projection is equivalent to the azp projection with mu set to 0.0. * in order to determine the axis order, the parameter "axtype={ra|dec} * {xlon|glat}{xlon|elat}" must have been set in the attribute list for the * function. the longpole and ro parameters may be set in either or both of * the axes attribute lists, but the value in the ra axis attribute list takes * precedence. */ int tnxinit (header, wcs) const char *header; /* FITS header */ struct WorldCoor *wcs; /* pointer to WCS structure */ { struct IRAFsurface *wf_gsopen(); char *str1, *str2, *lngstr, *latstr; extern void wcsrotset(); /* allocate space for the attribute strings */ str1 = malloc (SZ_ATSTRING); str2 = malloc (SZ_ATSTRING); hgetm (header, "WAT1", SZ_ATSTRING, str1); hgetm (header, "WAT2", SZ_ATSTRING, str2); lngstr = malloc (SZ_ATSTRING); latstr = malloc (SZ_ATSTRING); /* determine the native longitude of the pole of the celestial coordinate system corresponding to the FITS keyword longpole. this number has no default and should normally be set to 180 degrees. search both axes for this quantity. */ if (wcs->longpole > 360.0) { if (!igetr8 (str1, "longpole", &wcs->longpole)) { if (!igetr8 (str2, "longpole", &wcs->longpole)) wcs->longpole = 180.0; } } /* Fetch the ro projection parameter which is the radius of the generating sphere for the projection. if ro is absent which is the usual case set it to 180 / pi. search both axes for this quantity. */ if (!igetr8 (str1, "ro", &wcs->rodeg)) { if (!igetr8 (str2, "ro", &wcs->rodeg)) wcs->rodeg = 180.0 / PI; } /* Fetch the longitude correction surface. note that the attribute string may be of any length so the length of atvalue may have to be adjusted. */ if (!igets (str1, "lngcor", SZ_ATSTRING, lngstr)) { if (!igets (str2, "lngcor", SZ_ATSTRING, lngstr)) wcs->lngcor = NULL; else wcs->lngcor = wf_gsopen (lngstr); } else wcs->lngcor = wf_gsopen (lngstr); /* Fetch the latitude correction surface. note that the attribute string may be of any length so the length of atvalue may have to be adjusted. */ if (!igets (str2, "latcor", SZ_ATSTRING, latstr)) { if (!igets (str1, "latcor", SZ_ATSTRING, latstr)) wcs->latcor = NULL; else wcs->latcor = wf_gsopen (latstr); } else wcs->latcor = wf_gsopen (latstr); /* Compute image rotation */ wcsrotset (wcs); /* free working space. */ free (str1); free (str2); free (lngstr); free (latstr); /* Return 1 if there are no correction coefficients */ if (wcs->latcor == NULL && wcs->lngcor == NULL) return (1); else return (0); } /* tnxpos -- forward transform (physical to world) gnomonic projection. */ int tnxpos (xpix, ypix, wcs, xpos, ypos) double xpix, ypix; /*i physical coordinates (x, y) */ struct WorldCoor *wcs; /*i pointer to WCS descriptor */ double *xpos, *ypos; /*o world coordinates (ra, dec) */ { int ira, idec; double x, y, r, phi, theta, costhe, sinthe, dphi, cosphi, sinphi, dlng, z; double colatp, coslatp, sinlatp, longp; double xs, ys, ra, dec, xp, yp; double wf_gseval(); /* Convert from pixels to image coordinates */ xpix = xpix - wcs->crpix[0]; ypix = ypix - wcs->crpix[1]; /* Scale and rotate using CD matrix */ if (wcs->rotmat) { x = xpix * wcs->cd[0] + ypix * wcs->cd[1]; y = xpix * wcs->cd[2] + ypix * wcs->cd[3]; } else { /* Check axis increments - bail out if either 0 */ if (wcs->cdelt[0] == 0.0 || wcs->cdelt[1] == 0.0) { *xpos = 0.0; *ypos = 0.0; return 2; } /* Scale using CDELT */ xs = xpix * wcs->cdelt[0]; ys = ypix * wcs->cdelt[1]; /* Take out rotation from CROTA */ if (wcs->rot != 0.0) { double cosr = cos (degrad (wcs->rot)); double sinr = sin (degrad (wcs->rot)); x = xs * cosr - ys * sinr; y = xs * sinr + ys * cosr; } else { x = xs; y = ys; } } /* get the axis numbers */ if (wcs->coorflip) { ira = 1; idec = 0; } else { ira = 0; idec = 1; } colatp = degrad (90.0 - wcs->crval[idec]); coslatp = cos(colatp); sinlatp = sin(colatp); longp = degrad(wcs->longpole); /* Compute native spherical coordinates phi and theta in degrees from the projected coordinates. this is the projection part of the computation */ if (wcs->lngcor != NULL) xp = x + wf_gseval (wcs->lngcor, x, y); else xp = x; if (wcs->latcor != NULL) yp = y + wf_gseval (wcs->latcor, x, y); else yp = y; x = xp; y = yp; r = sqrt (x * x + y * y); /* Compute phi */ if (r == 0.0) phi = 0.0; else phi = atan2 (x, -y); /* Compute theta */ theta = atan2 (wcs->rodeg, r); /* Compute the celestial coordinates ra and dec from the native coordinates phi and theta. this is the spherical geometry part of the computation */ costhe = cos (theta); sinthe = sin (theta); dphi = phi - longp; cosphi = cos (dphi); sinphi = sin (dphi); /* Compute the ra */ x = sinthe * sinlatp - costhe * coslatp * cosphi; if (fabs (x) < SPHTOL) x = -cos (theta + colatp) + costhe * coslatp * (1.0 - cosphi); y = -costhe * sinphi; if (x != 0.0 || y != 0.0) dlng = atan2 (y, x); else dlng = dphi + PI ; ra = wcs->crval[ira] + raddeg(dlng); /* normalize ra */ if (wcs->crval[ira] >= 0.0) { if (ra < 0.0) ra = ra + 360.0; } else { if (ra > 0.0) ra = ra - 360.0; } if (ra > 360.0) ra = ra - 360.0; else if (ra < -360.0) ra = ra + 360.0; /* compute the dec */ if (fmod (dphi, PI) == 0.0) { dec = raddeg(theta + cosphi * colatp); if (dec > 90.0) dec = 180.0 - dec; if (dec < -90.0) dec = -180.0 - dec; } else { z = sinthe * coslatp + costhe * sinlatp * cosphi; if (fabs(z) > 0.99) { if (z >= 0.0) dec = raddeg(acos (sqrt(x * x + y * y))); else dec = raddeg(-acos (sqrt(x * x + y * y))); } else dec = raddeg(asin (z)); } /* store the results */ *xpos = ra; *ypos = dec; return (0); } /* tnxpix -- inverse transform (world to physical) gnomonic projection */ int tnxpix (xpos, ypos, wcs, xpix, ypix) double xpos, ypos; /*i world coordinates (ra, dec) */ struct WorldCoor *wcs; /*i pointer to WCS descriptor */ double *xpix, *ypix; /*o physical coordinates (x, y) */ { int ira, idec, niter; double ra, dec, cosdec, sindec, cosra, sinra, x, y, phi, theta; double s, r, dphi, z, dpi, dhalfpi, twopi, tx; double xm, ym, f, fx, fy, g, gx, gy, denom, dx, dy; double colatp, coslatp, sinlatp, longp, sphtol; double wf_gseval(), wf_gsder(); /* get the axis numbers */ if (wcs->coorflip) { ira = 1; idec = 0; } else { ira = 0; idec = 1; } /* Compute the transformation from celestial coordinates ra and dec to native coordinates phi and theta. this is the spherical geometry part of the transformation */ ra = degrad (xpos - wcs->crval[ira]); dec = degrad (ypos); cosra = cos (ra); sinra = sin (ra); cosdec = cos (dec); sindec = sin (dec); colatp = degrad (90.0 - wcs->crval[idec]); coslatp = cos (colatp); sinlatp = sin (colatp); if (wcs->longpole == 999.0) longp = degrad (180.0); else longp = degrad(wcs->longpole); dpi = PI; dhalfpi = dpi * 0.5; twopi = PI + PI; sphtol = SPHTOL; /* Compute phi */ x = sindec * sinlatp - cosdec * coslatp * cosra; if (fabs(x) < sphtol) x = -cos (dec + colatp) + cosdec * coslatp * (1.0 - cosra); y = -cosdec * sinra; if (x != 0.0 || y != 0.0) dphi = atan2 (y, x); else dphi = ra - dpi; phi = longp + dphi; if (phi > dpi) phi = phi - twopi; else if (phi < -dpi) phi = phi + twopi; /* Compute theta */ if (fmod (ra, dpi) == 0.0) { theta = dec + cosra * colatp; if (theta > dhalfpi) theta = dpi - theta; if (theta < -dhalfpi) theta = -dpi - theta; } else { z = sindec * coslatp + cosdec * sinlatp * cosra; if (fabs (z) > 0.99) { if (z >= 0.0) theta = acos (sqrt(x * x + y * y)); else theta = -acos (sqrt(x * x + y * y)); } else theta = asin (z); } /* Compute the transformation from native coordinates phi and theta to projected coordinates x and y */ s = sin (theta); if (s == 0.0) { x = BADCVAL; y = BADCVAL; } else { r = wcs->rodeg * cos (theta) / s; if (wcs->lngcor == NULL && wcs->latcor == NULL) { if (wcs->coorflip) { y = r * sin (phi); x = -r * cos (phi); } else { x = r * sin (phi); y = -r * cos (phi); } } else { xm = r * sin (phi); ym = -r * cos (phi); x = xm; y = ym; niter = 0; while (niter < max_niter) { if (wcs->lngcor != NULL) { f = x + wf_gseval (wcs->lngcor, x, y) - xm; fx = wf_gsder (wcs->lngcor, x, y, 1, 0); fx = 1.0 + fx; fy = wf_gsder (wcs->lngcor, x, y, 0, 1); } else { f = x - xm; fx = 1.0 ; fy = 0.0; } if (wcs->latcor != NULL) { g = y + wf_gseval (wcs->latcor, x, y) - ym; gx = wf_gsder (wcs->latcor, x, y, 1, 0); gy = wf_gsder (wcs->latcor, x, y, 0, 1); gy = 1.0 + gy; } else { g = y - ym; gx = 0.0 ; gy = 1.0; } denom = fx * gy - fy * gx; if (denom == 0.0) break; dx = (-f * gy + g * fy) / denom; dy = (-g * fx + f * gx) / denom; x = x + dx; y = y + dy; if (MAX(MAX(fabs(dx),fabs(dy)),MAX(fabs(f),fabs(g))) < 2.80e-8) break; niter = niter + 1; } /* Reverse x and y if axes flipped */ if (wcs->coorflip) { tx = x; x = y; y = tx; } } } /* Scale and rotate using CD matrix */ if (wcs->rotmat) { *xpix = x * wcs->dc[0] + y * wcs->dc[1]; *ypix = x * wcs->dc[2] + y * wcs->dc[3]; } else { /* Correct for rotation */ if (wcs->rot!=0.0) { double cosr = cos (degrad (wcs->rot)); double sinr = sin (degrad (wcs->rot)); *xpix = x * cosr + y * sinr; *ypix = y * cosr - x * sinr; } else { *xpix = x; *ypix = y; } /* Scale using CDELT */ if (wcs->xinc != 0.) *xpix = *xpix / wcs->xinc; if (wcs->yinc != 0.) *ypix = *ypix / wcs->yinc; } /* Convert to pixels */ *xpix = *xpix + wcs->xrefpix; *ypix = *ypix + wcs->yrefpix; return (0); } /* TNXCLOSE -- free up the distortion surface pointers */ void tnxclose (wcs) struct WorldCoor *wcs; /* pointer to the WCS descriptor */ { if (wcs->lngcor != NULL) wf_gsclose (wcs->lngcor); if (wcs->latcor != NULL) wf_gsclose (wcs->latcor); return; } /* copyright(c) 1986 association of universities for research in astronomy inc. * wfgsurfit.x -- surface fitting package used by wcs function drivers. * Translated to C from SPP by Jessica Mink, SAO, May 26, 1998 * * the following routines are used by the experimental function drivers tnx * and zpx to decode polynomial fits stored in the image header in the form * of a list of parameters and coefficients into surface descriptors in * ra / dec or longitude latitude. the polynomial surfaces so encoded consist * of corrections to function drivers tan and zpn. the package routines are * modelled after the equivalent gsurfit routines and are consistent with them. * the routines are: * * sf = wf_gsopen (wattstr) * wf_gsclose (sf) * * z = wf_gseval (sf, x, y) * ncoeff = wf_gscoeff (sf, coeff) * zder = wf_gsder (sf, x, y, nxder, nyder) * * wf_gsopen is used to open a surface fit encoded in a wcs attribute, returning * the sf surface fitting descriptor. wf_gsclose should be called later to free * the descriptor. wf_gseval is called to evaluate the surface at a point. */ #define SZ_GSCOEFFBUF 20 /* define the structure elements for the wf_gsrestore task */ #define TNX_SAVETYPE 0 #define TNX_SAVEXORDER 1 #define TNX_SAVEYORDER 2 #define TNX_SAVEXTERMS 3 #define TNX_SAVEXMIN 4 #define TNX_SAVEXMAX 5 #define TNX_SAVEYMIN 6 #define TNX_SAVEYMAX 7 #define TNX_SAVECOEFF 8 /* wf_gsopen -- decode the longitude / latitude or ra / dec mwcs attribute * and return a gsurfit compatible surface descriptor. */ struct IRAFsurface * wf_gsopen (astr) char *astr; /* the input mwcs attribute string */ { double dval; char *estr; int npar, szcoeff; double *coeff; struct IRAFsurface *gs; struct IRAFsurface *wf_gsrestore(); if (astr[1] == 0) return (NULL); gs = NULL; npar = 0; szcoeff = SZ_GSCOEFFBUF; coeff = (double *) malloc (szcoeff * sizeof (double)); estr = astr; while (*estr != (char) 0) { dval = strtod (astr, &estr); if (*estr == '.') estr++; if (*estr != (char) 0) { npar++; if (npar >= szcoeff) { szcoeff = szcoeff + SZ_GSCOEFFBUF; coeff = (double *) realloc (coeff, (szcoeff * sizeof (double))); } coeff[npar-1] = dval; astr = estr; while (*astr == ' ') astr++; } } gs = wf_gsrestore (coeff); free (coeff); if (npar == 0) return (NULL); else return (gs); } /* wf_gsclose -- procedure to free the surface descriptor */ static void wf_gsclose (sf) struct IRAFsurface *sf; /* the surface descriptor */ { if (sf != NULL) { if (sf->xbasis != NULL) free (sf->xbasis); if (sf->ybasis != NULL) free (sf->ybasis); if (sf->coeff != NULL) free (sf->coeff); free (sf); } return; } /* wf_gseval -- procedure to evaluate the fitted surface at a single point. * the wf->ncoeff coefficients are stored in the vector pointed to by sf->coeff. */ double wf_gseval (sf, x, y) struct IRAFsurface *sf; /* pointer to surface descriptor structure */ double x; /* x value */ double y; /* y value */ { double sum, accum; int i, ii, k, maxorder, xorder; /* Calculate the basis functions */ switch (sf->type) { case TNX_CHEBYSHEV: wf_gsb1cheb (x, sf->xorder, sf->xmaxmin, sf->xrange, sf->xbasis); wf_gsb1cheb (y, sf->yorder, sf->ymaxmin, sf->yrange, sf->ybasis); break; case TNX_LEGENDRE: wf_gsb1leg (x, sf->xorder, sf->xmaxmin, sf->xrange, sf->xbasis); wf_gsb1leg (y, sf->yorder, sf->ymaxmin, sf->yrange, sf->ybasis); break; case TNX_POLYNOMIAL: wf_gsb1pol (x, sf->xorder, sf->xbasis); wf_gsb1pol (y, sf->yorder, sf->ybasis); break; default: fprintf (stderr,"TNX_GSEVAL: unknown surface type\n"); return (0.0); } /* Initialize accumulator basis functions */ sum = 0.0; /* Loop over y basis functions */ if (sf->xorder > sf->yorder) maxorder = sf->xorder + 1; else maxorder = sf->yorder + 1; xorder = sf->xorder; ii = 0; for (i = 0; i < sf->yorder; i++) { /* Loop over the x basis functions */ accum = 0.0; for (k = 0; k < xorder; k++) { accum = accum + sf->coeff[ii] * sf->xbasis[k]; ii = ii + 1; } accum = accum * sf->ybasis[i]; sum = sum + accum; /* Elements of the coefficient vector where neither k = 1 or i = 1 are not calculated if sf->xterms = no. */ if (sf->xterms == TNX_XNONE) xorder = 1; else if (sf->xterms == TNX_XHALF) { if ((i + 1 + sf->xorder + 1) > maxorder) xorder = xorder - 1; } } return (sum); } /* TNX_GSCOEFF -- procedure to fetch the number and magnitude of the coefficients * if the sf->xterms = wf_xbi (yes) then the number of coefficients will be * (sf->xorder * sf->yorder); if wf_xterms is wf_xtri then the number * of coefficients will be (sf->xorder * sf->yorder - order * * (order - 1) / 2) where order is the minimum of the x and yorders; if * sf->xterms = TNX_XNONE then the number of coefficients will be * (sf->xorder + sf->yorder - 1). */ int wf_gscoeff (sf, coeff) struct IRAFsurface *sf; /* pointer to the surface fitting descriptor */ double *coeff; /* the coefficients of the fit */ { int ncoeff; /* the number of coefficients */ int i; /* Exctract coefficients from data structure and calculate their number */ ncoeff = sf->ncoeff; for (i = 0; i < ncoeff; i++) coeff[i] = sf->coeff[i]; return (ncoeff); } static double *coeff = NULL; static int nbcoeff = 0; /* wf_gsder -- procedure to calculate a new surface which is a derivative of * the input surface. */ double wf_gsder (sf1, x, y, nxd, nyd) struct IRAFsurface *sf1; /* pointer to the previous surface */ double x; /* x values */ double y; /* y values */ int nxd, nyd; /* order of the derivatives in x and y */ { int nxder, nyder, i, j, k, nbytes; int order, maxorder1, maxorder2, nmove1, nmove2; struct IRAFsurface *sf2 = 0; double *ptr1, *ptr2; double zfit, norm; double wf_gseval(); if (sf1 == NULL) return (0.0); if (nxd < 0 || nyd < 0) { fprintf (stderr, "TNX_GSDER: order of derivatives cannot be < 0\n"); return (0.0); } if (nxd == 0 && nyd == 0) { zfit = wf_gseval (sf1, x, y); return (zfit); } /* Allocate space for new surface */ sf2 = (struct IRAFsurface *) malloc (sizeof (struct IRAFsurface)); /* Check the order of the derivatives */ nxder = MIN (nxd, sf1->xorder - 1); nyder = MIN (nyd, sf1->yorder - 1); /* Set up new surface */ sf2->type = sf1->type; /* Set the derivative surface parameters */ if (sf2->type == TNX_LEGENDRE || sf2->type == TNX_CHEBYSHEV || sf2->type == TNX_POLYNOMIAL) { sf2->xterms = sf1->xterms; /* Find the order of the new surface */ switch (sf2->xterms) { case TNX_XNONE: if (nxder > 0 && nyder > 0) { sf2->xorder = 1; sf2->yorder = 1; sf2->ncoeff = 1; } else if (nxder > 0) { sf2->xorder = MAX (1, sf1->xorder - nxder); sf2->yorder = 1; sf2->ncoeff = sf2->xorder; } else if (nyder > 0) { sf2->xorder = 1; sf2->yorder = MAX (1, sf1->yorder - nyder); sf2->ncoeff = sf2->yorder; } break; case TNX_XHALF: maxorder1 = MAX (sf1->xorder+1, sf1->yorder+1); order = MAX(1, MIN(maxorder1-1-nyder-nxder,sf1->xorder-nxder)); sf2->xorder = order; order = MAX(1, MIN(maxorder1-1-nyder-nxder,sf1->yorder-nyder)); sf2->yorder = order; order = MIN (sf2->xorder, sf2->yorder); sf2->ncoeff = sf2->xorder * sf2->yorder - (order*(order-1)/2); break; default: sf2->xorder = MAX (1, sf1->xorder - nxder); sf2->yorder = MAX (1, sf1->yorder - nyder); sf2->ncoeff = sf2->xorder * sf2->yorder; } /* define the data limits */ sf2->xrange = sf1->xrange; sf2->xmaxmin = sf1->xmaxmin; sf2->yrange = sf1->yrange; sf2->ymaxmin = sf1->ymaxmin; } else { fprintf (stderr, "TNX_GSDER: unknown surface type %d\n", sf2->type); return (0.0); } /* Allocate space for coefficients and basis functions */ nbytes = sf2->ncoeff * sizeof(double); sf2->coeff = (double *) malloc (nbytes); nbytes = sf2->xorder * sizeof(double); sf2->xbasis = (double *) malloc (nbytes); nbytes = sf2->yorder * sizeof(double); sf2->ybasis = (double *) malloc (nbytes); /* Get coefficients */ nbytes = sf1->ncoeff * sizeof(double); if (nbytes > nbcoeff) { if (nbcoeff > 0) coeff = (double *) realloc (coeff, nbytes); else coeff = (double *) malloc (nbytes); nbcoeff = nbytes; } (void) wf_gscoeff (sf1, coeff); /* Compute the new coefficients */ switch (sf2->xterms) { case TNX_XFULL: ptr2 = sf2->coeff + (sf2->yorder - 1) * sf2->xorder; ptr1 = coeff + (sf1->yorder - 1) * sf1->xorder; for (i = sf1->yorder - 1; i >= nyder; i--) { for (j = i; j >= i-nyder+1; j--) { for (k = 0; k < sf2->xorder; k++) ptr1[nxder+k] = ptr1[nxder+k] * (double)(j); } for (j = sf1->xorder; j >= nxder+1; j--) { for (k = j; k >= j-nxder+1; k--) ptr1[j-1] = ptr1[j-1] * (double)(k - 1); } for (j = 0; j < sf2->xorder; j++) ptr2[j] = ptr1[nxder+j]; ptr2 = ptr2 - sf2->xorder; ptr1 = ptr1 - sf1->xorder; } break; case TNX_XHALF: maxorder1 = MAX (sf1->xorder + 1, sf1->yorder + 1); maxorder2 = MAX (sf2->xorder + 1, sf2->yorder + 1); ptr2 = sf2->coeff + sf2->ncoeff; ptr1 = coeff + sf1->ncoeff; for (i = sf1->yorder; i >= nyder+1; i--) { nmove1 = MAX (0, MIN (maxorder1 - i, sf1->xorder)); nmove2 = MAX (0, MIN (maxorder2 - i + nyder, sf2->xorder)); ptr1 = ptr1 - nmove1; ptr2 = ptr2 - nmove2; for (j = i; j > i - nyder + 1; j--) { for (k = 0; k < nmove2; k++) ptr1[nxder+k] = ptr1[nxder+k] * (double)(j-1); } for (j = nmove1; j >= nxder+1; j--) { for (k = j; k >= j-nxder+1; k--) ptr1[j-1] = ptr1[j-1] * (double)(k - 1); } for (j = 0; j < nmove2; j++) ptr2[j] = ptr1[nxder+j]; } break; default: if (nxder > 0 && nyder > 0) sf2->coeff[0] = 0.0; else if (nxder > 0) { ptr1 = coeff; ptr2 = sf2->coeff + sf2->ncoeff - 1; for (j = sf1->xorder; j >= nxder+1; j--) { for (k = j; k >= j - nxder + 1; k--) ptr1[j-1] = ptr1[j-1] * (double)(k - 1); ptr2[0] = ptr1[j-1]; ptr2 = ptr2 - 1; } } else if (nyder > 0) { ptr1 = coeff + sf1->ncoeff - 1; ptr2 = sf2->coeff; for (i = sf1->yorder; i >= nyder + 1; i--) { for (j = i; j >= i - nyder + 1; j--) *ptr1 = *ptr1 * (double)(j - 1); ptr1 = ptr1 - 1; } for (i = 0; i < sf2->ncoeff; i++) ptr2[i] = ptr1[i+1]; } } /* evaluate the derivatives */ zfit = wf_gseval (sf2, x, y); /* normalize */ if (sf2->type != TNX_POLYNOMIAL) { norm = pow (sf2->xrange, (double)nxder) * pow (sf2->yrange, (double)nyder); zfit = norm * zfit; } /* free the space */ wf_gsclose (sf2); return (zfit); } /* wf_gsrestore -- procedure to restore the surface fit encoded in the image header as a list of double precision parameters and coefficients to the surface descriptor for use by the evaluating routines. the surface parameters, surface type, xorder (or number of polynomial terms in x), yorder (or number of polynomial terms in y), xterms, xmin, xmax and ymin and ymax, are stored in the first eight elements of the double array fit, followed by the wf->ncoeff surface coefficients. */ struct IRAFsurface * wf_gsrestore (fit) double *fit; /* array containing the surface parameters and coefficients */ { struct IRAFsurface *sf; /* surface descriptor */ int surface_type, xorder, yorder, order, i; double xmin, xmax, ymin, ymax; xorder = (int) (fit[TNX_SAVEXORDER] + 0.5); if (xorder < 1) { fprintf (stderr, "wf_gsrestore: illegal x order %d\n", xorder); return (NULL); } yorder = (int) (fit[TNX_SAVEYORDER] + 0.5); if (yorder < 1) { fprintf (stderr, "wf_gsrestore: illegal y order %d\n", yorder); return (NULL); } xmin = fit[TNX_SAVEXMIN]; xmax = fit[TNX_SAVEXMAX]; if (xmax <= xmin) { fprintf (stderr, "wf_gsrestore: illegal x range %f-%f\n",xmin,xmax); return (NULL); } ymin = fit[TNX_SAVEYMIN]; ymax = fit[TNX_SAVEYMAX]; if (ymax <= ymin) { fprintf (stderr, "wf_gsrestore: illegal y range %f-%f\n",ymin,ymax); return (NULL); } /* Set surface type dependent surface descriptor parameters */ surface_type = (int) (fit[TNX_SAVETYPE] + 0.5); if (surface_type == TNX_LEGENDRE || surface_type == TNX_CHEBYSHEV || surface_type == TNX_POLYNOMIAL) { /* allocate space for the surface descriptor */ sf = (struct IRAFsurface *) malloc (sizeof (struct IRAFsurface)); sf->xorder = xorder; sf->xrange = 2.0 / (xmax - xmin); sf->xmaxmin = - (xmax + xmin) / 2.0; sf->yorder = yorder; sf->yrange = 2.0 / (ymax - ymin); sf->ymaxmin = - (ymax + ymin) / 2.0; sf->xterms = fit[TNX_SAVEXTERMS]; switch (sf->xterms) { case TNX_XNONE: sf->ncoeff = sf->xorder + sf->yorder - 1; break; case TNX_XHALF: order = MIN (xorder, yorder); sf->ncoeff = sf->xorder * sf->yorder - order * (order-1) / 2; break; case TNX_XFULL: sf->ncoeff = sf->xorder * sf->yorder; break; } } else { fprintf (stderr, "wf_gsrestore: unknown surface type %d\n", surface_type); return (NULL); } /* Set remaining curve parameters */ sf->type = surface_type; /* Restore coefficient array */ sf->coeff = (double *) malloc (sf->ncoeff*sizeof (double)); for (i = 0; i < sf->ncoeff; i++) sf->coeff[i] = fit[TNX_SAVECOEFF+i]; /* Allocate space for basis vectors */ sf->xbasis = (double *) malloc (sf->xorder*sizeof (double)); sf->ybasis = (double *) malloc (sf->yorder*sizeof (double)); return (sf); } /* wf_gsb1pol -- procedure to evaluate all the non-zero polynomial functions for a single point and given order. */ static void wf_gsb1pol (x, order, basis) double x; /*i data point */ int order; /*i order of polynomial, order = 1, constant */ double *basis; /*o basis functions */ { int i; basis[0] = 1.0; if (order == 1) return; basis[1] = x; if (order == 2) return; for (i = 2; i < order; i++) basis[i] = x * basis[i-1]; return; } /* wf_gsb1leg -- procedure to evaluate all the non-zero legendre functions for a single point and given order. */ static void wf_gsb1leg (x, order, k1, k2, basis) double x; /*i data point */ int order; /*i order of polynomial, order = 1, constant */ double k1, k2; /*i normalizing constants */ double *basis; /*o basis functions */ { int i; double ri, xnorm; basis[0] = 1.0; if (order == 1) return; xnorm = (x + k1) * k2 ; basis[1] = xnorm; if (order == 2) return; for (i = 2; i < order; i++) { ri = i; basis[i] = ((2.0 * ri - 1.0) * xnorm * basis[i-1] - (ri - 1.0) * basis[i-2]) / ri; } return; } /* wf_gsb1cheb -- procedure to evaluate all the non-zero chebyshev function coefficients for a given x and order. */ static void wf_gsb1cheb (x, order, k1, k2, basis) double x; /*i number of data points */ int order; /*i order of polynomial, 1 is a constant */ double k1, k2; /*i normalizing constants */ double *basis; /*o array of basis functions */ { int i; double xnorm; basis[0] = 1.0; if (order == 1) return; xnorm = (x + k1) * k2; basis[1] = xnorm; if (order == 2) return; for (i = 2; i < order; i++) basis[i] = 2. * xnorm * basis[i-1] - basis[i-2]; return; } /* Set surface polynomial from arguments */ int tnxpset (wcs, xorder, yorder, xterms, coeff) struct WorldCoor *wcs; /* World coordinate system structure */ int xorder; /* Number of x coefficients (same for x and y) */ int yorder; /* Number of y coefficients (same for x and y) */ int xterms; /* Number of xy coefficients (same for x and y) */ double *coeff; /* Plate fit coefficients */ { double *ycoeff; struct IRAFsurface *wf_gspset (); wcs->prjcode = WCS_TNX; wcs->lngcor = wf_gspset (xorder, yorder, xterms, coeff); ycoeff = coeff + wcs->lngcor->ncoeff; wcs->latcor = wf_gspset (xorder, yorder, xterms, ycoeff); return 0; } /* wf_gspset -- procedure to set the surface descriptor for use by the evaluating routines. from arguments. The surface parameters are surface type, xorder (number of polynomial terms in x), yorder (number of polynomial terms in y), xterms, and the surface coefficients. */ struct IRAFsurface * wf_gspset (xorder, yorder, xterms, coeff) int xorder; int yorder; int xterms; double *coeff; { struct IRAFsurface *sf; /* surface descriptor */ int surface_type, order, i; double xmin, xmax; double ymin, ymax; surface_type = TNX_POLYNOMIAL; xmin = 0.0; xmax = 0.0; ymin = 0.0; ymax = 0.0; if (surface_type == TNX_LEGENDRE || surface_type == TNX_CHEBYSHEV || surface_type == TNX_POLYNOMIAL) { /* allocate space for the surface descriptor */ sf = (struct IRAFsurface *) malloc (sizeof (struct IRAFsurface)); sf->xorder = xorder; sf->xrange = 2.0 / (xmax - xmin); sf->xmaxmin = -(xmax + xmin) / 2.0; sf->yorder = yorder; sf->yrange = 2.0 / (ymax - ymin); sf->ymaxmin = - (ymax + ymin) / 2.0; sf->xterms = xterms; switch (sf->xterms) { case TNX_XNONE: sf->ncoeff = sf->xorder + sf->yorder - 1; break; case TNX_XHALF: order = MIN (xorder, yorder); sf->ncoeff = sf->xorder * sf->yorder - order * (order-1) / 2; break; case TNX_XFULL: sf->ncoeff = sf->xorder * sf->yorder; break; } } else { fprintf (stderr, "TNX_GSSET: unknown surface type %d\n", surface_type); return (NULL); } /* Set remaining curve parameters */ sf->type = surface_type; /* Restore coefficient array */ sf->coeff = (double *) malloc (sf->ncoeff*sizeof (double)); for (i = 0; i < sf->ncoeff; i++) sf->coeff[i] = coeff[i]; /* Allocate space for basis vectors */ sf->xbasis = (double *) malloc (sf->xorder*sizeof (double)); sf->ybasis = (double *) malloc (sf->yorder*sizeof (double)); return (sf); } /* Mar 26 1998 New subroutines, translated from SPP * Apr 28 1998 Change all local flags to TNX_* and projection flag to WCS_TNX * May 11 1998 Fix use of pole longitude default * Sep 4 1998 Fix missed assignment in tnxpos from Allen Harris, SAO * Sep 10 1998 Fix bugs in tnxpix() * Sep 10 1998 Fix missed assignment in tnxpix from Allen Harris, SAO * * Oct 22 1999 Drop unused variables, fix case statements after lint * Dec 10 1999 Fix bug in gsder() which failed to allocate enough memory * Dec 10 1999 Compute wcs->rot using wcsrotset() in tnxinit() * * Feb 14 2001 Fixed off-by-one bug in legendre evaluation (Mike Jarvis) * * Apr 11 2002 Fix bug when .-terminated substring in wf_gsopen() * Apr 29 2002 Clean up code * Jun 26 2002 Increase size of WAT strings from 500 to 2000 * * Jun 27 2005 Drop unused arguments k1 and k2 from wf_gsb1pol() * * Jan 8 2007 Drop unused variable ncoeff in wf_gsder() * Jan 9 2007 Declare header const char in tnxinit() * Apr 3 2007 Fix offsets to hit last cooefficient in wf_gsder() * * Sep 5 2008 Fix wf_gseval() call in tnxpos() so unmodified x and y are used * Sep 9 2008 Fix loop in TNX_XFULL section of wf_gsder() * (last two bugs found by Ed Los) * Sep 17 2008 Fix tnxpos for null correction case (fix by Ed Los) */ wcstools-3.9.5/libwcs/ty2read.c0000664000016200001660000011740413065034446015470 0ustar minkoirsys/*** File libwcs/ty2read.c *** March 23, 2017 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 2000-2017 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include #include #include #include "fitsfile.h" #include "wcs.h" #include "wcscat.h" #define MAXREG 10000 /* pathname of Tycho 2 CDROM or catalog search engine URL */ char ty2cd[64]="/data/astrocat/tycho2"; static double *gdist; /* Array of distances to stars */ static int ndist = 0; static int ty2reg(); static int ty2regn(); static int ty2zone(); static int ty2size(); struct StarCat *ty2open(); void ty2close(); static int ty2star(); static int ty2size(); /* TY2READ -- Read Tycho 2 Star Catalog stars from CDROM */ int ty2read (refcat,cra,cdec,dra,ddec,drad,dradi,distsort,sysout,eqout,epout, mag1,mag2,sortmag,nstarmax,gnum,gra,gdec,gpra,gpdec,gmag,gtype,nlog) int refcat; /* Catalog code from wcscat.h */ double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ double dradi; /* Inner edge of annulus in degrees (ignore if 0) */ int distsort; /* 1 to sort stars by distance from center */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 or 2) */ int nstarmax; /* Maximum number of stars to be returned */ double *gnum; /* Array of Guide Star numbers (returned) */ double *gra; /* Array of right ascensions (returned) */ double *gdec; /* Array of declinations (returned) */ double *gpra; /* Array of right ascension proper motions (returned) */ double *gpdec; /* Array of declination proper motions (returned) */ double **gmag; /* Array of b and v magnitudes (returned) */ int *gtype; /* Array of object types (returned) */ int nlog; /* 1 for diagnostics */ { double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ double dist = 0.0; /* Distance from search center in degrees */ double faintmag=0.0; /* Faintest magnitude */ double maxdist=0.0; /* Largest distance */ int faintstar=0; /* Faintest star */ int farstar=0; /* Most distant star */ int nreg = 0; /* Number of Tycho 2 regions in search */ int regnum[MAXREG]; /* List of region numbers */ int rlist[MAXREG]; /* List of first stars in regions */ int nlist[MAXREG]; /* List of number of stars per region */ char inpath[128]; /* Pathname for input region file */ int sysref = WCS_J2000; /* Catalog coordinate system */ double eqref = 2000.0; /* Catalog equinox */ double epref = 2000.0; /* Catalog epoch */ double secmarg = 60.0; /* Arcsec/century margin for proper motion */ struct StarCat *starcat; struct Star *star; int verbose; int wrap; int ireg; int ierr; int magsort, magsort1; int jstar, iw; int nrmax = MAXREG; int nstar,i, ntot; int istar, istar1, istar2; /* int isp; */ int pass; double num, ra, dec, rapm, decpm, mag, magb, magv, magve, magbe; double rra1, rra2, rra2a, rdec1, rdec2; double rdist, ddist; char cstr[32], rastr[32], decstr[32]; char *str; ntot = 0; if (nlog > 0) verbose = 1; else verbose = 0; /* If pathname is a URL, search and return */ if ((str = getenv("TY2_PATH")) == NULL ) str = ty2cd; else strncpy (ty2cd, str, 64); if (!strncmp (str, "http:",5)) { return (webread (ty2cd,"tycho2",distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nstarmax, gnum,gra,gdec,gpra,gpdec,gmag,gtype,nlog)); } wcscstr (cstr, sysout, eqout, epout); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* Make mag1 always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } if (sortmag == 2) { magsort = 0; magsort1 = 1; } else { magsort = 1; magsort1 = 0; } /* Allocate table for distances of stars from search center */ if (nstarmax > ndist) { if (ndist > 0) free ((void *)gdist); gdist = (double *) malloc (nstarmax * sizeof (double)); if (gdist == NULL) { fprintf (stderr,"TY2READ: cannot allocate separation array\n"); return (0); } ndist = nstarmax; } /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; nstar = 0; jstar = 0; /* Get RA and Dec limits in catalog (J2000) coordinates */ RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref, secmarg, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); if (wrap) { rra2a = rra2; rra2 = 360.0; } else { rra2a = 0; } /* Write header if printing star entries as found */ if (nstarmax < 1) { char *revmessage; revmessage = getrevmsg(); printf ("catalog Tycho-2\n"); ra2str (rastr, 31, cra, 3); printf ("ra %s\n", rastr); dec2str (decstr, 31, cdec, 2); printf ("dec %s\n", decstr); printf ("rpmunit mas/year\n"); printf ("dpmunit mas/year\n"); if (drad != 0.0) { printf ("radmin %.1f\n", drad*60.0); if (dradi > 0) printf ("radimin %.1f\n", dradi*60.0); } else { printf ("dramin %.1f\n", dra*60.0* cosdeg (cdec)); printf ("ddecmin %.1f\n", ddec*60.0); } printf ("radecsys %s\n", cstr); printf ("equinox %.3f\n", eqout); printf ("epoch %.3f\n", epout); printf ("program scat %s\n", revmessage); printf ("tycho2_id ra dec "); printf (" magb magv"); if (refcat == TYCHO2E) printf (" magbe magve"); printf (" ura udec arcmin\n"); printf ("---------- ------------ ------------"); printf (" ----- -----"); if (refcat == TYCHO2E) printf (" ----- -----"); printf (" ------ ------ ------\n"); } /* If searching through RA = 0:00, split search in two */ for (iw = 0; iw <= wrap; iw++) { /* Find Tycho 2 Star Catalog regions in which to search */ nreg = ty2reg (rra1,rra2,rdec1,rdec2,nrmax,regnum,rlist,nlist,verbose); if (nreg <= 0) { fprintf (stderr,"TY2READ: no Tycho 2 region for %.2f-%.2f %.2f %.2f\n", rra1, rra2, rdec1, rdec2); rra1 = 0.0; rra2 = rra2a; continue; } /* Loop through region list */ for (ireg = 0; ireg < nreg; ireg++) { /* Open catalog file for this region */ istar1 = rlist[ireg]; istar2 = istar1 + nlist[ireg]; if (verbose) fprintf (stderr,"TY2READ: Searching stars %d through %d\n", istar1, istar2-1); /* Open file for this region of Tycho 2 catalog */ starcat = ty2open (rlist[ireg], nlist[ireg]); if (starcat == NULL) { fprintf (stderr,"TY2READ: File %s not found\n",inpath); return (0); } /* Loop through catalog for this region */ for (istar = istar1; istar < istar2; istar++) { if ((ierr = ty2star (starcat, star, istar))) { /* fprintf (stderr,"TY2READ: Cannot read star %d\n", istar); */ if (ierr < 3) break; else continue; } /* ID number */ num = star->num; /* Magnitude */ magb = star->xmag[0]; magv = star->xmag[1]; magbe = star->xmag[2]; magve = star->xmag[3]; mag = star->xmag[magsort]; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; /* Check position limits */ if (pass) { /* Get position in output coordinate system */ rapm = star->rapm; decpm = star->decpm; ra = star->ra; dec = star->dec; wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); /* Compute distance from search center */ if (drad > 0 || distsort) dist = wcsdist (cra,cdec,ra,dec); else dist = 0.0; /* Check radial distance to search center */ if (drad > 0) { if (dist > drad) pass = 0; if (dradi > 0.0 && dist < dradi) pass = 0; } /* Check distance along RA and Dec axes */ else { ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } } if (pass) { /* Spectral Type isp = (1000 * (int) star->isp[0]) + (int)star->isp[1]; */ /* Write star position and magnitudes to stdout */ if (nstarmax < 1) { ra2str (rastr, 31, ra, 3); dec2str (decstr, 31, dec, 2); dist = wcsdist (cra,cdec,ra,dec) * 60.0; printf ("%010.5f %s %s", num,rastr,decstr); printf (" %5.2f %5.2f", magb, magv); if (refcat == TYCHO2E) printf (" %5.2f %5.2f", magbe, magve); printf (" %6.1f %6.1f %.2f\n", rapm * 3600000.0 * cosdeg(dec), decpm * 3600000.0, dist / 60.0); } /* Save star position and magnitude in table */ if (nstar < nstarmax) { gnum[nstar] = num; gra[nstar] = ra; gdec[nstar] = dec; gpra[nstar] = rapm; gpdec[nstar] = decpm; gmag[0][nstar] = magb; gmag[1][nstar] = magv; if (refcat == TYCHO2E) { gmag[2][nstar] = star->xmag[2]; gmag[3][nstar] = star->xmag[3]; } gdist[nstar] = dist; if (dist > maxdist) { maxdist = dist; farstar = nstar; } if (mag > faintmag) { faintmag = mag; faintstar = nstar; } } /* If too many stars and distance sorting, replace farthest star */ else if (distsort) { if (dist < maxdist) { gnum[farstar] = num; gra[farstar] = ra; gdec[farstar] = dec; gpra[farstar] = rapm; gpdec[farstar] = decpm; gmag[0][farstar] = magb; gmag[1][farstar] = magv; if (refcat == TYCHO2E) { gmag[2][farstar] = star->xmag[2]; gmag[3][farstar] = star->xmag[3]; } gdist[farstar] = dist; /* Find new farthest star */ maxdist = 0.0; for (i = 0; i < nstarmax; i++) { if (gdist[i] > maxdist) { maxdist = gdist[i]; farstar = i; } } } } /* Else if too many stars, replace faintest star */ else if (mag < faintmag) { gnum[faintstar] = num; gra[faintstar] = ra; gdec[faintstar] = dec; gpra[faintstar] = rapm; gpdec[faintstar] = decpm; gmag[0][faintstar] = magb; gmag[1][faintstar] = magv; if (refcat == TYCHO2E) { gmag[2][faintstar] = star->xmag[2]; gmag[3][faintstar] = star->xmag[3]; } gdist[faintstar] = dist; faintmag = 0.0; /* Find new faintest star */ for (i = 0; i < nstarmax; i++) { if (gmag[magsort1][i] > faintmag) { faintmag = gmag[magsort1][i]; faintstar = i; } } } nstar++; if (nlog == 1) fprintf (stderr,"TY2READ: %11.6f: %9.5f %9.5f %5.2f %5.2f\n", num,ra,dec,magb,magv); /* End of accepted star processing */ } /* Log operation */ jstar++; if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"TY2READ: %5d / %5d / %5d sources\r", nstar,jstar,starcat->nstars); /* End of star loop */ } ntot = ntot + starcat->nstars; if (nlog > 0) fprintf (stderr,"TY2READ: %4d / %4d: %5d / %5d / %5d sources from region %4d \n", ireg+1,nreg,nstar,jstar,starcat->nstars,regnum[ireg]); /* Close region input file */ ty2close (starcat); } rra1 = 0.0; rra2 = rra2a; } /* close output file and summarize transfer */ if (nlog > 0) { if (nreg > 1) fprintf (stderr,"TY2READ: %d regions: %d / %d found\n",nreg,nstar,ntot); else fprintf (stderr,"TY2READ: 1 region: %d / %d found\n",nstar,ntot); if (nstar > nstarmax) fprintf (stderr,"TY2READ: %d stars found; only %d returned\n", nstar,nstarmax); } return (nstar); } /* TY2RNUM -- Read HST Guide Star Catalog stars from CDROM */ int ty2rnum (refcat, nstars,sysout,eqout,epout, gnum,gra,gdec,gpra,gpdec,gmag,gtype,nlog) int refcat; /* Catalog code from wcscat.h */ int nstars; /* Number of stars to find */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double *gnum; /* Array of Guide Star numbers (returned) */ double *gra; /* Array of right ascensions (returned) */ double *gdec; /* Array of declinations (returned) */ double *gpra; /* Array of right ascension proper motions (returned) */ double *gpdec; /* Array of declination proper motions (returned) */ double **gmag; /* Array of B and V magnitudes (returned) */ int *gtype; /* Array of object types (returned) */ int nlog; /* 1 for diagnostics */ { char inpath[128]; /* Pathname for input region file */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ struct StarCat *starcat; struct Star *star; char *str; int verbose; int rnum; int ierr; int jstar; int istar, istar1, istar2, jstar1, jstar2, nstar; /* int isp; */ double num, ra, dec, rapm, decpm, magb, magv; if (nlog == 1) verbose = 1; else verbose = 0; /* If pathname is a URL, search and return */ if ((str = getenv("TY2_PATH")) == NULL ) str = ty2cd; if (!strncmp (str, "http:",5)) return (webrnum (str,"tycho2",nstars,sysout,eqout,epout,1, gnum,gra,gdec,gpra,gpdec,gmag,gtype,nlog)); /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; nstar = 0; /* Loop through star list */ for (jstar = 0; jstar < nstars; jstar++) { rnum = (int) (gnum[jstar] + 0.0000001); /* Find numbered stars (rrrr.nnnnnn) */ if (gnum[jstar]-(double)rnum > 0.0000001) { ty2regn (rnum, &istar1, &istar2, verbose); nstar = istar2 - istar1 + 1; starcat = ty2open (istar1, nstar); if (starcat == NULL) { fprintf (stderr,"TY2RNUM: File %s not found\n",inpath); return (0); } for (istar = istar1; istar < istar2; istar++) { if ((ierr = ty2star (starcat, star, istar))) { /* fprintf (stderr,"TY2RNUM: Cannot read star %d\n", istar); */ gra[jstar] = 0.0; gdec[jstar] = 0.0; gmag[0][jstar] = 0.0; gmag[1][jstar] = 0.0; gmag[2][jstar] = 0.0; gmag[3][jstar] = 0.0; gtype[jstar] = 0; if (ierr < 3) break; } else { if (fabs (gnum[jstar] - star->num) < 0.0000005) break; } } ty2close (starcat); } /* Find nth sequential stars in catalog (not rrrr.nnnnn) */ else { /* Find out whether file has CR/LF or LF only at end of lines */ rnum = 1; ty2regn (rnum, &jstar1, &jstar2, verbose); istar = (int) (gnum[jstar] + 0.01); starcat = ty2open (istar, 10); if (starcat == NULL) { fprintf (stderr,"TY2RNUM: File %s not found\n",inpath); return (0); } if ((ierr = ty2star (starcat, star, istar))) { /* fprintf (stderr,"TY2RNUM: Cannot read star %d\n", istar); */ gra[jstar] = 0.0; gdec[jstar] = 0.0; gmag[0][jstar] = 0.0; gmag[1][jstar] = 0.0; if (refcat == TYCHO2E) { gmag[2][jstar] = 0.0; gmag[3][jstar] = 0.0; } gtype[jstar] = 0; if (ierr < 3) break; else continue; } ty2close (starcat); } /* If star has been found in catalog */ /* ID number */ num = star->num; /* Position in degrees at designated epoch */ ra = star->ra; dec = star->dec; rapm = star->rapm; decpm = star->decpm; wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); /* Magnitude */ magb = star->xmag[0]; magv = star->xmag[1]; /* Spectral Type isp = (1000 * (int) star->isp[0]) + (int)star->isp[1]; */ /* Save star position and magnitude in table */ gnum[jstar] = num; gra[jstar] = ra; gdec[jstar] = dec; gpra[jstar] = rapm; gpdec[jstar] = decpm; gmag[0][jstar] = magb; gmag[1][jstar] = magv; if (refcat == TYCHO2E) { gmag[2][jstar] = star->xmag[2]; gmag[3][jstar] = star->xmag[3]; } /* gtype[jstar] = isp; */ if (nlog == 1) fprintf (stderr,"TY2RNUM: %11.6f: %9.5f %9.5f %5.2f %5.2f %s \n", num, ra, dec, magb, magv, star->isp); /* End of star loop */ } /* Summarize search */ if (nlog > 0) fprintf (stderr,"TY2RNUM: %d / %d found\n", nstar, nstars); return (nstars); } /* TY2BIN -- Read Tycho 2 Star Catalog stars from CDROM */ int ty2bin (wcs, header, image, mag1, mag2, sortmag, magscale, nlog) struct WorldCoor *wcs; /* World coordinate system for image */ char *header; /* FITS header for output image */ char *image; /* Output FITS image */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 or 2) */ double magscale; /* Scaling factor for magnitude to pixel flux * (number of catalog objects per bin if 0) */ int nlog; /* 1 for diagnostics */ { double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ int nreg = 0; /* Number of Tycho 2 regions in search */ int regnum[MAXREG]; /* List of region numbers */ int rlist[MAXREG]; /* List of first stars in regions */ int nlist[MAXREG]; /* List of number of stars per region */ char inpath[128]; /* Pathname for input region file */ int sysref = WCS_J2000; /* Catalog coordinate system */ double eqref = 2000.0; /* Catalog equinox */ double epref = 2000.0; /* Catalog epoch */ double secmarg = 60.0; /* Arcsec/century margin for proper motion */ struct StarCat *starcat; struct Star *star; int verbose; int wrap; int ireg; int ierr; int magsort; int jstar, iw; int nrmax = MAXREG; int nstar, ntot; int istar, istar1, istar2; int pass; double num, ra, dec, mag, magb, magv; double rra1, rra2, rra2a, rdec1, rdec2; char cstr[32]; char *str; double xpix, ypix, flux; int ix, iy, offscl; int bitpix, w, h; /* Image bits/pixel and pixel width and height */ double logt = log(10.0); /* Get image dimensions */ bitpix = 0; (void)hgeti4 (header,"BITPIX",&bitpix); w = 0; (void)hgeti4 (header,"NAXIS1",&w); h = 0; (void)hgeti4 (header,"NAXIS2",&h); if (bitpix * w * h < 1) { fprintf (stderr, "TY2BIN: No pixels in image = %d bytes x %d x %d\n", bitpix, w, h); return (0); } ntot = 0; if (nlog > 0) verbose = 1; else verbose = 0; /* If pathname is a URL, search and return */ if ((str = getenv("TY2_PATH")) != NULL ) strncpy (ty2cd, str, 64); /* Set catalog search limits from image WCS information */ sysout = wcs->syswcs; eqout = wcs->equinox; epout = wcs->epoch; wcscstr (cstr, sysout, eqout, epout); wcssize (wcs, &cra, &cdec, &dra, &ddec); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* Make mag1 always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } if (sortmag == 2) magsort = 0; else magsort = 1; /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; nstar = 0; jstar = 0; /* Get RA and Dec limits in catalog (J2000) coordinates */ RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref, secmarg, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); if (wrap) { rra2a = rra2; rra2 = 360.0; } else { rra2a = 0.0; } /* If searching through RA = 0:00, split search in two */ for (iw = 0; iw <= wrap; iw++) { /* Find Tycho 2 Star Catalog regions in which to search */ nreg = ty2reg (rra1,rra2,rdec1,rdec2,nrmax,regnum,rlist,nlist,verbose); if (nreg <= 0) { fprintf (stderr,"TY2BIN: no Tycho 2 region for %.2f-%.2f %.2f %.2f\n", rra1, rra2, rdec1, rdec2); rra1 = 0.0; rra2 = rra2a; continue; } /* Loop through region list */ for (ireg = 0; ireg < nreg; ireg++) { /* Open catalog file for this region */ istar1 = rlist[ireg]; istar2 = istar1 + nlist[ireg]; /* if (verbose) fprintf (stderr,"TY2BIN: Searching stars %d through %d\n", istar1, istar2-1); */ /* Open file for this region of Tycho 2 catalog */ starcat = ty2open (rlist[ireg], nlist[ireg]); if (starcat == NULL) { fprintf (stderr,"TY2BIN: File %s not found\n",inpath); return (0); } /* Loop through catalog for this region */ for (istar = istar1; istar < istar2; istar++) { if ((ierr = ty2star (starcat, star, istar))) { /* fprintf (stderr,"TY2BIN: Cannot read star %d\n", istar); */ if (ierr < 3) break; else continue; } /* ID number */ num = star->num; ra = star->ra; dec = star->dec; /* Magnitude */ magb = star->xmag[0]; magv = star->xmag[1]; mag = star->xmag[magsort]; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; /* If this star was searched in first pass, skip it */ if (iw > 0 && ra > rra2) pass = 0; /* Save star in FITS image */ if (pass) { wcs2pix (wcs, ra, dec, &xpix, &ypix, &offscl); if (!offscl) { if (magscale > 0.0) flux = magscale * exp (logt * (-mag / 2.5)); else flux = 1.0; ix = (int) (xpix + 0.5); iy = (int) (ypix + 0.5); addpix1 (image, bitpix, w,h, 0.0,1.0, xpix,ypix, flux); nstar++; jstar++; } else { ix = 0; iy = 0; } if (nlog == 1) { fprintf (stderr,"TY2BIN: %11.5f: %9.5f %9.5f %s", num,ra,dec,cstr); if (magscale > 0.0) fprintf (stderr, " %5.2f", mag); if (!offscl) flux = getpix1 (image, bitpix, w, h, 0.0, 1.0, ix, iy); else flux = 0.0; fprintf (stderr," (%d,%d): %f\n", ix, iy, flux); } /* End of accepted star processing */ } /* Log operation jstar++; if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"TY2BIN: %5d / %5d / %5d sources\r", nstar,jstar,starcat->nstars); End of star loop */ } ntot = ntot + starcat->nstars; if (nlog > 0) fprintf (stderr,"TY2BIN: %4d / %4d: %5d / %5d / %5d sources from region %4d \r", ireg+1,nreg,nstar,jstar,starcat->nstars,regnum[ireg]); /* Close region input file */ ty2close (starcat); } rra1 = 0.0; rra2 = rra2a; } /* close output file and summarize transfer */ if (nlog > 0) { if (nreg > 1) fprintf (stderr,"\nTY2BIN: %d regions: %d / %d found\n",nreg,nstar,ntot); else fprintf (stderr,"\nTY2BIN: 1 region: %d / %d found\n",nstar,ntot); } return (nstar); } /* Tycho 2 region index for ty2regn() and ty2reg() */ /* First region in each declination zone */ static int treg1[24]={9490,9346,9134,8840,8464,8022,7523,6989,6412,5838,5260,4663, 1,594,1178,1729,2259,2781,3246,3652,4014,4294,4492,4615}; /* Last region in each declination zone */ static int treg2[24]={9537,9489,9345,9133,8839,8463,8021,7522,6988,6411,5837,5259, 593,1177,1728,2258,2780,3245,3651,4013,4293,4491,4614,4662}; static int indnchar = 0; /* Number of characters per line in table */ /* TY2REGN -- read the range of stars in a region from the Tycho 2 Catalog * index table. */ static int ty2regn (region, star1, star2, verbose) int region; /* Region to find */ int *star1; /* First star number in region (returned)*/ int *star2; /* Last star number in region (returned)*/ int verbose; /* 1 for diagnostics */ { char *tabpath; /* Pathname for regions table */ char *buffer; /* Buffer to hold index table */ char *line; char *str; char lf=(char)10; int deczone; int lpath; *star1 = 0; *star2 = 0; /* Find declination zone(s) in which this region exists */ for (deczone = 0; deczone < 24; deczone++) { if (region >= treg1[deczone] && region <= treg2[deczone]) break; } if (deczone > 24) return (0); /* Set path to Tycho 2 Catalog CDROM */ if ((str = getenv("TY2_PATH")) != NULL ) { lpath = strlen (str) + 16; tabpath = (char *) malloc (lpath); strcpy (tabpath, str); } else { lpath = strlen (ty2cd) + 16; tabpath = (char *) malloc (lpath); strcpy (tabpath, ty2cd); } /* Set pathname for index table file */ strcat (tabpath,"/data/index.dat"); /* Read the index table */ if ((buffer = getfilebuff (tabpath)) == NULL) { fprintf (stderr,"TY2REG: error reading region table %s\n",tabpath); return (0); } /* Figure out whether index file has LF or CRLF at end of lines */ if (buffer[42] == lf) indnchar = 43; else indnchar = 44; /* Read first star from regionth line of region table */ line = buffer + ((region - 1) * indnchar); *star1 = atoi (line); /* Read last star + 1 from region+1th line of region table */ *star2 = atoi (line+indnchar); free (buffer); free (tabpath); return (1); } /* TY2REG -- search the Tycho 2 Catalog index table for fields * in the specified range of coordinates and magnitudes. * Build lists containing the first star and number of stars for each range. */ static int ty2reg (ra1, ra2, dec1, dec2, nrmax, regnum, rstar, nstar, verbose) double ra1, ra2; /* Right ascension limits in degrees */ double dec1, dec2; /* Declination limits in degrees */ int nrmax; /* Maximum number of regions to find */ int *regnum; /* Region numbers (returned)*/ int *rstar; /* Region first star numbers (returned)*/ int *nstar; /* Region numbers of stars (returned)*/ int verbose; /* 1 for diagnostics */ { int nrgn; /* Number of regions found (returned) */ char *tabpath; /* Pathname for regions table */ char *buffer; /* Buffer to hold index table */ char *line; char *str; char lf=(char)10; int nwrap; /* 1 if 0h included in RA span*/ int iwrap; int num1, num2; int irow,iz1,iz2,jr1,jr2,i; int ir1 = 0; int ir2 = 0; int nsrch,nsrch1; double ralow, rahi; double declow, dechi, decmin, decmax; for (i = 0; i < nrmax; i++) { rstar[i] = 0; nstar[i] = 0; } nrgn = 0; /* Set path to Tycho 2 Catalog CDROM */ if ((str = getenv("TY2_PATH")) != NULL ) { tabpath = (char *) malloc (strlen (str) + 16); strcpy (tabpath, str); } else { tabpath = (char *) malloc (strlen (ty2cd) + 16); strcpy (tabpath, ty2cd); } /* Set pathname for index table file */ strcat (tabpath,"/data/index.dat"); /* Read the index table */ if ((buffer = getfilebuff (tabpath)) == NULL) { fprintf (stderr,"TY2REG: error reading region table %s\n",tabpath); return (0); } /* Figure out whether index file has LF or CRLF at end of lines */ if (buffer[42] == lf) indnchar = 43; else indnchar = 44; /* Find region range to search based on declination */ iz1 = ty2zone (dec1); iz2 = ty2zone (dec2); jr1 = 0; jr2 = 0; nwrap = 1; /* Search in only one region */ if (iz1 == iz2) { ir1 = treg1[iz1]; ir2 = treg2[iz1]; } /* Search region in northern hemisphere */ if (dec1 >= 0 && dec2 >= 0) { if (dec1 < dec2) { ir1 = treg1[iz1]; ir2 = treg2[iz2]; } else { ir1 = treg1[iz2]; ir2 = treg2[iz1]; } } /* Search region in southern hemisphere with multiple regions */ else if (dec1 < 0 && dec2 < 0) { if (dec1 < dec2) { ir1 = treg1[iz2]; ir2 = treg2[iz1]; } else { ir1 = treg1[iz1]; ir2 = treg2[iz2]; } } /* Search region spans equator */ else if (dec1 < 0 && dec2 >= 0) { nwrap = 2; /* southern part */ jr1 = treg1[11]; jr2 = treg2[iz1]; /* northern part */ ir1 = treg1[12]; ir2 = treg2[iz2]; } nsrch = ir2 - ir1 + 1; if (verbose) fprintf (stderr,"TY2REG: searching %d regions: %d - %d\n",nsrch,ir1,ir2); if (jr1 > 0) { nsrch1 = jr2 - jr1 + 1; if (verbose) fprintf (stderr,"TY2REG: searching %d regions: %d - %d\n",nsrch1,jr1,jr2); } if (verbose) fprintf(stderr,"TY2REG: RA: %.5f - %.5f, Dec: %.5f - %.5f\n",ra1,ra2,dec1,dec2); nrgn = 0; for (iwrap = 0; iwrap < nwrap; iwrap++) { for (irow = ir1 - 1; irow < ir2; irow++) { /* Read next line of region table */ line = buffer + (irow * indnchar); /* Declination range of the gs region */ /* note: southern dechi and declow are reversed */ num1 = atoi (line); num2 = atoi (line+indnchar); dechi = atof (line + 29); declow = atof (line + 36); if (dechi > declow) { decmin = declow - 0.1; decmax = dechi + 0.1; } else { decmax = declow + 0.1; decmin = dechi - 0.1; } if (decmax >= dec1 && decmin <= dec2) { /* Right ascension range of the Guide Star Catalog region */ ralow = atof (line + 15) - 0.1; if (ralow <= 0.0) ralow = 0.0; rahi = atof (line + 22) + 0.1; if (rahi > 360.0) rahi = 360.0; if (rahi <= 0.0) rahi = 360.0; /* Check RA if 0h RA not between region RA limits */ if (ra1 < ra2) { /* Add this region to list, if there is space */ if (ralow <= ra2 && rahi >= ra1) { /* if (verbose) fprintf (stderr,"TY2REG: Region %d added to search\n",irow); */ if (nrgn < nrmax) { regnum[nrgn] = irow; rstar[nrgn] = num1; nstar[nrgn] = num2 - num1; nrgn = nrgn + 1; } } } /* Check RA if 0h RA is between region RA limits */ else { if (ralow > rahi) rahi = rahi + 360.0; if (ralow <= ra2 || rahi >= ra1) { /* Add this region to list, if there is space */ /* if (verbose) fprintf (stderr,"TY2REG: Region %d added to search\n", irow); */ if (nrgn < nrmax) { regnum[nrgn] = irow; rstar[nrgn] = num1; nstar[nrgn] = num2 - num1; nrgn = nrgn + 1; } } } } } /* Handle wrap-around through the equator */ ir1 = jr1; ir2 = jr2; jr1 = 0; jr2 = 0; } free (buffer); return (nrgn); } /* TY2ZONE -- find the zone number where a declination can be found */ static int ty2zone (dec) double dec; /* declination in degrees */ { int zone; /* gsc zone (returned) */ double zonesize; int ndeczones = 12; /* number of declination zones per hemisphere */ double zdec = dec + 90.0; /* width of declination zones */ zonesize = 90.0 / ndeczones; zone = (int) (zdec / zonesize); if (zone < 0) zone = 0; if (zone > 23) zone = 23; return (zone); } /* TY2OPEN -- Open Tycho 2 catalog file, returning number of entries */ struct StarCat * ty2open (nstar, nread) int nstar; /* Number of first star to read */ int nread; /* Number of star entries to read */ { FILE *fcat; struct StarCat *sc; int lfile, lpath; int lread, lskip, nr; char *str; char *ty2file; char *ty2path; /* Full pathname for catalog file */ /* Set path to Tycho 2 Catalog CDROM */ if ((str = getenv("TY2_PATH")) != NULL ) { lpath = strlen(str) + 18; ty2path = (char *) malloc (lpath); strcpy (ty2path, str); } else { lpath = strlen(ty2cd) + 18; ty2path = (char *) malloc (lpath); strcpy (ty2path, ty2cd); } /* Set pathname for catalog file */ strcat (ty2path, "/data/catalog.dat"); /* Find length of Tycho 2 catalog file */ lfile = ty2size (ty2path); /* Check for existence of catalog */ if (lfile < 2) { fprintf (stderr,"TY2OPEN: Binary catalog %s has no entries\n",ty2path); free (ty2path); return (NULL); } /* Open Tycho 2 file */ if (!(fcat = fopen (ty2path, "r"))) { fprintf (stderr,"TY2OPEN: Tycho 2 file %s cannot be read\n",ty2path); free (ty2path); return (0); } /* Set Tycho 2 catalog header information */ sc = (struct StarCat *) calloc (1, sizeof (struct StarCat)); sc->byteswapped = 0; if (indnchar == 44) sc->nbent = 208; else sc->nbent = 207; sc->nstars = lfile / sc->nbent; /* Separate filename from pathname and save in structure */ ty2file = strrchr (ty2path,'/'); if (ty2file) ty2file = ty2file + 1; else ty2file = ty2path; if (strlen (ty2file) < 24) strcpy (sc->isfil, ty2file); else strncpy (sc->isfil, ty2file, 23); /* Set other catalog information in structure */ sc->inform = 'J'; sc->coorsys = WCS_J2000; sc->epoch = 2000.0; sc->equinox = 2000.0; sc->ifcat = fcat; sc->sptype = 2; /* Tycho 2 stars are not RA-sorted within regions */ sc->rasorted = 0; /* Read part of catalog into a buffer */ lread = nread * sc->nbent; lskip = (nstar - 1) * sc->nbent; sc->catdata = NULL; if ((sc->catdata = calloc (1, lread+1)) != NULL) { fseek (fcat, lskip, 0); nr = fread (sc->catdata, 1, lread, fcat); if (nr < lread) { fprintf (stderr,"TY2OPEN: Read %d / %d bytes\n", nr, lread); ty2close (sc); free (ty2path); return (NULL); } sc->catlast = sc->catdata + lread; } else { fprintf (stderr,"TY2OPEN: Cannot allocate %d-byte buffer.\n", lread); ty2close (sc); free (ty2path); return (NULL); } sc->istar = nstar; free (ty2path); return (sc); } void ty2close (sc) struct StarCat *sc; /* Star catalog descriptor */ { fclose (sc->ifcat); if (sc->catdata != NULL) free (sc->catdata); free (sc); return; } /* TY2STAR -- Get Tycho 2 catalog entry for one star; return 0 if successful */ static int ty2star (sc, st, istar) struct StarCat *sc; /* Star catalog descriptor */ struct Star *st; /* Current star entry */ int istar; /* Star sequence number in Tycho 2 catalog region file */ { char *line; double regnum, starnum, multnum; /* Drop out if catalog pointer is not set */ if (sc == NULL) { fprintf (stderr, "TY2STAR: Catalog pointer not set\n"); return (1); } /* Drop out if catalog is not open */ if (sc->ifcat == NULL) { fprintf (stderr, "TY2STAR: Catalog is not open\n"); return (2); } /* Drop out if star number is too large */ if (istar > sc->nstars) { fprintf (stderr, "TY2STAR: %d > %d is not in catalog\n", istar, sc->nstars); return (3); } /* Move buffer pointer to start of correct star entry */ if (istar > 0) { line = sc->catdata + ((istar - sc->istar) * sc->nbent); if (line >= sc->catlast) { fprintf (stderr, "TY2STAR: star %d past buffer\n", istar); return (4); } } else { line = sc->catdata; } /* Read catalog entry */ if (sc->nbent > sc->catlast-line) { fprintf (stderr, "TY2STAR: %d / %d bytes read for star %d\n", sc->catlast - line, sc->nbent, istar); return (5); } regnum = atof (line); starnum = atof (line+5); multnum = atof (line+11); st->num = regnum + (0.00001 * starnum) + (0.000001 * multnum); /* For Ed: if (starnum > 9999.0) { st->num = regnum + (0.00001 * starnum) + (0.000001 * multnum) } else { st->num = regnum + (0.0001 * starnum) + (0.00001 * multnum); } */ if (line[13] == 'X') { fprintf (stderr, "TY2STAR: No position for star %010.6f\n", st->num); return (6); } /* Read position in degrees */ st->ra = atof (line+15); st->dec = atof (line+28); /* Read proper motion and convert it to degrees (of RA and Dec) per year */ st->rapm = (atof (line+41) / 3600000.0) / cosdeg (st->dec); st->decpm = atof (line+49) / 3600000.0; /* Set B magnitude and error */ st->xmag[0] = atof (line+110); st->xmag[2] = atof (line+117); /* Set V magnitude and error */ st->xmag[1] = atof (line+123); st->xmag[3] = atof (line+130); /* Set main sequence spectral type st->isp[0] = (char)0; st->isp[1] = (char)0; bv2sp (NULL, st->xmag[1], st->xmag[0], st->isp); */ return (0); } /* TY2SIZE -- return size of Tycho 2 catalog file in bytes */ static int ty2size (filename) char *filename; /* Name of file for which to find size */ { FILE *diskfile; long filesize; /* Open file */ if ((diskfile = fopen (filename, "r")) == NULL) { return (-1); } /* Move to end of the file */ if (fseek (diskfile, 0, 2) == 0) { /* Position is the size of the file */ filesize = ftell (diskfile); } else { filesize = -1; } fclose (diskfile); return (filesize); } /* Jun 2 2000 New program, based on actread.c and gscread.c * Jun 13 2000 Correctly order magnitudes: 0=V, 1=B * Jun 26 2000 Add coordinate system to SearchLim() arguments * Sep 25 2000 Set sc->sptype to 2 to indicate presence of spectral type * Nov 29 2000 Add option to read catalog using HTTP * Dec 11 2000 Accept catalog search engine URL in ty2cd[] * * Jan 11 2001 All printing goes to stderr * Jun 14 2001 Drop spectral type approximation * Jun 15 2001 In ty2reg(), add 0.1 to tabulated region limits * Jun 19 2001 When no region found, print RA and Dec limits used * Jun 27 2001 Allocate gdist only if needed * Sep 11 2001 Change to single magnitude argeument * Sep 11 2001 Add sort magnitude argument to uacread() * Nov 20 2001 Change cos(degrad()) to cosdeg() * Dec 3 2001 Change default directory to /data/astrocat/tycho2 * * Apr 3 2002 Fix bug so magnitude filtering is actually done (all passed) * Apr 8 2002 Fix uninitialized variable * Apr 10 2002 Separate catalog and output sort mags (in:vb out: bv) * Oct 3 2002 Print stars as found in ty2read() if nstarmax < 1 * * Feb 3 2003 Include math.h because of fabs() * Feb 27 2003 Add 60 arcsec/century to margins of search box to get moving stars * Mar 11 2003 Fix position limit testing * Apr 3 2003 Drop unused variables after lint * Apr 14 2003 Explicitly get revision date if nstarmax < 1 * Jun 2 2003 Print proper motion as mas/year * Aug 8 2003 Increase MAXREG from 100 to 1000 * Aug 22 2003 Add radi argument for inner edge of search annulus * Sep 26 2003 Add ty2bin() to fill an image with sources * Sep 29 2003 Rewrite zone computation to deal with +-90 correctly * Oct 1 2003 Use wcs2pix() to decide whether to accept position in ty2bin() * Oct 6 2003 Update ty2read() and ty2bin() for improved RefLim() * Nov 18 2003 Fix bugs in ty2bin() * Dec 1 2003 Add missing tab to n=-1 header * * Apr 30 2004 Allow either LF or CRLF at end of lines in index and catalog * * May 18 2005 Add magnitude errors * Aug 5 2005 Make magnitude errors an option if refcat is TYCHO2E * * Apr 3 2006 Add refcat definition to ty2rnum() * Jun 20 2006 Initialize uninitialized variables * Oct 5 2006 Fix order of magnitudes to Bt-Vt from Vt-Bt * Nov 16 2006 Fix binning * * Jan 10 2007 Add dradi argument to webread() call * Jan 10 2007 Add match=1 argument to webrnum() * Jan 10 2007 Rewrite web access in ty2rnum() to reduce code * Jul 6 2007 Skip stars with no positions (=unfound Guide Stars?) * Jul 6 2007 Skip stars with entry read errors; stop if catalog problem * Jul 6 2007 Print read errors in ty2star() only * Jun 9 2007 Fix bug so that sequential catalog entry reading works * * Mar 23 2017 Add fifth digit to star numbers */ wcstools-3.9.5/libwcs/uacread.c0000664000016200001660000012521112107543545015516 0ustar minkoirsys/*** File libwcs/uacread.c *** January 11, 2007 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2007 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Subroutines to read from the USNO A and SA catalogs */ #include #include #include #include #include #include "wcs.h" #include "fitsfile.h" #include "wcscat.h" static int ucat=UA2; /* USNO A-2.0 directory pathname; replaced by UA2_PATH environment variable * Use this if CDROMs have been transferred to a single hard disk * Otherwise set to null string ("") and use cdroot * This may also be a URL to a catalog search engine */ static char ua2path[64]="/data/astrocat/ua2"; /* Uncomment following line to use ESO USNO-A server for UA2 static char ua2path[64]="http://archive.eso.org/skycat/servers/usnoa-server"; */ /* USNO SA-2.0 directory pathname; replaced by USA2_PATH environment variable * This may also be a URL to a catalog search engine */ static char usa2path[64]="/data/astrocat/usnosa20"; /* USNO SA-1.0 directory pathname; replaced by USA1_PATH environment variable * This may also be a URL to a catalog search engine */ static char usa1path[64]="/data/astrocat/usnosa10"; /* USNO A-1.0 directory pathname; replaced by UA1_PATH environment variable * Use this if CDROMs have been transferred to a single hard disk * Otherwise set to null string ("") and use cdroot * This may also be a URL to a catalog search engine */ static char ua1path[64]="/data/astrocat/ua1"; static char *uapath; /* Root directory for CDROMs; replaced by UA_ROOT environment variable */ /* Ignored if uapath or UA*_PATH are set */ static char cdroot[32]="/cdrom"; /* Names of CDROM's for USNO A Catalogs */ static char cdname[11][8]={"ua001","ua002","ua003","ua004","ua005","ua006", "ua007","ua008","ua009","ua010","ua011"}; /* Disks for 24 zones of USNO A-1.0 Catalog */ static int zdisk1[24]={1,1,6,5,3,2,1,4,6,5,7,10,8,7,8,9,9,4,10,3,2,6,2,3}; /* Disks for 24 zones of USNO A-2.0 Catalog */ static int zdisk2[24]={1,1,9,7,5,4,3,2,1,6,7,10,9,8,8,11,10,11,6,4,2,3,3,2}; typedef struct { int rasec, decsec, magetc; } UACstar; static int nstars; /* Number of stars in catalog */ static int cswap = 0; /* Byte reverse catalog to Intel/DEC order if 1 */ static double *udist; /* Array of distances to stars */ static int ndist = 0; static FILE *fcat; #define ABS(a) ((a) < 0 ? (-(a)) : (a)) #define NZONES 24 static double uacra(); static double uacdec(); static double uacmagr(); static double uacmagb(); int uacmagerr(); int uacgsc(); static int uacplate(); static int uaczones(); static int uaczone(); static int uacsra(); static int uacopen(); static int uacpath(); static int uacstar(); static void uacswap(); static int xplate = 0; /* If nonzero, use objects only from this plate */ void setuplate (xplate0) int xplate0; { xplate = xplate0; return; } int getuplate () { return (xplate); } /* USACREAD -- Read USNO SA Catalog stars from CDROM */ int usaread (cra,cdec,dra,ddec,drad,dradi,distsort,sysout,eqout,epout,mag1,mag2, sortmag,nstarmax,unum,ura,udec,umag,uplate,nlog) double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ double dradi; /* Inner edge of annulus in degrees (ignore if 0) */ int distsort; /* 1 to sort stars by distance from center */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 to nmag) */ int nstarmax; /* Maximum number of stars to be returned */ /* If < 1, print stars to stdout as found */ double *unum; /* Array of UA numbers (returned) */ double *ura; /* Array of right ascensions (returned) */ double *udec; /* Array of declinations (returned) */ double **umag; /* Array of red and blue magnitudes (returned) */ int *uplate; /* Array of plate numbers (returned) */ int nlog; /* Logging interval */ { int i; int uacread(); ucat = USA2; i = uacread ("usac",distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nstarmax, unum,ura,udec,umag,uplate,nlog); ucat = USA2; return (i); } /* UACREAD -- Read USNO A or SA Catalog stars from CDROM */ int uacread (refcatname,distsort,cra,cdec,dra,ddec,drad,dradi,sysout,eqout,epout, mag1,mag2,sortmag,nstarmax,unum,ura,udec,umag,uplate,nlog) char *refcatname; /* Name of catalog (UAC, USAC, UAC2, USAC2) */ int distsort; /* 1 to sort stars by distance from center */ double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ double dradi; /* Inner edge of annulus in degrees (ignore if 0) */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 or 2) */ int nstarmax; /* Maximum number of stars to be returned */ double *unum; /* Array of UA numbers (returned) */ double *ura; /* Array of right ascensions (returned) */ double *udec; /* Array of declinations (returned) */ double **umag; /* Array of red and blue magnitudes (returned) */ int *uplate; /* Array of plate numbers (returned) */ int nlog; /* Logging interval */ { double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ int nz; /* Number of input UA zone files */ int zlist[NZONES]; /* List of input UA zones */ UACstar star; /* UA catalog entry for one star */ double dist = 0.0; /* Distance from search center in degrees */ double faintmag=0.0; /* Faintest magnitude */ double maxdist=0.0; /* Largest distance */ int faintstar=0; /* Faintest star */ int farstar=0; /* Most distant star */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ double rra1, rra2, rdec1, rdec2; double num; /* UA numbers */ int wrap, iwrap; int verbose; int znum, itot,iz, i; int jtable,jstar; int itable = 0; int nstar, nread; int uara1, uara2, uadec1, uadec2; double ra,dec, rdist, ddist; double mag, magb, magr; int istar, istar1, istar2, plate; int nzmax = NZONES; /* Maximum number of declination zones */ /* int isp; char ispc[2]; */ int pass; int magsort; char *str; char cstr[32], rastr[32], numstr[32], decstr[32], catid[32]; char *title; itot = 0; if (nlog > 0) verbose = 1; else verbose = 0; /* Set catalog code and path to catalog */ if (strncmp (refcatname,"us",2)==0 || strncmp (refcatname,"US",2)==0) { if (strchr (refcatname, '2') != NULL) { if ((str = getenv("USA2_PATH")) != NULL) strcpy (usa2path,str); ucat = USA2; uapath = usa2path; } else { if ((str = getenv("USA1_PATH")) != NULL) strcpy (usa1path,str); ucat = USA1; uapath = usa1path; } } else if (strncmp (refcatname,"ua",2)==0 || strncmp (refcatname,"UA",2)==0) { if (strchr (refcatname, '2') != NULL) { if ((str = getenv("UA2_PATH")) != NULL) strcpy (ua2path,str); else if ((str = getenv("UA2_ROOT")) != NULL) { ua2path[0] = 0; strcpy (cdroot,str); } ucat = UA2; uapath = ua2path; } else { if ((str = getenv("UA1_PATH")) != NULL) strcpy (ua1path,str); else if ((str = getenv("UA1_ROOT")) != NULL) { ua1path[0] = 0; strcpy (cdroot,str); } ucat = UA1; uapath = ua1path; } } else { fprintf (stderr, "UACREAD: %s not a USNO catalog\n", refcatname); return (0); } /* If root pathname is a URL, search and return */ if (!strncmp (uapath, "http:",5)) { return (webread (uapath,refcatname,distsort,cra,cdec,dra,ddec,drad, dradi,sysout,eqout,epout,mag1,mag2,sortmag,nstarmax, unum,ura,udec,NULL,NULL,umag,uplate,nlog)); } wcscstr (cstr, sysout, eqout, epout); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* mag1 is always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } if (sortmag == 1) magsort = 0; else magsort = 1; /* Find UA Star Catalog regions in which to search */ rra1 = ra1; rra2 = ra2; rdec1 = dec1; rdec2 = dec2; RefLim (cra, cdec, dra, ddec, sysout, sysref, eqout, eqref, epout, epref, 0.0, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); nz = uaczones (rra1, rra2, rdec1, rdec2, nzmax, zlist, verbose); if (nz <= 0) { fprintf (stderr, "UACREAD: no USNO A zones found\n"); return (0); } /* Write header if printing star entries as found */ if (nstarmax < 1) { char *revmessage; revmessage = getrevmsg(); title = CatName (ucat, refcatname); printf ("catalog %s\n", title); free ((char *)title); ra2str (rastr, 31, cra, 3); printf ("ra %s\n", rastr); dec2str (decstr, 31, cdec, 2); printf ("dec %s\n", decstr); if (drad != 0.0) { printf ("radmin %.1f\n", drad*60.0); if (dradi > 0) printf ("radimin %.1f\n", dradi*60.0); } else { printf ("dramin %.1f\n", dra*60.0* cosdeg (cdec)); printf ("ddecmin %.1f\n", ddec*60.0); } printf ("radecsys %s\n", cstr); printf ("equinox %.3f\n", eqout); printf ("epoch %.3f\n", epout); printf ("program scat %s\n", revmessage); CatID (catid, ucat); printf ("%s ra dec ", catid); printf ("magb magr arcmin\n"); printf ("------------- ------------ ------------ "); printf ("----- ----- ------\n"); } uara1 = (int) (rra1 * 360000.0 + 0.5); uara2 = (int) (rra2 * 360000.0 + 0.5); uadec1 = (int) ((rdec1 * 360000.0) + 32400000.5); uadec2 = (int) ((rdec2 * 360000.0) + 32400000.5); if (nstarmax > ndist) { if (ndist > 0) free ((void *)udist); udist = (double *) malloc (nstarmax * sizeof (double)); if (udist == NULL) { fprintf (stderr,"UACREAD: cannot allocate separation array\n"); return (0); } ndist = nstarmax; } /* Loop through region list */ nstar = 0; for (iz = 0; iz < nz; iz++) { /* Get path to zone catalog */ znum = zlist[iz]; if ((nstars = uacopen (znum)) != 0) { jstar = 0; jtable = 0; for (iwrap = 0; iwrap <= wrap; iwrap++) { /* Find first star based on RA */ if (iwrap == 0 || wrap == 0) istar1 = uacsra (rra1); else istar1 = 1; /* Find last star based on RA */ if (iwrap == 1 || wrap == 0) istar2 = uacsra (rra2); else istar2 = nstars; if (istar1 == 0 || istar2 == 0) break; nread = istar2 - istar1 + 1; itable = 0; /* Loop through zone catalog for this region */ for (istar = istar1; istar <= istar2; istar++) { itable ++; jtable ++; if (uacstar (istar, &star)) { fprintf (stderr,"UACREAD: Cannot read star %d\n", istar); break; } /* Extract selected fields */ else { /* Check position limits */ if ((star.decsec >= uadec1 && star.decsec <= uadec2) && ((wrap && (star.rasec>=uara1 || star.rasec<=uara2)) || (!wrap && (star.rasec>=uara1 && star.rasec<=uara2)) )){ /* Check magnitude, distance, and plate number */ magb = uacmagb (star.magetc); magr = uacmagr (star.magetc); if (magsort == 1) mag = magr; else mag = magb; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; /* Check plate ID */ plate = uacplate (star.magetc); if (xplate != 0 && plate != xplate) pass = 0; /* Check position limits */ if (pass) { ra = uacra (star.rasec); dec = uacdec (star.decsec); wcscon (sysref,sysout,eqref,eqout,&ra,&dec,epout); /* Compute distance from search center */ if (distsort || drad > 0) dist = wcsdist (cra,cdec,ra,dec); else dist = 0.0; /* Check radial distance to search center */ if (drad > 0.0) { if (dist > drad) pass = 0; if (dradi > 0.0 && dist < dradi) pass = 0; } /* Check distance along RA and Dec axes */ else { ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } } if (pass) { num = (double) znum + (0.00000001 * (double)istar); /* Write star position and magnitudes to stdout */ if (nstarmax < 1) { CatNum (ucat, -13, 0, num, numstr); ra2str (rastr, 31, ra, 3); dec2str (decstr, 31, dec, 2); dist = wcsdist (cra,cdec,ra,dec) * 60.0; printf ("%s %s %s", numstr,rastr,decstr); printf (" %.2f %.2f %.2f\n", magb, magr, dist / 60.0); } /* Save star position and magnitude in table */ else if (nstar < nstarmax) { unum[nstar] = num; ura[nstar] = ra; udec[nstar] = dec; umag[0][nstar] = magb; umag[1][nstar] = magr; uplate[nstar] = plate; udist[nstar] = dist; if (dist > maxdist) { maxdist = dist; farstar = nstar; } if (mag > faintmag) { faintmag = mag; faintstar = nstar; } } /* If too many stars and distance sorting, replace furthest star */ else if (distsort) { if (dist < maxdist) { unum[farstar] = num; ura[farstar] = ra; udec[farstar] = dec; umag[0][farstar] = magb; umag[1][farstar] = magr; uplate[farstar] = plate; udist[farstar] = dist; /* Find new farthest star */ maxdist = 0.0; for (i = 0; i < nstarmax; i++) { if (udist[i] > maxdist) { maxdist = udist[i]; farstar = i; } } } } /* If too many stars, replace faintest star */ else if (mag < faintmag) { unum[faintstar] = num; ura[faintstar] = ra; udec[faintstar] = dec; umag[0][faintstar] = magb; umag[1][faintstar] = magr; uplate[faintstar] = plate; udist[faintstar] = dist; /* Find new faintest star */ faintmag = 0.0; for (i = 0; i < nstarmax; i++) { if (umag[magsort][i] > faintmag) { faintmag = umag[magsort][i]; faintstar = i; } } } nstar++; jstar++; if (nlog == 1) fprintf (stderr,"UACREAD: %04d.%08d: %9.5f %9.5f %s %5.2f %5.2f\n", znum,istar,ra,dec,cstr,magb,magr); /* End of accepted star processing */ } } /* End of individual star processing */ } /* Log operation */ if (nlog > 0 && itable%nlog == 0) fprintf (stderr,"UACREAD: zone %d (%2d / %2d) %8d / %8d / %8d sources\r", znum, iz+1, nz, jstar, itable, nread); /* End of star loop */ } /* End of wrap loop */ } /* Close zone input file */ (void) fclose (fcat); itot = itot + itable; if (nlog > 0) fprintf (stderr,"UACREAD: zone %d (%2d / %2d) %8d / %8d / %8d sources \n", znum, iz+1, nz, jstar, jtable, nstars); /* End of zone processing */ } /* End of zone loop */ } /* Summarize search */ if (nlog > 0) { if (nz > 1) fprintf (stderr,"UACREAD: %d zones: %d / %d found\n",nz,nstar,itot); else fprintf (stderr,"UACREAD: 1 zone: %d / %d found\n",nstar,itable); if (nstar > nstarmax) fprintf (stderr,"UACREAD: %d stars found; only %d returned\n", nstar,nstarmax); } return (nstar); } int usarnum (nnum,sysout,eqout,epout,unum,ura,udec,umag,uplate,nlog) int nnum; /* Number of stars to find */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double *unum; /* Array of UA numbers to find */ double *ura; /* Array of right ascensions (returned) */ double *udec; /* Array of declinations (returned) */ double **umag; /* Array of blue and red magnitudes (returned) */ int *uplate; /* Array of plate numbers (returned) */ int nlog; /* Logging interval */ { int i; int uacrnum(); ucat = USA1; i = uacrnum ("USAC",nnum,sysout,eqout,epout,unum,ura,udec,umag,uplate,nlog); ucat = UA1; return (i); } int uacrnum (refcatname,nnum,sysout,eqout,epout,unum,ura,udec,umag,uplate,nlog) char *refcatname; /* Name of catalog (UAC, USAC, UAC2, USAC2) */ int nnum; /* Number of stars to find */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double *unum; /* Array of UA numbers to find */ double *ura; /* Array of right ascensions (returned) */ double *udec; /* Array of declinations (returned) */ double **umag; /* Array of blue and red magnitudes (returned) */ int *uplate; /* Array of plate numbers (returned) */ int nlog; /* Logging interval */ { UACstar star; /* UA catalog entry for one star */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ /* int isp; char ispc[2]; */ int znum; int jnum; int nzone; int nfound = 0; double ra,dec; double magr, magb; double dstar; int istar, plate; char *str; /* Set catalog code and path to catalog */ if (strncmp (refcatname,"us",2)==0 || strncmp (refcatname,"US",2)==0) { if (strchr (refcatname, '2') != NULL) { if ((str = getenv("USA2_PATH")) != NULL) strcpy (usa2path,str); ucat = USA2; uapath = usa2path; } else { if ((str = getenv("USA1_PATH")) != NULL) strcpy (usa1path,str); ucat = USA1; uapath = usa1path; } } else if (strncmp (refcatname,"ua",2)==0 || strncmp (refcatname,"UA",2)==0) { if (strchr (refcatname, '2') != NULL) { if ((str = getenv("UA2_PATH")) != NULL) strcpy (ua2path,str); else if ((str = getenv("UA2_ROOT")) != NULL) { ua2path[0] = 0; strcpy (cdroot,str); } ucat = UA2; uapath = ua2path; } else { if ((str = getenv("UA1_PATH")) != NULL) strcpy (ua1path,str); else if ((str = getenv("UA1_ROOT")) != NULL) { ua1path[0] = 0; strcpy (cdroot,str); } ucat = UA1; uapath = ua1path; } } else { fprintf (stderr, "UACREAD: %s not a USNO catalog\n", refcatname); return (0); } /* If root pathname is a URL, search and return */ if (!strncmp (uapath, "http:",5)) { return (webrnum (uapath,refcatname,nnum,sysout,eqout,epout,1, unum,ura,udec,NULL,NULL,umag,uplate,nlog)); } /* Loop through star list */ for (jnum = 0; jnum < nnum; jnum++) { /* Get path to zone catalog */ znum = (int) unum[jnum]; if ((nzone = uacopen (znum)) != 0) { dstar = (unum[jnum] - znum) * 100000000.0; istar = (int) (dstar + 0.5); if (istar > nzone) { fprintf (stderr,"UACRNUM: Star %d > max. in zone %d\n", istar,nzone); break; } if (uacstar (istar, &star)) { fprintf (stderr,"UACRNUM: Cannot read star %d\n", istar); break; } /* Extract selected fields */ else { ra = uacra (star.rasec); /* Right ascension in degrees */ dec = uacdec (star.decsec); /* Declination in degrees */ magb = uacmagb (star.magetc); /* Blue magnitude */ magr = uacmagr (star.magetc); /* Red magnitude */ plate = uacplate (star.magetc); /* Plate number */ wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); /* Save star position and magnitude in table */ ura[nfound] = ra; udec[nfound] = dec; umag[0][nfound] = magb; umag[1][nfound] = magr; /* br2sp (NULL, magb, magr, ispc); isp = (1000 * (int)ispc[0]) + (int)ispc[1]; */ uplate[nfound] = plate; nfound++; if (nlog == 1) fprintf (stderr,"UACRNUM: %04d.%08d: %9.5f %9.5f %5.2f %5.2f\n", znum,istar,ra,dec,magb,magr); /* Log operation */ if (nlog > 0 && jnum%nlog == 0) fprintf (stderr,"UACRNUM: %4d.%8d %8d / %8d sources\r", znum, istar, jnum, nnum); (void) fclose (fcat); /* End of star processing */ } /* End of star */ } /* End of star loop */ } /* Summarize search */ if (nlog > 0) fprintf (stderr,"UACRNUM: %d / %d found\n",nfound,nnum); return (nfound); } /* USACBIN -- Fill a FITS WCS image with USNO SA Catalog stars */ int usabin (wcs, header, image, mag1, mag2, sortmag, magscale, nlog) struct WorldCoor *wcs; /* World coordinate system for image */ char *header; /* FITS header for output image */ char *image; /* Output FITS image */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 to nmag) */ double magscale; /* Scaling factor for magnitude to pixel flux * (number of catalog objects per bin if 0) */ int nlog; /* Logging interval */ { int i; int uacbin(); ucat = USA2; i = uacbin ("usac", wcs, header, image, mag1, mag2, sortmag, magscale, nlog); ucat = USA2; return (i); } /* UACBIN -- Fill a FITS WCS image with USNO A or SA Catalog stars */ int uacbin (refcatname, wcs, header, image, mag1, mag2, sortmag, magscale, nlog) char *refcatname; /* Name of catalog (UAC, USAC, UAC2, USAC2) */ struct WorldCoor *wcs; /* World coordinate system for image */ char *header; /* FITS header for output image */ char *image; /* Output FITS image */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 or 2) */ double magscale; /* Scaling factor for magnitude to pixel flux * (number of catalog objects per bin if 0) */ int nlog; /* Logging interval */ { double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ int nz; /* Number of input UA zone files */ int zlist[NZONES]; /* List of input UA zones */ UACstar star; /* UA catalog entry for one star */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ double rra1, rra2, rdec1, rdec2; int wrap, iwrap; int verbose; int znum, itot,iz; int jtable,jstar; int itable = 0; int nstar, nread; int uara1, uara2, uadec1, uadec2; double ra,dec, rdist, ddist; double mag, magb, magr; int istar, istar1, istar2, plate; int nzmax = NZONES; /* Maximum number of declination zones */ /* int isp; char ispc[2]; */ int pass; int ix, iy; int magsort; char *str; char cstr[32]; double xpix, ypix, flux; int offscl; int bitpix, w, h; /* Image bits/pixel and pixel width and height */ double logt = log(10.0); itot = 0; if (nlog > 0) verbose = 1; else verbose = 0; /* Set image parameters */ bitpix = 0; (void)hgeti4 (header, "BITPIX", &bitpix); w = 0; (void)hgeti4 (header, "NAXIS1", &w); h = 0; (void)hgeti4 (header, "NAXIS2", &h); /* Set catalog code and path to catalog */ if (strncmp (refcatname,"us",2)==0 || strncmp (refcatname,"US",2)==0) { if (strchr (refcatname, '2') != NULL) { if ((str = getenv("USA2_PATH")) != NULL) strcpy (usa2path,str); ucat = USA2; uapath = usa2path; } else { if ((str = getenv("USA1_PATH")) != NULL) strcpy (usa1path,str); ucat = USA1; uapath = usa1path; } } else if (strncmp (refcatname,"ua",2)==0 || strncmp (refcatname,"UA",2)==0) { if (strchr (refcatname, '2') != NULL) { if ((str = getenv("UA2_PATH")) != NULL) strcpy (ua2path,str); else if ((str = getenv("UA2_ROOT")) != NULL) { ua2path[0] = 0; strcpy (cdroot,str); } ucat = UA2; uapath = ua2path; } else { if ((str = getenv("UA1_PATH")) != NULL) strcpy (ua1path,str); else if ((str = getenv("UA1_ROOT")) != NULL) { ua1path[0] = 0; strcpy (cdroot,str); } ucat = UA1; uapath = ua1path; } } else { fprintf (stderr, "UACBIN: %s not a USNO catalog\n", refcatname); return (0); } /* Set catalog search limits from image WCS information */ sysout = wcs->syswcs; eqout = wcs->equinox; epout = wcs->epoch; wcscstr (cstr, sysout, eqout, epout); wcssize (wcs, &cra, &cdec, &dra, &ddec); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* mag1 is always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } if (sortmag == 1) magsort = 0; else magsort = 1; /* Find UA Star Catalog regions in which to search */ rra1 = ra1; rra2 = ra2; rdec1 = dec1; rdec2 = dec2; RefLim (cra, cdec, dra, ddec, sysout, sysref, eqout, eqref, epout, epref, 0.0, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); nz = uaczones (rra1, rra2, rdec1, rdec2, nzmax, zlist, verbose); if (nz <= 0) { fprintf (stderr, "UACBIN: no USNO A zones found\n"); return (0); } uara1 = (int) (rra1 * 360000.0 + 0.5); uara2 = (int) (rra2 * 360000.0 + 0.5); uadec1 = (int) ((rdec1 * 360000.0) + 32400000.5); uadec2 = (int) ((rdec2 * 360000.0) + 32400000.5); /* Loop through region list */ nstar = 0; for (iz = 0; iz < nz; iz++) { /* Get path to zone catalog */ znum = zlist[iz]; if ((nstars = uacopen (znum)) != 0) { jstar = 0; jtable = 0; for (iwrap = 0; iwrap <= wrap; iwrap++) { /* Find first star based on RA */ if (iwrap == 0 || wrap == 0) istar1 = uacsra (rra1); else istar1 = 1; /* Find last star based on RA */ if (iwrap == 1 || wrap == 0) istar2 = uacsra (rra2); else istar2 = nstars; if (istar1 == 0 || istar2 == 0) break; nread = istar2 - istar1 + 1; itable = 0; /* Loop through zone catalog for this region */ for (istar = istar1; istar <= istar2; istar++) { itable ++; jtable ++; if (uacstar (istar, &star)) { fprintf (stderr,"UACBIN: Cannot read star %d\n", istar); break; } /* Extract selected fields */ else { /* Check position limits */ if ((star.decsec >= uadec1 && star.decsec <= uadec2) && ((wrap && (star.rasec>=uara1 || star.rasec<=uara2)) || (!wrap && (star.rasec>=uara1 && star.rasec<=uara2)) )){ /* Check magnitude, distance, and plate number */ magb = uacmagb (star.magetc); magr = uacmagr (star.magetc); if (magsort == 1) mag = magr; else mag = magb; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; /* Check plate ID */ plate = uacplate (star.magetc); if (xplate != 0 && plate != xplate) pass = 0; /* Check position limits */ if (pass) { ra = uacra (star.rasec); dec = uacdec (star.decsec); wcscon (sysref,sysout,eqref,eqout,&ra,&dec,epout); /* Check distance along RA and Dec axes */ ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } /* Save star in FITS image */ if (pass) { wcs2pix (wcs, ra, dec, &xpix, &ypix, &offscl); if (!offscl) { if (magscale > 0.0) flux = magscale * exp (logt * (-mag / 2.5)); else flux = 1.0; ix = (int) (xpix + 0.5); iy = (int) (ypix + 0.5); addpix1 (image, bitpix, w,h, 0.0,1.0, xpix,ypix, flux); nstar++; jstar++; } else { ix = 0; iy = 0; } if (nlog == 1) { fprintf (stderr,"UACBIN: %04d.%08d: %9.5f %9.5f %s", znum,istar,ra,dec,cstr); if (magscale > 0.0) fprintf (stderr, " %5.2f", mag); if (!offscl) flux = getpix1 (image, bitpix, w, h, 0.0, 1.0, ix, iy); else flux = 0.0; fprintf (stderr," (%d,%d): %f\n", ix, iy, flux); } /* End of accepted star processing */ } } /* End of individual star processing */ } /* Log operation */ if (nlog > 0 && itable%nlog == 0) fprintf (stderr,"UACBIN: zone %d (%2d / %2d) %8d / %8d / %8d sources\r", znum, iz+1, nz, jstar, itable, nread); /* End of star loop */ } /* End of wrap loop */ } /* Close zone input file */ (void) fclose (fcat); itot = itot + itable; if (nlog > 0) fprintf (stderr,"UACBIN: zone %d (%2d / %2d) %8d / %8d / %8d sources \n", znum, iz+1, nz, jstar, jtable, nstars); /* End of zone processing */ } /* End of zone loop */ } /* Summarize search */ if (nlog > 0) { if (nz > 1) fprintf (stderr,"UACBIN: %d zones: %d / %d found\n",nz,nstar,itot); else fprintf (stderr,"UACBIN: 1 zone: %d / %d found\n",nstar,itable); } return (nstar); } /* Declination zone numbers */ int azone[NZONES]={0,75,150,225,300,375,450,525,600,675,750,825,900, 975,1050,1125,1200,1275,1350,1425,1500,1575,1650,1725}; /* UACZONES -- figure out which UA zones will need to be searched */ static int uaczones (ra1, ra2, dec1, dec2, nzmax, zones, verbose) double ra1, ra2; /* Right ascension limits in degrees */ double dec1, dec2; /* Declination limits in degrees */ int nzmax; /* Maximum number of zones to find */ int *zones; /* Region numbers (returned)*/ int verbose; /* 1 for diagnostics */ { int nrgn; /* Number of zones found (returned) */ int iz,iz1,iz2,i; for (i = 0; i < nzmax; i++) zones[i] = 0; nrgn = 0; /* Find zone range to search based on declination */ iz1 = uaczone (dec1); iz2 = uaczone (dec2); /* Tabulate zones to search */ i = 0; if (iz2 >= iz1) { for (iz = iz1; iz <= iz2; iz++) zones[i++] = azone[iz]; } else { for (iz = iz2; iz <= iz1; iz++) zones[i++] = azone[iz]; } nrgn = i; if (verbose) { fprintf(stderr,"UACZONES: %d zones: %d - %d\n",nrgn,zones[0],zones[i-1]); fprintf(stderr,"UACZONES: RA: %.5f - %.5f, Dec: %.5f - %.5f\n",ra1,ra2,dec1,dec2); } return (nrgn); } /* UACRA -- returns right ascension in degrees from the UA star structure */ static double uacra (rasec) int rasec; /* RA in 100ths of arcseconds from UA catalog entry */ { return ((double) (rasec) / 360000.0); } /* UACDEC -- returns the declination in degrees from the UA star structure */ static double uacdec (decsec) int decsec; /* Declination in 100ths of arcseconds from UA catalog entry */ { return ((double) (decsec - 32400000) / 360000.0); } /* UACMAGR -- returns the red magnitude from the UA star structure */ static double uacmagr (magetc) int magetc; /* Quality, plate, and magnitude from UA catalog entry */ { if (magetc < 0) return ((double) (-magetc % 1000) * 0.1); else return ((double) (magetc % 1000) * 0.1); } /* UACMAGB -- returns the blue magnitude from the UA star structure */ static double uacmagb (magetc) int magetc; /* Quality, plate, and magnitude from UA catalog entry */ { if (magetc < 0) return ((double) ((-magetc / 1000) % 1000) * 0.1); else return ((double) ((magetc / 1000) % 1000) * 0.1); } /* UACMAGERR -- returns 1 if magnitude is uncertain from UA star structure */ int uacmagerr (magetc) int magetc; /* Quality, plate, and magnitude from UA catalog entry */ { if (magetc < 0) return ((-magetc / 1000000000) % 10); else return ((magetc / 1000000000) % 10); } /* UACGSC -- returns 1 if UA star is in the HST Guide Star Catalog */ int uacgsc (magetc) int magetc; /* Quality, plate, and magnitude from UA catalog entry */ { if (magetc < 0) return (1); else return (0); } /* UACPLATE -- returns the plate number from the UA star structure */ static int uacplate (magetc) int magetc; /* Quality, plate, and magnitude from UA catalog entry */ { if (magetc < 0) return ((-magetc / 1000000) % 1000); else return ((magetc / 1000000) % 1000); } /* UACZONE -- find the UA zone number where a declination can be found */ static int uaczone (dec) double dec; /* declination in degrees */ { double zonesize = 7.5; /* number of degrees per declination zone */ int zone; zone = (int) ((dec + 90.0) / zonesize); if (zone > 23) zone = 23; else if (zone < 0) zone = 0; return (zone); } /* UACSRA -- Find UA star closest to specified right ascension */ static int uacsra (rax0) double rax0; /* Right ascension in degrees for which to search */ { int istar, istar1, istar2, nrep; double rax, ra1, ra, rdiff, rdiff1, rdiff2, sdiff; UACstar star; /* UA catalog entry for one star */ char rastrx[32]; int debug = 0; rax = rax0; if (debug) ra2str (rastrx, 31, rax, 3); istar1 = 1; if (uacstar (istar1, &star)) return (0); ra1 = uacra (star.rasec); istar = nstars; nrep = 0; while (istar != istar1 && nrep < 20) { if (uacstar (istar, &star)) break; else { ra = uacra (star.rasec); if (ra == ra1) break; if (debug) { char rastr[32]; ra2str (rastr, 31, ra, 3); fprintf (stderr,"UACSRA %d %d: %s (%s)\n", nrep,istar,rastr,rastrx); } rdiff = ra1 - ra; rdiff1 = ra1 - rax; rdiff2 = ra - rax; if (nrep > 20 && ABS(rdiff2) > ABS(rdiff1)) { istar = istar1; break; } nrep++; sdiff = (double)(istar - istar1) * rdiff1 / rdiff; istar2 = istar1 + (int) (sdiff + 0.5); ra1 = ra; istar1 = istar; istar = istar2; if (debug) { fprintf (stderr," ra1= %.5f ra= %.5f rax= %.5f\n", ra1,ra,rax); fprintf (stderr," rdiff= %.5f rdiff1= %.5f rdiff2= %.5f\n", rdiff,rdiff1,rdiff2); fprintf (stderr," istar1= %d istar= %d istar1= %d\n", istar1,istar,istar2); } if (istar < 1) istar = 1; if (istar > nstars) istar = nstars; if (istar == istar1) break; } } return (istar); } /* UACOPEN -- Open UA Catalog zone catalog, returning number of entries */ static int uacopen (znum) int znum; /* UA Catalog zone */ { char zonepath[64]; /* Pathname for input UA zone file */ UACstar star; /* UA catalog entry for one star */ int lfile; /* Get path to zone catalog */ if (uacpath (znum, zonepath)) { fprintf (stderr, "UACOPEN: Cannot find zone catalog for %d\n", znum); return (0); } /* Find number of stars in zone catalog by its length */ lfile = getfilesize (zonepath); if (lfile < 2) { fprintf (stderr,"UA zone catalog %s has no entries\n",zonepath); return (0); } else nstars = lfile / 12; /* Open zone catalog */ if (!(fcat = fopen (zonepath, "rb"))) { fprintf (stderr,"UA zone catalog %s cannot be read\n",zonepath); return (0); } /* Check to see if byte-swapping is necessary */ cswap = 0; if (uacstar (1, &star)) { fprintf (stderr,"UACOPEN: cannot read star 1 from UA zone catalog %s\n", zonepath); return (0); } else { if (star.rasec > 360 * 360000 || star.rasec < 0) { cswap = 1; /* fprintf (stderr,"UACOPEN: swapping bytes in UA zone catalog %s\n", zonepath); */ } else if (star.decsec > 180 * 360000 || star.decsec < 0) { cswap = 1; /* fprintf (stderr,"UACOPEN: swapping bytes in UA zone catalog %s\n", zonepath); */ } else cswap = 0; } return (nstars); } /* UACPATH -- Get UA Catalog region file pathname */ static int uacpath (zn, path) int zn; /* UA zone number */ char *path; /* Pathname of UA zone file */ { int iz; /* Zone index (0000 = 0, 0075 = 1, ...) */ int icd; /* CDROM number if multiple CDROMs used */ /* Return error code and null path if zone is out of range */ if (zn < 0 || zn > 1725) { fprintf (stderr, "UACPATH: zone %d out of range 0-1725\n",zn); path[0] = 0; return (-1); } /* Set path for USNO SA zone catalog */ if (ucat == USA1 || ucat == USA2) sprintf (path,"%s/zone%04d.cat", uapath, zn); /* Set zone catalog path when USNO A is in a single directory */ else if (strlen (uapath) > 0) sprintf (path,"%s/zone%04d.cat", uapath, zn); /* Set zone catalog path when USNO A is read from CDROMs */ else { iz = zn / 75; if (ucat == UA1) icd = zdisk1[iz]; else icd = zdisk2[iz]; sprintf (path,"%s/%s/zone%04d.cat", cdroot, cdname[icd-1], zn); } return (0); } /* UACSTAR -- Get UA catalog entry for one star; return 0 if successful */ static int uacstar (istar, star) int istar; /* Star sequence number in UA zone catalog */ UACstar *star; /* UA catalog entry for one star */ { int nbs, nbr, nbskip; if (istar < 1 || istar > nstars) { fprintf (stderr, "UACstar %d is not in catalog\n",istar); return (-1); } nbskip = 12 * (istar - 1); if (fseek (fcat,nbskip,SEEK_SET)) return (-1); nbs = sizeof (UACstar); nbr = fread (star, nbs, 1, fcat) * nbs; if (nbr < nbs) { fprintf (stderr, "UACstar %d / %d bytes read\n",nbr, nbs); return (-2); } if (cswap) uacswap ((char *)star); return (0); } /* UACSWAP -- Reverse bytes of UA Catalog entry */ static void uacswap (string) char *string; /* Start of vector of 4-byte ints */ { char *sbyte, *slast; char temp0, temp1, temp2, temp3; int nbytes = 12; /* Number of bytes to reverse */ slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp3 = sbyte[0]; temp2 = sbyte[1]; temp1 = sbyte[2]; temp0 = sbyte[3]; sbyte[0] = temp0; sbyte[1] = temp1; sbyte[2] = temp2; sbyte[3] = temp3; sbyte = sbyte + 4; } return; } /* Nov 15 1996 New subroutine * Dec 11 1996 Set ra<0 to ra+360 and ra>360 to ra-360 * Dec 16 1996 Add code to read a specific star * Dec 17 1996 Keep closest stars, not brightest, if searching within radius * * Mar 12 1997 Set paths for SA-1.0 and multiple CDROM A-1.0 * Mar 20 1997 Clean up UACRNUM after lint * Apr 23 1997 Fix bug which rejected stars in HST Guide Star Catalog * Nov 6 1997 Don't print star overrun unless logging * * Feb 20 1998 Speed up processing by searching in arcseconds, not degrees * Feb 20 1998 Speed up processing by searching RA and Dec, then rest * Apr 20 1998 Fix bug so stars within radius can be found * Jun 24 1998 Add string lengths to ra2str() and dec2str() calls * Jun 24 1998 Initialize byte-swapping flag in UACOPEN() * Sep 15 1998 Fix bug setting A 1.0 region path on CDROM found by Naoki Yasuda * Sep 22 1998 Convert coordinates in these subroutines * Oct 8 1998 Fix bug in uacread call in usaread() and uacrnum call in usarnum() * Oct 26 1998 Fix bug in search algorith for non-J2000 searches * Oct 29 1998 Correctly assign numbers when too many stars are found * Nov 20 1998 Add support for USNO A-2.0 and SA-2.0 catalogs * Nov 24 1998 Fix bug reading SA-2.0 catalog * * Feb 9 1999 Improve documentation * Jun 16 1999 Use SearchLim() * Aug 16 1999 Add RefLim() to get converted search coordinates right * Aug 16 1999 Fix bug to fix failure to search across 0:00 RA * Aug 25 1999 Return real number of stars from uacread() * Sep 10 1999 Set plate selection with subroutine, not argument * Sep 16 1999 Fix bug which didn't always return closest stars * Sep 16 1999 Add distsort argument so brightest stars in circle works, too * Oct 20 1999 Include wcscat.h * Oct 21 1999 Clean up code after lint * * Jun 9 2000 Fix bug detecting swapped files on Alphas and PCs if RA=0 * Jun 26 2000 Add coordinate system to SearchLim() arguments * Sep 22 2000 Return approximate spectral type instead of plate number * Nov 28 2000 Add option to read catalog using HTTP * Dec 1 2000 Return plate number, not bad spectral type * Dec 11 2000 Path may be set to catalog search engine URL * Dec 15 2000 Do away with separate usapath variable; use uapath * * Jun 14 2001 Make sure star number is correct in uacrnum() * Jun 27 2001 Use RefCat codes for ucat * Jun 27 2001 Print stars as found in uacread() if nstarmax < 1 * Jun 27 2001 Allocate udist only when larger array is needed * Sep 11 2001 Change to single magnitude argeument * Sep 11 2001 Add sort magnitude argument to uacread() * Sep 19 2001 Drop fitshead.h; it is in wcs.h * Sep 21 2001 Add commented-out URL of ESO web catalog server * Nov 20 2001 Change cos(degrad()) to cosdeg() * * Apr 10 2002 Simplify use of magsort * Jul 31 2002 Drop extra magb argument in uacrnum() * Oct 2 2002 Print current scat revision message * * Jan 21 2003 Print arcminute radial distance, not arcsecond for instant out * Feb 4 2003 Open catalog file rb instead of r (Martin Ploner, Bern) * Mar 10 2003 Improve test for position * Apr 3 2003 Drop unused variables after lint * Apr 14 2003 Explicitly get revision date if nstarmax < 1 * May 27 2003 Use getfilesize() to get file size * Aug 22 2003 Add radi argument for inner edge of search annulus * Sep 25 2003 Add usabin() and uacbin() to fill an image with sources * Oct 6 2003 Update uacread() and uacbin() for improved RefLim() * Nov 18 2003 Initialize image size and bits/pixel from header in uacbin() * Dec 1 2003 Add missing tab to n=-1 header * Dec 12 2003 Fix bug in wcs2pix() call in uacbin(); fix usacbin() subroutine * * Aug 30 2004 Include fitsfile.h and math.h * * Sep 13 2006 Change default paths to /data/astrocat * Sep 26 2006 Increase length of rastr and destr from 16 to 32 * Nov 15 2006 Fix binning * * Jan 10 2007 Add match=1 argument to webrnum() * Jan 10 2007 Add dradi arguemnt to uacread() call in usacread() */ wcstools-3.9.5/libwcs/ubcread.c0000664000016200001660000011705511750060474015524 0ustar minkoirsys/*** File libwcs/ubcread.c *** December 05, 2007 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 2003-2007 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Subroutines to read from the USNO-B1.0 catalog */ #include #include #include #include #include #include "wcs.h" #include "fitsfile.h" #include "wcscat.h" static int ucat=UB1; /* USNO B-1.0 directory pathname; replaced by UB1_PATH environment variable. * This may also be a URL to a catalog search engine */ static char ub1path[64]="/data/ub1"; /* USNO YB6 directory pathname; replaced by YB6_PATH environment variable. * This may also be a URL to a catalog search engine */ static char yb6path[64]="/data/astrocat2/usnoyb6"; static char *upath; typedef struct { int rasec, decsec, pm, pmerr, poserr, mag[5], magerr[5], index[5]; } UBCstar; static int nstars; /* Number of stars in catalog */ static int cswap = 0; /* Byte reverse catalog to Intel/DEC order if 1 */ static double *udist; /* Array of distances to stars */ static int ndist = 0; /* Number of stars in distance array */ static int minpmqual = 3; /* Proper motion quality limit (0=bad, 9=good)*/ void setminpmqual (n) int n; { minpmqual = n; return; } int getminpmqual () { return (minpmqual); } static int minid = 0; /* Minimum number of plate ID's (<0 excludes Tycho-2) */ void setminid (n) int n; { minid = n; return; } int getminid () { return (minid); } static FILE *fcat; #define ABS(a) ((a) < 0 ? (-(a)) : (a)) #define NZONES 1800 static double ubcra(); static double ubcdec(); static double ubcmag(); static double ubcpra(); static double ubcpdec(); static int ubcpmq(); static int ubcsg(); int ubcmagerr(); static int ubcndet(); static int ubczones(); static int ubczone(); static int ubcsra(); static int ubcopen(); static int ubcpath(); static int ubcstar(); static void ubcswap(); static int nbent = 80; /* UBCREAD -- Return USNO B1.0 or YB6 sources in specified region */ int ubcread (refcatname,distsort,cra,cdec,dra,ddec,drad,dradi,sysout,eqout,epout, mag1,mag2,sortmag,nstarmax,unum,ura,udec,upra,updec,umag,upmni,nlog) char *refcatname; /* Name of catalog (UB1 only, for now) */ int distsort; /* 1 to sort stars by distance from center */ double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ double dradi; /* Inner edge of search annulus in degrees (ignore if 0) */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 or 2) */ int nstarmax; /* Maximum number of stars to be returned */ double *unum; /* Array of UB numbers (returned) */ double *ura; /* Array of right ascensions (returned) */ double *udec; /* Array of declinations (returned) */ double *upra; /* Array of right ascension proper motions (returned) */ double *updec; /* Array of declination proper motions (returned) */ double **umag; /* Array of red and blue magnitudes (returned) */ int *upmni; /* Array of number of ids and pm quality (returned) */ int nlog; /* Logging interval */ { double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ int nz; /* Number of input UB zone files */ int zlist[NZONES]; /* List of input UB zones */ UBCstar star; /* UB catalog entry for one star */ double dist = 0.0; /* Distance from search center in degrees */ double faintmag=0.0; /* Faintest magnitude */ double maxdist=0.0; /* Largest distance */ double rdist, ddist; int faintstar=0; /* Faintest star */ int farstar=0; /* Most distant star */ int pmqual; int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ double rra1, rra2, rdec1, rdec2; double num; /* UB numbers */ double rapm, decpm, rapm0, decpm0; int wrap, iwrap; int verbose; int znum, itot,iz, i; int jtable,jstar; int itable = 0; int objtype = 0; int nstar, nread, pass; int ubra1, ubra2, ubdec1, ubdec2; int nsg, isg, qsg; double ra,dec, ra0, dec0; double mag, magtest, secmarg; int istar, istar1, istar2, pmni, nid; int nzmax = NZONES; /* Maximum number of declination zones */ int magsort; char *str; char cstr[32], rastr[32], numstr[32], decstr[32], catid[32]; char *title; itot = 0; if (nlog > 0) verbose = 1; else verbose = 0; /* Set catalog code and path to catalog */ if (strncasecmp (refcatname,"ub",2)==0) { if ((str = getenv("UB1_PATH")) != NULL) strcpy (ub1path,str); ucat = UB1; upath = ub1path; } else if (strncasecmp (refcatname,"yb",2)==0) { if ((str = getenv("YB6_PATH")) != NULL) strcpy (yb6path,str); ucat = YB6; upath = yb6path; } else { fprintf (stderr, "UBCREAD: %s not a USNO catalog\n", refcatname); return (0); } if (strchr (refcatname, 't')) objtype = 1; else objtype = 0; /* If root pathname is a URL, search and return */ if (!strncmp (upath, "http:",5)) { return (webread (upath,refcatname,distsort,cra,cdec,dra,ddec,drad, dradi,sysout,eqout,epout,mag1,mag2,sortmag,nstarmax, unum,ura,udec,upra,updec,umag,upmni,nlog)); } wcscstr (cstr, sysout, eqout, epout); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* mag1 is always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } /* Sort by 4th magnitude = R2 if sort magnitude is not set */ if (sortmag > 0 && sortmag < 6) magsort = sortmag - 1; else magsort = 3; /* Add 60 arcsec/century margins to region to get most stars which move */ if (minpmqual < 11 && (epout != 0.0 || sysout != sysref)) secmarg = 60.0; else secmarg = 0.0; /* Find RA and Dec limits in catalog coordinate system */ RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref,secmarg, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); /* Find declination zones to search */ nz = ubczones (rra1, rra2, rdec1, rdec2, nzmax, zlist, verbose); if (nz <= 0) { fprintf (stderr, "UBCREAD: no USNO B zones found\n"); return (0); } /* Write header if printing star entries as found */ if (nstarmax < 1) { char *revmessage; revmessage = getrevmsg(); title = CatName (ucat, refcatname); printf ("catalog %s\n", title); free ((char *)title); ra2str (rastr, 31, cra, 3); printf ("ra %s\n", rastr); dec2str (decstr, 31, cdec, 2); printf ("dec %s\n", decstr); printf ("rpmunit mas/year\n"); printf ("dpmunit mas/year\n"); if (drad != 0.0) { printf ("radmin %.1f\n", drad*60.0); if (dradi > 0) printf ("radimin %.1f\n", dradi*60.0); } else { printf ("dramin %.1f\n", dra*60.0* cosdeg (cdec)); printf ("ddecmin %.1f\n", ddec*60.0); } printf ("radecsys %s\n", cstr); printf ("equinox %.3f\n", eqout); printf ("epoch %.3f\n", epout); printf ("program scat %s\n", revmessage); CatID (catid, ucat); if (objtype) { printf ("%s ra dec ", catid); printf ("magb1 magr1 magb1 magb2 magn "); printf ("sgb1 sgr1 sgb1 sgb2 "); printf ("ura udec pm ni qsg arcmin\n"); printf ("------------ ------------ ------------ "); printf ("----- ----- ----- ----- ----- "); printf ("---- ---- ---- ---- "); printf ("----- ----- -- -- --- ------\n"); } else { printf ("%s ra dec ", catid); printf ("magb1 magr1 magb1 magb2 magn ura "); printf ("udec pm ni qsg arcmin\n"); printf ("------------ ------------ ------------ "); printf ("----- ----- ----- ----- ----- ----- "); printf ("----- -- -- --- ------\n"); } } /* Convert RA and Dec limits to same units as catalog for quick filter */ ubra1 = (int) (rra1 * 360000.0 + 0.5); ubra2 = (int) (rra2 * 360000.0 + 0.5); ubdec1 = (int) ((rdec1 * 360000.0) + 32400000.5); ubdec2 = (int) ((rdec2 * 360000.0) + 32400000.5); /* Convert dra to angular units for rectangular box on sky */ dra = dra / cos (degrad (cdec)); if (nstarmax > ndist) { if (ndist > 0) free ((void *)udist); udist = (double *) malloc (nstarmax * sizeof (double)); if (udist == NULL) { fprintf (stderr,"UBCREAD: cannot allocate separation array\n"); return (0); } ndist = nstarmax; } /* Loop through region list */ nstar = 0; for (iz = 0; iz < nz; iz++) { /* Get path to zone catalog */ znum = zlist[iz]; if ((nstars = ubcopen (znum)) != 0) { jstar = 0; jtable = 0; for (iwrap = 0; iwrap <= wrap; iwrap++) { /* Find first star based on RA */ if (iwrap == 0 || wrap == 0) { istar1 = ubcsra (rra1); if (istar1 > 1) istar1 = istar1 - 1; } else istar1 = 1; /* Find last star based on RA */ if (iwrap == 1 || wrap == 0) { istar2 = ubcsra (rra2); if (istar2 < nstars) istar2 = istar2 + 1; } else istar2 = nstars; if (istar1 == 0 || istar2 == 0) break; nread = istar2 - istar1 + 1; itable = 0; /* Loop through zone catalog for this region */ for (istar = istar1; istar <= istar2; istar++) { itable ++; jtable ++; if (ubcstar (istar, &star)) { fprintf (stderr,"UBCREAD: Cannot read star %d\n", istar); break; } /* Extract selected fields */ /* Check rough position limits */ if ((star.decsec >= ubdec1 && star.decsec <= ubdec2) && ((wrap && (star.rasec>=ubra1 || star.rasec<=ubra2)) || (!wrap && (star.rasec>=ubra1 && star.rasec<=ubra2)) )){ /* Set magnitude by which to sort and test */ mag = ubcmag (star.mag[magsort]); if (sortmag == 0) { if (mag > 30.0) mag = ubcmag (star.mag[1]); if (mag > 30.0) mag = ubcmag (star.mag[2]); if (mag > 30.0) mag = ubcmag (star.mag[0]); } pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; if (pass) { nid = ubcndet (star.pmerr); if (nid < minid) { if (minid > 0 && nid > 0) pass = 0; } if (minid < 0 && nid < -minid) pass = 0; } /* Test distance limits */ if (pass) { ra0 = ubcra (star.rasec); dec0 = ubcdec (star.decsec); ra = ra0; dec = dec0; pmqual = ubcpmq (star.pm); if (nid == 0) pmqual = 10; nsg = 0; qsg = 0; for (i = 0; i < 4; i++) { if (star.mag[i] > 0) { isg = ubcsg (star.mag[i]); if (isg > 0) { nsg++; qsg = qsg + isg; } } } if (pmqual == 10 || nsg < 1) qsg = 12; else qsg = qsg / nsg; pmni = (10000 * qsg) + (100 * pmqual) + nid; /* Convert to search equinox and epoch */ if (pmqual < minpmqual) { rapm = 0.0; decpm = 0.0; rapm0 = 0.0; decpm0 = 0.0; wcscon (sysref,sysout,eqref,eqout, &ra,&dec,epout); } else { rapm0 = ubcpra (star.pm) / cos (degrad (dec)); decpm0 = ubcpdec (star.pm); rapm = rapm0; decpm = decpm0; wcsconp (sysref,sysout,eqref,eqout,epref,epout, &ra, &dec, &rapm, &decpm); } if (distsort || drad > 0.0) dist = wcsdist (cra,cdec,ra,dec); else dist = 0.0; /* Test spatial limits */ if (drad > 0.0) { if (dist > drad) pass = 0; if (dradi > 0.0 && dist < dradi) pass = 0; } else { rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; ddist = wcsdist (ra,cdec,ra,dec); if (ddist > ddec) pass = 0; } } if (pass) { num = (double) znum + (0.0000001 * (double)istar); /* Write star position and magnitudes to stdout */ if (nstarmax < 1) { CatNum (ucat, -12, 0, num, numstr); ra2str (rastr, 31, ra, 3); dec2str (decstr, 31, dec, 2); dist = wcsdist (cra,cdec,ra,dec) * 60.0; printf ("%s %s %s", numstr,rastr,decstr); for (i = 0; i < 5; i++) printf (" %.2f",ubcmag(star.mag[i])); if (objtype) { for (i = 0; i < 4; i++) printf (" %2d",ubcsg(star.mag[i])); } printf (" %6.1f %6.1f", rapm * 3600000.0 * cosdeg(dec), decpm * 3600000.0); printf (" %d %d %d", pmqual, nid, qsg); printf (" %.2f\n", dist/60.0); } /* Save star position and magnitude in table */ else if (nstar < nstarmax) { unum[nstar] = num; ura[nstar] = ra; udec[nstar] = dec; upra[nstar] = rapm; updec[nstar] = decpm; for (i = 0; i < 5; i++) umag[i][nstar] = ubcmag (star.mag[i]); upmni[nstar] = pmni; udist[nstar] = dist; if (dist > maxdist) { maxdist = dist; farstar = nstar; } if (mag > faintmag) { faintmag = mag; faintstar = nstar; } } /* If too many stars and distance sorting, replace furthest star */ else if (distsort) { if (dist < maxdist) { unum[farstar] = num; ura[farstar] = ra; udec[farstar] = dec; udec[farstar] = dec; upra[farstar] = rapm; for (i = 0; i < 5; i++) umag[i][farstar] = ubcmag (star.mag[i]); upmni[farstar] = pmni; udist[farstar] = dist; /* Find new farthest star */ if (nstarmax > 1) { maxdist = 0.0; for (i = 0; i < nstarmax; i++) { if (udist[i] > maxdist) { maxdist = udist[i]; farstar = i; } } } else { maxdist = dist; farstar = 0; } } } /* If too many stars, replace faintest star */ else if (mag < faintmag) { unum[faintstar] = num; ura[faintstar] = ra; udec[faintstar] = dec; upra[faintstar] = rapm; updec[faintstar] = decpm; for (i = 0; i < 5; i++) umag[i][faintstar] = ubcmag (star.mag[i]); upmni[faintstar] = pmni; udist[faintstar] = dist; /* Find new faintest star */ faintmag = 0.0; for (i = 0; i < nstarmax; i++) { magtest = umag[magsort][i]; if (sortmag == 0) { if (faintmag < 30.0) faintmag = umag[1][i]; if (faintmag < 30.0) faintmag = umag[2][i]; if (faintmag < 30.0) faintmag = umag[0][i]; } if (magtest > faintmag) { faintmag = magtest; faintstar = i; } } } nstar++; jstar++; if (nlog == 1) { fprintf (stderr,"UBCREAD: %04d.%07d: %9.5f %9.5f %s\n", znum,istar,ra,dec,cstr); for (i = 0; i < 5; i++) fprintf (stderr, " %5.2f", ubcmag(star.mag[i])); fprintf (stderr,"\n"); } /* End of accepted star processing */ } /* End of individual star processing */ } /* Log operation */ if (nlog > 0 && itable%nlog == 0) fprintf (stderr,"UBCREAD: zone %d (%2d / %2d) %8d / %8d / %8d sources\r", znum, iz+1, nz, jstar, itable, nread); /* End of star loop */ } /* End of wrap loop */ } /* Close zone input file */ (void) fclose (fcat); itot = itot + itable; if (nlog > 0) fprintf (stderr,"UBCREAD: zone %d (%2d / %2d) %8d / %8d / %8d sources \n", znum, iz+1, nz, jstar, jtable, nstars); /* End of zone processing */ } /* End of zone loop */ } /* Summarize search */ if (nlog > 0) { if (nz > 1) fprintf (stderr,"UBCREAD: %d zones: %d / %d found\n",nz,nstar,itot); else fprintf (stderr,"UBCREAD: 1 zone: %d / %d found\n",nstar,itable); if (nstar > nstarmax) fprintf (stderr,"UBCREAD: %d stars found; only %d returned\n", nstar,nstarmax); } return (nstar); } /* UBCRNUM -- Return USNO-B1.0 sources with specified ID numbers */ int ubcrnum (refcatname,nnum,sysout,eqout,epout,unum,ura,udec,upra,updec,umag,upmni,nlog) char *refcatname; /* Name of catalog (UBC, USAC, UBC2, USAC2) */ int nnum; /* Number of stars to find */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double *unum; /* Array of UB numbers to find */ double *ura; /* Array of right ascensions (returned) */ double *udec; /* Array of declinations (returned) */ double *upra; /* Array of right ascension proper motions (returned) */ double *updec; /* Array of declination proper motions (returned) */ double **umag; /* Array of blue and red magnitudes (returned) */ int *upmni; /* Array of number of ids and pm quality (returned) */ int nlog; /* Logging interval */ { UBCstar star; /* UB catalog entry for one star */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ int znum; int jnum; int i; int nzone; int nfound = 0; int pmqual; double ra,dec; double rapm, decpm; double dstar; int istar, pmni, nid; int nsg, qsg; char *str; /* Set catalog code and path to catalog */ if (strncasecmp (refcatname,"ub",2)==0) { if ((str = getenv("UB1_PATH")) != NULL) strcpy (ub1path,str); ucat = UB1; upath = ub1path; } else if (strncasecmp (refcatname,"yb",2)==0) { if ((str = getenv("YB6_PATH")) != NULL) strcpy (yb6path,str); ucat = YB6; upath = yb6path; } else { fprintf (stderr, "UBCREAD: %s not a USNO catalog\n", refcatname); return (0); } /* If root pathname is a URL, search and return */ if (!strncmp (upath, "http:",5)) { return (webrnum (upath,refcatname,nnum,sysout,eqout,epout,1, unum,ura,udec,upra,updec,umag,upmni,nlog)); } /* Loop through star list */ for (jnum = 0; jnum < nnum; jnum++) { /* Get path to zone catalog */ znum = (int) unum[jnum]; if ((nzone = ubcopen (znum)) != 0) { dstar = (unum[jnum] - znum) * 10000000.0; istar = (int) (dstar + 0.5); if (istar > nzone) { fprintf (stderr,"UBCRNUM: Star %d > max. in zone %d\n", istar,nzone); break; } if (ubcstar (istar, &star)) { fprintf (stderr,"UBCRNUM: Cannot read star %d\n", istar); break; } /* Extract selected fields */ else { ra = ubcra (star.rasec); /* Right ascension in degrees */ dec = ubcdec (star.decsec); /* Declination in degrees */ pmqual = ubcpmq (star.pm); nid = ubcndet (star.pmerr); if (nid == 0) pmqual = 10; nsg = 0; qsg = 0; for (i = 0; i < 4; i++) { if (star.mag[i] > 0) { nsg++; qsg = qsg + ubcsg (star.mag[i]); } } if (pmqual == 10 || nsg < 1) qsg = 12; else qsg = qsg / nsg; pmni = (10000 * qsg) + (100 * pmqual) + nid; /* Convert to desired equinox and epoch */ if (pmqual < minpmqual) { rapm = 0.0; decpm = 0.0; wcscon (sysref,sysout,eqref,eqout,&ra,&dec,epout); } else { rapm = ubcpra (star.pm); decpm = ubcpdec (star.pm); wcsconp (sysref,sysout,eqref,eqout,epref,epout, &ra, &dec, &rapm, &decpm); } /* Save star position and magnitude in table */ ura[nfound] = ra; udec[nfound] = dec; upra[nfound] = rapm; updec[nfound] = decpm; upmni[nfound] = pmni; for (i = 0; i< 5; i++) umag[i][nfound] = ubcmag (star.mag[i]); nfound++; if (nlog == 1) { fprintf (stderr,"UBCRNUM: %04d.%08d: %9.5f %9.5f", znum,istar,ra,dec); for (i = 0; i < 5; i++) fprintf (stderr, " %5.2f", ubcmag(star.mag[i])); fprintf (stderr, "\n"); } /* Log operation */ if (nlog > 0 && jnum%nlog == 0) fprintf (stderr,"UBCRNUM: %4d.%8d %8d / %8d sources\r", znum, istar, jnum, nnum); (void) fclose (fcat); /* End of star processing */ } /* End of star */ } /* End of star loop */ } /* Summarize search */ if (nlog > 0) fprintf (stderr,"UBCRNUM: %d / %d found\n",nfound,nnum); return (nfound); } /* UBCBIN -- Fill FITS WCS image with USNO-B1.0 sources */ int ubcbin (refcatname, wcs, header, image, mag1, mag2, sortmag, magscale, nlog) char *refcatname; /* Name of catalog (UB1 only, for now) */ struct WorldCoor *wcs; /* World coordinate system for image */ char *header; /* FITS header for output image */ char *image; /* Output FITS image */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 or 2) */ double magscale; /* Scaling factor for magnitude to pixel flux * (number of catalog objects per bin if 0) */ int nlog; /* Logging interval */ { double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ int nz; /* Number of input UB zone files */ int zlist[NZONES]; /* List of input UB zones */ UBCstar star; /* UB catalog entry for one star */ double rdist, ddist; int pmqual; int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ double rra1, rra2, rdec1, rdec2; double rapm, decpm, rapm0, decpm0; double xpix, ypix, flux; int offscl; int wrap, iwrap; int verbose; int znum, itot,iz, i; int ix, iy; int nsg, qsg; int jtable,jstar; int itable = 0; int nstar, nread, pass; int ubra1, ubra2, ubdec1, ubdec2; double ra,dec, ra0, dec0; double mag, secmarg; int istar, istar1, istar2, pmni, nid; int nzmax = NZONES; /* Maximum number of declination zones */ int bitpix, w, h; /* Image bits/pixel and pixel width and height */ int magsort; char *str; char cstr[32]; double logt = log(10.0); itot = 0; if (nlog > 0) verbose = 1; else verbose = 0; /* Set catalog code and path to catalog */ if (strncasecmp (refcatname,"ub",2)==0) { if ((str = getenv("UB1_PATH")) != NULL) strcpy (ub1path,str); ucat = UB1; upath = ub1path; } else if (strncasecmp (refcatname,"yb",2)==0) { if ((str = getenv("YB6_PATH")) != NULL) strcpy (yb6path,str); ucat = YB6; upath = yb6path; } else { fprintf (stderr, "UBCBIN: %s not a USNO catalog\n", refcatname); return (0); } /* Set catalog search limits from image WCS information */ sysout = wcs->syswcs; eqout = wcs->equinox; epout = wcs->epoch; wcscstr (cstr, sysout, eqout, epout); wcssize (wcs, &cra, &cdec, &dra, &ddec); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* mag1 is always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } /* Bin using 4th magnitude = R2 if sort magnitude is not set */ if (sortmag > 0 && sortmag < 6) magsort = sortmag - 1; else magsort = 3; /* Set image parameters */ bitpix = 0; (void)hgeti4 (header, "BITPIX", &bitpix); w = 0; (void)hgeti4 (header, "NAXIS1", &w); h = 0; (void)hgeti4 (header, "NAXIS2", &h); /* Add 60 arcsec/century margins to region to get most stars which move */ if (minpmqual < 11 && (epout != 0.0 || sysout != sysref)) secmarg = 60.0; else secmarg = 0.0; /* Find RA and Dec limits in catalog coordinate system */ RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref,secmarg, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); /* Find declination zones to search */ nz = ubczones (rra1, rra2, rdec1, rdec2, nzmax, zlist, verbose); if (nz <= 0) { fprintf (stderr, "UBCBIN: no USNO B zones found\n"); return (0); } /* Convert RA and Dec limits to same units as catalog for quick filter */ ubra1 = (int) (rra1 * 360000.0 + 0.5); ubra2 = (int) (rra2 * 360000.0 + 0.5); ubdec1 = (int) ((rdec1 * 360000.0) + 32400000.5); ubdec2 = (int) ((rdec2 * 360000.0) + 32400000.5); /* Convert dra to angular units for rectangular box on sky */ dra = dra / cos (degrad (cdec)); /* Loop through region list */ nstar = 0; for (iz = 0; iz < nz; iz++) { /* Get path to zone catalog */ znum = zlist[iz]; if ((nstars = ubcopen (znum)) != 0) { jstar = 0; jtable = 0; for (iwrap = 0; iwrap <= wrap; iwrap++) { /* Find first star based on RA */ if (iwrap == 0 || wrap == 0) { istar1 = ubcsra (rra1); if (istar1 > 1) istar1 = istar1 - 1; } else istar1 = 1; /* Find last star based on RA */ if (iwrap == 1 || wrap == 0) { istar2 = ubcsra (rra2); if (istar2 < nstars) istar2 = istar2 + 1; } else istar2 = nstars; if (istar1 == 0 || istar2 == 0) break; nread = istar2 - istar1 + 1; itable = 0; /* Loop through zone catalog for this region */ for (istar = istar1; istar <= istar2; istar++) { itable ++; jtable ++; if (ubcstar (istar, &star)) { fprintf (stderr,"UBCBIN: Cannot read star %d\n", istar); break; } /* Extract selected fields */ /* Check rough position limits */ if ((star.decsec >= ubdec1 && star.decsec <= ubdec2) && ((wrap && (star.rasec>=ubra1 || star.rasec<=ubra2)) || (!wrap && (star.rasec>=ubra1 && star.rasec<=ubra2)) )){ /* Set magnitude by which to sort and test */ mag = ubcmag (star.mag[magsort]); if (sortmag == 0) { if (mag > 30.0) mag = ubcmag (star.mag[1]); if (mag > 30.0) mag = ubcmag (star.mag[2]); if (mag > 30.0) mag = ubcmag (star.mag[0]); } pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; if (pass) { nid = ubcndet (star.pmerr); if (nid < minid) { if (minid > 0 && nid > 0) pass = 0; } if (minid < 0 && nid < -minid) pass = 0; } /* Test distance limits */ if (pass) { ra0 = ubcra (star.rasec); dec0 = ubcdec (star.decsec); ra = ra0; dec = dec0; pmqual = ubcpmq (star.pm); if (nid == 0) pmqual = 10; nsg = 0; qsg = 0; for (i = 0; i < 4; i++) { if (star.mag[i] > 0) { nsg++; qsg = qsg + ubcsg (star.mag[i]); } } if (pmqual == 10 || nsg < 1) qsg = 12; else qsg = qsg / nsg; pmni = (10000 * qsg) + (100 * pmqual) + nid; /* Convert to search equinox and epoch */ if (pmqual < minpmqual) { rapm = 0.0; decpm = 0.0; rapm0 = 0.0; decpm0 = 0.0; wcscon (sysref,sysout,eqref,eqout, &ra,&dec,epout); } else { rapm0 = ubcpra (star.pm) / cos (degrad (dec)); decpm0 = ubcpdec (star.pm); rapm = rapm0; decpm = decpm0; wcsconp (sysref,sysout,eqref,eqout,epref,epout, &ra, &dec, &rapm, &decpm); } /* Test spatial limits */ rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; ddist = wcsdist (ra,cdec,ra,dec); if (ddist > ddec) pass = 0; } /* Save star in FITS image */ if (pass) { wcs2pix (wcs, ra, dec, &xpix, &ypix, &offscl); if (!offscl) { if (magscale > 0.0) flux = magscale * exp (logt * (-mag / 2.5)); else flux = 1.0; ix = (int) (xpix + 0.5); iy = (int) (ypix + 0.5); addpix1 (image, bitpix, w, h, 0.0, 1.0, ix, iy, flux); nstar++; jstar++; if (nlog == 1) { flux = getpix1 (image, bitpix, w, h, 0.0, 1.0, ix, iy); fprintf (stderr,"UBCBIN: %d %04d.%07d: %9.5f %9.5f %s", nstar,znum,nstar,ra,dec,cstr); if (magscale > 0.0) fprintf (stderr, " %5.2f", mag); fprintf (stderr," %5d %5d: %f\n", ix, iy, flux); } } /* End of accepted star processing */ } /* End of individual star processing */ } /* Log operation */ if (nlog > 0 && itable%nlog == 0) fprintf (stderr,"UBCBIN: zone %d (%2d / %2d) %8d / %8d / %8d sources\r", znum, iz+1, nz, jstar, itable, nread); /* End of star loop */ } /* End of wrap loop */ } /* Close zone input file */ (void) fclose (fcat); itot = itot + itable; if (nlog > 0) fprintf (stderr,"UBCBIN: zone %d (%2d / %2d) %8d / %8d / %8d sources \n", znum, iz+1, nz, jstar, jtable, nstars); /* End of zone processing */ } /* End of zone loop */ } /* Summarize search */ if (nlog > 0) { if (nz > 1) fprintf (stderr,"UBCBIN: %d zones: %d / %d found\n",nz,nstar,itot); else fprintf (stderr,"UBCBIN: 1 zone: %d / %d found\n",nstar,itable); } return (nstar); } /* UBCZONES -- figure out which UB zones will need to be searched */ static int ubczones (ra1, ra2, dec1, dec2, nzmax, zones, verbose) double ra1, ra2; /* Right ascension limits in degrees */ double dec1, dec2; /* Declination limits in degrees */ int nzmax; /* Maximum number of zones to find */ int *zones; /* Region numbers (returned)*/ int verbose; /* 1 for diagnostics */ { int nrgn; /* Number of zones found (returned) */ int iz,iz1,iz2,i; for (i = 0; i < nzmax; i++) zones[i] = 0; nrgn = 0; /* Find zone range to search based on declination */ iz1 = ubczone (dec1); iz2 = ubczone (dec2); /* Tabulate zones to search */ i = 0; if (iz2 >= iz1) { for (iz = iz1; iz <= iz2; iz++) zones[i++] = iz; } else { for (iz = iz2; iz <= iz1; iz++) zones[i++] = iz; } nrgn = i; if (verbose) { fprintf(stderr,"UBCZONES: %d zones: %d - %d\n",nrgn,zones[0],zones[i-1]); fprintf(stderr,"UBCZONES: RA: %.5f - %.5f, Dec: %.5f - %.5f\n",ra1,ra2,dec1,dec2); } return (nrgn); } /* UBCRA -- returns right ascension in degrees from the UB star structure */ static double ubcra (rasec) int rasec; /* RA in 100ths of arcseconds from UB catalog entry */ { return ((double) (rasec) / 360000.0); } /* UBCDEC -- returns the declination in degrees from the UB star structure */ static double ubcdec (decsec) int decsec; /* Declination in 100ths of arcseconds from UB catalog entry */ { return ((double) (decsec - 32400000) / 360000.0); } /* UBCMAG -- returns a magnitude from the UBC star structure */ static double ubcmag (magetc) int magetc; /* Magnitude 4 bytes from UB catalog entry */ { double xmag; if (ucat == YB6) xmag = 0.001 * (double) magetc; else if (magetc < 0) xmag = (double) (-magetc % 10000) * 0.01; else xmag = (double) (magetc % 10000) * 0.01; if (xmag == 0.00) xmag = 99.99; return (xmag); } /* UBCPRA -- returns RA proper motion in arcsec/year from UBC star structure */ static double ubcpra (magetc) int magetc; /* Proper motion field from UB catalog entry */ { double pm; if (magetc < 0) pm = (double) (-magetc % 10000); else pm = (double) (magetc % 10000); pm = ((pm * 0.002) - 10.0) / 3600.0; return (pm); } /* UBCPDEC -- returns Dec proper motion in arcsec/year from UBC star structure */ static double ubcpdec (magetc) int magetc; /* Proper motion field from UB catalog entry */ { double pm; if (ucat == YB6) pm = (double) (magetc / 10000); else if (magetc < 0) pm = (double) ((-magetc % 100000000) / 10000); else pm = (double) ((magetc % 100000000) / 10000); pm = ((pm * 0.002) - 10.0) / 3600.0; return (pm); } /* UBCPMQ -- returns proper motion probability (1-9) */ static int ubcpmq (magetc) int magetc; /* Quality, plate, and magnitude from UB catalog entry */ { if (magetc < 0) return (-magetc / 100000000); else return (magetc / 100000000); } /* UBCMAGERR -- returns 1 if magnitude is uncertain from UB star structure */ int ubcmagerr (magetc) int magetc; /* Quality, plate, and magnitude from UB catalog entry */ { if (magetc < 0) return ((-magetc / 1000000000) % 10); else return ((magetc / 1000000000) % 10); } /* UBCNDET -- returns number of detections; 0 = Tycho-2 Catalog */ static int ubcndet (magetc) int magetc; /* Quality, plate, and magnitude from UB catalog entry */ { if (ucat == YB6) return (0); else if (magetc < 0) return (-magetc / 100000000); else return (magetc / 100000000); } /* UBCSG -- returns closeness to star PSF (0-11) */ static int ubcsg (magetc) int magetc; /* Quality, plate, and magnitude from UB catalog entry */ { if (ucat == YB6) return (0); else if (magetc < 0) return (-magetc / 100000000); else return (magetc / 100000000); } /* UBCZONE -- find the UB zone number where a declination can be found */ static int ubczone (dec) double dec; /* declination in degrees */ { double zonesize = 0.1; /* number of degrees per declination zone */ int zone; zone = (int) ((dec + 90.0) / zonesize); if (zone > 1799) zone = 1799; else if (zone < 0) zone = 0; return (zone); } /* UBCSRA -- Find UB star closest to specified right ascension */ static int ubcsra (rax0) double rax0; /* Right ascension in degrees for which to search */ { int istar, istar1, istar2, nrep; double rax, ra1, ra, rdiff, rdiff1, rdiff2, sdiff; UBCstar star; /* UB catalog entry for one star */ char rastrx[32]; int debug = 0; rax = rax0; if (debug) ra2str (rastrx, 31, rax, 3); istar1 = 1; if (ubcstar (istar1, &star)) return (0); ra1 = ubcra (star.rasec); istar = nstars; nrep = 0; while (istar != istar1 && nrep < 30) { if (ubcstar (istar, &star)) break; else { ra = ubcra (star.rasec); if (ra == ra1) break; if (debug) { char rastr[32]; ra2str (rastr, 31, ra, 3); fprintf (stderr,"UBCSRA %d %d: %s (%s)\n", nrep,istar,rastr,rastrx); } rdiff = ra1 - ra; rdiff1 = ra1 - rax; rdiff2 = ra - rax; if (nrep > 25 && ABS(rdiff2) > ABS(rdiff1)) { istar = istar1; break; } nrep++; sdiff = (double)(istar - istar1) * rdiff1 / rdiff; istar2 = istar1 + (int) (sdiff + 0.5); ra1 = ra; if (debug) { fprintf (stderr," ra1= %.5f ra= %.5f rax= %.5f\n", ra1,ra,rax); fprintf (stderr," rdiff= %.5f rdiff1= %.5f rdiff2= %.5f\n", rdiff,rdiff1,rdiff2); fprintf (stderr," istar1= %d istar= %d istar2= %d\n", istar1,istar,istar2); } istar1 = istar; istar = istar2; if (istar < 1) istar = 1; if (istar > nstars) istar = nstars; if (istar == istar1) break; } } return (istar); } /* UBCOPEN -- Open UB Catalog zone catalog, returning number of entries */ static int ubcopen (znum) int znum; /* UB Catalog zone */ { char zonepath[64]; /* Pathname for input UB zone file */ UBCstar star; /* UB catalog entry for one star */ int lfile; /* Get path to zone catalog */ if (ubcpath (znum, zonepath)) { fprintf (stderr, "UBCOPEN: Cannot find zone catalog for %d\n", znum); return (0); } /* Find number of stars in zone catalog by its length */ lfile = getfilesize (zonepath); if (lfile < 2) { fprintf (stderr,"UB zone catalog %s has no entries\n",zonepath); return (0); } else nstars = lfile / nbent; /* Open zone catalog */ if (!(fcat = fopen (zonepath, "rb"))) { fprintf (stderr,"UB zone catalog %s cannot be read\n",zonepath); return (0); } /* Check to see if byte-swapping is necessary */ cswap = 0; if (ubcstar (1, &star)) { fprintf (stderr,"UBCOPEN: cannot read star 1 from UB zone catalog %s\n", zonepath); return (0); } else { if (star.rasec > 360 * 360000 || star.rasec < 0) { cswap = 1; /* fprintf (stderr,"UBCOPEN: swapping bytes in UB zone catalog %s\n", zonepath); */ } else if (star.decsec > 180 * 360000 || star.decsec < 0) { cswap = 1; /* fprintf (stderr,"UBCOPEN: swapping bytes in UB zone catalog %s\n", zonepath); */ } else cswap = 0; } return (nstars); } /* UBCPATH -- Get UB Catalog region file pathname */ static int ubcpath (zn, path) int zn; /* UB zone number */ char *path; /* Pathname of UB zone file */ { /* Return error code and null path if zone is out of range */ if (zn < 0 || zn > 1799) { fprintf (stderr, "UBCPATH: zone %d out of range 0-1799\n",zn); path[0] = (char) 0; return (-1); } /* Set path for USNO-B1.0 zone catalog */ sprintf (path,"%s/%03d/b%04d.cat", upath, zn/10, zn); return (0); } /* UBCSTAR -- Get UB catalog entry for one star; return 0 if successful */ static int ubcstar (istar, star) int istar; /* Star sequence number in UB zone catalog */ UBCstar *star; /* UB catalog entry for one star */ { int nbs, nbr, nbskip; if (istar < 1 || istar > nstars) { fprintf (stderr, "UBCstar %d is not in catalog\n",istar); return (-1); } nbskip = nbent * (istar - 1); if (fseek (fcat,nbskip,SEEK_SET)) return (-1); nbs = sizeof (UBCstar); nbr = fread (star, nbs, 1, fcat) * nbs; if (nbr < nbs) { fprintf (stderr, "UBCstar %d / %d bytes read\n",nbr, nbs); return (-2); } if (cswap) ubcswap ((char *)star); return (0); } /* UBCSWAP -- Reverse bytes of UB Catalog entry */ static void ubcswap (string) char *string; /* Start of vector of 4-byte ints */ { char *sbyte, *slast; char temp0, temp1, temp2, temp3; int nbytes = nbent; /* Number of bytes to reverse */ slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp3 = sbyte[0]; temp2 = sbyte[1]; temp1 = sbyte[2]; temp0 = sbyte[3]; sbyte[0] = temp0; sbyte[1] = temp1; sbyte[2] = temp2; sbyte[3] = temp3; sbyte = sbyte + 4; } return; } /* Jan 30 2003 New subroutine based on ubcread.c * Feb 4 2003 Open catalog file rb instead of r (Martin Ploner, Bern) * Mar 21 2003 Improve search limit test by always using wcsdist() * Apr 15 2003 Explicitly get revision date if nstarmax < 1 * May 27 2003 Use getfilesize() to get file size * Jun 2 2003 Print proper motion as mas/year * Aug 22 2003 Add radi argument for inner edge of search annulus * Sep 25 2003 Add ubcbin() to fill an image with sources * Oct 6 2003 Update ubcread() and ubcbin() for improved RefLim() * Dec 1 2003 Add missing tab to n=-1 header * Dec 4 2003 Add USNO YB6 catalog * Dec 12 2003 Fix bug in wcs2pix() call in ubcbin() * * Aug 27 2004 Include fitsfile.h * Nov 19 2004 Return galaxy/star type code (qsg=0-11) in upmni vector * * Jan 12 2005 Declare ubcsg() * * Jun 20 2006 Drop unused variables * Sep 26 2006 Increase length of rastr and destr from 16 to 32 * Nov 15 2006 Print coordinates if in verbose mode; convert coords to integer * * Jan 10 2007 Add match=1 argument to webrnum() * Nov 26 2007 Add one at each end of search range in ubcread() * Dec 05 2007 Add option to print per magnitude star/galaxy discriminators if ub1t * Dec 05 2007 Drop sg flag=0 from average qsg */ wcstools-3.9.5/libwcs/ucacread.c0000664000016200001660000016464212732776254015705 0ustar minkoirsys/*** File libwcs/ucacread.c *** June 22, 2016 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 2003-2016 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * ucacread() Read UCAC Star Catalog stars in a rectangle on the sky * ucacrnum() Read UCAC Star Catalog stars by number * ucacbin() Fill a FITS WECS image with UCAC Star Catalog stars * ucaczones() Make list of zones covered by a range of declinations * ucacsra (sc,st,zone,rax0) Find UCAC star closest to specified right ascension * ucacopen(zone, nstars) Open UCAC catalog file, returning number of entries * ucacclose (sc) Close UCAC catalog file * ucacstar (sc,st,zone,istar) Get UCAC catalog entry for one star */ #include #include #include #include #include #include #include "fitsfile.h" #include "wcs.h" #include "wcscat.h" #define MAXZONE 900 #define ABS(a) ((a) < 0 ? (-(a)) : (a)) /* #define UCAC_DEBUG 1 */ typedef struct { int rasec, decsec; short cmag; unsigned char era, edec, nobs, rflg, ncat, cflg; short epra, epdec; int rapm, decpm; unsigned char erapm, edecpm, qrapm, qdecpm; int id2m; short jmag, hmag, kmag, qm, cc; } UCAC2star; typedef struct { int rasec, decsec; short mmag, amag, sigmag; char objt, dsf; short sigra, sigdec; char na1, nu1, us1, cn1; short cepra, cepdec; int rapm, decpm; short sigpmr, sigpmd; int id2m; short jmag, hmag, kmag; char jq, hq, kq; char e2mpho[3]; short bmag, rmag, imag; char clbl; char bq, rq, iq; char catflg[10]; char g1, c1, leda, x2m; int rn; } UCAC3star; /* The following is from ucac4.h */ #pragma pack( 1) typedef struct { int32_t ra, spd; /* RA/dec at J2000.0, ICRS, in milliarcsec */ uint16_t magm, maga; /* UCAC fit model & aperture mags, .001 mag */ uint8_t mag_sigma; uint8_t obj_type, double_star_flag; int8_t ra_sigma, dec_sigma; /* sigmas in RA and dec at central epoch */ uint8_t n_ucac_total; /* Number of UCAC observations of this star */ uint8_t n_ucac_used; /* # UCAC observations _used_ for this star */ uint8_t n_cats_used; /* # catalogs (epochs) used for prop motion */ uint16_t epoch_ra; /* Central epoch for mean RA, minus 1900, .01y */ uint16_t epoch_dec; /* Central epoch for mean DE, minus 1900, .01y */ int16_t pm_ra; /* prop motion, .1 mas/yr = .01 arcsec/cy */ int16_t pm_dec; /* prop motion, .1 mas/yr = .01 arcsec/cy */ int8_t pm_ra_sigma; /* sigma in same units */ int8_t pm_dec_sigma; uint32_t twomass_id; /* 2MASS pts_key star identifier */ uint16_t mag_j, mag_h, mag_k; /* 2MASS J, H, K_s mags, in millimags */ uint8_t icq_flag[3]; uint8_t e2mpho[3]; /* 2MASS error photometry (in centimags) */ uint16_t apass_mag[5]; /* in millimags */ uint8_t apass_mag_sigma[5]; /* also in millimags */ uint8_t yale_gc_flags; /* Yale SPM g-flag * 10 + c-flag */ uint32_t catalog_flags; uint8_t leda_flag; /* LEDA galaxy match flag */ uint8_t twomass_ext_flag; /* 2MASS extended source flag */ uint32_t id_number; uint16_t ucac2_zone; uint32_t ucac2_number; } UCAC4star; #pragma pack( ) /* Fields in the u4hpm.dat file */ #define MAX_U4HPM_RECORDS 50 #define MAX_U4HPM_LINE 512 typedef struct u4hpm { int rnm; /* unique star identifier (col. 51 main data) */ int zn; /* UCAC4 zone number for this star */ int rnz; /* unning record number along that zone for this star */ int pmrc; /* actual proper motion in RA*cos(dec) [0.1 mas/yr] */ int pmd; /* actual proper motion in Dec [0.1 mas/yr] */ int ra; /* col. 1 of main data file (redundant) */ int dec; /* col. 2 of main data file (redundant) */ int maga; /* col. 4 of main data file (redundant) */ } U4HPM,*PU4HPM; int hpmLines = 0; U4HPM u4hpm_table[MAX_U4HPM_RECORDS]; /* pathname of UCAC1 decompressed data files or search engine URL */ char ucac1path[64]="/data/astrocat/ucac1"; /* pathname of UCAC2 decompressed data files or search engine URL */ char ucac2path[64]="/data/astrocat/ucac2"; /* pathname of UCAC3 decompressed data files or search engine URL */ char ucac3path[64]="/data/astrocat/ucac3"; /* pathname of UCAC4 decompressed data files or search engine URL */ char ucac4path[64]="/data/astrocat/ucac4/u4b"; /* Path name of UCAC4 proper motion catalog */ char hpmpath[] = "/data/astrocat/ucac4/u4i/u4hpm.dat"; char *ucacpath; static int ucat = 0; static double *gdist; /* Array of distances to stars */ static int ndist = 0; static int cswap = 0; /* Byte reverse catalog to Mac/Sun/network order if 1 */ static int ucaczones(); struct StarCat *ucacopen(); void ucacclose(); static int ucacsra(); static int ucacstar(); static void ucacswap4(); static void ucacswap2(); /* UCACREAD -- Read UCAC Star Catalog stars */ int ucacread (refcatname,cra,cdec,dra,ddec,drad,dradi,distsort,sysout,eqout,epout, mag1,mag2,sortmag,nstarmax,gnum,gra,gdec,gpra,gpdec,gmag,gtype,nlog) char *refcatname; /* Name of catalog (UAC, USAC, UAC2, USAC2) */ double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ double dradi; /* Inner edge of annulus in degrees (ignore if 0) */ int distsort; /* 1 to sort stars by distance from center */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1-8) */ int nstarmax; /* Maximum number of stars to be returned */ double *gnum; /* Array of Guide Star numbers (returned) */ double *gra; /* Array of right ascensions (returned) */ double *gdec; /* Array of declinations (returned) */ double *gpra; /* Array of right ascension proper motions (returned) */ double *gpdec; /* Array of declination proper motions (returned) */ double **gmag; /* Array of magnitudes (returned) */ int *gtype; /* Array of object types (returned) */ int nlog; /* 1 for diagnostics */ { double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ double dist = 0.0; /* Distance from search center in degrees */ double faintmag=0.0; /* Faintest magnitude */ double maxdist=0.0; /* Largest distance */ int faintstar=0; /* Faintest star */ int farstar=0; /* Most distant star */ int nz; /* Number of UCAC regions in search */ int zlist[MAXZONE]; /* List of region numbers */ int sysref = WCS_J2000; /* Catalog coordinate system */ double eqref = 2000.0; /* Catalog equinox */ double epref = 2000.0; /* Catalog epoch */ double secmarg = 60.0; /* Arcsec/century margin for proper motion */ struct StarCat *starcat; /* Star catalog data structure */ struct Star *star; /* Single star data structure */ double errra, errdec, errpmr, errpmd; int nim, ncat; int verbose; int wrap; int iz; int magsort; int jstar; int nrmax = MAXZONE; int nstar,i, ntot, imag; int istar, istar1, istar2; int jtable,iwrap, nread; int pass; int zone; int nmag; double num, ra, dec, rapm, decpm, mag; double rra1, rra2, rdec1, rdec2; double rdist, ddist; char cstr[32], rastr[32], decstr[32]; char ucacenv[16]; char *str; ntot = 0; if (nlog > 0) verbose = 1; else verbose = 0; /* Set catalog code and path to catalog */ if (strncmp (refcatname,"ucac2",5)==0 || strncmp (refcatname,"UCAC2",5)==0) { ucat = UCAC2; ucacpath = ucac2path; strcpy (ucacenv, "UCAC2_PATH"); nmag = 4; } else if (strncmp (refcatname,"ucac3",5)==0 || strncmp (refcatname,"UCAC3",5)==0) { ucat = UCAC3; ucacpath = ucac3path; strcpy (ucacenv, "UCAC3_PATH"); nmag = 8; } else if (strncmp (refcatname,"ucac4",5)==0 || strncmp (refcatname,"UCAC4",5)==0) { ucat = UCAC4; ucacpath = ucac4path; strcpy (ucacenv, "UCAC4_PATH"); nmag = 10; } else { ucat = UCAC1; ucacpath = ucac1path; strcpy (ucacenv, "UCAC1_PATH"); nmag = 1; } /* If pathname is set in environment, override local value */ if ((str = getenv (ucacenv)) != NULL ) ucacpath = str; /* If pathname is a URL, search and return */ if (!strncmp (ucacpath, "http:",5)) { return (webread (ucacpath,refcatname,distsort,cra,cdec,dra,ddec,drad, dradi,sysout,eqout,epout,mag1,mag2,sortmag,nstarmax, gnum,gra,gdec,gpra,gpdec,gmag,gtype,nlog)); } wcscstr (cstr, sysout, eqout, epout); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* Make mag1 always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } if (sortmag < 1) magsort = 0; else if (sortmag > nmag) magsort = nmag - 1; else magsort = sortmag - 1; /* Allocate table for distances of stars from search center */ if (nstarmax > ndist) { if (ndist > 0) free ((void *)gdist); gdist = (double *) malloc (nstarmax * sizeof (double)); if (gdist == NULL) { fprintf (stderr,"UCACREAD: cannot allocate separation array\n"); return (0); } ndist = nstarmax; } /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; nstar = 0; jstar = 0; /* Get RA and Dec limits in catalog (J2000) coordinates */ rra1 = ra1; rra2 = ra2; rdec1 = dec1; rdec2 = dec2; RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref,secmarg, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); /* Find UCAC Star Catalog zones in which to search */ nz = ucaczones (rdec1,rdec2,nrmax,zlist,verbose); if (nz <= 0) { fprintf (stderr,"UCACREAD: no UCAC zone for %.2f-%.2f %.2f %.2f\n", rra1, rra2, rdec1, rdec2); return (0); } /* Write header if printing star entries as found */ if (nstarmax < 1) { char *revmessage; revmessage = getrevmsg(); printf ("catalog UCAC1\n"); ra2str (rastr, 31, cra, 3); printf ("ra %s\n", rastr); dec2str (decstr, 31, cdec, 2); printf ("dec %s\n", decstr); printf ("rpmunit mas/year\n"); printf ("dpmunit mas/year\n"); if (drad != 0.0) { printf ("radmin %.1f\n", drad*60.0); if (dradi > 0) printf ("radimin %.1f\n", dradi*60.0); } else { printf ("dramin %.1f\n", dra*60.0* cosdeg (cdec)); printf ("ddecmin %.1f\n", ddec*60.0); } printf ("radecsys %s\n", cstr); printf ("equinox %.3f\n", eqout); printf ("epoch %.3f\n", epout); printf ("program scat %s\n", revmessage); printf ("ucac_id ra dec "); if (ucat == UCAC1) { printf ("mag ura udec arcmin\n"); printf ("---------- ------------ ------------ "); printf ("----- ------ ------ ------\n"); } else if (ucat == UCAC2) { printf ("raerr decerr magc "); printf ("magj magh magk mag "); printf ("pmra pmdec pmrerr pmderr "); printf ("ni nc arcsec\n"); printf ("---------- ------------ ------------ "); printf ("------ ------ ----- ----- ----- "); printf ("----- ----- ------ ------ ----- ----- "); printf ("-- -- ------\n"); } else if (ucat == UCAC3) { printf ("raerr decerr magb magr magi "); printf ("magj magh magk maga magm "); printf ("mag pmra pmdec pmrerr pmderr "); printf ("ni nc arcsec\n"); printf ("---------- ------------ ------------ "); printf ("------ ------ ----- ------ ----- "); printf ("----- ----- ----- ----- ----- "); printf ("----- ----- ----- ------ ------ "); printf ("-- -- ------\n"); } else if (ucat == UCAC4) { printf ("raerr decerr magb magv magg "); printf ("magr magi magj magj magk "); printf ("pmra pmdec pmrerr pmderr "); printf ("ni nc arcsec\n"); printf ("---------- ------------ ------------ "); printf ("------ ------ ----- ------ ----- "); printf ("----- ----- ----- ----- ----- "); printf ("----- ----- ------ ------ "); printf ("-- -- ------\n"); } } /* Loop through zone list */ nstar = 0; for (iz = 0; iz < nz; iz++) { /* Get path to zone catalog */ zone = zlist[iz]; #ifdef UCAC_DEBUG if (zone == 183) { fprintf(stderr,"at zone %d\n",zone); } #endif /* UCAC_DEBUG */ if ((starcat = ucacopen (zone)) != 0) { jstar = 0; jtable = 0; for (iwrap = 0; iwrap <= wrap; iwrap++) { /* Find first star based on RA */ if (iwrap == 0 || wrap == 0) { istar1 = ucacsra (starcat, star, zone, rra1); if (istar1 > 5) istar1 = istar1 - 5; else istar1 = 1; } else istar1 = 1; /* Find last star based on RA */ if (iwrap == 1 || wrap == 0) { istar2 = ucacsra (starcat, star, zone, rra2); if (istar2 < starcat->nstars - 5) istar2 = istar2 + 5; else istar2 = starcat->nstars; } else istar2 = starcat->nstars; if (istar1 == 0 || istar2 == 0) break; nread = istar2 - istar1 + 1; /* Loop through zone catalog for this region */ for (istar = istar1; istar <= istar2; istar++) { jtable ++; if (ucacstar (starcat, star, zone, istar)) { fprintf(stderr,"UCACREAD: Cannot read star %d\n",istar); break; } /* ID number */ num = star->num; /* Magnitude */ mag = star->xmag[magsort]; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; /* Check position limits */ if (pass) { /* Get position in output coordinate system */ ra = star->ra; dec = star->dec; rapm = star->rapm; decpm = star->decpm; errra = star->errra; errdec = star->errdec; errpmr = star->errpmr; errpmd = star->errpmd; nim = star->nimage; ncat = star->ncat; wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); /* Compute distance from search center */ if (drad > 0 || distsort) dist = wcsdist (cra,cdec,ra,dec); else dist = 0.0; /* Check radial distance to search center */ if (drad > 0) { if (dist > drad) pass = 0; if (dradi > 0.0 && dist < dradi) pass = 0; } /* Check distance along RA and Dec axes */ else { ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } } if (pass) { /* Write star position and magnitude to stdout */ if (nstarmax < 1) { ra2str (rastr, 31, ra, 3); dec2str (decstr, 31, dec, 2); dist = wcsdist (cra,cdec,ra,dec) * 3600.0; printf ("%010.6f %s %s", num,rastr,decstr); if (ucat == UCAC2 || ucat == UCAC3 || ucat == UCAC4) printf (" %5.3f %5.3f", errra * 3600.0 * cosdeg (dec), errdec * 3600.0); if (ucat == UCAC1) printf (" %5.2f", mag); else printf (" %5.2f %5.2f %5.2f %5.2f", star->xmag[0], star->xmag[1], star->xmag[2], star->xmag[3]); if (ucat == UCAC3 || ucat == UCAC4) printf (" %5.2f %5.2f %5.2f %5.2f", star->xmag[4], star->xmag[5], star->xmag[6], star->xmag[7]); printf (" %5.2f %6.1f %6.1f", mag, rapm*3600000.0*cosdeg (dec), decpm*3600000.0); printf (" %6.1f %6.1f", errpmr*3600000.0, errpmd*3600000.0); printf (" %2d %2d %.3f\n", nim, ncat, dist); } /* Save star position and magnitude in table */ else if (nstar < nstarmax) { gnum[nstar] = num; gra[nstar] = ra; gdec[nstar] = dec; gpra[nstar] = rapm; gpdec[nstar] = decpm; if (ucat == UCAC1) gmag[0][nstar] = mag; else { for (imag = 0; imag < nmag; imag++) gmag[imag][nstar] = star->xmag[imag]; gmag[nmag][nstar] = star->errra; gmag[nmag+1][nstar] = star->errdec; gmag[nmag+2][nstar] = star->errpmr; gmag[nmag+3][nstar] = star->errpmd; gtype[nstar] = (1000 * nim) + ncat; } gdist[nstar] = dist; if (dist > maxdist) { maxdist = dist; farstar = nstar; } if (mag > faintmag) { faintmag = mag; faintstar = nstar; } } /* If too many stars and distance sorting, replace farthest star */ else if (distsort) { if (dist < maxdist) { gnum[farstar] = num; gra[farstar] = ra; gdec[farstar] = dec; gpra[farstar] = rapm; gpdec[farstar] = decpm; if (ucat == UCAC1) gmag[0][farstar] = mag; else { for (imag = 0; imag < nmag; imag++) gmag[imag][farstar] = star->xmag[imag]; gmag[nmag][farstar] = star->errra; gmag[nmag+1][farstar] = star->errdec; gmag[nmag+2][farstar] = star->errpmr; gmag[nmag+3][farstar] = star->errpmd; gtype[farstar] = (1000 * nim) + ncat; } gdist[farstar] = dist; /* Find new farthest star */ maxdist = 0.0; for (i = 0; i < nstarmax; i++) { if (gdist[i] > maxdist) { maxdist = gdist[i]; farstar = i; } } } } /* Else if too many stars, replace faintest star */ else if (mag < faintmag) { gnum[faintstar] = num; gra[faintstar] = ra; gdec[faintstar] = dec; gpra[faintstar] = rapm; gpdec[faintstar] = decpm; if (ucat == UCAC1) gmag[0][faintstar] = mag; else { for (imag = 0; imag < nmag; imag++) gmag[imag][faintstar] = star->xmag[imag]; gmag[nmag][faintstar] = star->errra; gmag[nmag+1][faintstar] = star->errdec; gmag[nmag+2][faintstar] = star->errpmr; gmag[nmag+3][faintstar] = star->errpmd; gtype[faintstar] = (1000 * nim) + ncat; } gdist[faintstar] = dist; /* Find new faintest star */ faintmag = 0.0; for (i = 0; i < nstarmax; i++) { if (gmag[magsort][i] > faintmag) { faintmag = gmag[magsort][i]; faintstar = i; } } } nstar++; if (nlog == 1) fprintf (stderr,"UCACREAD: %11.6f: %9.5f %9.5f %5.2f\n", num,ra,dec,mag); /* End of accepted star processing */ } /* Log operation */ jstar++; if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"UCACREAD: %5d / %5d / %5d sources\r", nstar,jstar,starcat->nstars); /* End of star loop */ } /* End of 0:00 RA wrap loop */ } /* End of successful zone file loop */ ntot = ntot + starcat->nstars; if (nlog > 0) fprintf (stderr,"UCACREAD: %4d / %4d: %5d / %5d / %5d sources from zone %4d \n", iz+1,nz,nstar,jstar,starcat->nstars,zlist[iz]); /* Close region input file */ ucacclose (starcat); } /* End of zone loop */ } /* Summarize transfer */ if (nlog > 0) { if (nz > 1) fprintf (stderr,"UCACREAD: %d zones: %d / %d found\n",nz,nstar,ntot); else fprintf (stderr,"UCACREAD: 1 region: %d / %d found\n",nstar,ntot); if (nstar > nstarmax) fprintf (stderr,"UCACREAD: %d stars found; only %d returned\n", nstar,nstarmax); } return (nstar); } /* UCACRNUM -- Read HST Guide Star Catalog stars from CDROM */ int ucacrnum (refcatname,nstars,sysout,eqout,epout, gnum,gra,gdec,gpra,gpdec,gmag,gtype,nlog) char *refcatname; /* Name of catalog (UAC, USAC, UAC2, USAC2) */ int nstars; /* Number of stars to find */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double *gnum; /* Array of Guide Star numbers (returned) */ double *gra; /* Array of right ascensions (returned) */ double *gdec; /* Array of declinations (returned) */ double *gpra; /* Array of right ascension proper motions (returned) */ double *gpdec; /* Array of declination proper motions (returned) */ double **gmag; /* Array of B and V magnitudes (returned) */ int *gtype; /* Array of object types (returned) */ int nlog; /* 1 for diagnostics */ { int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ struct StarCat *starcat; struct Star *star; char *str; char ucacenv[16]; int verbose; int zone, zone0; int jstar, imag, nmag; int istar, nstar; double num, ra, dec, rapm, decpm, mag; if (nlog == 1) verbose = 1; else verbose = 0; /* Set catalog code and path to catalog */ if (strncmp (refcatname,"ucac4",5)==0 || strncmp (refcatname,"UCAC4",5)==0) { ucat = UCAC4; ucacpath = ucac4path; strcpy (ucacenv, "UCAC4_PATH"); nmag = 8; } if (strncmp (refcatname,"ucac3",5)==0 || strncmp (refcatname,"UCAC3",5)==0) { ucat = UCAC3; ucacpath = ucac3path; strcpy (ucacenv, "UCAC3_PATH"); nmag = 8; } else if (strncmp (refcatname,"ucac2",5)==0 || strncmp (refcatname,"UCAC2",5)==0) { ucat = UCAC2; ucacpath = ucac2path; strcpy (ucacenv, "UCAC2_PATH"); nmag = 4; } else { ucat = UCAC1; ucacpath = ucac1path; strcpy (ucacenv, "UCAC1_PATH"); nmag = 1; } /* If pathname is set in environment, override local value */ if ((str = getenv(ucacenv)) != NULL ) ucacpath = str; /* If pathname is a URL, search and return */ if (!strncmp (ucacpath, "http:",5)) return (webrnum (ucacpath,refcatname,nstars,sysout,eqout,epout,1, gnum,gra,gdec,gpra,gpdec,gmag,gtype,nlog)); /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; nstar = 0; zone0 = 0; starcat = NULL; /* Loop through star list */ for (jstar = 0; jstar < nstars; jstar++) { zone = (int) (gnum[jstar] + 0.0000001); /* Find numbered stars (rrr.nnnnnn) */ istar = (int) ((gnum[jstar] - (double) zone + 0.0000001) * 1000000.0); if (istar > 0) { if (zone != zone0) { if (starcat != NULL) ucacclose (starcat); starcat = ucacopen (zone); } if (starcat == NULL) { fprintf (stderr,"UCACRNUM: Zone %d file not found\n", zone); return (0); } if (ucacstar (starcat, star, zone, istar)) { fprintf (stderr,"UCACRNUM: Cannot read star %d.%06d\n", zone, istar); gra[jstar] = 0.0; gdec[jstar] = 0.0; if (ucat == UCAC1) gmag[0][jstar] = 0.0; else { for (imag = 0; imag < nmag; imag++) gmag[imag][jstar] = 0.0; } gtype[jstar] = 0; continue; } /* If star has been found in catalog */ /* ID number */ num = star->num; /* Position in degrees at designated epoch */ ra = star->ra; dec = star->dec; rapm = star->rapm; decpm = star->decpm; wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); /* Magnitude */ mag = star->xmag[0]; /* Save star position and magnitude in table */ gnum[jstar] = num; gra[jstar] = ra; gdec[jstar] = dec; gpra[jstar] = rapm; gpdec[jstar] = decpm; gmag[0][jstar] = mag; gtype[jstar] = (1000 * star->nimage) + star->ncat; if (ucat == UCAC1) gmag[0][jstar] = star->xmag[0]; else { for (imag = 0; imag < nmag; imag++) gmag[imag][jstar] = star->xmag[imag]; gmag[nmag][jstar] = star->errra; gmag[nmag+1][jstar] = star->errdec; gmag[nmag+2][jstar] = star->errpmr; gmag[nmag+3][jstar] = star->errpmd; gtype[jstar] = (1000 * star->nimage) + star->ncat; } if (nlog == 1) { if (ucat == UCAC1) fprintf (stderr,"UCACRNUM: %11.6f: %9.5f %9.5f %5.2f %s \n", num, ra, dec, mag, star->isp); else if (ucat == UCAC2) { fprintf (stderr,"UCACRNUM: %11.6f: %9.5f %9.5f %5.2f", num, ra, dec, star->xmag[0]); fprintf (stderr," %5.2f %5.2f %5.2f", star->xmag[1],star->xmag[2],star->xmag[3]); fprintf (stderr," %d %d\n",star->nimage,star->ncat); } else if (ucat == UCAC3) { fprintf (stderr,"UCACRNUM: %11.6f: %9.5f %9.5f %5.2f %5.2f", num, ra, dec, star->xmag[0],star->xmag[1]); fprintf (stderr," %5.2f %5.2f %5.2f", star->xmag[2], star->xmag[3], star->xmag[4]); fprintf (stderr," %5.2f %5.2f %5.2f", star->xmag[5], star->xmag[6], star->xmag[7]); fprintf (stderr," %d %d\n",star->nimage,star->ncat); } else if (ucat == UCAC4) { fprintf (stderr,"UCACRNUM: %11.6f: %9.5f %9.5f %5.2f %5.2f", num, ra, dec, star->xmag[0],star->xmag[1]); fprintf (stderr," %5.2f %5.2f %5.2f", star->xmag[2], star->xmag[3], star->xmag[4]); fprintf (stderr," %5.2f %5.2f %5.2f", star->xmag[5], star->xmag[6], star->xmag[7]); fprintf (stderr," %d %d\n",star->nimage,star->ncat); } else { fprintf(stderr,"ucacread CATALOG NUMBER ERROR %d in line %d\n",ucat,__LINE__); exit(-1); } } } /* End of star loop */ } /* Summarize search */ ucacclose (starcat); if (nlog > 0) fprintf (stderr,"UCACRNUM: %d / %d found\n",nstar,starcat->nstars); return (nstars); } /* UCACBIN -- Fill a FITS WCS image with UCAC Star Catalog stars */ int ucacbin (refcatname, wcs, header, image, mag1, mag2, sortmag, magscale, nlog) char *refcatname; /* Name of catalog (UAC, USAC, UAC2, USAC2) */ struct WorldCoor *wcs; /* World coordinate system for image */ char *header; /* FITS header for output image */ char *image; /* Output FITS image */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 or 2) */ double magscale; /* Scaling factor for magnitude to pixel flux * (number of catalog objects per bin if 0) */ int nlog; /* 1 for diagnostics */ { double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ int nz; /* Number of UCAC regions in search */ int zlist[MAXZONE]; /* List of region numbers */ int sysref = WCS_J2000; /* Catalog coordinate system */ double eqref = 2000.0; /* Catalog equinox */ double epref = 2000.0; /* Catalog epoch */ double secmarg = 60.0; /* Arcsec/century margin for proper motion */ struct StarCat *starcat; /* Star catalog data structure */ struct Star *star; /* Single star cata structure */ int verbose; int wrap; int ix, iy, iz; int magsort; int jstar; int nrmax = MAXZONE; int nstar, ntot; int istar, istar1, istar2; int jtable,iwrap, nread; int pass; int zone; double num, ra, dec, rapm, decpm, mag; double rra1, rra2, rdec1, rdec2; double rdist, ddist; char cstr[32]; char ucacenv[16]; char *str; double xpix, ypix, flux; int offscl; int bitpix, w, h; /* Image bits/pixel and pixel width and height */ double logt = log(10.0); ntot = 0; if (nlog > 0) verbose = 1; else verbose = 0; /* Set catalog code and path to catalog */ if (strncmp (refcatname,"ucac4",5)==0 || strncmp (refcatname,"UCAC4",5)==0) { ucat = UCAC4; ucacpath = ucac4path; strcpy (ucacenv, "UCAC4_PATH"); } if (strncmp (refcatname,"ucac3",5)==0 || strncmp (refcatname,"UCAC3",5)==0) { ucat = UCAC3; ucacpath = ucac3path; strcpy (ucacenv, "UCAC3_PATH"); } else if (strncmp (refcatname,"ucac2",5)==0 || strncmp (refcatname,"UCAC2",5)==0) { ucat = UCAC2; ucacpath = ucac2path; strcpy (ucacenv, "UCAC2_PATH"); } else { ucat = UCAC1; ucacpath = ucac1path; strcpy (ucacenv, "UCAC1_PATH"); } /* If pathname is set in environment, override local value */ if ((str = getenv (ucacenv)) != NULL ) ucacpath = str; /* Set image parameters */ bitpix = 0; (void)hgeti4 (header, "BITPIX", &bitpix); w = 0; (void)hgeti4 (header, "NAXIS1", &w); h = 0; (void)hgeti4 (header, "NAXIS2", &h); /* Set catalog search limits from image WCS information */ sysout = wcs->syswcs; eqout = wcs->equinox; epout = wcs->epoch; wcscstr (cstr, sysout, eqout, epout); wcssize (wcs, &cra, &cdec, &dra, &ddec); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* Make mag1 always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } if (sortmag < 1) magsort = 0; else if (sortmag > 4) magsort = 3; else magsort = sortmag - 1; /* Allocate catalog entry buffer */ star = (struct Star *) calloc (1, sizeof (struct Star)); star->num = 0.0; nstar = 0; jstar = 0; /* Get RA and Dec limits in catalog (J2000) coordinates */ rra1 = ra1; rra2 = ra2; rdec1 = dec1; rdec2 = dec2; RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref,secmarg, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); /* Find UCAC Star Catalog zones in which to search */ nz = ucaczones (rdec1,rdec2,nrmax,zlist,verbose); if (nz <= 0) { fprintf (stderr,"UCACBIN: no UCAC zone for %.2f-%.2f %.2f %.2f\n", rra1, rra2, rdec1, rdec2); return (0); } /* Loop through zone list */ nstar = 0; for (iz = 0; iz < nz; iz++) { /* Get path to zone catalog */ zone = zlist[iz]; if ((starcat = ucacopen (zone)) != 0) { jstar = 0; jtable = 0; for (iwrap = 0; iwrap <= wrap; iwrap++) { /* Find first star based on RA */ if (iwrap == 0 || wrap == 0) istar1 = ucacsra (starcat, star, zone, rra1); else istar1 = 1; /* Find last star based on RA */ if (iwrap == 1 || wrap == 0) istar2 = ucacsra (starcat, star, zone, rra2); else istar2 = starcat->nstars; if (istar1 == 0 || istar2 == 0) break; nread = istar2 - istar1 + 1; /* Loop through zone catalog for this region */ for (istar = istar1; istar <= istar2; istar++) { jtable ++; if (ucacstar (starcat, star, zone, istar)) { fprintf(stderr,"UCACBIN: Cannot read star %d\n",istar); break; } /* ID number */ num = star->num; /* Magnitude */ mag = star->xmag[magsort]; /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; /* Check position limits */ if (pass) { /* Get position in output coordinate system */ rapm = star->rapm; decpm = star->decpm; ra = star->ra; dec = star->dec; wcsconp (sysref, sysout, eqref, eqout, epref, epout, &ra, &dec, &rapm, &decpm); /* Check distance along RA and Dec axes */ ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } /* Save star in FITS image */ if (pass) { wcs2pix (wcs, ra, dec, &xpix, &ypix, &offscl); if (!offscl) { if (magscale > 0.0) flux = magscale * exp (logt * (-mag / 2.5)); else flux = 1.0; ix = (int) (xpix + 0.5); iy = (int) (ypix + 0.5); addpix1 (image, bitpix, w,h, 0.0,1.0, xpix,ypix, flux); nstar++; jstar++; } else { ix = 0; iy = 0; } if (nlog == 1) { fprintf (stderr,"UCACBIN: %11.6f: %9.5f %9.5f %s", num,ra,dec,cstr); if (magscale > 0.0) fprintf (stderr, " %5.2f", mag); if (!offscl) flux = getpix1 (image, bitpix, w, h, 0.0, 1.0, ix, iy); else flux = 0.0; fprintf (stderr," (%d,%d): %f\n", ix, iy, flux); } /* End of accepted star processing */ } /* Log operation */ jstar++; if (nlog > 0 && istar%nlog == 0) fprintf (stderr,"UCACBIN: %5d / %5d / %5d sources\r", nstar,jstar,starcat->nstars); /* End of star loop */ } /* End of 0:00 RA wrap loop */ } /* End of successful zone file loop */ ntot = ntot + starcat->nstars; if (nlog > 0) fprintf (stderr,"UCACBIN: %4d / %4d: %5d / %5d / %5d sources from zone %4d \n", iz+1,nz,nstar,jstar,starcat->nstars,zlist[iz]); /* Close region input file */ ucacclose (starcat); } /* End of zone loop */ } /* Summarize transfer */ if (nlog > 0) { if (nz > 1) fprintf (stderr,"UCACBIN: %d zones: %d / %d found\n",nz,nstar,ntot); else fprintf (stderr,"UCACBIN: 1 region: %d / %d found\n",nstar,ntot); } return (nstar); } /* UCACZONE -- Compute the zones over which to search * in the specified range of coordinates. * Build lists containing the first star and number of stars for each range. */ static int ucaczones (dec1, dec2, nzmax, zones, verbose) double dec1, dec2; /* Declination limits in degrees */ int nzmax; /* Maximum number of zones to find */ int *zones; /* Zone numbers (returned)*/ int verbose; /* 1 for diagnostics */ { int nz; /* Number of declination zones found (returned) */ int iz, iz1, iz2; int i; double spd1, spd2; for (i = 0; i < nzmax; i++) zones[i] = 0; /* Find first and last declination zone to search */ spd1 = 90.0 + dec1; iz1 = (int) ((spd1 * 2.0) + 0.99999); if (iz1 < 1) iz1 = 1; spd2 = 90.0 + dec2; iz2 = (int) ((spd2 * 2.0) + 0.99999); if (ucat == UCAC1 && iz2 > 169) iz2 = 169; if (ucat == UCAC2 && iz2 > 288) iz2 = 288; if (ucat == UCAC3 && iz2 > 360) iz2 = 360; if (ucat == UCAC4) { iz1 = (int) ((spd1 * 5.0) + 0.99999); if (iz1 < 1) iz1 = 1; spd2 = 90.0 + dec2; iz2 = (int) ((spd2 * 5.0) + 0.99999); if (iz2 > 900) { iz2 = 900; } } if (iz1 > iz2) return (0); nz = iz2 - iz1 + 1; if (verbose) { fprintf (stderr,"UCACZONES: searching %d zones: %d - %d\n",nz,iz1,iz2); fprintf(stderr,"UCACZONES: Dec: %.5f - %.5f\n", dec1,dec2); } i = 0; for (iz = iz1; iz <= iz2; iz++) { zones[i] = iz; i++; } return (nz); } /* UCACSRA -- Find UCAC star closest to specified right ascension */ static int ucacsra (sc, st, zone, rax0) struct StarCat *sc; /* Star catalog descriptor */ struct Star *st; /* Current star entry */ int zone; /* Declination zone */ double rax0; /* Right ascension in degrees for which to search */ { int istar, istar1, istar2, nrep; double rax, ra1, ra2, ra, rdiff, rdiff1, rdiff2, sdiff; char rastrx[32]; int debug = 0; int maxnrep; #ifdef UCAC_DEBUG if (zone == 183) { debug = 1; fprintf(stderr,"Entering UCACSRA, zone %d\n",zone); } else { debug = 0; } #endif /* UCAC_DEBUG */ rax = rax0; if (debug) ra2str (rastrx, 31, rax, 3); istar1 = 1; ucacstar (sc, st, zone, istar1); ra1 = st->ra; istar2 = sc->nstars; maxnrep = sc->nstars; istar = (istar1+istar2)/2; nrep = 0; while (istar != istar1 && nrep < maxnrep) { if (ucacstar (sc, st, zone, istar)) { break; } else { ra = st->ra; if (ra == ra1) break; if (debug) { char rastr[32]; ra2str (rastr, 31, ra, 3); fprintf (stderr,"UCACSRA %d %d: %s (%s)\n", nrep,istar,rastr,rastrx); } nrep++; if (ra > rax) { istar2 = istar; ra2 = ra; } else { istar1 = istar; ra1 = ra; } istar = (istar1+istar2)/2; if (debug) { fprintf (stderr," ra1= %.5f ra2= %.5f rax= %.5f\n", ra1,ra2,rax); fprintf (stderr," istar1= %d istar= %d istar2= %d\n", istar1,istar,istar2); } if (istar < 1) istar = 1; if (istar > sc->nstars) istar = sc->nstars; if (istar == istar1) break; } } return (istar); } /* UCACOPEN -- Open UCAC catalog file, returning number of entries */ struct StarCat * ucacopen (zone) int zone; /* Number of catalog zone to read */ { FILE *fcat; struct StarCat *sc; int lfile, lpath; char *zonefile; char *zonepath; /* Full pathname for catalog file */ /* Set pathname for catalog file */ lpath = strlen (ucacpath) + 16; zonepath = (char *) malloc (lpath); if (ucat == UCAC1) sprintf (zonepath, "%s/u1/z%03d", ucacpath, zone); else if (ucat == UCAC2) sprintf (zonepath, "%s/u2/z%03d", ucacpath, zone); else if (ucat == UCAC3) sprintf (zonepath, "%s/z%03d", ucacpath, zone); else if (ucat == UCAC4) sprintf (zonepath, "%s/z%03d", ucacpath, zone); else { fprintf(stderr,"ucacread CATALOG NUMBER ERROR %d in line %d\n",ucat,__LINE__); exit(-1); } /* Set UCAC catalog header information */ sc = (struct StarCat *) calloc (1, sizeof (struct StarCat)); sc->byteswapped = 0; /* Set number of stars in this zone catalog */ if (ucat == UCAC1) sc->nbent = 67; else if (ucat == UCAC2) sc->nbent = 44; else if (ucat == UCAC3) sc->nbent = 84; else if (ucat == UCAC4) sc->nbent = sizeof(UCAC4star); else { fprintf(stderr,"ucacread CATALOG NUMBER ERROR %d in line %d\n",ucat,__LINE__); exit(-1); } lfile = getfilesize (zonepath); if (lfile < 2) { fprintf (stderr,"UCAC zone catalog %s has no entries\n",zonepath); free (sc); sc = NULL; return (NULL); } else sc->nstars = lfile / sc->nbent; /* Open UCAC file */ if (!(fcat = fopen (zonepath, "r"))) { fprintf (stderr,"UCACOPEN: UCAC file %s cannot be read\n",zonepath); free (sc); return (NULL); } /* Separate filename from pathname and save in structure */ zonefile = strrchr (zonepath,'/'); if (zonefile) zonefile = zonefile + 1; else zonefile = zonepath; if (strlen (zonefile) < 24) strcpy (sc->isfil, zonefile); else strncpy (sc->isfil, zonefile, 23); /* Set other catalog information in structure */ sc->inform = 'J'; sc->coorsys = WCS_J2000; sc->epoch = 2000.0; sc->equinox = 2000.0; sc->ifcat = fcat; sc->sptype = 0; if (ucat == UCAC1) sc->nmag = 1; else if (ucat == UCAC2) sc->nmag = 4; else if (ucat == UCAC3) sc->nmag = 8; else if (ucat == UCAC4) sc->nmag = 8; else { fprintf(stderr,"ucacread CATALOG NUMBER ERROR %d in line %d\n",ucat,__LINE__); exit(-1); } /* UCAC stars are RA-sorted within declination zones */ sc->rasorted = 1; /* Check to see if byte-swapping is necessary */ cswap = 0; if (ucat == UCAC2) { UCAC2star us2; /* UCAC2 catalog entry for one star */ int nbr; nbr = fread (&us2, 1, sc->nbent, sc->ifcat); if (nbr < 1) { fprintf (stderr, "UCACOPEN: cannot read star 1 from UCAC2 zone catalog %s\n", zonepath); return (0); } /* RA should be between 0 and 360 degrees in milliarcseconds */ if (us2.rasec > 360 * 3600000 || us2.rasec < 0) cswap = 1; /* Dec should be between -90 and +90 degrees in milliarcseconds */ else if (us2.decsec > 90 * 3600000 || us2.decsec < -90 * 3600000) cswap = 1; /* J H K magnitudes should be near-positive */ else if (us2.jmag < -1000 || us2.hmag < -1000 || us2.kmag < -1000) cswap = 1; else cswap = 0; /* if (cswap) fprintf (stderr, "UCACOPEN: swapping bytes in UCAC2 zone catalog %s\n", zonepath); */ } else if (ucat == UCAC3) { UCAC3star us3; /* UCAC3 catalog entry for one star */ int nbr; nbr = fread (&us3, 1, sc->nbent, sc->ifcat); if (nbr < 1) { fprintf (stderr, "UCACOPEN: cannot read star 1 from UCAC3 zone catalog %s\n", zonepath); return (0); } /* RA should be between 0 and 360 degrees in milliarcseconds */ if (us3.rasec > 360 * 3600000 || us3.rasec < 0) cswap = 1; /* Dec should be between -90 and +90 degrees in milliarcseconds */ else if (us3.decsec > 180 * 3600000 || us3.decsec < -180 * 3600000) cswap = 1; /* J H K magnitudes should be near-positive */ else if (us3.jmag < -1000 || us3.hmag < -1000 || us3.kmag < -1000) cswap = 1; else cswap = 0; /* if (cswap) fprintf (stderr, "UCACOPEN: swapping bytes in UCAC2 zone catalog %s\n",zomepath); */ } else if (ucat == UCAC4) { UCAC4star us4; /* UCAC4 catalog entry for one star */ int nbr; nbr = fread (&us4, 1, sc->nbent, sc->ifcat); if (nbr < 1) { fprintf (stderr, "UCACOPEN: cannot read star 1 from UCAC4 zone catalog %s\n", zonepath); return (0); } /* RA should be between 0 and 360 degrees in milliarcseconds */ if (us4.ra > 360 * 3600000 || us4.ra < 0) cswap = 1; /* Dec should be between -90 and +90 degrees in milliarcseconds */ else if (us4.spd > 180 * 3600000 || us4.spd < 0) cswap = 1; /* J H K magnitudes should be near-positive */ else if (us4.mag_j < -1000 || us4.mag_h < -1000 || us4.mag_k < -1000) cswap = 1; else cswap = 0; if (cswap) fprintf (stderr, "UCACOPEN: swapping bytes in UCAC4 zone catalog %s\n",zonepath); } else { fprintf(stderr,"ucacread CATALOG NUMBER ERROR %d in line %d\n",ucat,__LINE__); exit(-1); } sc->istar = 0; free (zonepath); return (sc); } void ucacclose (sc) struct StarCat *sc; /* Star catalog descriptor */ { fclose (sc->ifcat); free (sc); return; } /* UCACSTAR -- Get UCAC catalog entry for one star; return 0 if successful */ static int ucacstar (sc, st, zone, istar) struct StarCat *sc; /* Star catalog descriptor */ struct Star *st; /* Current star entry */ int zone; /* Declination zone */ int istar; /* Star sequence number in UCAC catalog region file */ { char line[256]; int nbr, nbskip; UCAC2star us2; /* UCAC2 catalog entry for one star */ UCAC3star us3; /* UCAC3 catalog entry for one star */ UCAC4star us4; /* UCAC4 catalog entry for one star */ int hpmIndex; int lineLen; int nvals; FILE *hpmHandle; char inLine[MAX_U4HPM_LINE]; char *inBuffer; PU4HPM pU4hpm = NULL; /* Drop out if catalog pointer is not set */ if (sc == NULL) return (1); /* Drop out if catalog is not open */ if (sc->ifcat == NULL) return (2); /* Drop out if star number is too small or too large */ if (istar < 1 || istar > sc->nstars) { fprintf (stderr, "UCAC star %d is not in catalog\n",istar); return (-1); } /* Move file pointer to start of correct star entry */ nbskip = sc->nbent * (istar - 1); if (fseek (sc->ifcat,nbskip,SEEK_SET)) return (-1); if (ucat == UCAC1) nbr = fread (line, 1, sc->nbent, sc->ifcat); else if (ucat == UCAC2) nbr = fread (&us2, 1, sc->nbent, sc->ifcat); else if (ucat == UCAC3) nbr = fread (&us3, 1, sc->nbent, sc->ifcat); else if (ucat == UCAC4) nbr = fread (&us4, 1, sc->nbent, sc->ifcat); else { fprintf(stderr,"ucacread CATALOG NUMBER ERROR %d in line %d\n",ucat,__LINE__); exit(-1); } if (nbr < sc->nbent) { fprintf (stderr, "UCACSTAR %d / %d bytes read\n",nbr, sc->nbent); return (-2); } #if 0 if ((zone == 552) && (istar == 43247)) { printf("At zone %d and istar %d\n",zone,istar); } #endif /* Star ID number = region.sequence */ st->num = (double) zone + (0.000001 * (double) istar); /* Read UCAC1 position and proper motion from ASCII file */ if (ucat == UCAC1) { /* Read position in degrees */ st->ra = atof (line) / 3600000.0; st->dec = (atof (line+10) / 3600000.0) - 90.0; /* Read proper motion and convert it to to degrees/year */ st->rapm = (atof (line+41) / 3600000.0) / cosdeg (st->dec); st->decpm = atof (line+48) / 3600000.0; /* Set V magnitude */ st->xmag[0] = atof (line+20) * 0.01; } /* Read UCAC2 position, proper motion, and magnitudes from binary file */ else if (ucat == UCAC2) { if (cswap) { ucacswap4 (&us2.rasec); ucacswap4 (&us2.decsec); ucacswap4 (&us2.rapm); ucacswap4 (&us2.decpm); ucacswap2 (&us2.cmag); ucacswap2 (&us2.jmag); ucacswap2 (&us2.hmag); ucacswap2 (&us2.kmag); } st->ra = (double) us2.rasec / 3600000.0; st->dec = (double) us2.decsec / 3600000.0; st->errra = (double) us2.era / 3600000.0; /* mas */ st->errra = st->errra / cosdeg (st->dec); /* to RA deg */ st->errdec = (double) us2.edec / 3600000.0; /* mas */ st->rapm = (double) us2.rapm / 36000000.0; /* 0.1mas/yr */ st->decpm = (double) us2.decpm / 36000000.0; /* 0.1mas/yr */ st->errpmr = (double) us2.erapm / 36000000.0; /* 0.1mas/yr */ st->errpmr = st->errpmr / cosdeg (st->dec); /* to RA deg */ st->errpmd = (double) us2.edecpm / 36000000.0; /* 0.1mas/yr */ st->xmag[0] = ((double) us2.jmag) / 1000.0; st->xmag[1] = ((double) us2.hmag) / 1000.0; st->xmag[2] = ((double) us2.kmag) / 1000.0; st->xmag[3] = ((double) us2.cmag) / 100.0; st->nimage = (int) us2.nobs; st->ncat = (int) us2.ncat; } /* Read UCAC3 position, proper motion, and magnitudes from binary file */ else if (ucat == UCAC3) { if (cswap) { ucacswap4 (&us3.rasec); ucacswap4 (&us3.decsec); ucacswap4 (&us3.rapm); ucacswap4 (&us3.decpm); ucacswap2 (&us3.sigra); ucacswap2 (&us3.sigdec); ucacswap2 (&us3.sigpmr); ucacswap2 (&us3.sigpmd); ucacswap2 (&us3.mmag); ucacswap2 (&us3.amag); ucacswap2 (&us3.jmag); ucacswap2 (&us3.hmag); ucacswap2 (&us3.kmag); ucacswap2 (&us3.bmag); ucacswap2 (&us3.rmag); ucacswap2 (&us3.imag); } st->ra = (double) us3.rasec / 3600000.0; /* mas */ st->dec = (double) us3.decsec / 3600000.0; /* mas */ st->dec = st->dec - 90.0; st->errra = (double) us3.sigra / 3600000.0; /* mas */ st->errra = st->errra / cosdeg (st->dec); /* to RA deg */ st->errdec = (double) us3.sigdec / 3600000.0; /* mas */ st->rapm = (double) us3.rapm / 36000000.0; /* 0.1mas/yr */ st->rapm = st->rapm / cosdeg (st->dec); /* to RA deg */ st->decpm = (double) us3.decpm / 36000000.0; /* 0.1mas/yr */ st->errpmr = (double) us3.sigpmr / 36000000.0; /* 0.1mas/yr */ st->errpmr = st->errpmr / cosdeg (st->dec); /* to RA deg */ st->errpmd = (double) us3.sigpmd / 36000000.0; /* 0.1mas/yr */ st->nimage = (int) us3.nu1; st->ncat = (int) us3.us1; if (us3.bmag == 0) st->xmag[0] = 99.990; else st->xmag[0] = ((double) us3.bmag) / 1000.0; if (us3.rmag == 0) st->xmag[1] = 99.990; else st->xmag[1] = ((double) us3.rmag) / 1000.0; if (us3.imag == 0) st->xmag[2] = 99.990; else st->xmag[2] = ((double) us3.imag) / 1000.0; if (us3.jmag == 0) st->xmag[3] = 99.990; else st->xmag[3] = ((double) us3.jmag) / 1000.0; if (us3.hmag == 0) st->xmag[4] = 99.990; else st->xmag[4] = ((double) us3.hmag) / 1000.0; if (us3.kmag == 0) st->xmag[5] = 99.990; else st->xmag[5] = ((double) us3.kmag) / 1000.0; if (us3.mmag == 0) st->xmag[6] = 99.990; else st->xmag[6] = ((double) us3.mmag) / 1000.0; if (us3.amag == 0) st->xmag[7] = 99.990; else st->xmag[7] = ((double) us3.amag) / 1000.0; } else if (ucat == UCAC4) { if (cswap) { ucacswap4 (&us4.ra); ucacswap4 (&us4.spd); ucacswap4 (&us4.pm_ra); ucacswap4 (&us4.pm_dec); ucacswap4 (&us4.id_number); ucacswap2 (&us4.ra_sigma); ucacswap2 (&us4.dec_sigma); ucacswap2 (&us4.pm_ra_sigma); ucacswap2 (&us4.pm_dec_sigma); ucacswap2 (&us4.magm); ucacswap2 (&us4.maga); ucacswap2 (&us4.mag_j); ucacswap2 (&us4.mag_h); ucacswap2 (&us4.mag_k); ucacswap2 (&us4.apass_mag[0]); ucacswap2 (&us4.apass_mag[1]); ucacswap2 (&us4.apass_mag[2]); ucacswap2 (&us4.apass_mag[3]); ucacswap2 (&us4.apass_mag[4]); } st->ra = (double) us4.ra / 3600000.0; /* mas */ st->dec = (double) us4.spd / 3600000.0; /* mas */ st->dec = st->dec - 90.0; st->errra = (double) us4.ra_sigma / 3600000.0; /* mas */ st->errra = st->errra / cosdeg (st->dec); /* to RA deg */ st->errdec = (double) us4.dec_sigma / 3600000.0; /* mas */ /* Must get proper motions from a different catalog */ if ((us4.pm_ra == 32767) || (us4.pm_dec == 32767)) { if (hpmLines == 0) { /* Read in the high proper motion catalog */ hpmHandle = fopen(hpmpath,"rt"); if (hpmHandle == NULL) { printf("ERROR: failed to open %s\n",hpmpath); exit(-1); } hpmLines = 0; while(1) { if (hpmLines >= MAX_U4HPM_RECORDS) { printf("ERROR: MAX_U4HPM_RECORDS exceeded\n"); exit(-1); } pU4hpm = &u4hpm_table[hpmLines]; memset(pU4hpm,0,sizeof(U4HPM)); inBuffer = fgets(inLine,MAX_U4HPM_LINE,hpmHandle); if (inBuffer == NULL) { break; } lineLen = strlen(inBuffer); /* Trim off the carriage return */ if (inBuffer[lineLen-1] == 10) { inBuffer[lineLen-1] = 0; lineLen--; } /* Trim off the line feed */ if (inBuffer[lineLen-1] == 13) { inBuffer[lineLen-1] = 0; lineLen--; } nvals = sscanf(inBuffer,"%d %d %d %d %d %d %d %d", &pU4hpm->rnm, &pU4hpm->zn, &pU4hpm->rnz, &pU4hpm->pmrc, &pU4hpm->pmd, &pU4hpm->ra, &pU4hpm->dec, &pU4hpm->maga); if (nvals != 8) { fprintf(stderr,"Error reading line %d of u4hpm %s\n",hpmLines,inLine); } else { hpmLines++; } } fclose(hpmHandle); } for (hpmIndex = 0; hpmIndex < hpmLines; hpmIndex++) { pU4hpm = &u4hpm_table[hpmIndex]; if ((zone == pU4hpm->zn) && (us4.id_number == pU4hpm->rnm) && (us4.ra == pU4hpm->ra) && (us4.spd == pU4hpm->dec) && (us4.maga == pU4hpm->maga)) { /* We have a match */ st->rapm = (1.0 * pU4hpm->pmrc) / 36000000.0; /* 0.1 mas/yr */ st->rapm = st->rapm / cosdeg (st->dec); /* to RA deg */ st->decpm = (1.0 * pU4hpm->pmd) / 36000000.0; /* 0.1 mas/yr */ break; } } if (hpmIndex == hpmLines) { fprintf(stderr,"ERROR: no proper motion found for zone %d entry %d\n",zone,us4.id_number); } } else { st->rapm = (double) us4.pm_ra / 36000000.0; /* 0.1mas/yr */ st->rapm = st->rapm / cosdeg (st->dec); /* to RA deg */ st->decpm = (double) us4.pm_dec / 36000000.0; /* 0.1mas/yr */ } st->errpmr = (double) (us4.pm_ra_sigma+128) / 36000000.0; /* 0.1mas/yr */ st->errpmr = st->errpmr / cosdeg (st->dec); /* to RA deg */ st->errpmd = (double) (us4.pm_dec_sigma+128) / 36000000.0; /* 0.1mas/yr */ st->nimage = (int) us4.n_ucac_used; st->ncat = (int) us4.n_cats_used; if (us4.apass_mag[0] == 20000) st->xmag[0] = 99.990; else st->xmag[0] = ((double) us4.apass_mag[0]) / 1000.0; if (us4.apass_mag[1] == 20000) st->xmag[1] = 99.990; else st->xmag[1] = ((double) us4.apass_mag[1]) / 1000.0; if (us4.apass_mag[2] == 20000) st->xmag[2] = 99.990; else st->xmag[2] = ((double) us4.apass_mag[2]) / 1000.0; if (us4.apass_mag[3] == 20000) st->xmag[3] = 99.990; else st->xmag[3] = ((double) us4.apass_mag[3]) / 1000.0; if (us4.apass_mag[4] == 20000) st->xmag[4] = 99.990; else st->xmag[4] = ((double) us4.apass_mag[4]) / 1000.0; if (us4.mag_j == 0) st->xmag[5] = 99.990; else st->xmag[5] = ((double) us4.mag_j) / 1000.0; if (us4.mag_h == 0) st->xmag[6] = 99.990; else st->xmag[6] = ((double) us4.mag_h) / 1000.0; if (us4.mag_k == 0) st->xmag[7] = 99.990; else st->xmag[7] = ((double) us4.mag_k) / 1000.0; if (us4.magm == 20000) st->xmag[8] = 99.990; else st->xmag[8] = ((double) us4.magm) / 1000.0; if (us4.maga == 20000) st->xmag[9] = 99.990; else st->xmag[9] = ((double) us4.maga) / 1000.0; /* DASCH specific. Since we are sorting on mag[8], try using APASS B or mag[9] first */ if (st->xmag[9] < 90.0) { st->xmag[8] = st->xmag[9]; } if (st->xmag[0] < 90.0) { st->xmag[8] = st->xmag[0]; } } else { fprintf(stderr,"ucacread CATALOG NUMBER ERROR %d in line %d\n",ucat,__LINE__); exit(-1); } #if 0 if ((zone == 256) && (istar == 149200)) { printf("At zone %d and istar %d\n",zone,istar); } #endif #ifdef UCAC_DEBUG if (zone == 183) { fprintf(stderr,"istar %6d, ra %.3f dec %.3f\n",istar,st->ra,st->dec); } #endif /* UCAC_DEBUG */ return (0); } /* UCACSWAP2 -- Swap bytes in Integer*2 number in place */ static void ucacswap2 (string) char *string; /* Address of starting point of bytes to swap */ { char *sbyte, temp; sbyte = string; temp = sbyte[0]; sbyte[0] = sbyte[1]; sbyte[1] = temp; return; } /* UCACSWAP4 -- Reverse bytes of Integer*4 or Real*4 number in place */ static void ucacswap4 (string) char *string; /* Address of Integer*4 or Real*4 vector */ { char temp0, temp1, temp2, temp3; temp3 = string[0]; temp2 = string[1]; temp1 = string[2]; temp0 = string[3]; string[0] = temp0; string[1] = temp1; string[2] = temp2; string[3] = temp3; return; } /* Apr 24 2003 New subroutines, based on ty2read.c and uacread.c * May 30 2003 Add UCAC2, compute file size rather than reading it from file * Jun 2 2003 Print proper motions as mas/year * Aug 22 2003 Add radi argument for inner edge of search annulus * Sep 25 2003 Add ucacbin() to fill an image with sources * Oct 6 2003 Update ubcread() and ubcbin() for improved RefLim() * Nov 10 2003 Fix byte-swapping test in ucacopen() found by Ed Beshore * Nov 18 2003 Initialize image size and bits/pixel from header in ucacbin() * Dec 1 2003 Add missing tab to n=-1 header * Dec 12 2003 Fix bug in wcs2pix() call in ucacbin() * * Jan 4 2005 Fix bug in if statement on line 626 found by Dan Katz at JPL * * Jun 20 2006 Drop unused variables * Sep 26 2006 Increase length of rastr and destr from 16 to 32 * Nov 16 2006 Fix binning * * Jan 8 2007 Drop unused variable in ucacbin() * Jan 10 2007 Add match=1 argument to webrnum() * Jul 11 2007 Add magnitude byte-swap check * * Oct 5 2009 Add UCAC3 * Oct 15 2009 Read extra stars in RA * Oct 22 2009 Set UCAC3 magnitudes to 99.99 if zero * Oct 30 2009 Add position and proper motion error to Star structure * Nov 2 2009 Print UCAC3 errors if n = -1 * Nov 5 2009 Return number of images and catalogs in gtype * Nov 5 2009 Return errors in position and proper motion as magnitudes * Nov 5 2009 Return UCAC2 and UCAC3 RA proper motion and error as RA degrees * Dec 14 2009 Drop nmag1 from ucacread() and ucacrnum(); it wasn't being used * * Jan 29 2013 Add UCAC4 support see "DASCH" tag for DASCH-specific changes * * Jun 12 2015 Fix UCAC4 support to include BVgriJHK magnitudes correctly * * Jun 22 2016 Remove extra variables from format string (via Ole Streicher) */ wcstools-3.9.5/libwcs/ujcread.c0000664000016200001660000007340611750060474015535 0ustar minkoirsys/*** File libwcs/ujcread.c *** July 5, 2007 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2007 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include #include #include "wcs.h" #include "fitsfile.h" #include "wcscat.h" static char cdu[64]="/data/ujcat/catalog"; /* pathname of UJ 1.0 CDROM */ typedef struct { int rasec, decsec, magetc; } UJCstar; static int nstars; /* Number of stars in catalog */ static int cswap = 0; /* Byte reverse catalog to Intel/DEC order if 1 */ static FILE *fcat; static int refcat; /* Code for catalog */ static char *catname; #define ABS(a) ((a) < 0 ? (-(a)) : (a)) #define NZONES 24 static double ujcra(); static double ujcdec(); static double ujcmag(); static int ujcplate(); static int ujczones(); static int ujczone(); static int ujcsra(); static int ujcopen(); static int ujcpath(); static int ujcstar(); static void ujcswap(); /* UJCREAD -- Read USNO J Catalog stars from CDROM or plate catalog from file */ int ujcread (refcatname,cra,cdec,dra,ddec,drad,dradi,distsort,sysout,eqout,epout, mag1,mag2,nstarmax,unum,ura,udec,umag,uplate,verbose) char *refcatname; /* Name of catalog (UJC, xxxxx.usno) */ double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ double dradi; /* Inner edge of annulus in degrees (ignore if 0) */ int distsort; /* 1 to sort stars by distance from center */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int nstarmax; /* Maximum number of stars to be returned */ double *unum; /* Array of UJ numbers (returned) */ double *ura; /* Array of right ascensions (returned) */ double *udec; /* Array of declinations (returned) */ double **umag; /* Array of magnitudes (returned) */ int *uplate; /* Array of plate numbers (returned) */ int verbose; /* 1 for diagnostics */ { double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ double dist = 0.0; /* Distance from search center in degrees */ double faintmag=0.0; /* Faintest magnitude */ double maxdist=0.0; /* Largest distance */ int faintstar=0; /* Faintest star */ int farstar=0; /* Most distant star */ int magsort=0; double *udist; /* Array of distances to stars */ int nz; /* Number of input UJ zone files */ int zlist[NZONES]; /* List of input UJ zones */ UJCstar star; /* UJ catalog entry for one star */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ char cstr[32]; double num; /* UJ number */ int xplate; /* If nonzero, use objects only from this plate */ double rra1, rra2, rdec1, rdec2; int wrap, iwrap; int znum, itot,iz; int nlog,jstar, mprop, nmag; int itable = 0; int nstar, i; int pass; double ra,dec; double mag; double rdist, ddist; int istar, istar1, istar2, plate; int nzmax = NZONES; /* Maximum number of declination zones */ char *str; char title[128]; itot = 0; xplate = getuplate (); /* Set catalog code and path to catalog */ catname = refcatname; refcat = RefCat (refcatname,title,&sysref,&eqref,&epref,&mprop,&nmag); if (refcat == UJC && (str = getenv("UJ_PATH")) != NULL ) { /* If pathname is a URL, search and return */ if (!strncmp (str, "http:",5)) { return (webread (str,"ujc",distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,magsort,nstarmax, unum,ura,udec,NULL,NULL,umag,uplate,verbose)); } else strcpy (cdu,str); } wcscstr (cstr, sysout, eqout, epout); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* mag1 is always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } rra1 = ra1; rra2 = ra2; rdec1 = dec1; rdec2 = dec2; RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref,0.0, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); /* Find UJ Star Catalog regions in which to search */ if (refcat == UJC) { nz = ujczones (rra1, rra2, rdec1, rdec2, nzmax, zlist, verbose); if (nz <= 0) { fprintf (stderr,"UJCREAD: no UJ zones found\n"); return (0); } } else nz = 1; udist = (double *) calloc (nstarmax, sizeof (double)); /* Logging interval */ if (verbose) nlog = 100; else nlog = 0; nstar = 0; /* Loop through region list */ for (iz = 0; iz < nz; iz++) { /* Get path to zone catalog */ znum = zlist[iz]; if ((nstars = ujcopen (znum)) != 0) { jstar = 0; itable = 0; for (iwrap = 0; iwrap <= wrap; iwrap++) { /* Find first star based on RA */ if (iwrap == 0 || wrap == 0) istar1 = ujcsra (rra1); else istar1 = 1; /* Find last star based on RA */ if (iwrap == 1 || wrap == 0) istar2 = ujcsra (rra2); else istar2 = nstars; if (istar1 == 0 || istar2 == 0) break; /* Loop through zone catalog for this region */ for (istar = istar1; istar <= istar2; istar++) { itable ++; if (ujcstar (istar, &star)) { fprintf (stderr,"UJCREAD: Cannot read star %d\n", istar); break; } /* Extract selected fields if not probable duplicate */ else if (star.magetc > 0) { mag = ujcmag (star.magetc); /* Magnitude */ /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; /* Check plate number */ plate = ujcplate (star.magetc); /* Plate number */ if (xplate != 0 && plate != xplate) pass = 0; /* Check position limits */ if (pass) { ra = ujcra (star.rasec); /* RA in degrees */ dec = ujcdec (star.decsec); /* Dec in degrees */ /* Get position in output coordinate system */ wcscon (sysref,sysout,eqref,eqout,&ra,&dec,epout); /* Compute distance from search center */ if (drad > 0 || distsort) dist = wcsdist (cra,cdec,ra,dec); else dist = 0.0; /* Check radial distance to search center */ if (drad > 0) { if (dist > drad) pass = 0; if (dradi > 0.0 && dist < dradi) pass = 0; } /* Check distance along RA and Dec axes */ else { ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } } if (pass) { if (refcat == UJC) num = (double) znum + (0.0000001*(double)istar); else num = (double)istar; /* Save star position and magnitude in table */ if (nstar < nstarmax) { unum[nstar] = num; ura[nstar] = ra; udec[nstar] = dec; umag[0][nstar] = mag; uplate[nstar] = plate; udist[nstar] = dist; if (dist > maxdist) { maxdist = dist; farstar = nstar; } if (mag > faintmag) { faintmag = mag; faintstar = nstar; } } /* If too many stars and distance sorting, replace furthest star */ else if (distsort) { if (dist < maxdist) { unum[farstar] = num; ura[farstar] = ra; udec[farstar] = dec; umag[0][farstar] = mag; uplate[farstar] = plate; udist[farstar] = dist; /* Find new farthest star */ maxdist = 0.0; for (i = 0; i < nstarmax; i++) { if (udist[i] > maxdist) { maxdist = udist[i]; farstar = i; } } } } /* If too many stars, replace faintest star */ else if (mag < faintmag) { unum[faintstar] = num; ura[faintstar] = ra; udec[faintstar] = dec; umag[0][faintstar] = mag; uplate[faintstar] = plate; udist[faintstar] = dist; faintmag = 0.0; /* Find new faintest star */ for (i = 0; i < nstarmax; i++) { if (umag[0][i] > faintmag) { faintmag = umag[0][i]; faintstar = i; } } } nstar++; jstar++; if (nlog == 1) fprintf (stderr,"UJCREAD: %04d.%04d: %9.5f %9.5f %s %5.2f\n", znum,istar,ra,dec,cstr,mag); /* End of accepted star processing */ } /* End of individual star processing */ } /* Log operation */ if (nlog > 0 && itable%nlog == 0) fprintf (stderr,"UJCREAD: zone %d (%4d / %4d) %6d / %6d sources\r", znum, iz+1, nz, jstar, itable); /* End of star loop */ } /* End of wrap loop */ } /* Close zone input file */ (void) fclose (fcat); itot = itot + itable; if (nlog > 0) fprintf (stderr,"UJCREAD: zone %d (%4d / %4d) %6d / %6d / %8d sources\n", znum, iz+1, nz, jstar, itable, nstars); /* End of zone processing */ } /* End of zone loop */ } /* Summarize search */ if (nlog > 0) { if (nz > 1) fprintf (stderr,"UJCREAD: %d zone: %d / %d found\n",nz,nstar,itot); else fprintf (stderr,"UJCREAD: 1 zone: %d / %d found\n",nstar,itable); if (nstar > nstarmax) fprintf (stderr,"UJCREAD: %d stars found; only %d returned\n", nstar,nstarmax); } free ((char *)udist); return (nstar); } /* UJCRNUM -- Read USNO J Catalog stars from CDROM or plate catalog from file */ int ujcrnum (refcatname,nnum,sysout,eqout,epout,unum,ura,udec,umag,uplate,nlog) char *refcatname; /* Name of catalog (UAC, USAC, UAC2, USAC2) */ int nnum; /* Number of stars to find */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double *unum; /* Array of UA numbers to find */ double *ura; /* Array of right ascensions (returned) */ double *udec; /* Array of declinations (returned) */ double **umag; /* Array of red magnitudes (returned) */ int *uplate; /* Array of plate numbers (returned) */ int nlog; /* Logging interval */ { UJCstar star; /* UJ catalog entry for one star */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ int znum; int jnum; int nzone; int nfound = 0; double ra,dec; double mag; int istar, plate, mprop, nmag; char *str; char title[128]; /* Set catalog code and path to catalog */ catname = refcatname; refcat = RefCat (refcatname,title,&sysref,&eqref,&epref,&mprop,&nmag); if (refcat == UJC && (str = getenv("UJ_PATH")) != NULL ) { /* If pathname is a URL, search and return */ if (!strncmp (str, "http:",5)) { return (webrnum (str,"ujc",nnum,sysout,eqout,epout,1, unum,ura,udec,NULL,NULL,umag,uplate,nlog)); } else strcpy (cdu,str); } /* Loop through star list */ for (jnum = 0; jnum < nnum; jnum++) { /* Get path to zone catalog */ znum = (int) unum[jnum]; if ((nzone = ujcopen (znum)) != 0) { if (refcat == UJC) istar = (int) (((unum[jnum] - znum) * 100000000.0) + 0.5); else istar = (int) (unum[jnum] + 0.5); /* Check to make sure star can be in this zone */ if (istar > nzone) { fprintf (stderr,"UJCRNUM: Star %d > zone max. %d\n", istar, nzone); break; } /* Read star entry from catalog */ if (ujcstar (istar, &star)) { fprintf (stderr,"UJCRNUM: Cannot read star %d\n", istar); break; } /* Extract selected fields if not probable duplicate */ else if (star.magetc > 0) { ra = ujcra (star.rasec); /* Right ascension in degrees */ dec = ujcdec (star.decsec); /* Declination in degrees */ wcscon (sysref, sysout, eqref, eqout, &ra, &dec, epout); mag = ujcmag (star.magetc); /* Magnitude */ plate = ujcplate (star.magetc); /* Plate number */ /* Save star position and magnitude in table */ ura[nfound] = ra; udec[nfound] = dec; umag[0][nfound] = mag; uplate[nfound] = plate; nfound++; if (nlog == 1) fprintf (stderr,"UJCRNUM: %04d.%08d: %9.5f %9.5f %5.2f\n", znum,istar,ra,dec,mag); /* Log operation */ if (nlog > 0 && jnum%nlog == 0) fprintf (stderr,"UJCRNUM: %04d.%08d %8d / %8d sources\r", znum, istar, jnum, nnum); (void) fclose (fcat); /* End of star processing */ } /* End of star */ } /* End of star loop */ } /* Summarize search */ if (nlog > 0) fprintf (stderr,"UJCRNUM: %d / %d found\n",nfound,nnum); return (nfound); } /* UJCBIN -- Fill a FITS WCS image with USNO J Catalog stars */ int ujcbin (refcatname, wcs, header, image, mag1,mag2, magscale, verbose) char *refcatname; /* Name of catalog (UJC, xxxxx.usno) */ struct WorldCoor *wcs; /* World coordinate system for image */ char *header; /* FITS header for output image */ char *image; /* Output FITS image */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ double magscale; /* Scaling factor for magnitude to pixel flux * (number of catalog objects per bin if 0) */ int verbose; /* 1 for diagnostics */ { double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double ra1,ra2; /* Limiting right ascensions of region in degrees */ double dec1,dec2; /* Limiting declinations of region in degrees */ int nz; /* Number of input UJ zone files */ int zlist[NZONES]; /* List of input UJ zones */ UJCstar star; /* UJ catalog entry for one star */ int sysref=WCS_J2000; /* Catalog coordinate system */ double eqref=2000.0; /* Catalog equinox */ double epref=2000.0; /* Catalog epoch */ char cstr[32]; int xplate; /* If nonzero, use objects only from this plate */ double rra1, rra2, rdec1, rdec2; int wrap, iwrap; int znum, itot,iz; int nlog,jstar, mprop, nmag; int itable = 0; int nstar; int pass; int ix, iy; double ra,dec; double mag; double rdist, ddist; int istar, istar1, istar2, plate; int nzmax = NZONES; /* Maximum number of declination zones */ char *str; char title[128]; double xpix, ypix, flux; int offscl; int bitpix, w, h; /* Image bits/pixel and pixel width and height */ double logt = log(10.0); itot = 0; xplate = getuplate (); /* Set image parameters */ bitpix = 0; (void)hgeti4 (header, "BITPIX", &bitpix); w = 0; (void)hgeti4 (header, "NAXIS1", &w); h = 0; (void)hgeti4 (header, "NAXIS2", &h); /* Set catalog code and path to catalog */ catname = refcatname; refcat = RefCat (refcatname,title,&sysref,&eqref,&epref,&mprop,&nmag); if (refcat == UJC && (str = getenv("UJ_PATH")) != NULL ) strcpy (cdu,str); /* Set catalog search limits from image WCS information */ sysout = wcs->syswcs; eqout = wcs->equinox; epout = wcs->epoch; wcscstr (cstr, sysout, eqout, epout); wcssize (wcs, &cra, &cdec, &dra, &ddec); SearchLim (cra,cdec,dra,ddec,sysout,&ra1,&ra2,&dec1,&dec2,verbose); /* mag1 is always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } rra1 = ra1; rra2 = ra2; rdec1 = dec1; rdec2 = dec2; RefLim (cra,cdec,dra,ddec,sysout,sysref,eqout,eqref,epout,epref,0.0, &rra1, &rra2, &rdec1, &rdec2, &wrap, verbose); /* Find UJ Star Catalog regions in which to search */ if (refcat == UJC) { nz = ujczones (rra1, rra2, rdec1, rdec2, nzmax, zlist, verbose); if (nz <= 0) { fprintf (stderr,"UJCBIN: no UJ zones found\n"); return (0); } } else nz = 1; /* Logging interval */ if (verbose) nlog = 100; else nlog = 0; nstar = 0; /* Loop through region list */ for (iz = 0; iz < nz; iz++) { /* Get path to zone catalog */ znum = zlist[iz]; if ((nstars = ujcopen (znum)) != 0) { jstar = 0; itable = 0; for (iwrap = 0; iwrap <= wrap; iwrap++) { /* Find first star based on RA */ if (iwrap == 0 || wrap == 0) istar1 = ujcsra (rra1); else istar1 = 1; /* Find last star based on RA */ if (iwrap == 1 || wrap == 0) istar2 = ujcsra (rra2); else istar2 = nstars; if (istar1 == 0 || istar2 == 0) break; /* Loop through zone catalog for this region */ for (istar = istar1; istar <= istar2; istar++) { itable ++; if (ujcstar (istar, &star)) { fprintf (stderr,"UJCBIN: Cannot read star %d\n", istar); break; } /* Extract selected fields if not probable duplicate */ else if (star.magetc > 0) { mag = ujcmag (star.magetc); /* Magnitude */ /* Check magnitude limits */ pass = 1; if (mag1 != mag2 && (mag < mag1 || mag > mag2)) pass = 0; /* Check plate number */ plate = ujcplate (star.magetc); /* Plate number */ if (xplate != 0 && plate != xplate) pass = 0; /* Check position limits */ if (pass) { ra = ujcra (star.rasec); /* RA in degrees */ dec = ujcdec (star.decsec); /* Dec in degrees */ /* Get position in output coordinate system */ wcscon (sysref,sysout,eqref,eqout,&ra,&dec,epout); /* Check distance along RA and Dec axes */ ddist = wcsdist (cra,cdec,cra,dec); if (ddist > ddec) pass = 0; rdist = wcsdist (cra,dec,ra,dec); if (rdist > dra) pass = 0; } /* Save star in FITS image */ if (pass) { wcs2pix (wcs, ra, dec, &xpix, &ypix, &offscl); if (!offscl) { if (magscale > 0.0) flux = magscale * exp (logt * (-mag / 2.5)); else flux = 1.0; ix = (int) (xpix + 0.5); iy = (int) (ypix + 0.5); addpix1 (image, bitpix, w,h, 0.0,1.0, xpix,ypix, flux); nstar++; jstar++; } else { ix = 0; iy = 0; } if (nlog == 1) { fprintf (stderr,"UJCBIN: %04d.%04d: %9.5f %9.5f %s", znum, istar,ra,dec,cstr); if (magscale > 0.0) fprintf (stderr, " %5.2f", mag); if (!offscl) flux = getpix1 (image, bitpix, w, h, 0.0, 1.0, ix, iy); else flux = 0.0; fprintf (stderr," (%d,%d): %f\n", ix, iy, flux); } /* End of accepted star processing */ } /* End of individual star processing */ } /* Log operation */ if (nlog > 0 && itable%nlog == 0) fprintf (stderr,"UJCBIN: zone %d (%4d / %4d) %6d / %6d sources\r", znum, iz+1, nz, jstar, itable); /* End of star loop */ } /* End of wrap loop */ } /* Close zone input file */ (void) fclose (fcat); itot = itot + itable; if (nlog > 0) fprintf (stderr,"UJCBIN: zone %d (%4d / %4d) %6d / %6d / %8d sources\n", znum, iz+1, nz, jstar, itable, nstars); /* End of zone processing */ } /* End of zone loop */ } /* Summarize search */ if (nlog > 0) { if (nz > 1) fprintf (stderr,"UJCBIN: %d zone: %d / %d found\n",nz,nstar,itot); else fprintf (stderr,"UJCBIN: 1 zone: %d / %d found\n",nstar,itable); } return (nstar); } /* Declination zone numbers */ int zone[NZONES]={0,75,150,225,300,375,450,525,600,675,750,825,900, 975,1050,1125,1200,1275,1350,1425,1500,1575,1650,1725}; /* UJCZONES -- figure out which UJ zones will need to be searched */ static int ujczones (ra1, ra2, dec1, dec2, nzmax, zones, verbose) double ra1, ra2; /* Right ascension limits in degrees */ double dec1, dec2; /* Declination limits in degrees */ int nzmax; /* Maximum number of zones to find */ int *zones; /* Region numbers (returned)*/ int verbose; /* 1 for diagnostics */ { int nrgn; /* Number of zones found (returned) */ int iz,iz1,iz2,i; for (i = 0; i < nzmax; i++) zones[i] = 0; nrgn = 0; /* Find zone range to search based on declination */ iz1 = ujczone (dec1); iz2 = ujczone (dec2); /* Tabulate zones to search */ i = 0; if (iz2 >= iz1) { for (iz = iz1; iz <= iz2; iz++) zones[i++] = zone[iz]; } else { for (iz = iz2; iz <= iz1; iz++) zones[i++] = zone[iz]; } nrgn = i; if (verbose) { fprintf (stderr,"UJCREG: %d zones: %d - %d\n",nrgn,zones[0],zones[i-1]); fprintf(stderr,"UJCREG: RA: %.5f - %.5f, Dec: %.5f - %.5f\n",ra1,ra2,dec1,dec2); } return (nrgn); } /* UJCRA -- returns right ascension in degrees from the UJ star structure */ static double ujcra (rasec) int rasec; /* RA in 100ths of arcseconds from UJ catalog entry */ { return ((double) (rasec) / 360000.0); } /* UJCDEC -- returns the declination in degrees from the UJ star structure */ static double ujcdec (decsec) int decsec; /* Declination in 100ths of arcseconds from UJ catalog entry */ { return ((double) (decsec - 32400000) / 360000.0); } /* UJCMAG -- returns the magnitude from the UJ star structure */ static double ujcmag (magetc) int magetc; /* Quality, plate, and magnitude from UJ catalog entry */ { if (magetc < 0) return ((double) (-magetc % 10000) * 0.01); else return ((double) (magetc % 10000) * 0.01); } /* UJCPLATE -- returns the plate number from the UJ star structure */ static int ujcplate (magetc) int magetc; /* Quality, plate, and magnitude from UJ catalog entry */ { if (magetc < 0) return ( (-magetc % 10000000) / 10000); else return ( (magetc % 10000000) / 10000); } /* UJCZONE -- find the UJ zone number where a declination can be found */ static int ujczone (dec) double dec; /* declination in degrees */ { double zonesize = 7.5; /* number of degrees per declination zone */ return ((int) ((dec + 90.0) / zonesize)); } /* UJCSRA -- Find UJ star closest to specified right ascension */ static int ujcsra (rax0) double rax0; /* Right ascension for which to search */ { int istar, istar1, istar2, nrep; double rax, ra1, ra, rdiff, rdiff1, rdiff2, sdiff; UJCstar star; /* UJ catalog entry for one star */ char rastrx[32]; int debug = 0; rax = rax0; ra2str (rastrx, 31, rax, 3); istar1 = 1; if (ujcstar (istar1, &star)) return (0); ra1 = ujcra (star.rasec); istar = nstars; nrep = 0; while (istar != istar1 && nrep < 20) { if (ujcstar (istar, &star)) break; else { ra = ujcra (star.rasec); if (ra == ra1) break; if (debug) { char rastr[32]; ra2str (rastr, 31, ra, 3); fprintf (stderr,"UJCSRA %d %d: %s (%s)\n", nrep,istar,rastr,rastrx); } rdiff = ra1 - ra; rdiff1 = ra1 - rax; rdiff2 = ra - rax; if (nrep > 20 && ABS(rdiff2) > ABS(rdiff1)) { istar = istar1; break; } nrep++; sdiff = (double)(istar - istar1) * rdiff1 / rdiff; istar2 = istar1 + (int) (sdiff + 0.5); ra1 = ra; istar1 = istar; istar = istar2; if (debug) { fprintf (stderr,"UJCSRA: ra1= %.5f ra= %.5f rax= %.5f\n", ra1,ra,rax); fprintf (stderr,"UJCSRA: rdiff= %.5f rdiff1= %.5f rdiff2= %.5f\n", rdiff,rdiff1,rdiff2); fprintf (stderr,"UJCSRA: istar1= %d istar= %d istar1= %d\n", istar1,istar,istar2); } if (istar < 1) istar = 1; if (istar > nstars) istar = nstars; if (istar == istar1) break; } } return (istar); } /* UJCOPEN -- Open UJ Catalog zone catalog, returning number of entries */ static int ujcopen (znum) int znum; /* UJ Catalog zone */ { char zonepath[128]; /* Pathname for input UJ zone file */ UJCstar star; /* UJ catalog entry for one star */ int lfile; /* Get path to zone catalog */ if (ujcpath (znum, zonepath)) { fprintf (stderr, "UJCOPEN: Cannot find zone catalog for %d\n", znum); return (0); } /* Find number of stars in zone catalog by its length */ lfile = getfilesize (zonepath); if (lfile < 2) { fprintf (stderr,"UJCOPEN: Zone catalog %s has no entries\n",zonepath); return (0); } else nstars = lfile / 12; /* Open zone catalog */ if (!(fcat = fopen (zonepath, "rb"))) { fprintf (stderr,"UJCOPEN: Zone catalog %s cannot be read\n",zonepath); return (0); } /* Check to see if byte-swapping is necessary */ cswap = 0; if (ujcstar (1, &star)) { fprintf (stderr,"UJCOPEN: cannot read star 1 from UJ zone catalog %s\n", zonepath); return (0); } else { if (star.decsec < 0) { cswap = 1; fprintf (stderr,"UJCOPEN: swapping bytes in UJ zone catalog %s\n", zonepath); } else cswap = 0; } return (nstars); } /* UJCPATH -- Get UJ Catalog region file pathname */ static int ujcpath (zn, path) int zn; /* UJ zone number */ char *path; /* Pathname of UJ zone file */ { if (refcat == USNO) { strcpy (path, catname); return (0); } else if (zn < 0 || zn > 1725) { fprintf (stderr, "UJCPATH: zone %d out of range 0-1725\n",zn); return (-1); } else if (strchr (cdu,'C')) sprintf (path,"%s/ZONE%04d.CAT", cdu, zn); else sprintf (path,"%s/zone%04d.cat", cdu, zn); return (0); } /* UJCSTAR -- Get UJ catalog entry for one star; return 0 if successful */ static int ujcstar (istar, star) int istar; /* Star sequence number in UJ zone catalog */ UJCstar *star; /* UJ catalog entry for one star */ { int nbs, nbr, nbskip; if (istar < 1 || istar > nstars) { fprintf (stderr, "UJCstar %d is not in catalog\n",istar); return (-1); } nbskip = 12 * (istar - 1); if (fseek (fcat,nbskip,SEEK_SET)) return (-1); nbs = sizeof (UJCstar); nbr = fread (star, nbs, 1, fcat) * nbs; if (nbr < nbs) { fprintf (stderr, "UJCstar %d / %d bytes read\n",nbr, nbs); return (-2); } if (cswap) ujcswap ((char *)star); return (0); } /* UJCSWAP -- Reverse bytes of UJ Catalog entry */ static void ujcswap (string) char *string; /* Start of vector of 4-byte ints */ { char *sbyte, *slast; char temp0, temp1, temp2, temp3; int nbytes = 12; /* Number of bytes to reverse */ slast = string + nbytes; sbyte = string; while (sbyte < slast) { temp3 = sbyte[0]; temp2 = sbyte[1]; temp1 = sbyte[2]; temp0 = sbyte[3]; sbyte[0] = temp0; sbyte[1] = temp1; sbyte[2] = temp2; sbyte[3] = temp3; sbyte = sbyte + 4; } return; } /* May 20 1996 New subroutine * May 23 1996 Add optional plate number check * Aug 6 1996 Remove unused variables after lint * Oct 15 1996 Add comparison when testing an assignment * Oct 17 1996 Fix after lint: cast argument to UJCSWAP * Nov 13 1996 Return no more than maximum star number * Nov 13 1996 Write all error messages to stderr with subroutine names * Nov 15 1996 Implement search radius; change input arguments * Dec 12 1996 Improve logging * Dec 17 1996 Add code to keep brightest or closest stars if too many found * Dec 18 1996 Add code to read a specific star * Mar 20 1997 Clean up UJCRNUM after lint * * Jun 24 1998 Add string lengths to ra2str() and dec2str() calls * Jun 24 1998 Initialize byte-swapping flag in UJCOPEN() * Sep 22 1998 Convert to desired output coordinate system * Oct 29 1998 Correctly assign numbers when too many stars are found * * Jun 16 1999 Use SearchLim() * Aug 16 1999 Add RefLim() to get converted search coordinates right * Aug 16 1999 Fix bug to fix failure to search across 0:00 RA * Aug 25 1999 Return real number of stars from ujcread() * Aug 26 1999 Set nlog to 100 if verbose mode is on * Sep 10 1999 Set plate selection with subroutine, not argument * Sep 16 1999 Fix bug which didn't always return closest stars * Sep 16 1999 Add distsort argument so brightest stars in circle works, too * Oct 20 1999 Include wcscat.h * Oct 21 1999 Delete unused variables after lint * * Jun 26 2000 Add coordinate system to SearchLim() arguments * Oct 25 2000 Add USNO plate catalogs; fix byte order test * Nov 29 2000 Add option to read UJ catalog using HTTP * * Jan 11 2001 All printing is to stderr * Jun 7 2001 Add proper motion flag and number of magnitudes to RefCat() * Sep 19 2001 Drop fitshead.h; it is in wcs.h * * Feb 4 2003 Open catalog file rb instead of r (Martin Ploner, Bern) * Mar 11 2003 Improve position filtering * May 27 2003 Use getfilesize() to get file length * Aug 22 2003 Add radi argument for inner edge of search annulus * Sep 25 2003 Add ujcbin() to fill an image with sources * Oct 6 2003 Update ujcread() and ujcbin() for improved RefLim() * Nov 18 2003 Initialize image size and bits/pixel from header in ujcbin() * Dec 12 2003 Fix bug in wcs2pix() call in ujcbin() * * Aug 30 2004 Include fitsfile.h and math.h * * Jun 20 2006 Initialize uninitialized variables * Sep 26 2006 Increase length of rastr and destr from 16 to 32 * Nov 16 2006 Fix binning * * Jan 8 2007 Fix bad format statement in ujcbin() * Jan 10 2007 Add match=1 argument to webrnum() * Jul 5 2007 Fix bug in ujcread() and ujcbin() which always rejected stars */ wcstools-3.9.5/libwcs/wcs.c0000664000016200001660000025336612733325551014723 0ustar minkoirsys/*** File libwcs/wcs.c *** June 24, 2016 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1994-2016 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: wcs.c (World Coordinate Systems) * Purpose: Convert FITS WCS to pixels and vice versa: * Subroutine: wcsxinit (cra,cdec,secpix,xrpix,yrpix,nxpix,nypix,rotate,equinox,epoch,proj) * sets a WCS structure from arguments * Subroutine: wcskinit (nxpix,nypix,ctype1,ctype2,crpix1,crpix2,crval1,crval2, cd,cdelt1,cdelt2,crota,equinox,epoch) * sets a WCS structure from keyword-based arguments * Subroutine: wcsreset (wcs,crpix1,crpix2,crval1,crval2,cdelt1,cdelt2,crota,cd, equinox) * resets an existing WCS structure from arguments * Subroutine: wcsdeltset (wcs,cdelt1,cdelt2,crota) sets rotation and scaling * Subroutine: wcscdset (wcs, cd) sets rotation and scaling from a CD matrix * Subroutine: wcspcset (wcs,cdelt1,cdelt2,pc) sets rotation and scaling * Subroutine: wcseqset (wcs, equinox) resets an existing WCS structure to new equinox * Subroutine: iswcs(wcs) returns 1 if WCS structure is filled, else 0 * Subroutine: nowcs(wcs) returns 0 if WCS structure is filled, else 1 * Subroutine: wcscent (wcs) prints the image center and size in WCS units * Subroutine: wcssize (wcs, cra, cdec, dra, ddec) returns image center and size * Subroutine: wcsfull (wcs, cra, cdec, width, height) returns image center and size * Subroutine: wcsrange (wcs, ra1, ra2, dec1, dec2) returns image coordinate limits * Subroutine: wcsshift (wcs,cra,cdec) resets the center of a WCS structure * Subroutine: wcsdist (x1,y1,x2,y2) compute angular distance between ra/dec or lat/long * Subroutine: wcsdiff (x1,y1,x2,y2) compute angular distance between ra/dec or lat/long * Subroutine: wcscominit (wcs,command) sets up a command format for execution by wcscom * Subroutine: wcsoutinit (wcs,coor) sets up the coordinate system used by pix2wcs * Subroutine: getwcsout (wcs) returns current output coordinate system used by pix2wcs * Subroutine: wcsininit (wcs,coor) sets up the coordinate system used by wcs2pix * Subroutine: getwcsin (wcs) returns current input coordinate system used by wcs2pix * Subroutine: setwcsdeg(wcs, new) sets WCS output in degrees or hh:mm:ss * Subroutine: getradecsys(wcs) returns current coordinate system type * Subroutine: wcscom (wcs,file,x,y,wcstr) executes a command using the current world coordinates * Subroutine: setwcslin (wcs, mode) sets output string mode for LINEAR * Subroutine: pix2wcst (wcs,xpix,ypix,wcstring,lstr) pixels -> sky coordinate string * Subroutine: pix2wcs (wcs,xpix,ypix,xpos,ypos) pixel coordinates -> sky coordinates * Subroutine: wcsc2pix (wcs,xpos,ypos,coorsys,xpix,ypix,offscl) sky coordinates -> pixel coordinates * Subroutine: wcs2pix (wcs,xpos,ypos,xpix,ypix,offscl) sky coordinates -> pixel coordinates * Subroutine: wcszin (izpix) sets third dimension for pix2wcs() and pix2wcst() * Subroutine: wcszout (wcs) returns third dimension from wcs2pix() * Subroutine: setwcsfile (filename) Set file name for error messages * Subroutine: setwcserr (errmsg) Set error message * Subroutine: wcserr() Print error message * Subroutine: setdefwcs (wcsproj) Set flag to choose AIPS or WCSLIB WCS subroutines * Subroutine: getdefwcs() Get flag to switch between AIPS and WCSLIB subroutines * Subroutine: savewcscoor (wcscoor) * Subroutine: getwcscoor() Return preset output default coordinate system * Subroutine: savewcscom (i, wcscom) Save specified WCS command * Subroutine: setwcscom (wcs) Initialize WCS commands * Subroutine: getwcscom (i) Return specified WCS command * Subroutine: wcsfree (wcs) Free storage used by WCS structure * Subroutine: freewcscom (wcs) Free storage used by WCS commands * Subroutine: cpwcs (&header, cwcs) */ #include /* strstr, NULL */ #include /* stderr */ #include #include "wcs.h" #ifndef VMS #include #endif static char wcserrmsg[80]; static char wcsfile[256]={""}; static void wcslibrot(); void wcsrotset(); static int wcsproj0 = 0; static int izpix = 0; static double zpix = 0.0; void wcsfree (wcs) struct WorldCoor *wcs; /* WCS structure */ { if (nowcs (wcs)) { /* Free WCS structure if allocated but not filled */ if (wcs) free (wcs); return; } /* Free WCS on which this WCS depends */ if (wcs->wcs) { wcsfree (wcs->wcs); wcs->wcs = NULL; } freewcscom (wcs); if (wcs->wcsname != NULL) free (wcs->wcsname); if (wcs->lin.imgpix != NULL) free (wcs->lin.imgpix); if (wcs->lin.piximg != NULL) free (wcs->lin.piximg); if (wcs->inv_x != NULL) poly_end (wcs->inv_x); if (wcs->inv_y != NULL) poly_end (wcs->inv_y); free (wcs); return; } /* Set up a WCS structure from subroutine arguments */ struct WorldCoor * wcsxinit (cra,cdec,secpix,xrpix,yrpix,nxpix,nypix,rotate,equinox,epoch,proj) double cra; /* Center right ascension in degrees */ double cdec; /* Center declination in degrees */ double secpix; /* Number of arcseconds per pixel */ double xrpix; /* Reference pixel X coordinate */ double yrpix; /* Reference pixel X coordinate */ int nxpix; /* Number of pixels along x-axis */ int nypix; /* Number of pixels along y-axis */ double rotate; /* Rotation angle (clockwise positive) in degrees */ int equinox; /* Equinox of coordinates, 1950 and 2000 supported */ double epoch; /* Epoch of coordinates, used for FK4/FK5 conversion * no effect if 0 */ char *proj; /* Projection */ { struct WorldCoor *wcs; double cdelt1, cdelt2; wcs = (struct WorldCoor *) calloc (1, sizeof(struct WorldCoor)); /* Set WCSLIB flags so that structures will be reinitialized */ wcs->cel.flag = 0; wcs->lin.flag = 0; wcs->wcsl.flag = 0; /* Image dimensions */ wcs->naxis = 2; wcs->naxes = 2; wcs->lin.naxis = 2; wcs->nxpix = nxpix; wcs->nypix = nypix; wcs->wcsproj = wcsproj0; wcs->crpix[0] = xrpix; wcs->crpix[1] = yrpix; wcs->xrefpix = wcs->crpix[0]; wcs->yrefpix = wcs->crpix[1]; wcs->lin.crpix = wcs->crpix; wcs->crval[0] = cra; wcs->crval[1] = cdec; wcs->xref = wcs->crval[0]; wcs->yref = wcs->crval[1]; wcs->cel.ref[0] = wcs->crval[0]; wcs->cel.ref[1] = wcs->crval[1]; wcs->cel.ref[2] = 999.0; strcpy (wcs->c1type,"RA"); strcpy (wcs->c2type,"DEC"); /* Allan Brighton: 28.4.98: for backward compat., remove leading "--" */ while (proj && *proj == '-') proj++; strncpy (wcs->ptype,proj, 3); wcs->ptype[3] = (char) 0; strcpy (wcs->ctype[0],"RA---"); strcpy (wcs->ctype[1],"DEC--"); strcat (wcs->ctype[0],proj); strcat (wcs->ctype[1],proj); if (wcstype (wcs, wcs->ctype[0], wcs->ctype[1])) { wcsfree (wcs); return (NULL); } /* Approximate world coordinate system from a known plate scale */ cdelt1 = -secpix / 3600.0; cdelt2 = secpix / 3600.0; wcsdeltset (wcs, cdelt1, cdelt2, rotate); wcs->lin.cdelt = wcs->cdelt; wcs->lin.pc = wcs->pc; /* Coordinate reference frame and equinox */ wcs->equinox = (double) equinox; if (equinox > 1980) strcpy (wcs->radecsys,"FK5"); else strcpy (wcs->radecsys,"FK4"); if (epoch > 0) wcs->epoch = epoch; else wcs->epoch = 0.0; wcs->wcson = 1; wcs->syswcs = wcscsys (wcs->radecsys); wcsoutinit (wcs, wcs->radecsys); wcsininit (wcs, wcs->radecsys); wcs->eqout = 0.0; wcs->printsys = 1; wcs->tabsys = 0; /* Initialize special WCS commands */ setwcscom (wcs); return (wcs); } /* Set up a WCS structure from subroutine arguments based on FITS keywords */ struct WorldCoor * wcskinit (naxis1, naxis2, ctype1, ctype2, crpix1, crpix2, crval1, crval2, cd, cdelt1, cdelt2, crota, equinox, epoch) int naxis1; /* Number of pixels along x-axis */ int naxis2; /* Number of pixels along y-axis */ char *ctype1; /* FITS WCS projection for axis 1 */ char *ctype2; /* FITS WCS projection for axis 2 */ double crpix1, crpix2; /* Reference pixel coordinates */ double crval1, crval2; /* Coordinates at reference pixel in degrees */ double *cd; /* Rotation matrix, used if not NULL */ double cdelt1, cdelt2; /* scale in degrees/pixel, ignored if cd is not NULL */ double crota; /* Rotation angle in degrees, ignored if cd is not NULL */ int equinox; /* Equinox of coordinates, 1950 and 2000 supported */ double epoch; /* Epoch of coordinates, used for FK4/FK5 conversion * no effect if 0 */ { struct WorldCoor *wcs; wcs = (struct WorldCoor *) calloc (1, sizeof(struct WorldCoor)); /* Set WCSLIB flags so that structures will be reinitialized */ wcs->cel.flag = 0; wcs->lin.flag = 0; wcs->wcsl.flag = 0; /* Image dimensions */ wcs->naxis = 2; wcs->naxes = 2; wcs->lin.naxis = 2; wcs->nxpix = naxis1; wcs->nypix = naxis2; wcs->wcsproj = wcsproj0; wcs->crpix[0] = crpix1; wcs->crpix[1] = crpix2; wcs->xrefpix = wcs->crpix[0]; wcs->yrefpix = wcs->crpix[1]; wcs->lin.crpix = wcs->crpix; if (wcstype (wcs, ctype1, ctype2)) { wcsfree (wcs); return (NULL); } if (wcs->latbase == 90) crval2 = 90.0 - crval2; else if (wcs->latbase == -90) crval2 = crval2 - 90.0; wcs->crval[0] = crval1; wcs->crval[1] = crval2; wcs->xref = wcs->crval[0]; wcs->yref = wcs->crval[1]; wcs->cel.ref[0] = wcs->crval[0]; wcs->cel.ref[1] = wcs->crval[1]; wcs->cel.ref[2] = 999.0; if (cd != NULL) wcscdset (wcs, cd); else if (cdelt1 != 0.0) wcsdeltset (wcs, cdelt1, cdelt2, crota); else { wcsdeltset (wcs, 1.0, 1.0, crota); setwcserr ("WCSRESET: setting CDELT to 1"); } wcs->lin.cdelt = wcs->cdelt; wcs->lin.pc = wcs->pc; /* Coordinate reference frame and equinox */ wcs->equinox = (double) equinox; if (equinox > 1980) strcpy (wcs->radecsys,"FK5"); else strcpy (wcs->radecsys,"FK4"); if (epoch > 0) wcs->epoch = epoch; else wcs->epoch = 0.0; wcs->wcson = 1; strcpy (wcs->radecout, wcs->radecsys); wcs->syswcs = wcscsys (wcs->radecsys); wcsoutinit (wcs, wcs->radecsys); wcsininit (wcs, wcs->radecsys); wcs->eqout = 0.0; wcs->printsys = 1; wcs->tabsys = 0; /* Initialize special WCS commands */ setwcscom (wcs); return (wcs); } /* Set projection in WCS structure from FITS keyword values */ int wcstype (wcs, ctype1, ctype2) struct WorldCoor *wcs; /* World coordinate system structure */ char *ctype1; /* FITS WCS projection for axis 1 */ char *ctype2; /* FITS WCS projection for axis 2 */ { int i, iproj; int nctype = NWCSTYPE; char ctypes[NWCSTYPE][4]; char dtypes[10][4]; /* Initialize projection types */ strcpy (ctypes[0], "LIN"); strcpy (ctypes[1], "AZP"); strcpy (ctypes[2], "SZP"); strcpy (ctypes[3], "TAN"); strcpy (ctypes[4], "SIN"); strcpy (ctypes[5], "STG"); strcpy (ctypes[6], "ARC"); strcpy (ctypes[7], "ZPN"); strcpy (ctypes[8], "ZEA"); strcpy (ctypes[9], "AIR"); strcpy (ctypes[10], "CYP"); strcpy (ctypes[11], "CAR"); strcpy (ctypes[12], "MER"); strcpy (ctypes[13], "CEA"); strcpy (ctypes[14], "COP"); strcpy (ctypes[15], "COD"); strcpy (ctypes[16], "COE"); strcpy (ctypes[17], "COO"); strcpy (ctypes[18], "BON"); strcpy (ctypes[19], "PCO"); strcpy (ctypes[20], "SFL"); strcpy (ctypes[21], "PAR"); strcpy (ctypes[22], "AIT"); strcpy (ctypes[23], "MOL"); strcpy (ctypes[24], "CSC"); strcpy (ctypes[25], "QSC"); strcpy (ctypes[26], "TSC"); strcpy (ctypes[27], "NCP"); strcpy (ctypes[28], "GLS"); strcpy (ctypes[29], "DSS"); strcpy (ctypes[30], "PLT"); strcpy (ctypes[31], "TNX"); strcpy (ctypes[32], "ZPX"); strcpy (ctypes[33], "TPV"); /* Initialize distortion types */ strcpy (dtypes[1], "SIP"); if (!strncmp (ctype1, "LONG",4)) strncpy (ctype1, "XLON",4); strcpy (wcs->ctype[0], ctype1); /* This is only to catch special non-standard projections */ strncpy (wcs->ptype, ctype1, 3); wcs->ptype[3] = 0; /* Linear coordinates */ if (!strncmp (ctype1,"LINEAR",6)) { wcs->prjcode = WCS_LIN; strcpy (wcs->c1type, "LIN"); strcpy (wcs->ptype, "LIN"); } /* Pixel coordinates */ else if (!strncmp (ctype1,"PIXEL",6)) { wcs->prjcode = WCS_PIX; strcpy (wcs->c1type, "PIX"); strcpy (wcs->ptype, "PIX"); } /*Detector pixel coordinates */ else if (strsrch (ctype1,"DET")) { wcs->prjcode = WCS_PIX; strcpy (wcs->c1type, "PIX"); strcpy (wcs->ptype, "PIX"); } /* Set up right ascension, declination, latitude, or longitude */ else if (ctype1[0] == 'R' || ctype1[0] == 'D' || ctype1[0] == 'A' || ctype1[1] == 'L') { wcs->c1type[0] = ctype1[0]; wcs->c1type[1] = ctype1[1]; if (ctype1[2] == '-') { wcs->c1type[2] = 0; iproj = 3; } else { wcs->c1type[2] = ctype1[2]; iproj = 4; if (ctype1[3] == '-') { wcs->c1type[3] = 0; } else { wcs->c1type[3] = ctype1[3]; wcs->c1type[4] = 0; } } if (ctype1[iproj] == '-') iproj = iproj + 1; if (ctype1[iproj] == '-') iproj = iproj + 1; if (ctype1[iproj] == '-') iproj = iproj + 1; if (ctype1[iproj] == '-') iproj = iproj + 1; wcs->ptype[0] = ctype1[iproj]; wcs->ptype[1] = ctype1[iproj+1]; wcs->ptype[2] = ctype1[iproj+2]; wcs->ptype[3] = 0; sprintf (wcs->ctype[0],"%-4s %3s",wcs->c1type,wcs->ptype); for (i = 0; i < 8; i++) if (wcs->ctype[0][i] == ' ') wcs->ctype[0][i] = '-'; /* Find projection type */ wcs->prjcode = 0; /* default type is linear */ for (i = 1; i < nctype; i++) { if (!strncmp(wcs->ptype, ctypes[i], 3)) wcs->prjcode = i; } /* Handle "obsolete" NCP projection (now WCSLIB should be OK) if (wcs->prjcode == WCS_NCP) { if (wcs->wcsproj == WCS_BEST) wcs->wcsproj = WCS_OLD; else if (wcs->wcsproj == WCS_ALT) wcs->wcsproj = WCS_NEW; } */ /* Work around bug in WCSLIB handling of CAR projection else if (wcs->prjcode == WCS_CAR) { if (wcs->wcsproj == WCS_BEST) wcs->wcsproj = WCS_OLD; else if (wcs->wcsproj == WCS_ALT) wcs->wcsproj = WCS_NEW; } */ /* Work around bug in WCSLIB handling of COE projection else if (wcs->prjcode == WCS_COE) { if (wcs->wcsproj == WCS_BEST) wcs->wcsproj = WCS_OLD; else if (wcs->wcsproj == WCS_ALT) wcs->wcsproj = WCS_NEW; } else if (wcs->wcsproj == WCS_BEST) */ if (wcs->wcsproj == WCS_BEST) wcs->wcsproj = WCS_NEW; else if (wcs->wcsproj == WCS_ALT) wcs->wcsproj = WCS_OLD; /* if (wcs->wcsproj == WCS_OLD && ( wcs->prjcode != WCS_STG && wcs->prjcode != WCS_AIT && wcs->prjcode != WCS_MER && wcs->prjcode != WCS_GLS && wcs->prjcode != WCS_ARC && wcs->prjcode != WCS_TAN && wcs->prjcode != WCS_TNX && wcs->prjcode != WCS_SIN && wcs->prjcode != WCS_PIX && wcs->prjcode != WCS_LIN && wcs->prjcode != WCS_CAR && wcs->prjcode != WCS_COE && wcs->prjcode != WCS_NCP && wcs->prjcode != WCS_ZPX)) wcs->wcsproj = WCS_NEW; */ /* Handle NOAO corrected TNX as uncorrected TAN if oldwcs is set */ if (wcs->wcsproj == WCS_OLD && wcs->prjcode == WCS_TNX) { wcs->ctype[0][6] = 'A'; wcs->ctype[0][7] = 'N'; wcs->prjcode = WCS_TAN; } /* Handle NOAO corrected ZPX as uncorrected ZPN if oldwcs is set */ if (wcs->wcsproj == WCS_OLD && wcs->prjcode == WCS_ZPX) { wcs->ctype[0][6] = 'P'; wcs->ctype[0][7] = 'N'; wcs->prjcode = WCS_ZPN; } } /* If not sky coordinates, assume linear */ else { wcs->prjcode = WCS_LIN; strcpy (wcs->c1type, "LIN"); strcpy (wcs->ptype, "LIN"); return (0); } /* Second coordinate type */ if (!strncmp (ctype2, "NPOL",4)) { ctype2[0] = ctype1[0]; strncpy (ctype2+1, "LAT",3); wcs->latbase = 90; strcpy (wcs->radecsys,"NPOLE"); wcs->syswcs = WCS_NPOLE; } else if (!strncmp (ctype2, "SPA-",4)) { ctype2[0] = ctype1[0]; strncpy (ctype2+1, "LAT",3); wcs->latbase = -90; strcpy (wcs->radecsys,"SPA"); wcs->syswcs = WCS_SPA; } else wcs->latbase = 0; strcpy (wcs->ctype[1], ctype2); /* Linear coordinates */ if (!strncmp (ctype2,"LINEAR",6)) { wcs->prjcode = WCS_LIN; strcpy (wcs->c2type, "LIN"); } /* Pixel coordinates */ else if (!strncmp (ctype2,"PIXEL",6)) { wcs->prjcode = WCS_PIX; strcpy (wcs->c2type, "PIX"); } /* Detector coordinates */ else if (!strncmp (ctype2,"DET",3)) { wcs->prjcode = WCS_PIX; strcpy (wcs->c2type, "PIX"); } /* Set up right ascension, declination, latitude, or longitude */ else if (ctype2[0] == 'R' || ctype2[0] == 'D' || ctype2[0] == 'A' || ctype2[1] == 'L') { wcs->c2type[0] = ctype2[0]; wcs->c2type[1] = ctype2[1]; if (ctype2[2] == '-') { wcs->c2type[2] = 0; iproj = 3; } else { wcs->c2type[2] = ctype2[2]; iproj = 4; if (ctype2[3] == '-') { wcs->c2type[3] = 0; } else { wcs->c2type[3] = ctype2[3]; wcs->c2type[4] = 0; } } if (ctype2[iproj] == '-') iproj = iproj + 1; if (ctype2[iproj] == '-') iproj = iproj + 1; if (ctype2[iproj] == '-') iproj = iproj + 1; if (ctype2[iproj] == '-') iproj = iproj + 1; if (!strncmp (ctype1, "DEC", 3) || !strncmp (ctype1+1, "LAT", 3)) wcs->coorflip = 1; else wcs->coorflip = 0; if (ctype2[1] == 'L' || ctype2[0] == 'A') { wcs->degout = 1; wcs->ndec = 5; } else { wcs->degout = 0; wcs->ndec = 3; } sprintf (wcs->ctype[1],"%-4s %3s",wcs->c2type,wcs->ptype); for (i = 0; i < 8; i++) if (wcs->ctype[1][i] == ' ') wcs->ctype[1][i] = '-'; } /* If not sky coordinates, assume linear */ else { strcpy (wcs->c2type, "LIN"); wcs->prjcode = WCS_LIN; } /* Set distortion code from CTYPE1 extension */ setdistcode (wcs, ctype1); return (0); } int wcsreset (wcs, crpix1, crpix2, crval1, crval2, cdelt1, cdelt2, crota, cd) struct WorldCoor *wcs; /* World coordinate system data structure */ double crpix1, crpix2; /* Reference pixel coordinates */ double crval1, crval2; /* Coordinates at reference pixel in degrees */ double cdelt1, cdelt2; /* scale in degrees/pixel, ignored if cd is not NULL */ double crota; /* Rotation angle in degrees, ignored if cd is not NULL */ double *cd; /* Rotation matrix, used if not NULL */ { if (nowcs (wcs)) return (-1); /* Set WCSLIB flags so that structures will be reinitialized */ wcs->cel.flag = 0; wcs->lin.flag = 0; wcs->wcsl.flag = 0; /* Reference pixel coordinates and WCS value */ wcs->crpix[0] = crpix1; wcs->crpix[1] = crpix2; wcs->xrefpix = wcs->crpix[0]; wcs->yrefpix = wcs->crpix[1]; wcs->lin.crpix = wcs->crpix; wcs->crval[0] = crval1; wcs->crval[1] = crval2; wcs->xref = wcs->crval[0]; wcs->yref = wcs->crval[1]; if (wcs->coorflip) { wcs->cel.ref[1] = wcs->crval[0]; wcs->cel.ref[0] = wcs->crval[1]; } else { wcs->cel.ref[0] = wcs->crval[0]; wcs->cel.ref[1] = wcs->crval[1]; } /* Keep ref[2] and ref[3] from input */ /* Initialize to no plate fit */ wcs->ncoeff1 = 0; wcs->ncoeff2 = 0; if (cd != NULL) wcscdset (wcs, cd); else if (cdelt1 != 0.0) wcsdeltset (wcs, cdelt1, cdelt2, crota); else { wcs->xinc = 1.0; wcs->yinc = 1.0; setwcserr ("WCSRESET: setting CDELT to 1"); } /* Coordinate reference frame, equinox, and epoch */ if (!strncmp (wcs->ptype,"LIN",3) || !strncmp (wcs->ptype,"PIX",3)) wcs->degout = -1; wcs->wcson = 1; return (0); } void wcseqset (wcs, equinox) struct WorldCoor *wcs; /* World coordinate system data structure */ double equinox; /* Desired equinox as fractional year */ { if (nowcs (wcs)) return; /* Leave WCS alone if already at desired equinox */ if (wcs->equinox == equinox) return; /* Convert center from B1950 (FK4) to J2000 (FK5) */ if (equinox == 2000.0 && wcs->equinox == 1950.0) { if (wcs->coorflip) { fk425e (&wcs->crval[1], &wcs->crval[0], wcs->epoch); wcs->cel.ref[1] = wcs->crval[0]; wcs->cel.ref[0] = wcs->crval[1]; } else { fk425e (&wcs->crval[0], &wcs->crval[1], wcs->epoch); wcs->cel.ref[0] = wcs->crval[0]; wcs->cel.ref[1] = wcs->crval[1]; } wcs->xref = wcs->crval[0]; wcs->yref = wcs->crval[1]; wcs->equinox = 2000.0; strcpy (wcs->radecsys, "FK5"); wcs->syswcs = WCS_J2000; wcs->cel.flag = 0; wcs->wcsl.flag = 0; } /* Convert center from J2000 (FK5) to B1950 (FK4) */ else if (equinox == 1950.0 && wcs->equinox == 2000.0) { if (wcs->coorflip) { fk524e (&wcs->crval[1], &wcs->crval[0], wcs->epoch); wcs->cel.ref[1] = wcs->crval[0]; wcs->cel.ref[0] = wcs->crval[1]; } else { fk524e (&wcs->crval[0], &wcs->crval[1], wcs->epoch); wcs->cel.ref[0] = wcs->crval[0]; wcs->cel.ref[1] = wcs->crval[1]; } wcs->xref = wcs->crval[0]; wcs->yref = wcs->crval[1]; wcs->equinox = 1950.0; strcpy (wcs->radecsys, "FK4"); wcs->syswcs = WCS_B1950; wcs->cel.flag = 0; wcs->wcsl.flag = 0; } wcsoutinit (wcs, wcs->radecsys); wcsininit (wcs, wcs->radecsys); return; } /* Set scale and rotation in WCS structure */ void wcscdset (wcs, cd) struct WorldCoor *wcs; /* World coordinate system structure */ double *cd; /* CD matrix, ignored if NULL */ { double tcd; if (cd == NULL) return; wcs->rotmat = 1; wcs->cd[0] = cd[0]; wcs->cd[1] = cd[1]; wcs->cd[2] = cd[2]; wcs->cd[3] = cd[3]; (void) matinv (2, wcs->cd, wcs->dc); /* Compute scale */ wcs->xinc = sqrt (cd[0]*cd[0] + cd[2]*cd[2]); wcs->yinc = sqrt (cd[1]*cd[1] + cd[3]*cd[3]); /* Deal with x=Dec/y=RA case */ if (wcs->coorflip) { tcd = cd[1]; cd[1] = -cd[2]; cd[2] = -tcd; } wcslibrot (wcs); wcs->wcson = 1; /* Compute image rotation */ wcsrotset (wcs); wcs->cdelt[0] = wcs->xinc; wcs->cdelt[1] = wcs->yinc; return; } /* Set scale and rotation in WCS structure from axis scale and rotation */ void wcsdeltset (wcs, cdelt1, cdelt2, crota) struct WorldCoor *wcs; /* World coordinate system structure */ double cdelt1; /* degrees/pixel in first axis (or both axes) */ double cdelt2; /* degrees/pixel in second axis if nonzero */ double crota; /* Rotation counterclockwise in degrees */ { double *pci; double crot, srot; int i, j, naxes; naxes = wcs->naxis; if (naxes > 2) naxes = 2; wcs->cdelt[0] = cdelt1; if (cdelt2 != 0.0) wcs->cdelt[1] = cdelt2; else wcs->cdelt[1] = cdelt1; wcs->xinc = wcs->cdelt[0]; wcs->yinc = wcs->cdelt[1]; pci = wcs->pc; for (i = 0; i < naxes; i++) { for (j = 0; j < naxes; j++) { if (i ==j) *pci = 1.0; else *pci = 0.0; pci++; } } wcs->rotmat = 0; /* If image is reversed, value of CROTA is flipped, too */ wcs->rot = crota; if (wcs->rot < 0.0) wcs->rot = wcs->rot + 360.0; if (wcs->rot >= 360.0) wcs->rot = wcs->rot - 360.0; crot = cos (degrad(wcs->rot)); if (cdelt1 * cdelt2 > 0) srot = sin (-degrad(wcs->rot)); else srot = sin (degrad(wcs->rot)); /* Set CD matrix */ wcs->cd[0] = wcs->cdelt[0] * crot; if (wcs->cdelt[0] < 0) wcs->cd[1] = -fabs (wcs->cdelt[1]) * srot; else wcs->cd[1] = fabs (wcs->cdelt[1]) * srot; if (wcs->cdelt[1] < 0) wcs->cd[2] = fabs (wcs->cdelt[0]) * srot; else wcs->cd[2] = -fabs (wcs->cdelt[0]) * srot; wcs->cd[3] = wcs->cdelt[1] * crot; (void) matinv (2, wcs->cd, wcs->dc); /* Set rotation matrix */ wcslibrot (wcs); /* Set image rotation and mirroring */ if (wcs->coorflip) { if (wcs->cdelt[0] < 0 && wcs->cdelt[1] > 0) { wcs->imflip = 1; wcs->imrot = wcs->rot - 90.0; if (wcs->imrot < -180.0) wcs->imrot = wcs->imrot + 360.0; wcs->pa_north = wcs->rot; wcs->pa_east = wcs->rot - 90.0; if (wcs->pa_east < -180.0) wcs->pa_east = wcs->pa_east + 360.0; } else if (wcs->cdelt[0] > 0 && wcs->cdelt[1] < 0) { wcs->imflip = 1; wcs->imrot = wcs->rot + 90.0; if (wcs->imrot > 180.0) wcs->imrot = wcs->imrot - 360.0; wcs->pa_north = wcs->rot; wcs->pa_east = wcs->rot - 90.0; if (wcs->pa_east < -180.0) wcs->pa_east = wcs->pa_east + 360.0; } else if (wcs->cdelt[0] > 0 && wcs->cdelt[1] > 0) { wcs->imflip = 0; wcs->imrot = wcs->rot + 90.0; if (wcs->imrot > 180.0) wcs->imrot = wcs->imrot - 360.0; wcs->pa_north = wcs->imrot; wcs->pa_east = wcs->rot + 90.0; if (wcs->pa_east > 180.0) wcs->pa_east = wcs->pa_east - 360.0; } else if (wcs->cdelt[0] < 0 && wcs->cdelt[1] < 0) { wcs->imflip = 0; wcs->imrot = wcs->rot - 90.0; if (wcs->imrot < -180.0) wcs->imrot = wcs->imrot + 360.0; wcs->pa_north = wcs->imrot; wcs->pa_east = wcs->rot + 90.0; if (wcs->pa_east > 180.0) wcs->pa_east = wcs->pa_east - 360.0; } } else { if (wcs->cdelt[0] < 0 && wcs->cdelt[1] > 0) { wcs->imflip = 0; wcs->imrot = wcs->rot; wcs->pa_north = wcs->rot + 90.0; if (wcs->pa_north > 180.0) wcs->pa_north = wcs->pa_north - 360.0; wcs->pa_east = wcs->rot + 180.0; if (wcs->pa_east > 180.0) wcs->pa_east = wcs->pa_east - 360.0; } else if (wcs->cdelt[0] > 0 && wcs->cdelt[1] < 0) { wcs->imflip = 0; wcs->imrot = wcs->rot + 180.0; if (wcs->imrot > 180.0) wcs->imrot = wcs->imrot - 360.0; wcs->pa_north = wcs->imrot + 90.0; if (wcs->pa_north > 180.0) wcs->pa_north = wcs->pa_north - 360.0; wcs->pa_east = wcs->imrot + 180.0; if (wcs->pa_east > 180.0) wcs->pa_east = wcs->pa_east - 360.0; } else if (wcs->cdelt[0] > 0 && wcs->cdelt[1] > 0) { wcs->imflip = 1; wcs->imrot = -wcs->rot; wcs->pa_north = wcs->imrot + 90.0; if (wcs->pa_north > 180.0) wcs->pa_north = wcs->pa_north - 360.0; wcs->pa_east = wcs->rot; } else if (wcs->cdelt[0] < 0 && wcs->cdelt[1] < 0) { wcs->imflip = 1; wcs->imrot = wcs->rot + 180.0; if (wcs->imrot > 180.0) wcs->imrot = wcs->imrot - 360.0; wcs->pa_north = wcs->imrot + 90.0; if (wcs->pa_north > 180.0) wcs->pa_north = wcs->pa_north - 360.0; wcs->pa_east = wcs->rot + 90.0; if (wcs->pa_east > 180.0) wcs->pa_east = wcs->pa_east - 360.0; } } return; } /* Set scale and rotation in WCS structure */ void wcspcset (wcs, cdelt1, cdelt2, pc) struct WorldCoor *wcs; /* World coordinate system structure */ double cdelt1; /* degrees/pixel in first axis (or both axes) */ double cdelt2; /* degrees/pixel in second axis if nonzero */ double *pc; /* Rotation matrix, ignored if NULL */ { double *pci, *pc0i; int i, j, naxes; if (pc == NULL) return; naxes = wcs->naxis; /* if (naxes > 2) naxes = 2; */ if (naxes < 1 || naxes > 9) { naxes = wcs->naxes; wcs->naxis = naxes; } wcs->cdelt[0] = cdelt1; if (cdelt2 != 0.0) wcs->cdelt[1] = cdelt2; else wcs->cdelt[1] = cdelt1; wcs->xinc = wcs->cdelt[0]; wcs->yinc = wcs->cdelt[1]; /* Set rotation matrix */ pci = wcs->pc; pc0i = pc; for (i = 0; i < naxes; i++) { for (j = 0; j < naxes; j++) { *pci = *pc0i; pci++; pc0i++; } } /* Set CD matrix */ if (naxes > 1) { wcs->cd[0] = pc[0] * wcs->cdelt[0]; wcs->cd[1] = pc[1] * wcs->cdelt[0]; wcs->cd[2] = pc[naxes] * wcs->cdelt[1]; wcs->cd[3] = pc[naxes+1] * wcs->cdelt[1]; } else { wcs->cd[0] = pc[0] * wcs->cdelt[0]; wcs->cd[1] = 0.0; wcs->cd[2] = 0.0; wcs->cd[3] = 1.0; } (void) matinv (2, wcs->cd, wcs->dc); wcs->rotmat = 1; (void)linset (&wcs->lin); wcs->wcson = 1; wcsrotset (wcs); return; } /* Set up rotation matrix for WCSLIB projection subroutines */ static void wcslibrot (wcs) struct WorldCoor *wcs; /* World coordinate system structure */ { int i, mem, naxes; naxes = wcs->naxis; if (naxes > 2) naxes = 2; if (naxes < 1 || naxes > 9) { naxes = wcs->naxes; wcs->naxis = naxes; } mem = naxes * naxes * sizeof(double); if (wcs->lin.piximg == NULL) wcs->lin.piximg = (double*)malloc(mem); if (wcs->lin.piximg != NULL) { if (wcs->lin.imgpix == NULL) wcs->lin.imgpix = (double*)malloc(mem); if (wcs->lin.imgpix != NULL) { wcs->lin.flag = LINSET; if (naxes == 2) { for (i = 0; i < 4; i++) { wcs->lin.piximg[i] = wcs->cd[i]; } } else if (naxes == 3) { for (i = 0; i < 9; i++) wcs->lin.piximg[i] = 0.0; wcs->lin.piximg[0] = wcs->cd[0]; wcs->lin.piximg[1] = wcs->cd[1]; wcs->lin.piximg[3] = wcs->cd[2]; wcs->lin.piximg[4] = wcs->cd[3]; wcs->lin.piximg[8] = 1.0; } else if (naxes == 4) { for (i = 0; i < 16; i++) wcs->lin.piximg[i] = 0.0; wcs->lin.piximg[0] = wcs->cd[0]; wcs->lin.piximg[1] = wcs->cd[1]; wcs->lin.piximg[4] = wcs->cd[2]; wcs->lin.piximg[5] = wcs->cd[3]; wcs->lin.piximg[10] = 1.0; wcs->lin.piximg[15] = 1.0; } (void) matinv (naxes, wcs->lin.piximg, wcs->lin.imgpix); wcs->lin.crpix = wcs->crpix; wcs->lin.cdelt = wcs->cdelt; wcs->lin.pc = wcs->pc; wcs->lin.flag = LINSET; } } return; } /* Compute image rotation */ void wcsrotset (wcs) struct WorldCoor *wcs; /* World coordinate system structure */ { int off; double cra, cdec, xc, xn, xe, yc, yn, ye; /* If image is one-dimensional, leave rotation angle alone */ if (wcs->nxpix < 1.5 || wcs->nypix < 1.5) { wcs->imrot = wcs->rot; wcs->pa_north = wcs->rot + 90.0; wcs->pa_east = wcs->rot + 180.0; return; } /* Do not try anything if image is LINEAR (not Cartesian projection) */ if (wcs->syswcs == WCS_LINEAR) return; wcs->xinc = fabs (wcs->xinc); wcs->yinc = fabs (wcs->yinc); /* Compute position angles of North and East in image */ xc = wcs->xrefpix; yc = wcs->yrefpix; pix2wcs (wcs, xc, yc, &cra, &cdec); if (wcs->coorflip) { wcs2pix (wcs, cra+wcs->yinc, cdec, &xe, &ye, &off); wcs2pix (wcs, cra, cdec+wcs->xinc, &xn, &yn, &off); } else { wcs2pix (wcs, cra+wcs->xinc, cdec, &xe, &ye, &off); wcs2pix (wcs, cra, cdec+wcs->yinc, &xn, &yn, &off); } wcs->pa_north = raddeg (atan2 (yn-yc, xn-xc)); if (wcs->pa_north < -90.0) wcs->pa_north = wcs->pa_north + 360.0; wcs->pa_east = raddeg (atan2 (ye-yc, xe-xc)); if (wcs->pa_east < -90.0) wcs->pa_east = wcs->pa_east + 360.0; /* Compute image rotation angle from North */ if (wcs->pa_north < -90.0) wcs->imrot = 270.0 + wcs->pa_north; else wcs->imrot = wcs->pa_north - 90.0; /* Compute CROTA */ if (wcs->coorflip) { wcs->rot = wcs->imrot + 90.0; if (wcs->rot < 0.0) wcs->rot = wcs->rot + 360.0; } else wcs->rot = wcs->imrot; if (wcs->rot < 0.0) wcs->rot = wcs->rot + 360.0; if (wcs->rot >= 360.0) wcs->rot = wcs->rot - 360.0; /* Set image mirror flag based on axis orientation */ wcs->imflip = 0; if (wcs->pa_east - wcs->pa_north < -80.0 && wcs->pa_east - wcs->pa_north > -100.0) wcs->imflip = 1; if (wcs->pa_east - wcs->pa_north < 280.0 && wcs->pa_east - wcs->pa_north > 260.0) wcs->imflip = 1; if (wcs->pa_north - wcs->pa_east > 80.0 && wcs->pa_north - wcs->pa_east < 100.0) wcs->imflip = 1; if (wcs->coorflip) { if (wcs->imflip) wcs->yinc = -wcs->yinc; } else { if (!wcs->imflip) wcs->xinc = -wcs->xinc; } return; } /* Return 1 if WCS structure is filled, else 0 */ int iswcs (wcs) struct WorldCoor *wcs; /* World coordinate system structure */ { if (wcs == NULL) return (0); else return (wcs->wcson); } /* Return 0 if WCS structure is filled, else 1 */ int nowcs (wcs) struct WorldCoor *wcs; /* World coordinate system structure */ { if (wcs == NULL) return (1); else return (!wcs->wcson); } /* Reset the center of a WCS structure */ void wcsshift (wcs,rra,rdec,coorsys) struct WorldCoor *wcs; /* World coordinate system structure */ double rra; /* Reference pixel right ascension in degrees */ double rdec; /* Reference pixel declination in degrees */ char *coorsys; /* FK4 or FK5 coordinates (1950 or 2000) */ { if (nowcs (wcs)) return; /* Approximate world coordinate system from a known plate scale */ wcs->crval[0] = rra; wcs->crval[1] = rdec; wcs->xref = wcs->crval[0]; wcs->yref = wcs->crval[1]; /* Coordinate reference frame */ strcpy (wcs->radecsys,coorsys); wcs->syswcs = wcscsys (coorsys); if (wcs->syswcs == WCS_B1950) wcs->equinox = 1950.0; else wcs->equinox = 2000.0; return; } /* Print position of WCS center, if WCS is set */ void wcscent (wcs) struct WorldCoor *wcs; /* World coordinate system structure */ { double xpix,ypix, xpos1, xpos2, ypos1, ypos2; char wcstring[32]; double width, height, secpix, secpixh, secpixw; int lstr = 32; if (nowcs (wcs)) (void)fprintf (stderr,"No WCS information available\n"); else { if (wcs->prjcode == WCS_DSS) (void)fprintf (stderr,"WCS plate center %s\n", wcs->center); xpix = 0.5 * wcs->nxpix; ypix = 0.5 * wcs->nypix; (void) pix2wcst (wcs,xpix,ypix,wcstring, lstr); (void)fprintf (stderr,"WCS center %s %s %s %s at pixel (%.2f,%.2f)\n", wcs->ctype[0],wcs->ctype[1],wcstring,wcs->ptype,xpix,ypix); /* Image width */ (void) pix2wcs (wcs,1.0,ypix,&xpos1,&ypos1); (void) pix2wcs (wcs,wcs->nxpix,ypix,&xpos2,&ypos2); if (wcs->syswcs == WCS_LINEAR) { width = xpos2 - xpos1; if (width < 100.0) (void)fprintf (stderr, "WCS width = %.5f %s ",width, wcs->units[0]); else (void)fprintf (stderr, "WCS width = %.3f %s ",width, wcs->units[0]); } else { width = wcsdist (xpos1,ypos1,xpos2,ypos2); if (width < 1/60.0) (void)fprintf (stderr, "WCS width = %.2f arcsec ",width*3600.0); else if (width < 1.0) (void)fprintf (stderr, "WCS width = %.2f arcmin ",width*60.0); else (void)fprintf (stderr, "WCS width = %.3f degrees ",width); } secpixw = width / (wcs->nxpix - 1.0); /* Image height */ (void) pix2wcs (wcs,xpix,1.0,&xpos1,&ypos1); (void) pix2wcs (wcs,xpix,wcs->nypix,&xpos2,&ypos2); if (wcs->syswcs == WCS_LINEAR) { height = ypos2 - ypos1; if (height < 100.0) (void)fprintf (stderr, " height = %.5f %s ",height, wcs->units[1]); else (void)fprintf (stderr, " height = %.3f %s ",height, wcs->units[1]); } else { height = wcsdist (xpos1,ypos1,xpos2,ypos2); if (height < 1/60.0) (void) fprintf (stderr, " height = %.2f arcsec",height*3600.0); else if (height < 1.0) (void) fprintf (stderr, " height = %.2f arcmin",height*60.0); else (void) fprintf (stderr, " height = %.3f degrees",height); } secpixh = height / (wcs->nypix - 1.0); /* Image scale */ if (wcs->syswcs == WCS_LINEAR) { (void) fprintf (stderr,"\n"); (void) fprintf (stderr,"WCS %.5f %s/pixel, %.5f %s/pixel\n", wcs->xinc,wcs->units[0],wcs->yinc,wcs->units[1]); } else { if (wcs->xinc != 0.0 && wcs->yinc != 0.0) secpix = (fabs(wcs->xinc) + fabs(wcs->yinc)) * 0.5 * 3600.0; else if (secpixh > 0.0 && secpixw > 0.0) secpix = (secpixw + secpixh) * 0.5 * 3600.0; else if (wcs->xinc != 0.0 || wcs->yinc != 0.0) secpix = (fabs(wcs->xinc) + fabs(wcs->yinc)) * 3600.0; else secpix = (secpixw + secpixh) * 3600.0; if (secpix < 100.0) (void) fprintf (stderr, " %.3f arcsec/pixel\n",secpix); else if (secpix < 3600.0) (void) fprintf (stderr, " %.3f arcmin/pixel\n",secpix/60.0); else (void) fprintf (stderr, " %.3f degrees/pixel\n",secpix/3600.0); } } return; } /* Return RA and Dec of image center, plus size in RA and Dec */ void wcssize (wcs, cra, cdec, dra, ddec) struct WorldCoor *wcs; /* World coordinate system structure */ double *cra; /* Right ascension of image center (deg) (returned) */ double *cdec; /* Declination of image center (deg) (returned) */ double *dra; /* Half-width in right ascension (deg) (returned) */ double *ddec; /* Half-width in declination (deg) (returned) */ { double width, height; /* Find right ascension and declination of coordinates */ if (iswcs(wcs)) { wcsfull (wcs, cra, cdec, &width, &height); *dra = 0.5 * width / cos (degrad (*cdec)); *ddec = 0.5 * height; } else { *cra = 0.0; *cdec = 0.0; *dra = 0.0; *ddec = 0.0; } return; } /* Return RA and Dec of image center, plus size in degrees */ void wcsfull (wcs, cra, cdec, width, height) struct WorldCoor *wcs; /* World coordinate system structure */ double *cra; /* Right ascension of image center (deg) (returned) */ double *cdec; /* Declination of image center (deg) (returned) */ double *width; /* Width in degrees (returned) */ double *height; /* Height in degrees (returned) */ { double xpix, ypix, xpos1, xpos2, ypos1, ypos2, xcpix, ycpix; double xcent, ycent; /* Find right ascension and declination of coordinates */ if (iswcs(wcs)) { xcpix = (0.5 * wcs->nxpix) + 0.5; ycpix = (0.5 * wcs->nypix) + 0.5; (void) pix2wcs (wcs,xcpix,ycpix,&xcent, &ycent); *cra = xcent; *cdec = ycent; /* Compute image width in degrees */ xpix = 0.500001; (void) pix2wcs (wcs,xpix,ycpix,&xpos1,&ypos1); xpix = wcs->nxpix + 0.499999; (void) pix2wcs (wcs,xpix,ycpix,&xpos2,&ypos2); if (strncmp (wcs->ptype,"LIN",3) && strncmp (wcs->ptype,"PIX",3)) { *width = wcsdist (xpos1,ypos1,xpos2,ypos2); } else *width = sqrt (((ypos2-ypos1) * (ypos2-ypos1)) + ((xpos2-xpos1) * (xpos2-xpos1))); /* Compute image height in degrees */ ypix = 0.5; (void) pix2wcs (wcs,xcpix,ypix,&xpos1,&ypos1); ypix = wcs->nypix + 0.5; (void) pix2wcs (wcs,xcpix,ypix,&xpos2,&ypos2); if (strncmp (wcs->ptype,"LIN",3) && strncmp (wcs->ptype,"PIX",3)) *height = wcsdist (xpos1,ypos1,xpos2,ypos2); else *height = sqrt (((ypos2-ypos1) * (ypos2-ypos1)) + ((xpos2-xpos1) * (xpos2-xpos1))); } else { *cra = 0.0; *cdec = 0.0; *width = 0.0; *height = 0.0; } return; } /* Return minimum and maximum RA and Dec of image in degrees */ void wcsrange (wcs, ra1, ra2, dec1, dec2) struct WorldCoor *wcs; /* World coordinate system structure */ double *ra1; /* Minimum right ascension of image (deg) (returned) */ double *ra2; /* Maximum right ascension of image (deg) (returned) */ double *dec1; /* Minimum declination of image (deg) (returned) */ double *dec2; /* Maximum declination of image (deg) (returned) */ { double xpos1, xpos2, xpos3, xpos4, ypos1, ypos2, ypos3, ypos4, temp; if (iswcs(wcs)) { /* Compute image corner coordinates in degrees */ (void) pix2wcs (wcs,1.0,1.0,&xpos1,&ypos1); (void) pix2wcs (wcs,1.0,wcs->nypix,&xpos2,&ypos2); (void) pix2wcs (wcs,wcs->nxpix,1.0,&xpos3,&ypos3); (void) pix2wcs (wcs,wcs->nxpix,wcs->nypix,&xpos4,&ypos4); /* Find minimum right ascension or longitude */ *ra1 = xpos1; if (xpos2 < *ra1) *ra1 = xpos2; if (xpos3 < *ra1) *ra1 = xpos3; if (xpos4 < *ra1) *ra1 = xpos4; /* Find maximum right ascension or longitude */ *ra2 = xpos1; if (xpos2 > *ra2) *ra2 = xpos2; if (xpos3 > *ra2) *ra2 = xpos3; if (xpos4 > *ra2) *ra2 = xpos4; if (wcs->syswcs != WCS_LINEAR && wcs->syswcs != WCS_XY) { if (*ra2 - *ra1 > 180.0) { temp = *ra1; *ra1 = *ra2; *ra2 = temp; } } /* Find minimum declination or latitude */ *dec1 = ypos1; if (ypos2 < *dec1) *dec1 = ypos2; if (ypos3 < *dec1) *dec1 = ypos3; if (ypos4 < *dec1) *dec1 = ypos4; /* Find maximum declination or latitude */ *dec2 = ypos1; if (ypos2 > *dec2) *dec2 = ypos2; if (ypos3 > *dec2) *dec2 = ypos3; if (ypos4 > *dec2) *dec2 = ypos4; } else { *ra1 = 0.0; *ra2 = 0.0; *dec1 = 0.0; *dec2 = 0.0; } return; } /* Compute distance in degrees between two sky coordinates */ double wcsdist (x1,y1,x2,y2) double x1,y1; /* (RA,Dec) or (Long,Lat) in degrees */ double x2,y2; /* (RA,Dec) or (Long,Lat) in degrees */ { double r, diffi; double pos1[3], pos2[3], w, diff; int i; /* Convert two vectors to direction cosines */ r = 1.0; d2v3 (x1, y1, r, pos1); d2v3 (x2, y2, r, pos2); /* Modulus squared of half the difference vector */ w = 0.0; for (i = 0; i < 3; i++) { diffi = pos1[i] - pos2[i]; w = w + (diffi * diffi); } w = w / 4.0; if (w > 1.0) w = 1.0; /* Angle beween the vectors */ diff = 2.0 * atan2 (sqrt (w), sqrt (1.0 - w)); diff = raddeg (diff); return (diff); } /* Compute distance in degrees between two sky coordinates */ double wcsdist1 (x1,y1,x2,y2) double x1,y1; /* (RA,Dec) or (Long,Lat) in degrees */ double x2,y2; /* (RA,Dec) or (Long,Lat) in degrees */ { double d1, d2, r; double pos1[3], pos2[3], w, diff; int i; /* Convert two vectors to direction cosines */ r = 1.0; d2v3 (x1, y1, r, pos1); d2v3 (x2, y2, r, pos2); w = 0.0; d1 = 0.0; d2 = 0.0; for (i = 0; i < 3; i++) { w = w + (pos1[i] * pos2[i]); d1 = d1 + (pos1[i] * pos1[i]); d2 = d2 + (pos2[i] * pos2[i]); } diff = acosdeg (w / (sqrt (d1) * sqrt (d2))); return (diff); } /* Compute distance in degrees between two sky coordinates away from pole */ double wcsdiff (x1,y1,x2,y2) double x1,y1; /* (RA,Dec) or (Long,Lat) in degrees */ double x2,y2; /* (RA,Dec) or (Long,Lat) in degrees */ { double xdiff, ydiff, ycos, diff; ycos = cos (degrad ((y2 + y1) / 2.0)); xdiff = x2 - x1; if (xdiff > 180.0) xdiff = xdiff - 360.0; if (xdiff < -180.0) xdiff = xdiff + 360.0; xdiff = xdiff / ycos; ydiff = (y2 - y1); diff = sqrt ((xdiff * xdiff) + (ydiff * ydiff)); return (diff); } /* Initialize catalog search command set by -wcscom */ void wcscominit (wcs, i, command) struct WorldCoor *wcs; /* World coordinate system structure */ int i; /* Number of command (0-9) to initialize */ char *command; /* command with %s where coordinates will go */ { int lcom,icom; if (iswcs(wcs)) { lcom = strlen (command); if (lcom > 0) { if (wcs->command_format[i] != NULL) free (wcs->command_format[i]); wcs->command_format[i] = (char *) calloc (lcom+2, 1); if (wcs->command_format[i] == NULL) return; for (icom = 0; icom < lcom; icom++) { if (command[icom] == '_') wcs->command_format[i][icom] = ' '; else wcs->command_format[i][icom] = command[icom]; } wcs->command_format[i][lcom] = 0; } } return; } /* Execute Unix command with world coordinates (from x,y) and/or filename */ void wcscom ( wcs, i, filename, xfile, yfile, wcstring ) struct WorldCoor *wcs; /* World coordinate system structure */ int i; /* Number of command (0-9) to execute */ char *filename; /* Image file name */ double xfile,yfile; /* Image pixel coordinates for WCS command */ char *wcstring; /* WCS String from pix2wcst() */ { char command[120]; char comform[120]; char xystring[32]; char *fileform, *posform, *imform; int ier; if (nowcs (wcs)) { (void)fprintf(stderr,"WCSCOM: no WCS\n"); return; } if (wcs->command_format[i] != NULL) strcpy (comform, wcs->command_format[i]); else strcpy (comform, "sgsc -ah %s"); if (comform[0] > 0) { /* Create and execute search command */ fileform = strsrch (comform,"%f"); imform = strsrch (comform,"%x"); posform = strsrch (comform,"%s"); if (imform != NULL) { *(imform+1) = 's'; (void)sprintf (xystring, "%.2f %.2f", xfile, yfile); if (fileform != NULL) { *(fileform+1) = 's'; if (posform == NULL) { if (imform < fileform) (void)sprintf(command, comform, xystring, filename); else (void)sprintf(command, comform, filename, xystring); } else if (fileform < posform) { if (imform < fileform) (void)sprintf(command, comform, xystring, filename, wcstring); else if (imform < posform) (void)sprintf(command, comform, filename, xystring, wcstring); else (void)sprintf(command, comform, filename, wcstring, xystring); } else if (imform < posform) (void)sprintf(command, comform, xystring, wcstring, filename); else if (imform < fileform) (void)sprintf(command, comform, wcstring, xystring, filename); else (void)sprintf(command, comform, wcstring, filename, xystring); } else if (posform == NULL) (void)sprintf(command, comform, xystring); else if (imform < posform) (void)sprintf(command, comform, xystring, wcstring); else (void)sprintf(command, comform, wcstring, xystring); } else if (fileform != NULL) { *(fileform+1) = 's'; if (posform == NULL) (void)sprintf(command, comform, filename); else if (fileform < posform) (void)sprintf(command, comform, filename, wcstring); else (void)sprintf(command, comform, wcstring, filename); } else (void)sprintf(command, comform, wcstring); ier = system (command); if (ier) (void)fprintf(stderr,"WCSCOM: %s failed %d\n",command,ier); } return; } /* Initialize WCS output coordinate system for use by PIX2WCS() */ void wcsoutinit (wcs, coorsys) struct WorldCoor *wcs; /* World coordinate system structure */ char *coorsys; /* Input world coordinate system: FK4, FK5, B1950, J2000, GALACTIC, ECLIPTIC fk4, fk5, b1950, j2000, galactic, ecliptic */ { int sysout, i; if (nowcs (wcs)) return; /* If argument is null, set to image system and equinox */ if (coorsys == NULL || strlen (coorsys) < 1 || !strcmp(coorsys,"IMSYS") || !strcmp(coorsys,"imsys")) { sysout = wcs->syswcs; strcpy (wcs->radecout, wcs->radecsys); wcs->eqout = wcs->equinox; if (sysout == WCS_B1950) { if (wcs->eqout != 1950.0) { wcs->radecout[0] = 'B'; sprintf (wcs->radecout+1,"%.4f", wcs->equinox); i = strlen(wcs->radecout) - 1; if (wcs->radecout[i] == '0') wcs->radecout[i] = (char)0; i = strlen(wcs->radecout) - 1; if (wcs->radecout[i] == '0') wcs->radecout[i] = (char)0; i = strlen(wcs->radecout) - 1; if (wcs->radecout[i] == '0') wcs->radecout[i] = (char)0; } else strcpy (wcs->radecout, "B1950"); } else if (sysout == WCS_J2000) { if (wcs->eqout != 2000.0) { wcs->radecout[0] = 'J'; sprintf (wcs->radecout+1,"%.4f", wcs->equinox); i = strlen(wcs->radecout) - 1; if (wcs->radecout[i] == '0') wcs->radecout[i] = (char)0; i = strlen(wcs->radecout) - 1; if (wcs->radecout[i] == '0') wcs->radecout[i] = (char)0; i = strlen(wcs->radecout) - 1; if (wcs->radecout[i] == '0') wcs->radecout[i] = (char)0; } else strcpy (wcs->radecout, "J2000"); } } /* Ignore new coordinate system if it is not supported */ else { if ((sysout = wcscsys (coorsys)) < 0) return; /* Do not try to convert linear or alt-az coordinates */ if (sysout != wcs->syswcs && (wcs->syswcs == WCS_LINEAR || wcs->syswcs == WCS_ALTAZ)) return; strcpy (wcs->radecout, coorsys); wcs->eqout = wcsceq (coorsys); } wcs->sysout = sysout; if (wcs->wcson) { /* Set output in degrees flag and number of decimal places */ if (wcs->sysout == WCS_GALACTIC || wcs->sysout == WCS_ECLIPTIC || wcs->sysout == WCS_PLANET) { wcs->degout = 1; wcs->ndec = 5; } else if (wcs->sysout == WCS_ALTAZ) { wcs->degout = 1; wcs->ndec = 5; } else if (wcs->sysout == WCS_NPOLE || wcs->sysout == WCS_SPA) { wcs->degout = 1; wcs->ndec = 5; } else { wcs->degout = 0; wcs->ndec = 3; } } return; } /* Return current value of WCS output coordinate system set by -wcsout */ char * getwcsout(wcs) struct WorldCoor *wcs; /* World coordinate system structure */ { if (nowcs (wcs)) return (NULL); else return(wcs->radecout); } /* Initialize WCS input coordinate system for use by WCS2PIX() */ void wcsininit (wcs, coorsys) struct WorldCoor *wcs; /* World coordinate system structure */ char *coorsys; /* Input world coordinate system: FK4, FK5, B1950, J2000, GALACTIC, ECLIPTIC fk4, fk5, b1950, j2000, galactic, ecliptic */ { int sysin, i; if (nowcs (wcs)) return; /* If argument is null, set to image system and equinox */ if (coorsys == NULL || strlen (coorsys) < 1) { wcs->sysin = wcs->syswcs; strcpy (wcs->radecin, wcs->radecsys); wcs->eqin = wcs->equinox; if (wcs->sysin == WCS_B1950) { if (wcs->eqin != 1950.0) { wcs->radecin[0] = 'B'; sprintf (wcs->radecin+1,"%.4f", wcs->equinox); i = strlen(wcs->radecin) - 1; if (wcs->radecin[i] == '0') wcs->radecin[i] = (char)0; i = strlen(wcs->radecin) - 1; if (wcs->radecin[i] == '0') wcs->radecin[i] = (char)0; i = strlen(wcs->radecin) - 1; if (wcs->radecin[i] == '0') wcs->radecin[i] = (char)0; } else strcpy (wcs->radecin, "B1950"); } else if (wcs->sysin == WCS_J2000) { if (wcs->eqin != 2000.0) { wcs->radecin[0] = 'J'; sprintf (wcs->radecin+1,"%.4f", wcs->equinox); i = strlen(wcs->radecin) - 1; if (wcs->radecin[i] == '0') wcs->radecin[i] = (char)0; i = strlen(wcs->radecin) - 1; if (wcs->radecin[i] == '0') wcs->radecin[i] = (char)0; i = strlen(wcs->radecin) - 1; if (wcs->radecin[i] == '0') wcs->radecin[i] = (char)0; } else strcpy (wcs->radecin, "J2000"); } } /* Ignore new coordinate system if it is not supported */ if ((sysin = wcscsys (coorsys)) < 0) return; wcs->sysin = sysin; wcs->eqin = wcsceq (coorsys); strcpy (wcs->radecin, coorsys); return; } /* Return current value of WCS input coordinate system set by wcsininit */ char * getwcsin (wcs) struct WorldCoor *wcs; /* World coordinate system structure */ { if (nowcs (wcs)) return (NULL); else return (wcs->radecin); } /* Set WCS output in degrees or hh:mm:ss dd:mm:ss, returning old flag value */ int setwcsdeg(wcs, new) struct WorldCoor *wcs; /* World coordinate system structure */ int new; /* 1: degrees, 0: h:m:s d:m:s */ { int old; if (nowcs (wcs)) return (0); old = wcs->degout; wcs->degout = new; if (new == 1 && old == 0 && wcs->ndec == 3) wcs->ndec = 6; if (new == 0 && old == 1 && wcs->ndec == 5) wcs->ndec = 3; return(old); } /* Set number of decimal places in pix2wcst output string */ int wcsndec (wcs, ndec) struct WorldCoor *wcs; /* World coordinate system structure */ int ndec; /* Number of decimal places in output string */ /* If < 0, return current unchanged value */ { if (nowcs (wcs)) return (0); else if (ndec >= 0) wcs->ndec = ndec; return (wcs->ndec); } /* Return current value of coordinate system */ char * getradecsys(wcs) struct WorldCoor *wcs; /* World coordinate system structure */ { if (nowcs (wcs)) return (NULL); else return (wcs->radecsys); } /* Set output string mode for LINEAR coordinates */ void setwcslin (wcs, mode) struct WorldCoor *wcs; /* World coordinate system structure */ int mode; /* mode = 0: x y linear mode = 1: x units x units mode = 2: x y linear units */ { if (iswcs (wcs)) wcs->linmode = mode; return; } /* Convert pixel coordinates to World Coordinate string */ int pix2wcst (wcs, xpix, ypix, wcstring, lstr) struct WorldCoor *wcs; /* World coordinate system structure */ double xpix,ypix; /* Image coordinates in pixels */ char *wcstring; /* World coordinate string (returned) */ int lstr; /* Length of world coordinate string (returned) */ { double xpos,ypos; char rastr[32], decstr[32]; int minlength, lunits, lstring; if (nowcs (wcs)) { if (lstr > 0) wcstring[0] = 0; return(0); } pix2wcs (wcs,xpix,ypix,&xpos,&ypos); /* If point is off scale, set string accordingly */ if (wcs->offscl) { (void)sprintf (wcstring,"Off map"); return (1); } /* Print coordinates in degrees */ else if (wcs->degout == 1) { minlength = 9 + (2 * wcs->ndec); if (lstr > minlength) { deg2str (rastr, 32, xpos, wcs->ndec); deg2str (decstr, 32, ypos, wcs->ndec); if (wcs->tabsys) (void)sprintf (wcstring,"%s %s", rastr, decstr); else (void)sprintf (wcstring,"%s %s", rastr, decstr); lstr = lstr - minlength; } else { if (wcs->tabsys) strncpy (wcstring,"********* **********",lstr); else strncpy (wcstring,"*******************",lstr); lstr = 0; } } /* print coordinates in sexagesimal notation */ else if (wcs->degout == 0) { minlength = 18 + (2 * wcs->ndec); if (lstr > minlength) { if (wcs->sysout == WCS_J2000 || wcs->sysout == WCS_B1950) { ra2str (rastr, 32, xpos, wcs->ndec); dec2str (decstr, 32, ypos, wcs->ndec-1); } else { dec2str (rastr, 32, xpos, wcs->ndec); dec2str (decstr, 32, ypos, wcs->ndec); } if (wcs->tabsys) { (void)sprintf (wcstring,"%s %s", rastr, decstr); } else { (void)sprintf (wcstring,"%s %s", rastr, decstr); } lstr = lstr - minlength; } else { if (wcs->tabsys) { strncpy (wcstring,"************* *************",lstr); } else { strncpy (wcstring,"**************************",lstr); } lstr = 0; } } /* Label galactic coordinates */ if (wcs->sysout == WCS_GALACTIC) { if (lstr > 9 && wcs->printsys) { if (wcs->tabsys) strcat (wcstring," galactic"); else strcat (wcstring," galactic"); } } /* Label ecliptic coordinates */ else if (wcs->sysout == WCS_ECLIPTIC) { if (lstr > 9 && wcs->printsys) { if (wcs->tabsys) strcat (wcstring," ecliptic"); else strcat (wcstring," ecliptic"); } } /* Label planet coordinates */ else if (wcs->sysout == WCS_PLANET) { if (lstr > 9 && wcs->printsys) { if (wcs->tabsys) strcat (wcstring," planet"); else strcat (wcstring," planet"); } } /* Label alt-az coordinates */ else if (wcs->sysout == WCS_ALTAZ) { if (lstr > 7 && wcs->printsys) { if (wcs->tabsys) strcat (wcstring," alt-az"); else strcat (wcstring," alt-az"); } } /* Label north pole angle coordinates */ else if (wcs->sysout == WCS_NPOLE) { if (lstr > 7 && wcs->printsys) { if (wcs->tabsys) strcat (wcstring," long-npa"); else strcat (wcstring," long-npa"); } } /* Label south pole angle coordinates */ else if (wcs->sysout == WCS_SPA) { if (lstr > 7 && wcs->printsys) { if (wcs->tabsys) strcat (wcstring," long-spa"); else strcat (wcstring," long-spa"); } } /* Label equatorial coordinates */ else if (wcs->sysout==WCS_B1950 || wcs->sysout==WCS_J2000) { if (lstr > (int) strlen(wcs->radecout)+1 && wcs->printsys) { if (wcs->tabsys) strcat (wcstring," "); else strcat (wcstring," "); strcat (wcstring, wcs->radecout); } } /* Output linear coordinates */ else { num2str (rastr, xpos, 0, wcs->ndec); num2str (decstr, ypos, 0, wcs->ndec); lstring = strlen (rastr) + strlen (decstr) + 1; lunits = strlen (wcs->units[0]) + strlen (wcs->units[1]) + 2; if (wcs->syswcs == WCS_LINEAR && wcs->linmode == 1) { if (lstr > lstring + lunits) { if (strlen (wcs->units[0]) > 0) { strcat (rastr, " "); strcat (rastr, wcs->units[0]); } if (strlen (wcs->units[1]) > 0) { strcat (decstr, " "); strcat (decstr, wcs->units[1]); } lstring = lstring + lunits; } } if (lstr > lstring) { if (wcs->tabsys) (void)sprintf (wcstring,"%s %s", rastr, decstr); else (void)sprintf (wcstring,"%s %s", rastr, decstr); } else { if (wcs->tabsys) strncpy (wcstring,"********** *********",lstr); else strncpy (wcstring,"*******************",lstr); } if (wcs->syswcs == WCS_LINEAR && wcs->linmode != 1 && lstr > lstring + 7) strcat (wcstring, " linear"); if (wcs->syswcs == WCS_LINEAR && wcs->linmode == 2 && lstr > lstring + lunits + 7) { if (strlen (wcs->units[0]) > 0) { strcat (wcstring, " "); strcat (wcstring, wcs->units[0]); } if (strlen (wcs->units[1]) > 0) { strcat (wcstring, " "); strcat (wcstring, wcs->units[1]); } } } return (1); } /* Convert pixel coordinates to World Coordinates */ void pix2wcs (wcs,xpix,ypix,xpos,ypos) struct WorldCoor *wcs; /* World coordinate system structure */ double xpix,ypix; /* x and y image coordinates in pixels */ double *xpos,*ypos; /* RA and Dec in degrees (returned) */ { double xpi, ypi, xp, yp; double eqin, eqout; int wcspos(); if (nowcs (wcs)) return; wcs->xpix = xpix; wcs->ypix = ypix; wcs->zpix = zpix; wcs->offscl = 0; /* If this WCS is converted from another WCS rather than pixels, convert now */ if (wcs->wcs != NULL) { pix2wcs (wcs->wcs, xpix, ypix, &xpi, &ypi); } else { pix2foc (wcs, xpix, ypix, &xpi, &ypi); } /* Convert image coordinates to sky coordinates */ /* Use Digitized Sky Survey plate fit */ if (wcs->prjcode == WCS_DSS) { if (dsspos (xpi, ypi, wcs, &xp, &yp)) wcs->offscl = 1; } /* Use SAO plate fit */ else if (wcs->prjcode == WCS_PLT) { if (platepos (xpi, ypi, wcs, &xp, &yp)) wcs->offscl = 1; } /* Use NOAO IRAF corrected plane tangent projection */ else if (wcs->prjcode == WCS_TNX) { if (tnxpos (xpi, ypi, wcs, &xp, &yp)) wcs->offscl = 1; } /* Use NOAO IRAF corrected zenithal projection */ else if (wcs->prjcode == WCS_ZPX) { if (zpxpos (xpi, ypi, wcs, &xp, &yp)) wcs->offscl = 1; } /* Use Classic AIPS projections */ else if (wcs->wcsproj == WCS_OLD || wcs->prjcode <= 0) { if (worldpos (xpi, ypi, wcs, &xp, &yp)) wcs->offscl = 1; } /* Use Mark Calabretta's WCSLIB projections */ else if (wcspos (xpi, ypi, wcs, &xp, &yp)) wcs->offscl = 1; /* Do not change coordinates if offscale */ if (wcs->offscl) { *xpos = 0.0; *ypos = 0.0; } else { /* Convert coordinates to output system, if not LINEAR */ if (wcs->prjcode > 0) { /* Convert coordinates to desired output system */ eqin = wcs->equinox; eqout = wcs->eqout; wcscon (wcs->syswcs,wcs->sysout,eqin,eqout,&xp,&yp,wcs->epoch); } if (wcs->latbase == 90) yp = 90.0 - yp; else if (wcs->latbase == -90) yp = yp - 90.0; wcs->xpos = xp; wcs->ypos = yp; *xpos = xp; *ypos = yp; } /* Keep RA/longitude within range if spherical coordinate output (Not LINEAR or XY) */ if (wcs->sysout > 0 && wcs->sysout != 6 && wcs->sysout != 10) { if (*xpos < 0.0) *xpos = *xpos + 360.0; else if (*xpos > 360.0) *xpos = *xpos - 360.0; } return; } /* Convert World Coordinates to pixel coordinates */ void wcs2pix (wcs, xpos, ypos, xpix, ypix, offscl) struct WorldCoor *wcs; /* World coordinate system structure */ double xpos,ypos; /* World coordinates in degrees */ double *xpix,*ypix; /* Image coordinates in pixels */ int *offscl; /* 0 if within bounds, else off scale */ { wcsc2pix (wcs, xpos, ypos, wcs->radecin, xpix, ypix, offscl); return; } /* Convert World Coordinates to pixel coordinates */ void wcsc2pix (wcs, xpos, ypos, coorsys, xpix, ypix, offscl) struct WorldCoor *wcs; /* World coordinate system structure */ double xpos,ypos; /* World coordinates in degrees */ char *coorsys; /* Input world coordinate system: FK4, FK5, B1950, J2000, GALACTIC, ECLIPTIC fk4, fk5, b1950, j2000, galactic, ecliptic * If NULL, use image WCS */ double *xpix,*ypix; /* Image coordinates in pixels */ int *offscl; /* 0 if within bounds, else off scale */ { double xp, yp, xpi, ypi; double eqin, eqout; int sysin; int wcspix(); if (nowcs (wcs)) return; *offscl = 0; xp = xpos; yp = ypos; if (wcs->latbase == 90) yp = 90.0 - yp; else if (wcs->latbase == -90) yp = yp - 90.0; if (coorsys == NULL) { sysin = wcs->syswcs; eqin = wcs->equinox; } else { sysin = wcscsys (coorsys); eqin = wcsceq (coorsys); } wcs->zpix = 1.0; /* Convert coordinates to same system as image */ if (sysin > 0 && sysin != 6 && sysin != 10) { eqout = wcs->equinox; wcscon (sysin, wcs->syswcs, eqin, eqout, &xp, &yp, wcs->epoch); } /* Convert sky coordinates to image coordinates */ /* Use Digitized Sky Survey plate fit */ if (wcs->prjcode == WCS_DSS) { if (dsspix (xp, yp, wcs, &xpi, &ypi)) *offscl = 1; } /* Use SAO polynomial plate fit */ else if (wcs->prjcode == WCS_PLT) { if (platepix (xp, yp, wcs, &xpi, &ypi)) *offscl = 1; } /* Use NOAO IRAF corrected plane tangent projection */ else if (wcs->prjcode == WCS_TNX) { if (tnxpix (xp, yp, wcs, &xpi, &ypi)) *offscl = 1; } /* Use NOAO IRAF corrected zenithal projection */ else if (wcs->prjcode == WCS_ZPX) { if (zpxpix (xp, yp, wcs, &xpi, &ypi)) *offscl = 1; } /* Use Classic AIPS projections */ else if (wcs->wcsproj == WCS_OLD || wcs->prjcode <= 0) { if (worldpix (xp, yp, wcs, &xpi, &ypi)) *offscl = 1; } /* Use Mark Calabretta's WCSLIB projections */ else if (wcspix (xp, yp, wcs, &xpi, &ypi)) { *offscl = 1; } /* If this WCS is converted from another WCS rather than pixels, convert now */ if (wcs->wcs != NULL) { wcsc2pix (wcs->wcs, xpi, ypi, NULL, xpix, ypix, offscl); } else { foc2pix (wcs, xpi, ypi, xpix, ypix); /* Set off-scale flag to 2 if off image but within bounds of projection */ if (!*offscl) { if (*xpix < 0.5 || *ypix < 0.5) *offscl = 2; else if (*xpix > wcs->nxpix + 0.5 || *ypix > wcs->nypix + 0.5) *offscl = 2; } } wcs->offscl = *offscl; wcs->xpos = xpos; wcs->ypos = ypos; wcs->xpix = *xpix; wcs->ypix = *ypix; return; } int wcspos (xpix, ypix, wcs, xpos, ypos) /* Input: */ double xpix; /* x pixel number (RA or long without rotation) */ double ypix; /* y pixel number (dec or lat without rotation) */ struct WorldCoor *wcs; /* WCS parameter structure */ /* Output: */ double *xpos; /* x (RA) coordinate (deg) */ double *ypos; /* y (dec) coordinate (deg) */ { int offscl; int i; int wcsrev(); double wcscrd[4], imgcrd[4], pixcrd[4]; double phi, theta; *xpos = 0.0; *ypos = 0.0; pixcrd[0] = xpix; pixcrd[1] = ypix; if (wcs->prjcode == WCS_CSC || wcs->prjcode == WCS_QSC || wcs->prjcode == WCS_TSC) pixcrd[2] = (double) (izpix + 1); else pixcrd[2] = zpix; pixcrd[3] = 1.0; for (i = 0; i < 4; i++) imgcrd[i] = 0.0; offscl = wcsrev ((void *)&wcs->ctype, &wcs->wcsl, pixcrd, &wcs->lin, imgcrd, &wcs->prj, &phi, &theta, wcs->crval, &wcs->cel, wcscrd); if (offscl == 0) { *xpos = wcscrd[wcs->wcsl.lng]; *ypos = wcscrd[wcs->wcsl.lat]; } return (offscl); } int wcspix (xpos, ypos, wcs, xpix, ypix) /* Input: */ double xpos; /* x (RA) coordinate (deg) */ double ypos; /* y (dec) coordinate (deg) */ struct WorldCoor *wcs; /* WCS parameter structure */ /* Output: */ double *xpix; /* x pixel number (RA or long without rotation) */ double *ypix; /* y pixel number (dec or lat without rotation) */ { int offscl; int wcsfwd(); double wcscrd[4], imgcrd[4], pixcrd[4]; double phi, theta; *xpix = 0.0; *ypix = 0.0; if (wcs->wcsl.flag != WCSSET) { if (wcsset (wcs->lin.naxis, (void *)&wcs->ctype, &wcs->wcsl) ) return (1); } /* Set input for WCSLIB subroutines */ wcscrd[0] = 0.0; wcscrd[1] = 0.0; wcscrd[2] = 0.0; wcscrd[3] = 0.0; wcscrd[wcs->wcsl.lng] = xpos; wcscrd[wcs->wcsl.lat] = ypos; /* Initialize output for WCSLIB subroutines */ pixcrd[0] = 0.0; pixcrd[1] = 0.0; pixcrd[2] = 1.0; pixcrd[3] = 1.0; imgcrd[0] = 0.0; imgcrd[1] = 0.0; imgcrd[2] = 1.0; imgcrd[3] = 1.0; /* Invoke WCSLIB subroutines for coordinate conversion */ offscl = wcsfwd ((void *)&wcs->ctype, &wcs->wcsl, wcscrd, wcs->crval, &wcs->cel, &phi, &theta, &wcs->prj, imgcrd, &wcs->lin, pixcrd); if (!offscl) { *xpix = pixcrd[0]; *ypix = pixcrd[1]; if (wcs->prjcode == WCS_CSC || wcs->prjcode == WCS_QSC || wcs->prjcode == WCS_TSC) wcs->zpix = pixcrd[2] - 1.0; else wcs->zpix = pixcrd[2]; } return (offscl); } /* Set third dimension for cube projections */ int wcszin (izpix0) int izpix0; /* coordinate in third dimension (if < 0, return current value without changing it */ { if (izpix0 > -1) { izpix = izpix0; zpix = (double) izpix0; } return (izpix); } /* Return third dimension for cube projections */ int wcszout (wcs) struct WorldCoor *wcs; /* WCS parameter structure */ { return ((int) wcs->zpix); } /* Set file name for error messages */ void setwcsfile (filename) char *filename; /* FITS or IRAF file with WCS */ { if (strlen (filename) < 256) strcpy (wcsfile, filename); else strncpy (wcsfile, filename, 255); return; } /* Set error message */ void setwcserr (errmsg) char *errmsg; /* Error mesage < 80 char */ { strcpy (wcserrmsg, errmsg); return; } /* Print error message */ void wcserr () { if (strlen (wcsfile) > 0) fprintf (stderr, "%s in file %s\n",wcserrmsg, wcsfile); else fprintf (stderr, "%s\n",wcserrmsg); return; } /* Flag to use AIPS WCS subroutines instead of WCSLIB */ void setdefwcs (wp) int wp; { wcsproj0 = wp; return; } int getdefwcs () { return (wcsproj0); } /* Save output default coordinate system */ static char wcscoor0[16]; void savewcscoor (wcscoor) char *wcscoor; { strcpy (wcscoor0, wcscoor); return; } /* Return preset output default coordinate system */ char * getwcscoor () { return (wcscoor0); } /* Save default commands */ static char *wcscom0[10]; void savewcscom (i, wcscom) int i; char *wcscom; { int lcom; if (i < 0) i = 0; else if (i > 9) i = 9; lcom = strlen (wcscom) + 2; wcscom0[i] = (char *) calloc (lcom, 1); if (wcscom0[i] != NULL) strcpy (wcscom0[i], wcscom); return; } void setwcscom (wcs) struct WorldCoor *wcs; /* WCS parameter structure */ { char envar[16]; int i; char *str; if (nowcs(wcs)) return; for (i = 0; i < 10; i++) { if (i == 0) strcpy (envar, "WCS_COMMAND"); else sprintf (envar, "WCS_COMMAND%d", i); if (wcscom0[i] != NULL) wcscominit (wcs, i, wcscom0[i]); else if ((str = getenv (envar)) != NULL) wcscominit (wcs, i, str); else if (i == 1) wcscominit (wcs, i, "sua2 -ah %s"); /* F1= Search USNO-A2.0 Catalog */ else if (i == 2) wcscominit (wcs, i, "sgsc -ah %s"); /* F2= Search HST GSC */ else if (i == 3) wcscominit (wcs, i, "sty2 -ah %s"); /* F3= Search Tycho-2 Catalog */ else if (i == 4) wcscominit (wcs, i, "sppm -ah %s"); /* F4= Search PPM Catalog */ else if (i == 5) wcscominit (wcs, i, "ssao -ah %s"); /* F5= Search SAO Catalog */ else wcs->command_format[i] = NULL; } return; } char * getwcscom (i) int i; { return (wcscom0[i]); } void freewcscom (wcs) struct WorldCoor *wcs; /* WCS parameter structure */ { int i; for (i = 0; i < 10; i++) { if (wcscom0[i] != NULL) { free (wcscom0[i]); wcscom0[i] = NULL; } } if (iswcs (wcs)) { for (i = 0; i < 10; i++) { if (wcs->command_format[i] != NULL) { free (wcs->command_format[i]); } } } return; } int cpwcs (header, cwcs) char **header; /* Pointer to start of FITS header */ char *cwcs; /* Keyword suffix character for output WCS */ { double tnum; int dkwd[MAXNKWD]; int i, maxnkwd, ikwd, nleft, lbuff, lhead, nkwd, nbytes; int nkwdw; char **kwd; char *newhead, *oldhead; char kwdc[16], keyword[16]; char tstr[80]; /* Allocate array of keywords to be transferred */ maxnkwd = MAXNKWD; kwd = (char **)calloc (maxnkwd, sizeof(char *)); for (ikwd = 0; ikwd < maxnkwd; ikwd++) kwd[ikwd] = (char *) calloc (16, 1); /* Make list of all possible keywords to be transferred */ nkwd = 0; strcpy (kwd[++nkwd], "EPOCH"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "EQUINOX"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "RADECSYS"); dkwd[nkwd] = 0; strcpy (kwd[++nkwd], "CTYPE1"); dkwd[nkwd] = 0; strcpy (kwd[++nkwd], "CTYPE2"); dkwd[nkwd] = 0; strcpy (kwd[++nkwd], "CRVAL1"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "CRVAL2"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "CDELT1"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "CDELT2"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "CRPIX1"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "CRPIX2"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "CROTA1"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "CROTA2"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "CD1_1"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "CD1_2"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "CD2_1"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "CD2_2"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "PC1_1"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "PC1_2"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "PC2_1"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "PC2_2"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "PC001001"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "PC001002"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "PC002001"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "PC002002"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "LATPOLE"); dkwd[nkwd] = 1; strcpy (kwd[++nkwd], "LONPOLE"); dkwd[nkwd] = 1; for (i = 1; i < 13; i++) { sprintf (keyword,"CO1_%d", i); strcpy (kwd[++nkwd], keyword); dkwd[nkwd] = 1; } for (i = 1; i < 13; i++) { sprintf (keyword,"CO2_%d", i); strcpy (kwd[++nkwd], keyword); dkwd[nkwd] = 1; } for (i = 0; i < 10; i++) { sprintf (keyword,"PROJP%d", i); strcpy (kwd[++nkwd], keyword); dkwd[nkwd] = 1; } for (i = 0; i < MAXPV; i++) { sprintf (keyword,"PV1_%d", i); strcpy (kwd[++nkwd], keyword); dkwd[nkwd] = 1; } for (i = 0; i < MAXPV; i++) { sprintf (keyword,"PV2_%d", i); strcpy (kwd[++nkwd], keyword); dkwd[nkwd] = 1; } /* Allocate new header buffer if needed */ lhead = (ksearch (*header, "END") - *header) + 80; lbuff = gethlength (*header); nleft = (lbuff - lhead) / 80; if (nleft < nkwd) { nbytes = lhead + (nkwd * 80) + 400; newhead = (char *) calloc (1, nbytes); strncpy (newhead, *header, lhead); oldhead = *header; header = &newhead; free (oldhead); } /* Copy keywords to new WCS ID in header */ nkwdw = 0; for (i = 0; i < nkwd; i++) { if (dkwd[i]) { if (hgetr8 (*header, kwd[i], &tnum)) { nkwdw++; if (!strncmp (kwd[i], "PC0", 3)) { if (!strcmp (kwd[i], "PC001001")) strcpy (kwdc, "PC1_1"); else if (!strcmp (kwd[i], "PC001002")) strcpy (kwdc, "PC1_2"); else if (!strcmp (kwd[i], "PC002001")) strcpy (kwdc, "PC2_1"); else strcpy (kwdc, "PC2_2"); } else strcpy (kwdc, kwd[i]); strncat (kwdc, cwcs, 1); (void)hputr8 (*header, kwdc, tnum); } } else { if (hgets (*header, kwd[i], 80, tstr)) { nkwdw++; if (!strncmp (kwd[i], "RADECSYS", 8)) strcpy (kwdc, "RADECSY"); else strcpy (kwdc, kwd[i]); strncat (kwdc, cwcs, 1); hputs (*header, kwdc, tstr); } } } /* Free keyword list array */ for (ikwd = 0; ikwd < maxnkwd; ikwd++) free (kwd[ikwd]); free (kwd); kwd = NULL; return (nkwdw); } /* Oct 28 1994 new program * Dec 21 1994 Implement CD rotation matrix * Dec 22 1994 Allow RA and DEC to be either x,y or y,x * * Mar 6 1995 Add Digital Sky Survey plate fit * May 2 1995 Add prototype of PIX2WCST to WCSCOM * May 25 1995 Print leading zero for hours and degrees * Jun 21 1995 Add WCS2PIX to get pixels from WCS * Jun 21 1995 Read plate scale from FITS header for plate solution * Jul 6 1995 Pass WCS structure as argument; malloc it in WCSINIT * Jul 6 1995 Check string lengths in PIX2WCST * Aug 16 1995 Add galactic coordinate conversion to PIX2WCST * Aug 17 1995 Return 0 from iswcs if wcs structure is not yet set * Sep 8 1995 Do not include malloc.h if VMS * Sep 8 1995 Check for legal WCS before trying anything * Sep 8 1995 Do not try to set WCS if missing key keywords * Oct 18 1995 Add WCSCENT and WCSDIST to print center and size of image * Nov 6 1995 Include stdlib.h instead of malloc.h * Dec 6 1995 Fix format statement in PIX2WCST * Dec 19 1995 Change MALLOC to CALLOC to initialize array to zeroes * Dec 19 1995 Explicitly initialize rotation matrix and yinc * Dec 22 1995 If SECPIX is set, use approximate WCS * Dec 22 1995 Always print coordinate system * * Jan 12 1996 Use plane-tangent, not linear, projection if SECPIX is set * Jan 12 1996 Add WCSSET to set WCS without an image * Feb 15 1996 Replace all calls to HGETC with HGETS * Feb 20 1996 Add tab table output from PIX2WCST * Apr 2 1996 Convert all equinoxes to B1950 or J2000 * Apr 26 1996 Get and use image epoch for accurate FK4/FK5 conversions * May 16 1996 Clean up internal documentation * May 17 1996 Return width in right ascension degrees, not sky degrees * May 24 1996 Remove extraneous print command from WCSSIZE * May 28 1996 Add NOWCS and WCSSHIFT subroutines * Jun 11 1996 Drop unused variables after running lint * Jun 12 1996 Set equinox as well as system in WCSSHIFT * Jun 14 1996 Make DSS keyword searches more robust * Jul 1 1996 Allow for SECPIX1 and SECPIX2 keywords * Jul 2 1996 Test for CTYPE1 instead of CRVAL1 * Jul 5 1996 Declare all subroutines in wcs.h * Jul 19 1996 Add subroutine WCSFULL to return real image size * Aug 12 1996 Allow systemless coordinates which cannot be converted * Aug 15 1996 Allow LINEAR WCS to pass numbers through transparently * Aug 15 1996 Add WCSERR to print error message under calling program control * Aug 16 1996 Add latitude and longitude as image coordinate types * Aug 26 1996 Fix arguments to HLENGTH in WCSNINIT * Aug 28 1996 Explicitly set OFFSCL in WCS2PIX if coordinates outside image * Sep 3 1996 Return computed pixel values even if they are offscale * Sep 6 1996 Allow filename to be passed by WCSCOM * Oct 8 1996 Default to 2000 for EQUINOX and EPOCH and FK5 for RADECSYS * Oct 8 1996 If EPOCH is 0 and EQUINOX is not set, default to 1950 and FK4 * Oct 15 1996 Add comparison when testing an assignment * Oct 16 1996 Allow PIXEL CTYPE which means WCS is same as image coordinates * Oct 21 1996 Add WCS_COMMAND environment variable * Oct 25 1996 Add image scale to WCSCENT * Oct 30 1996 Fix bugs in WCS2PIX * Oct 31 1996 Fix CD matrix rotation angle computation * Oct 31 1996 Use inline degree <-> radian conversion functions * Nov 1 1996 Add option to change number of decimal places in PIX2WCST * Nov 5 1996 Set wcs->crot to 1 if rotation matrix is used * Dec 2 1996 Add altitide/azimuth coordinates * Dec 13 1996 Fix search format setting from environment * * Jan 22 1997 Add ifdef for Eric Mandel (SAOtng) * Feb 5 1997 Add wcsout for Eric Mandel * Mar 20 1997 Drop unused variable STR in WCSCOM * May 21 1997 Do not make pixel coordinates mod 360 in PIX2WCST * May 22 1997 Add PIXEL prjcode = -1; * Jul 11 1997 Get center pixel x and y from header even if no WCS * Aug 7 1997 Add NOAO PIXSCALi keywords for default WCS * Oct 15 1997 Do not reset reference pixel in WCSSHIFT * Oct 20 1997 Set chip rotation * Oct 24 1997 Keep longitudes between 0 and 360, not -180 and +180 * Nov 5 1997 Do no compute crot and srot; they are now computed in worldpos * Dec 16 1997 Set rotation and axis increments from CD matrix * * Jan 6 1998 Deal with J2000 and B1950 as EQUINOX values (from ST) * Jan 7 1998 Read INSTRUME and DETECTOR header keywords * Jan 7 1998 Fix tab-separated output * Jan 9 1998 Precess coordinates if either FITS projection or *DSS plate* * Jan 16 1998 Change PTYPE to not include initial hyphen * Jan 16 1998 Change WCSSET to WCSXINIT to avoid conflict with Calabretta * Jan 23 1998 Change PCODE to PRJCODE to avoid conflict with Calabretta * Jan 27 1998 Add LATPOLE and LONGPOLE for Calabretta projections * Feb 5 1998 Make cd and dc into vectors; use matinv() to invert cd * Feb 5 1998 In wcsoutinit(), check that corsys is a valid pointer * Feb 18 1998 Fix bugs for Calabretta projections * Feb 19 1998 Add wcs structure access subroutines from Eric Mandel * Feb 19 1998 Add wcsreset() to make sure derived values are reset * Feb 19 1998 Always set oldwcs to 1 if NCP projection * Feb 19 1998 Add subroutine to set oldwcs default * Feb 20 1998 Initialize projection types one at a time for SunOS C * Feb 23 1998 Add TNX projection from NOAO; treat it as TAN * Feb 23 1998 Compute size based on max and min coordinates, not sides * Feb 26 1998 Add code to set center pixel if part of detector array * Mar 6 1998 Write 8-character values to RADECSYS * Mar 9 1998 Add naxis to WCS structure * Mar 16 1998 Use separate subroutine for IRAF TNX projection * Mar 20 1998 Set PC matrix if more than two axes and it's not in header * Mar 20 1998 Reset lin flag in WCSRESET if CDELTn * Mar 20 1998 Set CD matrix with CDELTs and CROTA in wcsinit and wcsreset * Mar 20 1998 Allow initialization of rotation angle alone * Mar 23 1998 Use dsspos() and dsspix() instead of platepos() and platepix() * Mar 24 1998 Set up PLT/PLATE plate polynomial fit using platepos() and platepix() * Mar 25 1998 Read plate fit coefficients from header in getwcscoeffs() * Mar 27 1998 Check for FITS WCS before DSS WCS * Mar 27 1998 Compute scale from edges if xinc and yinc not set in wcscent() * Apr 6 1998 Change plate coefficient keywords from PLTij to COi_j * Apr 6 1998 Read all coefficients in line instead of with subroutine * Apr 7 1998 Change amd_i_coeff to i_coeff * Apr 8 1998 Add wcseqset to change equinox after wcs has been set * Apr 10 1998 Use separate counters for x and y polynomial coefficients * Apr 13 1998 Use CD/CDELT+CDROTA if oldwcs is set * Apr 14 1998 Use codes instead of strings for various coordinate systems * Apr 14 1998 Separate input coordinate conversion from output conversion * Apr 14 1998 Use wcscon() for most coordinate conversion * Apr 17 1998 Always compute cdelt[] * Apr 17 1998 Deal with reversed axis more correctly * Apr 17 1998 Compute rotation angle and approximate CDELTn for polynomial * Apr 23 1998 Deprecate xref/yref in favor of crval[] * Apr 23 1998 Deprecate xrefpix/yrefpix in favor of crpix[] * Apr 23 1998 Add LINEAR to coordinate system types * Apr 23 1998 Always use AIPS subroutines for LINEAR or PIXEL * Apr 24 1998 Format linear coordinates better * Apr 28 1998 Change coordinate system flags to WCS_* * Apr 28 1998 Change projection flags to WCS_* * Apr 28 1998 Add subroutine wcsc2pix for coordinates to pixels with system * Apr 28 1998 Add setlinmode() to set output string mode for LINEAR coordinates * Apr 30 1998 Fix bug by setting degree flag for lat and long in wcsinit() * Apr 30 1998 Allow leading "-"s in projecting in wcsxinit() * May 1 1998 Assign new output coordinate system only if legitimate system * May 1 1998 Do not allow oldwcs=1 unless allowed projection * May 4 1998 Fix bug in units reading for LINEAR coordinates * May 6 1998 Initialize to no CD matrix * May 6 1998 Use TAN instead of TNX if oldwcs * May 12 1998 Set 3rd and 4th coordinates in wcspos() * May 12 1998 Return *xpos and *ypos = 0 in pix2wcs() if offscale * May 12 1998 Declare undeclared external subroutines after lint * May 13 1998 Add equinox conversion to specified output equinox * May 13 1998 Set output or input system to image with null argument * May 15 1998 Return reference pixel, cdelts, and rotation for DSS * May 20 1998 Fix bad bug so setlinmode() is no-op if wcs not set * May 20 1998 Fix bug so getwcsout() returns null pointer if wcs not set * May 27 1998 Change WCS_LPR back to WCS_LIN; allow CAR in oldwcs * May 28 1998 Go back to old WCSFULL, computing height and width from center * May 29 1998 Add wcskinit() to initialize WCS from arguments * May 29 1998 Add wcstype() to set projection from arguments * May 29 1998 Add wcscdset(), and wcsdeltset() to set scale from arguments * Jun 1 1998 In wcstype(), reconstruct ctype for WCS structure * Jun 11 1998 Split off header-dependent subroutines to wcsinit.c * Jun 18 1998 Add wcspcset() for PC matrix initialization * Jun 24 1998 Add string lengths to ra2str(), dec2str, and deg2str() calls * Jun 25 1998 Use AIPS software for CAR projection * Jun 25 1998 Add wcsndec to set number of decimal places in output string * Jul 6 1998 Add wcszin() and wcszout() to use third dimension of images * Jul 7 1998 Change setlinmode() to setwcslin(); setdegout() to setwcsdeg() * Jul 10 1998 Initialize matrices correctly for naxis > 2 in wcs<>set() * Jul 16 1998 Initialize coordinates to be returned in wcspos() * Jul 17 1998 Link lin structure arrays to wcs structure arrays * Jul 20 1998 In wcscdset() compute sign of xinc and yinc from CD1_1, CD 2_2 * Jul 20 1998 In wcscdset() compute sign of rotation based on CD1_1, CD 1_2 * Jul 22 1998 Add wcslibrot() to compute lin() rotation matrix * Jul 30 1998 Set wcs->naxes and lin.naxis in wcsxinit() and wcskinit() * Aug 5 1998 Use old WCS subroutines to deal with COE projection (for ESO) * Aug 14 1998 Add option to print image coordinates with wcscom() * Aug 14 1998 Add multiple command options to wcscom*() * Aug 31 1998 Declare undeclared arguments to wcspcset() * Sep 3 1998 Set CD rotation and cdelts from sky axis position angles * Sep 16 1998 Add option to use North Polar Angle instead of Latitude * Sep 29 1998 Initialize additional WCS commands from the environment * Oct 14 1998 Fix bug in wcssize() which didn't divide dra by cos(dec) * Nov 12 1998 Fix sign of CROTA when either axis is reflected * Dec 2 1998 Fix non-arcsecond scale factors in wcscent() * Dec 2 1998 Add PLANET coordinate system to pix2wcst() * Jan 20 1999 Free lin.imgpix and lin.piximg in wcsfree() * Feb 22 1999 Fix bug setting latitude reference value of latbase != 0 * Feb 22 1999 Fix bug so that quad cube faces are 0-5, not 1-6 * Mar 16 1999 Always initialize all 4 imgcrds and pixcrds in wcspix() * Mar 16 1999 Always return (0,0) from wcs2pix if offscale * Apr 7 1999 Add code to put file name in error messages * Apr 7 1999 Document utility subroutines at end of file * May 6 1999 Fix bug printing height of LINEAR image * Jun 16 1999 Add wcsrange() to return image RA and Dec limits * Jul 8 1999 Always use FK5 and FK4 instead of J2000 and B1950 in RADECSYS * Aug 16 1999 Print dd:mm:ss dd:mm:ss if not J2000 or B1950 output * Aug 20 1999 Add WCS string argument to wcscom(); don't compute it there * Aug 20 1999 Change F3 WCS command default from Tycho to ACT * Oct 15 1999 Free wcs using wcsfree() * Oct 21 1999 Drop declarations of unused functions after lint * Oct 25 1999 Drop out of wcsfree() if wcs is null pointer * Nov 17 1999 Fix bug which caused software to miss NCP projection * * Jan 24 2000 Default to AIPS for NCP, CAR, and COE proj.; if -z use WCSLIB * Feb 24 2000 If coorsys is null in wcsc2pix, wcs->radecin is assumed * May 10 2000 In wcstype(), default to WCS_LIN, not error (after Bill Joye) * Jun 22 2000 In wcsrotset(), leave rotation angle alone in 1-d image * Jul 3 2000 Initialize wcscrd[] to zero in wcspix() * * Feb 20 2001 Add recursion to wcs2pix() and pix2wcs() for dependent WCS's * Mar 20 2001 Add braces to avoid ambiguity in if/else groupings * Mar 22 2001 Free WCS structure in wcsfree even if it is not filled * Sep 12 2001 Fix bug which omitted tab in pix2wcst() galactic coord output * * Mar 7 2002 Fix bug which gave wrong pa's and rotation for reflected RA * (but correct WCS conversions!) * Mar 28 2002 Add SZP projection * Apr 3 2002 Synchronize projection types with other subroutines * Apr 3 2002 Drop special cases of projections * Apr 9 2002 Implement inversion of multiple WCSs in wcsc2pix() * Apr 25 2002 Use Tycho-2 catalog instead of ACT in setwcscom() * May 13 2002 Free WCSNAME in wcsfree() * * Mar 31 2003 Add distcode to wcstype() * Apr 1 2003 Add calls to foc2pix() in wcs2pix() and pix2foc() in pix2wcs() * May 20 2003 Declare argument i in savewcscom() * Sep 29 2003 Fix bug to compute width and height correctly in wcsfull() * Sep 29 2003 Fix bug to deal with all-sky images orrectly in wcsfull() * Oct 1 2003 Rename wcs->naxes to wcs->naxis to match WCSLIB 3.2 * Nov 3 2003 Set distortion code by calling setdistcode() in wcstype() * Dec 3 2003 Add back wcs->naxes for compatibility * Dec 3 2003 Add braces in if...else in pix2wcst() * * Sep 17 2004 If spherical coordinate output, keep 0 < long/RA < 360 * Sep 17 2004 Fix bug in wcsfull() when wrapping around RA=0:00 * Nov 1 2004 Keep wcs->rot between 0 and 360 * * Mar 9 2005 Fix bug in wcsrotset() which set rot > 360 to 360 * Jun 27 2005 Fix ctype in calls to wcs subroutines * Jul 21 2005 Fix bug in wcsrange() at RA ~= 0.0 * * Apr 24 2006 Always set inverse CD matrix to 2 dimensions in wcspcset() * May 3 2006 (void *) pointers so arguments match type, from Robert Lupton * Jun 30 2006 Set only 2-dimensional PC matrix; that is all lin* can deal with * Oct 30 2006 In pix2wcs(), do not limit x to between 0 and 360 if XY or LINEAR * Oct 30 2006 In wcsc2pix(), do not precess LINEAR or XY coordinates * Dec 21 2006 Add cpwcs() to copy WCS keywords to new suffix * * Jan 4 2007 Fix pointer to header in cpwcs() * Jan 5 2007 Drop declarations of wcscon(); it is in wcs.h * Jan 9 2006 Drop declarations of fk425e() and fk524e(); moved to wcs.h * Jan 9 2006 Drop *pix() and *pos() external declarations; moved to wcs.h * Jan 9 2006 Drop matinv() external declaration; it is already in wcslib.h * Feb 15 2007 If CTYPEi contains DET, set to WCS_PIX projection * Feb 23 2007 Fix bug when checking for "DET" in CTYPEi * Apr 2 2007 Fix PC to CD matrix conversion * Jul 25 2007 Compute distance between two coordinates using d2v3() * * Apr 7 2010 In wcstype() set number of WCS projections from NWCSTYPE * * Mar 11 2011 Add NOAO ZPX projection (Frank Valdes) * Mar 14 2011 Delete j<=MAXPV PVi_j parameters (for SCAMP polynomials via Ed Los) * Mar 17 2011 Fix WCSDEP bug found by Ed Los * May 9 2011 Free WCS structure recursively if WCSDEP is used * Sep 1 2011 Add TPV projection type for SCAMP TAN with PVs * * Oct 19 2012 Drop d1 and d2 from wcsdist(); diffi from wcsdist1() * Oct 19 2012 Drop depwcs; it's in main wcs structure * * Jun 8 2016 Increase ctype, ctype1, and ctype2 to 16 characters for distortion * Jun 23 2016 Set initial allocation of keyword arrays to MAXNKWD instead of 100 in cpwcs() * Jun 24 2016 wcs->ptype contains only 3-letter projection code */ wcstools-3.9.5/libwcs/wcscon.c0000664000016200001660000020360712726340057015414 0ustar minkoirsys/*** File wcscon.c *** June 9, 2016 *** Doug Mink, Harvard-Smithsonian Center for Astrophysics *** Some subroutines are based on Starlink subroutines by Patrick Wallace *** Copyright (C) 1995-2016 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: wcscon.c (World Coordinate System conversion) * Purpose: Convert between various sky coordinate systems * Subroutine: wcscon (sys1,sys2,eq1,eq2,theta,phi,epoch) * convert between coordinate systems * Subroutine: wcsconp (sys1,sys2,eq1,eq2,ep1,ep2,dtheta,dphi,ptheta,pphi) * convert coordinates and proper motion between coordinate systems * Subroutine: wcsconv (sys1,sys2,eq1,eq2,ep1,ep2,dtheta,dphi,ptheta,pphi,px,rv) * convert coordinates and proper motion between coordinate systems * Subroutine: wcscsys (cstring) returns code for coordinate system in string * Subroutine: wcsceq (wcstring) returns equinox in years from system string * Subroutine: wcscstr (sys,equinox,epoch) returns system string from equinox * Subroutine: fk524 (ra,dec) Convert J2000(FK5) to B1950(FK4) coordinates * Subroutine: fk524e (ra, dec, epoch) (more accurate for known position epoch) * Subroutine: fk524m (ra,dec,rapm,decpm) exact * Subroutine: fk524pv (ra,dec,rapm,decpm,parallax,rv) more exact * Subroutine: fk425 (ra,dec) Convert B1950(FK4) to J2000(FK5) coordinates * Subroutine: fk425e (ra, dec, epoch) (more accurate for known position epoch) * Subroutine: fk425m (ra, dec, rapm, decpm) exact * Subroutine: fk425pv (ra,dec,rapm,decpm,parallax,rv) more exact * Subroutine: fk42gal (dtheta,dphi) Convert B1950(FK4) to galactic coordinates * Subroutine: fk52gal (dtheta,dphi) Convert J2000(FK5) to galactic coordinates * Subroutine: gal2fk4 (dtheta,dphi) Convert galactic coordinates to B1950(FK4) * Subroutine: gal2fk5 (dtheta,dphi) Convert galactic coordinates to J2000 #ifndef VMS #include #endif #include /* for fprintf() and sprintf() */ #include #include #include "wcs.h" void fk524(), fk524e(), fk524m(), fk524pv(); void fk425(), fk425e(), fk425m(), fk425pv(); void fk42gal(), fk52gal(), gal2fk4(), gal2fk5(); void fk42ecl(), fk52ecl(), ecl2fk4(), ecl2fk5(); /* Convert from coordinate system sys1 to coordinate system sys2, converting proper motions, too, and adding them if an epoch is specified */ void wcsconp (sys1, sys2, eq1, eq2, ep1, ep2, dtheta, dphi, ptheta, pphi) int sys1; /* Input coordinate system (J2000, B1950, ECLIPTIC, GALACTIC */ int sys2; /* Output coordinate system (J2000, B1950, ECLIPTIC, GALACTIC */ double eq1; /* Input equinox (default of sys1 if 0.0) */ double eq2; /* Output equinox (default of sys2 if 0.0) */ double ep1; /* Input Besselian epoch in years (for proper motion) */ double ep2; /* Output Besselian epoch in years (for proper motion) */ double *dtheta; /* Longitude or right ascension in degrees Input in sys1, returned in sys2 */ double *dphi; /* Latitude or declination in degrees Input in sys1, returned in sys2 */ double *ptheta; /* Longitude or right ascension proper motion in RA degrees/year Input in sys1, returned in sys2 */ double *pphi; /* Latitude or declination proper motion in Dec degrees/year Input in sys1, returned in sys2 */ { void fk5prec(), fk4prec(); /* Set equinoxes if 0.0 */ if (eq1 == 0.0) { if (sys1 == WCS_B1950) eq1 = 1950.0; else eq1 = 2000.0; } if (eq2 == 0.0) { if (sys2 == WCS_B1950) eq2 = 1950.0; else eq2 = 2000.0; } /* Set epochs if 0.0 */ if (ep1 == 0.0) { if (sys1 == WCS_B1950) ep1 = 1950.0; else ep1 = 2000.0; } if (ep2 == 0.0) { if (sys2 == WCS_B1950) ep2 = 1950.0; else ep2 = 2000.0; } if (sys1 == WCS_ICRS && sys2 == WCS_ICRS) eq2 = eq1; if (sys1 == WCS_J2000 && sys2 == WCS_ICRS && eq1 == 2000.0) { eq2 = eq1; sys1 = sys2; } /* Set systems and equinoxes so that ICRS coordinates are not precessed */ if (sys1 == WCS_ICRS && sys2 == WCS_J2000 && eq2 == 2000.0) { eq1 = eq2; sys1 = sys2; } /* If systems and equinoxes are the same, add proper motion and return */ if (sys2 == sys1 && eq1 == eq2) { if (ep1 != ep2) { if (sys1 == WCS_J2000) { *dtheta = *dtheta + ((ep2 - ep1) * *ptheta); *dphi = *dphi + ((ep2 - ep1) * *pphi); } else if (sys1 == WCS_B1950) { *dtheta = *dtheta + ((ep2 - ep1) * *ptheta); *dphi = *dphi + ((ep2 - ep1) * *pphi); } } if (eq1 != eq2) { if (sys1 == WCS_B1950) fk4prec (eq1, eq2, dtheta, dphi); if (sys1 == WCS_J2000) fk5prec (eq1, 2000.0, dtheta, dphi); } return; } /* Precess from input equinox to input system equinox, if necessary */ if (sys1 == WCS_B1950 && eq1 != 1950.0) fk4prec (eq1, 1950.0, dtheta, dphi); if (sys1 == WCS_J2000 && eq1 != 2000.0) fk5prec (eq1, 2000.0, dtheta, dphi); /* Convert to B1950 FK4 */ if (sys2 == WCS_B1950) { if (sys1 == WCS_J2000) { if (*ptheta != 0.0 || *pphi != 0.0) { fk524m (dtheta, dphi, ptheta, pphi); if (ep2 != 1950.0) { *dtheta = *dtheta + ((ep2 - 1950.0) * *ptheta); *dphi = *dphi + ((ep2 - 1950.0) * *pphi); } } else if (ep2 != 1950.0) fk524e (dtheta, dphi, ep2); else fk524 (dtheta, dphi); } else if (sys1 == WCS_GALACTIC) gal2fk4 (dtheta, dphi); else if (sys1 == WCS_ECLIPTIC) ecl2fk4 (dtheta, dphi, ep2); } else if (sys2 == WCS_J2000) { if (sys1 == WCS_B1950) { if (*ptheta != 0.0 || *pphi != 0.0) { fk425m (dtheta, dphi, ptheta, pphi); if (ep2 != 2000.0) { *dtheta = *dtheta + ((ep2 - 2000.0) * *ptheta); *dphi = *dphi + ((ep2 - 2000.0) * *pphi); } } else if (ep2 > 0.0) fk425e (dtheta, dphi, ep2); else fk425 (dtheta, dphi); } else if (sys1 == WCS_GALACTIC) gal2fk5 (dtheta, dphi); else if (sys1 == WCS_ECLIPTIC) ecl2fk5 (dtheta, dphi, ep2); } else if (sys2 == WCS_GALACTIC) { if (sys1 == WCS_B1950) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } fk42gal (dtheta, dphi); } else if (sys1 == WCS_J2000) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } fk52gal (dtheta, dphi); } else if (sys1 == WCS_ECLIPTIC) { ecl2fk5 (dtheta, dphi, ep2); fk52gal (dtheta, dphi); } } else if (sys2 == WCS_ECLIPTIC) { if (sys1 == WCS_B1950) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } if (ep2 > 0.0) fk42ecl (dtheta, dphi, ep2); else fk42ecl (dtheta, dphi, 1950.0); } else if (sys1 == WCS_J2000) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } fk52ecl (dtheta, dphi, ep2); } else if (sys1 == WCS_GALACTIC) { gal2fk5 (dtheta, dphi); fk52ecl (dtheta, dphi, ep2); } } /* Precess to desired equinox, if necessary */ if (sys2 == WCS_B1950 && eq2 != 1950.0) fk4prec (1950.0, eq2, dtheta, dphi); if (sys2 == WCS_J2000 && eq2 != 2000.0) fk5prec (2000.0, eq2, dtheta, dphi); /* Keep latitude/declination between +90 and -90 degrees */ if (*dphi > 90.0) { *dphi = 180.0 - *dphi; *dtheta = *dtheta + 180.0; } else if (*dphi < -90.0) { *dphi = -180.0 - *dphi; *dtheta = *dtheta + 180.0; } /* Keep longitude/right ascension between 0 and 360 degrees */ if (*dtheta > 360.0) *dtheta = *dtheta - 360.0; else if (*dtheta < 0.0) *dtheta = *dtheta + 360.0; return; } /* Convert from coordinate system sys1 to coordinate system sys2, converting proper motions, too, and adding them if an epoch is specified */ void wcsconv (sys1, sys2, eq1, eq2, ep1, ep2, dtheta, dphi, ptheta, pphi, px, rv) int sys1; /* Input coordinate system (J2000, B1950, ECLIPTIC, GALACTIC */ int sys2; /* Output coordinate system (J2000, B1950, ECLIPTIC, GALACTIC */ double eq1; /* Input equinox (default of sys1 if 0.0) */ double eq2; /* Output equinox (default of sys2 if 0.0) */ double ep1; /* Input Besselian epoch in years (for proper motion) */ double ep2; /* Output Besselian epoch in years (for proper motion) */ double *dtheta; /* Longitude or right ascension in degrees Input in sys1, returned in sys2 */ double *dphi; /* Latitude or declination in degrees Input in sys1, returned in sys2 */ double *ptheta; /* Longitude or right ascension proper motion in degrees/year Input in sys1, returned in sys2 */ double *pphi; /* Latitude or declination proper motion in degrees/year Input in sys1, returned in sys2 */ double *px; /* Parallax in arcseconds */ double *rv; /* Radial velocity in km/sec */ { void fk5prec(), fk4prec(); /* Set equinoxes if 0.0 */ if (eq1 == 0.0) { if (sys1 == WCS_B1950) eq1 = 1950.0; else eq1 = 2000.0; } if (eq2 == 0.0) { if (sys2 == WCS_B1950) eq2 = 1950.0; else eq2 = 2000.0; } /* Set epochs if 0.0 */ if (ep1 == 0.0) { if (sys1 == WCS_B1950) ep1 = 1950.0; else ep1 = 2000.0; } if (ep2 == 0.0) { if (sys2 == WCS_B1950) ep2 = 1950.0; else ep2 = 2000.0; } /* Set systems and equinoxes so that ICRS coordinates are not precessed */ if (sys1 == WCS_ICRS && sys2 == WCS_ICRS) eq2 = eq1; if (sys1 == WCS_J2000 && sys2 == WCS_ICRS && eq1 == 2000.0) { eq2 = eq1; sys1 = sys2; } if (sys1 == WCS_ICRS && sys2 == WCS_J2000 && eq2 == 2000.0) { eq1 = eq2; sys1 = sys2; } /* If systems and equinoxes are the same, add proper motion and return */ if (sys2 == sys1 && eq1 == eq2) { if (ep1 != ep2) { if (sys1 == WCS_J2000) { *dtheta = *dtheta + ((ep2 - ep1) * *ptheta); *dphi = *dphi + ((ep2 - ep1) * *pphi); } else if (sys1 == WCS_B1950) { *dtheta = *dtheta + ((ep2 - ep1) * *ptheta); *dphi = *dphi + ((ep2 - ep1) * *pphi); } } return; } /* Precess from input equinox to input system equinox, if necessary */ if (eq1 != eq2) { if (sys1 == WCS_B1950 && eq1 != 1950.0) fk4prec (eq1, 1950.0, dtheta, dphi); if (sys1 == WCS_J2000 && eq1 != 2000.0) fk5prec (eq1, 2000.0, dtheta, dphi); } /* Convert to B1950 FK4 */ if (sys2 == WCS_B1950) { if (sys1 == WCS_J2000) { if (*ptheta != 0.0 || *pphi != 0.0) { if (*px != 0.0 || *rv != 0.0) fk524pv (dtheta, dphi, ptheta, pphi, px, rv); else fk524m (dtheta, dphi, ptheta, pphi); if (ep1 == 2000.0) ep1 = 1950.0; if (ep2 != 1950.0) { *dtheta = *dtheta + ((ep2 - 1950.0) * *ptheta); *dphi = *dphi + ((ep2 - 1950.0) * *pphi); } } else if (ep2 != 1950.0) fk524e (dtheta, dphi, ep2); else fk524 (dtheta, dphi); } else if (sys1 == WCS_GALACTIC) gal2fk4 (dtheta, dphi); else if (sys1 == WCS_ECLIPTIC) ecl2fk4 (dtheta, dphi, ep2); } else if (sys2 == WCS_J2000) { if (sys1 == WCS_B1950) { if (*ptheta != 0.0 || *pphi != 0.0) { if (*px != 0.0 || *rv != 0.0) fk425pv (dtheta, dphi, ptheta, pphi, px, rv); else fk425m (dtheta, dphi, ptheta, pphi); if (ep2 != 2000.0) { *dtheta = *dtheta + ((ep2 - 2000.0) * *ptheta); *dphi = *dphi + ((ep2 - 2000.0) * *pphi); } } else if (ep2 > 0.0) fk425e (dtheta, dphi, ep2); else fk425 (dtheta, dphi); } else if (sys1 == WCS_GALACTIC) gal2fk5 (dtheta, dphi); else if (sys1 == WCS_ECLIPTIC) ecl2fk5 (dtheta, dphi, ep2); } else if (sys2 == WCS_GALACTIC) { if (sys1 == WCS_B1950) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } fk42gal (dtheta, dphi); } else if (sys1 == WCS_J2000) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } fk52gal (dtheta, dphi); } else if (sys1 == WCS_ECLIPTIC) { ecl2fk5 (dtheta, dphi, ep2); fk52gal (dtheta, dphi); } } else if (sys2 == WCS_ECLIPTIC) { if (sys1 == WCS_B1950) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } if (ep2 > 0.0) fk42ecl (dtheta, dphi, ep2); else fk42ecl (dtheta, dphi, 1950.0); } else if (sys1 == WCS_J2000) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } fk52ecl (dtheta, dphi, ep2); } else if (sys1 == WCS_GALACTIC) { gal2fk5 (dtheta, dphi); fk52ecl (dtheta, dphi, ep2); } } /* Precess to desired equinox, if necessary */ if (eq1 != eq2) { if (sys2 == WCS_B1950 && eq2 != 1950.0) fk4prec (1950.0, eq2, dtheta, dphi); if (sys2 == WCS_J2000 && eq2 != 2000.0) fk5prec (2000.0, eq2, dtheta, dphi); } /* Keep latitude/declination between +90 and -90 degrees */ if (*dphi > 90.0) { *dphi = 180.0 - *dphi; *dtheta = *dtheta + 180.0; } else if (*dphi < -90.0) { *dphi = -180.0 - *dphi; *dtheta = *dtheta + 180.0; } /* Keep longitude/right ascension between 0 and 360 degrees */ if (*dtheta > 360.0) *dtheta = *dtheta - 360.0; else if (*dtheta < 0.0) *dtheta = *dtheta + 360.0; return; } /* Convert from coordinate system sys1 to coordinate system sys2 */ void wcscon (sys1, sys2, eq1, eq2, dtheta, dphi, epoch) int sys1; /* Input coordinate system (J2000, B1950, ECLIPTIC, GALACTIC */ int sys2; /* Output coordinate system (J2000, B1950, ECLIPTIC, GALACTIC */ double eq1; /* Input equinox (default of sys1 if 0.0) */ double eq2; /* Output equinox (default of sys2 if 0.0) */ double *dtheta; /* Longitude or right ascension in degrees Input in sys1, returned in sys2 */ double *dphi; /* Latitude or declination in degrees Input in sys1, returned in sys2 */ double epoch; /* Besselian epoch in years */ { void fk5prec(), fk4prec(); /* Set equinoxes if 0.0 */ if (eq1 == 0.0) { if (sys1 == WCS_B1950) eq1 = 1950.0; else eq1 = 2000.0; } if (eq2 == 0.0) { if (sys2 == WCS_B1950) eq2 = 1950.0; else eq2 = 2000.0; } /* Set systems and equinoxes so that ICRS coordinates are not precessed */ if (sys1 == WCS_ICRS && sys2 == WCS_ICRS) eq2 = eq1; if (sys1 == WCS_J2000 && sys2 == WCS_ICRS && eq1 == 2000.0) { eq2 = eq1; sys1 = sys2; } if (sys1 == WCS_ICRS && sys2 == WCS_J2000 && eq2 == 2000.0) { eq1 = eq2; sys1 = sys2; } /* If systems and equinoxes are the same, return */ if (sys2 == sys1 && eq1 == eq2) return; /* Precess from input equinox, if necessary */ if (eq1 != eq2) { if (sys1 == WCS_B1950 && eq1 != 1950.0) fk4prec (eq1, 1950.0, dtheta, dphi); if (sys1 == WCS_J2000 && eq1 != 2000.0) fk5prec (eq1, 2000.0, dtheta, dphi); } /* Convert to B1950 FK4 */ if (sys2 == WCS_B1950) { if (sys1 == WCS_J2000) { if (epoch > 0) fk524e (dtheta, dphi, epoch); else fk524 (dtheta, dphi); } else if (sys1 == WCS_GALACTIC) gal2fk4 (dtheta, dphi); else if (sys1 == WCS_ECLIPTIC) { if (epoch > 0) ecl2fk4 (dtheta, dphi, epoch); else ecl2fk4 (dtheta, dphi, 1950.0); } } else if (sys2 == WCS_J2000) { if (sys1 == WCS_B1950) { if (epoch > 0) fk425e (dtheta, dphi, epoch); else fk425 (dtheta, dphi); } else if (sys1 == WCS_GALACTIC) gal2fk5 (dtheta, dphi); else if (sys1 == WCS_ECLIPTIC) { if (epoch > 0) ecl2fk5 (dtheta, dphi, epoch); else ecl2fk5 (dtheta, dphi, 2000.0); } } else if (sys2 == WCS_GALACTIC) { if (sys1 == WCS_B1950) fk42gal (dtheta, dphi); else if (sys1 == WCS_J2000) fk52gal (dtheta, dphi); else if (sys1 == WCS_ECLIPTIC) { if (epoch > 0) ecl2fk5 (dtheta, dphi, epoch); else ecl2fk5 (dtheta, dphi, 2000.0); fk52gal (dtheta, dphi); } } else if (sys2 == WCS_ECLIPTIC) { if (sys1 == WCS_B1950) { if (epoch > 0) fk42ecl (dtheta, dphi, epoch); else fk42ecl (dtheta, dphi, 1950.0); } else if (sys1 == WCS_J2000) { if (epoch > 0) fk52ecl (dtheta, dphi, epoch); else fk52ecl (dtheta, dphi, 2000.0); } else if (sys1 == WCS_GALACTIC) { gal2fk5 (dtheta, dphi); if (epoch > 0) fk52ecl (dtheta, dphi, epoch); else fk52ecl (dtheta, dphi, 2000.0); } } /* Precess to desired equinox, if necessary */ if (eq1 != eq2) { if (sys2 == WCS_B1950 && eq2 != 1950.0) fk4prec (1950.0, eq2, dtheta, dphi); if (sys2 == WCS_J2000 && eq2 != 2000.0) fk5prec (2000.0, eq2, dtheta, dphi); } /* Keep latitude/declination between +90 and -90 degrees */ if (*dphi > 90.0) { *dphi = 180.0 - *dphi; *dtheta = *dtheta + 180.0; } else if (*dphi < -90.0) { *dphi = -180.0 - *dphi; *dtheta = *dtheta + 180.0; } /* Keep longitude/right ascension between 0 and 360 degrees */ if (*dtheta > 360.0) *dtheta = *dtheta - 360.0; else if (*dtheta < 0.0) *dtheta = *dtheta + 360.0; return; } /* Set coordinate system from string */ int wcscsys (wcstring) char *wcstring; /* Name of coordinate system */ { double equinox; if (wcstring[0] == 'J' || wcstring[0] == 'j' || !strcmp (wcstring,"2000") || !strcmp (wcstring, "2000.0") || !strcmp (wcstring,"ICRS") || !strcmp (wcstring, "icrs") || !strncmp (wcstring,"FK5",3) || !strncmp (wcstring, "fk5",3)) return WCS_J2000; if (wcstring[0] == 'B' || wcstring[0] == 'b' || !strcmp (wcstring,"1950") || !strcmp (wcstring, "1950.0") || !strncmp (wcstring,"FK4",3) || !strncmp (wcstring, "fk4",3)) return WCS_B1950; else if (wcstring[0] == 'I' || wcstring[0] == 'i' ) return WCS_ICRS; else if (wcstring[0] == 'G' || wcstring[0] == 'g' ) return WCS_GALACTIC; else if (wcstring[0] == 'E' || wcstring[0] == 'e' ) return WCS_ECLIPTIC; else if (wcstring[0] == 'A' || wcstring[0] == 'a' ) return WCS_ALTAZ; else if (wcstring[0] == 'N' || wcstring[0] == 'n' ) return WCS_NPOLE; else if (wcstring[0] == 'L' || wcstring[0] == 'l' ) return WCS_LINEAR; else if (!strncasecmp (wcstring, "pixel", 5)) return WCS_XY; else if (wcstring[0] == 'P' || wcstring[0] == 'p' ) return WCS_PLANET; else if (isnum (wcstring) == 1 || isnum (wcstring) == 2) { equinox = atof (wcstring); if (equinox > 1980.0) return WCS_J2000; else if (equinox > 1900.0) return WCS_B1950; else return -1; } else return -1; } /* Set equinox from string (return 0.0 if not obvious) */ double wcsceq (wcstring) char *wcstring; /* Name of coordinate system */ { if (wcstring[0] == 'J' || wcstring[0] == 'j' || wcstring[0] == 'B' || wcstring[0] == 'b') return (atof (wcstring+1)); else if (!strncmp (wcstring, "FK4",3) || !strncmp (wcstring, "fk4",3)) return (1950.0); else if (!strncmp (wcstring, "FK5",3) || !strncmp (wcstring, "fk5",3)) return (2000.0); else if (!strncmp (wcstring, "ICRS",4) || !strncmp (wcstring, "icrs",4)) return (2000.0); else if (wcstring[0] == '1' || wcstring[0] == '2') return (atof (wcstring)); else return (0.0); } /* Set coordinate system type string from system and equinox */ void wcscstr (cstr, syswcs, equinox, epoch) char *cstr; /* Coordinate system string (returned) */ int syswcs; /* Coordinate system code */ double equinox; /* Equinox of coordinate system */ double epoch; /* Epoch of coordinate system */ { char *estr; if (syswcs == WCS_XY) { strcpy (cstr, "XY"); return; } /* Try to figure out coordinate system if it is not set */ if (epoch == 0.0) epoch = equinox; if (syswcs < 0) { if (equinox > 0.0) { if (equinox == 2000.0) syswcs = WCS_J2000; else if (equinox == 1950.0) syswcs = WCS_B1950; } else if (epoch > 0.0) { if (epoch > 1980.0) { syswcs = WCS_J2000; equinox = 2000.0; } else { syswcs = WCS_B1950; equinox = 1950.0; } } else syswcs = WCS_J2000; } /* Set coordinate system string from system flag and epoch */ if (syswcs == WCS_B1950) { if (epoch == 1950.0 || epoch == 0.0) strcpy (cstr, "B1950"); else sprintf (cstr, "B%7.2f", equinox); if ((estr = strsrch (cstr,".00")) != NULL) { estr[0] = (char) 0; estr[1] = (char) 0; estr[2] = (char) 0; } } else if (syswcs == WCS_GALACTIC) strcpy (cstr, "galactic"); else if (syswcs == WCS_ECLIPTIC) strcpy (cstr, "ecliptic"); else if (syswcs == WCS_J2000) { if (epoch == 2000.0 || epoch == 0.0) strcpy (cstr, "J2000"); else sprintf (cstr, "J%7.2f", equinox); if ((estr = strsrch (cstr,".00")) != NULL) { estr[0] = (char) 0; estr[1] = (char) 0; estr[2] = (char) 0; } } else if (syswcs == WCS_ICRS) { strcpy (cstr, "ICRS"); } else if (syswcs == WCS_PLANET) { strcpy (cstr, "PLANET"); } else if (syswcs == WCS_LINEAR || syswcs == WCS_XY) { strcpy (cstr, "LINEAR"); } return; } /* Constant vector and matrix (by columns) These values were obtained by inverting C.Hohenkerk's forward matrix (private communication), which agrees with the one given in reference 2 but which has one additional decimal place. */ static double a[3] = {-1.62557e-6, -0.31919e-6, -0.13843e-6}; static double ad[3] = {1.245e-3, -1.580e-3, -0.659e-3}; static double d2pi = 6.283185307179586476925287; /* two PI */ static double tiny = 1.e-30; /* small number to avoid arithmetic problems */ /* FK524 convert J2000 FK5 star data to B1950 FK4 based on Starlink sla_fk524 by P.T.Wallace 27 October 1987 */ static double emi[6][6] = { { 0.9999256795, /* emi[0][0] */ 0.0111814828, /* emi[0][1] */ 0.0048590039, /* emi[0][2] */ -0.00000242389840, /* emi[0][3] */ -0.00000002710544, /* emi[0][4] */ -0.00000001177742 }, /* emi[0][5] */ { -0.0111814828, /* emi[1][0] */ 0.9999374849, /* emi[1][1] */ -0.0000271771, /* emi[1][2] */ 0.00000002710544, /* emi[1][3] */ -0.00000242392702, /* emi[1][4] */ 0.00000000006585 }, /* emi[1][5] */ { -0.0048590040, /* emi[2][0] */ -0.0000271557, /* emi[2][1] */ 0.9999881946, /* emi[2][2] */ 0.00000001177742, /* emi[2][3] */ 0.00000000006585, /* emi[2][4] */ -0.00000242404995 }, /* emi[2][5] */ { -0.000551, /* emi[3][0] */ 0.238509, /* emi[3][1] */ -0.435614, /* emi[3][2] */ 0.99990432, /* emi[3][3] */ 0.01118145, /* emi[3][4] */ 0.00485852 }, /* emi[3][5] */ { -0.238560, /* emi[4][0] */ -0.002667, /* emi[4][1] */ 0.012254, /* emi[4][2] */ -0.01118145, /* emi[4][3] */ 0.99991613, /* emi[4][4] */ -0.00002717 }, /* emi[4][5] */ { 0.435730, /* emi[5][0] */ -0.008541, /* emi[5][1] */ 0.002117, /* emi[5][2] */ -0.00485852, /* emi[5][3] */ -0.00002716, /* emi[5][4] */ 0.99996684 } /* emi[5][5] */ }; void fk524 (ra,dec) double *ra; /* Right ascension in degrees (J2000 in, B1950 out) */ double *dec; /* Declination in degrees (J2000 in, B1950 out) */ { double rapm; /* Proper motion in right ascension */ double decpm; /* Proper motion in declination */ /* In: deg/jul.yr. Out: deg/trop.yr. */ rapm = (double) 0.0; decpm = (double) 0.0; fk524m (ra, dec, &rapm, &decpm); return; } void fk524e (ra, dec, epoch) double *ra; /* Right ascension in degrees (J2000 in, B1950 out) */ double *dec; /* Declination in degrees (J2000 in, B1950 out) */ double epoch; /* Besselian epoch in years */ { double rapm; /* Proper motion in right ascension */ double decpm; /* Proper motion in declination */ /* In: deg/jul.yr. Out: deg/trop.yr. */ rapm = (double) 0.0; decpm = (double) 0.0; fk524m (ra, dec, &rapm, &decpm); *ra = *ra + (rapm * (epoch - 1950.0)); *dec = *dec + (decpm * (epoch - 1950.0)); return; } void fk524m (ra,dec,rapm,decpm) double *ra; /* Right ascension in degrees (J2000 in, B1950 out) */ double *dec; /* Declination in degrees (J2000 in, B1950 out) */ double *rapm; /* Proper motion in right ascension */ double *decpm; /* Proper motion in declination */ /* In: ra/dec deg/jul.yr. Out: ra/dec deg/trop.yr. */ { double parallax = 0.0; double rv = 0.0; fk524pv (ra, dec, rapm, decpm, ¶llax, &rv); return; } void fk524pv (ra,dec,rapm,decpm, parallax, rv) double *ra; /* Right ascension in degrees (J2000 in, B1950 out) */ double *dec; /* Declination in degrees (J2000 in, B1950 out) */ double *rapm; /* Proper motion in right ascension */ double *decpm; /* Proper motion in declination * In: ra/dec degrees/Julian year (not ra*cos(dec)) * Out: ra/dec degrees/tropical year */ double *parallax; /* Parallax (arcsec) */ double *rv; /* Rradial velocity (km/s, +ve = moving away) */ /* This routine converts stars from the IAU 1976 FK5 Fricke system, to the old Bessel-Newcomb FK4 system, using Yallop's implementation (see ref 2) of a matrix method due to Standish (see ref 3). The numerical values of ref 2 are used canonically. * Conversion from other than Julian epoch 2000.0 to other than Besselian epoch 1950.0 will require use of the appropriate precession, proper motion, and e-terms routines before and/or after fk524 is called. * In the FK4 catalogue the proper motions of stars within 10 degrees of the poles do not embody the differential e-term effect and should, strictly speaking, be handled in a different manner from stars outside these regions. however, given the general lack of homogeneity of the star data available for routine astrometry, the difficulties of handling positions that may have been determined from astrometric fields spanning the polar and non-polar regions, the likelihood that the differential e-terms effect was not taken into account when allowing for proper motion in past astrometry, and the undesirability of a discontinuity in the algorithm, the decision has been made in this routine to include the effect of differential e-terms on the proper motions for all stars, whether polar or not, at epoch 2000, and measuring on the sky rather than in terms of dra, the errors resulting from this simplification are less than 1 milliarcsecond in position and 1 milliarcsecond per century in proper motion. References: 1 "Mean and apparent place computations in the new IAU System. I. The transformation of astrometric catalog systems to the equinox J2000.0." Smith, C.A.; Kaplan, G.H.; Hughes, J.A.; Seidelmann, P.K.; Yallop, B.D.; Hohenkerk, C.Y. Astronomical Journal vol. 97, Jan. 1989, p. 265-273. 2 "Mean and apparent place computations in the new IAU System. II. Transformation of mean star places from FK4 B1950.0 to FK5 J2000.0 using matrices in 6-space." Yallop, B.D.; Hohenkerk, C.Y.; Smith, C.A.; Kaplan, G.H.; Hughes, J.A.; Seidelmann, P.K.; Astronomical Journal vol. 97, Jan. 1989, p. 274-279. 3 Seidelmann, P.K. (ed), 1992. "Explanatory Supplement to the Astronomical Almanac", ISBN 0-935702-68-7. 4 "Conversion of positions and proper motions from B1950.0 to the IAU system at J2000.0", Standish, E.M. Astronomy and Astrophysics, vol. 115, no. 1, Nov. 1982, p. 20-22. P.T.Wallace Starlink 19 December 1993 Doug Mink Smithsonian Astrophysical Observatory 1 November 2000 */ { double r2000,d2000; /* J2000.0 ra,dec (radians) */ double r1950,d1950; /* B1950.0 ra,dec (rad) */ /* Miscellaneous */ double ur,ud; double sr, cr, sd, cd, x, y, z, w, wd; double v1[6],v2[6]; double xd,yd,zd; double rxyz, rxysq, rxy; double dra,ddec; int i,j; int diag = 0; /* Constants */ double zero = (double) 0.0; double vf = 21.095; /* Km per sec to AU per tropical century */ /* = 86400 * 36524.2198782 / 149597870 */ /* Convert J2000 RA and Dec from degrees to radians */ r2000 = degrad (*ra); d2000 = degrad (*dec); /* Convert J2000 RA and Dec proper motion from degrees/year to arcsec/tc */ ur = *rapm * 360000.0; ud = *decpm * 360000.0; /* Spherical to Cartesian */ sr = sin (r2000); cr = cos (r2000); sd = sin (d2000); cd = cos (d2000); x = cr * cd; y = sr * cd; z = sd; v1[0] = x; v1[1] = y; v1[2] = z; if (ur != zero || ud != zero) { v1[3] = -(ur*y) - (cr*sd*ud); v1[4] = (ur*x) - (sr*sd*ud); v1[5] = (cd*ud); } else { v1[3] = zero; v1[4] = zero; v1[5] = zero; } /* Convert position + velocity vector to bn system */ for (i = 0; i < 6; i++) { w = zero; for (j = 0; j < 6; j++) { w = w + emi[i][j] * v1[j]; } v2[i] = w; } /* Vector components */ x = v2[0]; y = v2[1]; z = v2[2]; /* Magnitude of position vector */ rxyz = sqrt (x*x + y*y + z*z); /* Apply e-terms to position */ w = (x * a[0]) + (y * a[1]) + (z * a[2]); x = x + (a[0] * rxyz) - (w * x); y = y + (a[1] * rxyz) - (w * y); z = z + (a[2] * rxyz) - (w * z); /* Recompute magnitude of position vector */ rxyz = sqrt (x*x + y*y + z*z); /* Apply e-terms to position and velocity */ x = v2[0]; y = v2[1]; z = v2[2]; w = (x * a[0]) + (y * a[1]) + (z * a[2]); wd = (x * ad[0]) + (y * ad[1]) + (z * ad[2]); x = x + (a[0] * rxyz) - (w * x); y = y + (a[1] * rxyz) - (w * y); z = z + (a[2] * rxyz) - (w * z); xd = v2[3] + (ad[0] * rxyz) - (wd * x); yd = v2[4] + (ad[1] * rxyz) - (wd * y); zd = v2[5] + (ad[2] * rxyz) - (wd * z); /* Convert to spherical */ rxysq = (x * x) + (y * y); rxy = sqrt (rxysq); /* Convert back to spherical coordinates */ if (x == zero && y == zero) r1950 = zero; else { r1950 = atan2 (y,x); if (r1950 < zero) r1950 = r1950 + d2pi; } d1950 = atan2 (z,rxy); if (rxy > tiny) { ur = (x*yd - y*xd) / rxysq; ud = (zd*rxysq - z * (x*xd + y*yd)) / ((rxysq + z*z) * rxy); } if (*parallax > tiny) { *rv = ((x * xd) + (y * yd) + (z * zd)) / (*parallax * vf * rxyz); *parallax = *parallax / rxyz; } /* Return results */ *ra = raddeg (r1950); *dec = raddeg (d1950); *rapm = ur / 360000.0; *decpm = ud / 360000.0; if (diag) { dra = 240.0 * raddeg (r1950 - r2000); ddec = 3600.0 * raddeg (d1950 - d2000); fprintf(stderr,"B1950-J2000: dra= %11.5f sec ddec= %f11.5f arcsec\n", dra, ddec); } return; } /* Convert B1950.0 FK4 star data to J2000.0 FK5 */ static double em[6][6] = { { 0.9999256782, /* em[0][0] */ -0.0111820611, /* em[0][1] */ -0.0048579477, /* em[0][2] */ 0.00000242395018, /* em[0][3] */ -0.00000002710663, /* em[0][4] */ -0.00000001177656 }, /* em[0][5] */ { 0.0111820610, /* em[1][0] */ 0.9999374784, /* em[1][1] */ -0.0000271765, /* em[1][2] */ 0.00000002710663, /* em[1][3] */ 0.00000242397878, /* em[1][4] */ -0.00000000006587 }, /* em[1][5] */ { 0.0048579479, /* em[2][0] */ -0.0000271474, /* em[2][1] */ 0.9999881997, /* em[2][2] */ 0.00000001177656, /* em[2][3] */ -0.00000000006582, /* em[2][4] */ 0.00000242410173 }, /* em[2][5] */ { -0.000551, /* em[3][0] */ -0.238565, /* em[3][1] */ 0.435739, /* em[3][2] */ 0.99994704, /* em[3][3] */ -0.01118251, /* em[3][4] */ -0.00485767 }, /* em[3][5] */ { 0.238514, /* em[4][0] */ -0.002667, /* em[4][1] */ -0.008541, /* em[4][2] */ 0.01118251, /* em[4][3] */ 0.99995883, /* em[4][4] */ -0.00002718 }, /* em[4][5] */ { -0.435623, /* em[5][0] */ 0.012254, /* em[5][1] */ 0.002117, /* em[5][2] */ 0.00485767, /* em[5][3] */ -0.00002714, /* em[5][4] */ 1.00000956 } /* em[5][5] */ }; void fk425 (ra, dec) double *ra; /* Right ascension in degrees (B1950 in, J2000 out) */ double *dec; /* Declination in degrees (B1950 in, J2000 out) */ { double rapm; /* Proper motion in right ascension */ double decpm; /* Proper motion in declination */ /* In: rad/trop.yr. Out: rad/jul.yr. */ rapm = (double) 0.0; decpm = (double) 0.0; fk425m (ra, dec, &rapm, &decpm); return; } void fk425e (ra, dec, epoch) double *ra; /* Right ascension in degrees (B1950 in, J2000 out) */ double *dec; /* Declination in degrees (B1950 in, J2000 out) */ double epoch; /* Besselian epoch in years */ { double rapm; /* Proper motion in right ascension */ double decpm; /* Proper motion in declination */ /* In: rad/trop.yr. Out: rad/jul.yr. */ rapm = (double) 0.0; decpm = (double) 0.0; fk425m (ra, dec, &rapm, &decpm); *ra = *ra + (rapm * (epoch - 2000.0)); *dec = *dec + (decpm * (epoch - 2000.0)); return; } void fk425m (ra, dec, rapm, decpm) double *ra, *dec; /* Right ascension and declination in degrees input: B1950.0,FK4 returned: J2000.0,FK5 */ double *rapm, *decpm; /* Proper motion in right ascension and declination input: B1950.0,FK4 returned: J2000.0,FK5 ra/dec deg/trop.yr. ra/dec deg/jul.yr. */ { double parallax = 0.0; double rv = 0.0; fk425pv (ra, dec, rapm, decpm, ¶llax, &rv); return; } void fk425pv (ra,dec,rapm,decpm, parallax, rv) double *ra; /* Right ascension in degrees (J2000 in, B1950 out) */ double *dec; /* Declination in degrees (J2000 in, B1950 out) */ double *rapm; /* Proper motion in right ascension */ double *decpm; /* Proper motion in declination * In: ra/dec degrees/Julian year (not ra*cos(dec)) * Out: ra/dec degrees/tropical year */ double *parallax; /* Parallax (arcsec) */ double *rv; /* Rradial velocity (km/s, +ve = moving away) */ /* This routine converts stars from the old Bessel-Newcomb FK4 system to the IAU 1976 FK5 Fricke system, using Yallop's implementation (see ref 2) of a matrix method due to Standish (see ref 3). The numerical values of ref 2 are used canonically. * Conversion from other than Besselian epoch 1950.0 to other than Julian epoch 2000.0 will require use of the appropriate precession, proper motion, and e-terms routines before and/or after fk425 is called. * In the FK4 catalogue the proper motions of stars within 10 degrees of the poles do not embody the differential e-term effect and should, strictly speaking, be handled in a different manner from stars outside these regions. however, given the general lack of homogeneity of the star data available for routine astrometry, the difficulties of handling positions that may have been determined from astrometric fields spanning the polar and non-polar regions, the likelihood that the differential e-terms effect was not taken into account when allowing for proper motion in past astrometry, and the undesirability of a discontinuity in the algorithm, the decision has been made in this routine to include the effect of differential e-terms on the proper motions for all stars, whether polar or not, at epoch 2000, and measuring on the sky rather than in terms of dra, the errors resulting from this simplification are less than 1 milliarcsecond in position and 1 milliarcsecond per century in proper motion. References: 1 "Mean and apparent place computations in the new IAU System. I. The transformation of astrometric catalog systems to the equinox J2000.0." Smith, C.A.; Kaplan, G.H.; Hughes, J.A.; Seidelmann, P.K.; Yallop, B.D.; Hohenkerk, C.Y. Astronomical Journal vol. 97, Jan. 1989, p. 265-273. 2 "Mean and apparent place computations in the new IAU System. II. Transformation of mean star places from FK4 B1950.0 to FK5 J2000.0 using matrices in 6-space." Yallop, B.D.; Hohenkerk, C.Y.; Smith, C.A.; Kaplan, G.H.; Hughes, J.A.; Seidelmann, P.K.; Astronomical Journal vol. 97, Jan. 1989, p. 274-279. 3 "Conversion of positions and proper motions from B1950.0 to the IAU system at J2000.0", Standish, E.M. Astronomy and Astrophysics, vol. 115, no. 1, Nov. 1982, p. 20-22. P.T.Wallace Starlink 20 December 1993 Doug Mink Smithsonian Astrophysical Observatory 7 June 1995 */ { double r1950,d1950; /* B1950.0 ra,dec (rad) */ double r2000,d2000; /* J2000.0 ra,dec (rad) */ /* Miscellaneous */ double ur,ud,sr,cr,sd,cd,w,wd; double x,y,z,xd,yd,zd, dra,ddec; double rxyz, rxysq, rxy, rxyzsq, spxy, spxyz; int i,j; int diag = 0; double r0[3],rd0[3]; /* star position and velocity vectors */ double v1[6],v2[6]; /* combined position and velocity vectors */ /* Constants */ double zero = (double) 0.0; double vf = 21.095; /* Km per sec to AU per tropical century */ /* = 86400 * 36524.2198782 / 149597870 */ /* Convert B1950 RA and Dec from degrees to radians */ r1950 = degrad (*ra); d1950 = degrad (*dec); /* Convert B1950 RA and Dec proper motion from degrees/year to arcsec/tc */ ur = *rapm * 360000.0; ud = *decpm * 360000.0; /* Convert direction to Cartesian */ sr = sin (r1950); cr = cos (r1950); sd = sin (d1950); cd = cos (d1950); r0[0] = cr * cd; r0[1] = sr * cd; r0[2] = sd; /* Convert motion to Cartesian */ w = vf * *rv * *parallax; if (ur != zero || ud != zero || (*rv != zero && *parallax != zero)) { rd0[0] = (-sr * cd * ur) - (cr * sd * ud) + (w * r0[0]); rd0[1] = (cr * cd * ur) - (sr * sd * ud) + (w * r0[1]); rd0[2] = (cd * ud) + (w * r0[2]); } else { rd0[0] = zero; rd0[1] = zero; rd0[2] = zero; } /* Remove e-terms from position and express as position+velocity 6-vector */ w = (r0[0] * a[0]) + (r0[1] * a[1]) + (r0[2] * a[2]); for (i = 0; i < 3; i++) v1[i] = r0[i] - a[i] + (w * r0[i]); /* Remove e-terms from proper motion and express as 6-vector */ wd = (r0[0] * ad[0]) + (r0[1] * ad[1]) + (r0[2] * ad[2]); for (i = 0; i < 3; i++) v1[i+3] = rd0[i] - ad[i] + (wd * r0[i]); /* Alternately: Put proper motion in 6-vector without adding e-terms for (i = 0; i < 3; i++) v1[i+3] = rd0[i]; */ /* Convert position + velocity vector to FK5 system */ for (i = 0; i < 6; i++) { w = zero; for (j = 0; j < 6; j++) { w += em[i][j] * v1[j]; } v2[i] = w; } /* Vector components */ x = v2[0]; y = v2[1]; z = v2[2]; xd = v2[3]; yd = v2[4]; zd = v2[5]; /* Magnitude of position vector */ rxysq = x*x + y*y; rxy = sqrt (rxysq); rxyzsq = rxysq + z*z; rxyz = sqrt (rxyzsq); spxy = (x * xd) + (y * yd); spxyz = spxy + (z * zd); /* Convert back to spherical coordinates */ if (x == zero && y == zero) r2000 = zero; else { r2000 = atan2 (y,x); if (r2000 < zero) r2000 = r2000 + d2pi; } d2000 = atan2 (z,rxy); if (rxy > tiny) { ur = ((x * yd) - (y * xd)) / rxysq; ud = ((zd * rxysq) - (z * spxy)) / (rxyzsq * rxy); } if (*parallax > tiny) { *rv = spxyz / (*parallax * rxyz * vf); *parallax = *parallax / rxyz; } /* Return results */ *ra = raddeg (r2000); *dec = raddeg (d2000); *rapm = ur / 360000.0; *decpm = ud / 360000.0; if (diag) { dra = 240.0 * raddeg (r2000 - r1950); ddec = 3600.0 * raddeg (d2000 - d1950); fprintf(stderr,"J2000-B1950: dra= %11.5f sec ddec= %f11.5f arcsec\n", dra, ddec); } return; } int idg=0; /* l2,b2 system of galactic coordinates * p = 192.25 ra of galactic north pole (mean b1950.0) * q = 62.6 inclination of galactic to mean b1950.0 equator * r = 33 longitude of ascending node * p,q,r are degrees * Equatorial to galactic rotation matrix (The Eulerian angles are p, q, 90-r) +cp.cq.sr-sp.cr +sp.cq.sr+cp.cr -sq.sr -cp.cq.cr-sp.sr -sp.cq.cr+cp.sr +sq.cr cp.sq +sp.sq +cq */ static double bgal[3][3] = {{-0.066988739415,-0.872755765852,-0.483538914632}, {0.492728466075,-0.450346958020, 0.744584633283}, {-0.867600811151,-0.188374601723, 0.460199784784}}; /*--- Transform B1950.0 FK4 equatorial coordinates to * IAU 1958 galactic coordinates */ void fk42gal (dtheta,dphi) double *dtheta; /* B1950.0 FK4 right ascension in degrees Galactic longitude (l2) in degrees (returned) */ double *dphi; /* B1950.0 FK4 declination in degrees Galactic latitude (b2) in degrees (returned) */ /* Input equatorial coordinates are B1950 FK4. Use fk52gal() to convert from j2000.0 coordinates. Reference: Blaauw et al, MNRAS,121,123 (1960) */ { double pos[3],pos1[3],r,dl,db,rl,rb,rra,rdec,dra,ddec; void v2s3(),s2v3(); int i; char *eqcoor, *eqstrn(); dra = *dtheta; ddec = *dphi; rra = degrad (dra); rdec = degrad (ddec); /* remove e-terms */ /* call jpabe (rra,rdec,-1,idg) */ /* Spherical to Cartesian */ r = 1.; s2v3 (rra,rdec,r,pos); /* rotate to galactic */ for (i = 0; i<3; i++) { pos1[i] = pos[0]*bgal[i][0] + pos[1]*bgal[i][1] + pos[2]*bgal[i][2]; } /* Cartesian to spherical */ v2s3 (pos1,&rl,&rb,&r); dl = raddeg (rl); db = raddeg (rb); *dtheta = dl; *dphi = db; /* Print result if in diagnostic mode */ if (idg) { eqcoor = eqstrn (dra,ddec); fprintf (stderr,"FK42GAL: B1950 RA,Dec= %s\n",eqcoor); fprintf (stderr,"FK42GAL: long = %.5f lat = %.5f\n",dl,db); free (eqcoor); } return; } /*--- Transform IAU 1958 galactic coordinates to B1950.0 'FK4' * equatorial coordinates */ void gal2fk4 (dtheta,dphi) double *dtheta; /* Galactic longitude (l2) in degrees B1950 FK4 RA in degrees (returned) */ double *dphi; /* Galactic latitude (b2) in degrees B1950 FK4 Dec in degrees (returned) */ /* Output equatorial coordinates are B1950.0 FK4. Use gal2fk5() to convert to J2000 coordinates. Reference: Blaauw et al, MNRAS,121,123 (1960) */ { double pos[3],pos1[3],r,dl,db,rl,rb,rra,rdec,dra,ddec; void v2s3(),s2v3(); char *eqcoor, *eqstrn(); int i; /* spherical to cartesian */ dl = *dtheta; db = *dphi; rl = degrad (dl); rb = degrad (db); r = 1.0; s2v3 (rl,rb,r,pos); /* rotate to equatorial coordinates */ for (i = 0; i < 3; i++) { pos1[i] = pos[0]*bgal[0][i] + pos[1]*bgal[1][i] + pos[2]*bgal[2][i]; } /* cartesian to spherical */ v2s3 (pos1,&rra,&rdec,&r); /* introduce e-terms */ /* jpabe (rra,rdec,-1,idg); */ dra = raddeg (rra); ddec = raddeg (rdec); *dtheta = dra; *dphi = ddec; /* print result if in diagnostic mode */ if (idg) { fprintf (stderr,"GAL2FK4: long = %.5f lat = %.5f\n",dl,db); eqcoor = eqstrn (dra,ddec); fprintf (stderr,"GAL2FK4: B1950 RA,Dec= %s\n",eqcoor); free (eqcoor); } return; } /* l2,b2 system of galactic coordinates p = 192.25 ra of galactic north pole (mean b1950.0) q = 62.6 inclination of galactic to mean b1950.0 equator r = 33 longitude of ascending node p,q,r are degrees */ /* Equatorial to galactic rotation matrix The eulerian angles are p, q, 90-r +cp.cq.sr-sp.cr +sp.cq.sr+cp.cr -sq.sr -cp.cq.cr-sp.sr -sp.cq.cr+cp.sr +sq.cr +cp.sq +sp.sq +cq */ static double jgal[3][3] = {{-0.054875539726,-0.873437108010,-0.483834985808}, {0.494109453312,-0.444829589425, 0.746982251810}, {-0.867666135858,-0.198076386122, 0.455983795705}}; /* Transform J2000 equatorial coordinates to IAU 1958 galactic coordinates */ void fk52gal (dtheta,dphi) double *dtheta; /* J2000 right ascension in degrees Galactic longitude (l2) in degrees (returned) */ double *dphi; /* J2000 declination in degrees Galactic latitude (b2) in degrees (returned) */ /* Rotation matrices by P.T.Wallace, Starlink eqgal and galeq, March 1986 */ /* Input equatorial coordinates are J2000 FK5. Use gal2fk4() if converting from B1950 FK4 coordinates. Reference: Blaauw et al, MNRAS,121,123 (1960) */ { double pos[3],pos1[3],r,dl,db,rl,rb,rra,rdec,dra,ddec; void v2s3(),s2v3(); char *eqcoor, *eqstrn(); int i; /* Spherical to cartesian */ dra = *dtheta; ddec = *dphi; rra = degrad (dra); rdec = degrad (ddec); r = 1.0; (void)s2v3 (rra,rdec,r,pos); /* Rotate to galactic */ for (i = 0; i < 3; i++) { pos1[i] = pos[0]*jgal[i][0] + pos[1]*jgal[i][1] + pos[2]*jgal[i][2]; } /* Cartesian to spherical */ v2s3 (pos1,&rl,&rb,&r); dl = raddeg (rl); db = raddeg (rb); *dtheta = dl; *dphi = db; /* Print result if in diagnostic mode */ if (idg) { eqcoor = eqstrn (dra,ddec); fprintf (stderr,"FK52GAL: J2000 RA,Dec= %s\n",eqcoor); fprintf (stderr,"FK52GAL: long = %.5f lat = %.5f\n",dl,db); free (eqcoor); } return; } /*--- Transform IAU 1958 galactic coordinates to J2000 equatorial coordinates */ void gal2fk5 (dtheta,dphi) double *dtheta; /* Galactic longitude (l2) in degrees J2000.0 ra in degrees (returned) */ double *dphi; /* Galactic latitude (b2) in degrees J2000.0 dec in degrees (returned) */ /* Output equatorial coordinates are J2000. Use gal2fk4() to convert to B1950 coordinates. Reference: Blaauw et al, MNRAS,121,123 (1960) */ { double pos[3],pos1[3],r,dl,db,rl,rb,rra,rdec,dra,ddec; void v2s3(),s2v3(); int i; char *eqcoor, *eqstrn(); /* Spherical to Cartesian */ dl = *dtheta; db = *dphi; rl = degrad (dl); rb = degrad (db); r = 1.0; s2v3 (rl,rb,r,pos); /* Rotate to equatorial coordinates */ for (i = 0; i < 3; i++) { pos1[i] = pos[0]*jgal[0][i] + pos[1]*jgal[1][i] + pos[2]*jgal[2][i]; } /* Cartesian to Spherical */ v2s3 (pos1,&rra,&rdec,&r); dra = raddeg (rra); ddec = raddeg (rdec); *dtheta = dra; *dphi = ddec; /* Print result if in diagnostic mode */ if (idg) { fprintf (stderr,"GAL2FK5: long = %.5f lat = %.5f\n",dl,db); eqcoor = eqstrn (dra,ddec); fprintf (stderr,"GAL2FK5: J2000 RA,Dec= %s\n",eqcoor); free (eqcoor); } return; } /* Return string with right ascension in hours and declination in degrees */ char *eqstrn (dra, ddec) double dra; /* Right ascension in degrees */ double ddec; /* Declination in degrees */ { char *eqcoor; /* ASCII character string of position (returned) */ char decp; int rah,irm,decd,decm; double xpos,ypos,xp,yp,ras,decs; /* Right ascension to hours, minutes, and seconds */ xpos = dra / 15.0; rah = (int) xpos; xp = (double) 60.0 * (xpos - (double) rah); irm = (int) xp; ras = (double) 60.0 * (xp - (double) irm); /* Declination to degrees, minutes, seconds */ if (ddec < 0) { ypos = -ddec; decp = '-'; } else { decp = '+'; ypos = ddec; } decd = (int) ypos; yp = (double) 60.0 * (ypos - (double) decd); decm = (int) yp; decs = (double) 60.0 * (yp - (double) decm); eqcoor = malloc (32); (void)sprintf (eqcoor,"%02d:%02d:%06.3f %c%02d:%02d:%05.2f", rah,irm,ras,decp,decd,decm,decs); if (eqcoor[6] == ' ') eqcoor[6] = '0'; if (eqcoor[20] == ' ') eqcoor[20] = '0'; return (eqcoor); } /* Convert geocentric equatorial rectangular coordinates to right ascension and declination, and distance */ /* These routines are based on similar ones in Pat Wallace's slalib package */ /* Convert B1950 right ascension and declination to ecliptic coordinates */ void fk42ecl (dtheta, dphi, epoch) double *dtheta; /* B1950 right ascension in degrees Galactic longitude (l2) in degrees (returned) */ double *dphi; /* B1950 declination in degrees Galactic latitude (b2) in degrees (returned) */ double epoch; /* Besselian epoch in years */ { void fk425e(), fk52ecl(); /* Convert from B1950 to J2000 coordinates */ fk425e (dtheta, dphi, epoch); /* Convert from J2000 to ecliptic coordinates */ fk52ecl (dtheta, dphi, epoch); return; } /* Convert J2000 right ascension and declination to ecliptic coordinates */ void fk52ecl (dtheta, dphi, epoch) double *dtheta; /* J2000 right ascension in degrees Galactic longitude (l2) in degrees (returned) */ double *dphi; /* J2000 declination in degrees Galactic latitude (b2) in degrees (returned) */ double epoch; /* Besselian epoch in years */ { int i, j; double t, eps0, rphi, rtheta; double v1[3], v2[3], r; double rmat[9], *rmati; /* Rotation matrix */ void rotmat(), v2s3(), s2v3(), fk5prec(); /* Precess coordinates from J2000 to epoch */ if (epoch != 2000.0) fk5prec (2000.0, epoch, dtheta, dphi); /* Convert from degrees to radians */ rtheta = degrad (*dtheta); rphi = degrad (*dphi); /* Convert RA,Dec to x,y,z */ r = 1.0; s2v3 (rtheta, rphi, r, v1); /* Interval between basic epoch J2000.0 and current epoch (JC) in centuries*/ t = (epoch - 2000.0) * 0.01; /* Mean obliquity */ eps0 = secrad ((84381.448 + (-46.8150 + (-0.00059 + 0.001813*t) * t) * t)); /* Form the equatorial to ecliptic rotation matrix (IAU 1980 theory). * References: Murray, C.A., Vectorial Astrometry, section 4.3. * The matrix is in the sense v[ecl] = rmat * v[equ]; the * equator, equinox and ecliptic are mean of date. */ rotmat (1, eps0, 0.0, 0.0, rmat); /* Multiply position vector by equatoria to eccliptic rotation matrix */ rmati = rmat; for (i = 0; i < 3; i++) { v2[i] = 0; for (j = 0; j < 3; j++) v2[i] = v2[i] + (*rmati++ * v1[j]); } /* Convert x,y,z to latitude, longitude */ v2s3 (v2, &rtheta, &rphi, &r); /* Convert from radians to degrees */ *dtheta = raddeg (rtheta); *dphi = raddeg (rphi); } /* Convert ecliptic coordinates to B1950 right ascension and declination */ void ecl2fk4 (dtheta, dphi, epoch) double *dtheta; /* Galactic longitude (l2) in degrees B1950 right ascension in degrees (returned) */ double *dphi; /* Galactic latitude (b2) in degrees B1950 declination in degrees (returned) */ double epoch; /* Besselian epoch in years */ { void ecl2fk5(), fk524e(); /* Convert from ecliptic to J2000 coordinates */ ecl2fk5 (dtheta, dphi, epoch); /* Convert from J2000 to B1950 coordinates */ fk524e (dtheta, dphi, epoch); return; } /* Convert ecliptic coordinates to J2000 right ascension and declination */ void ecl2fk5 (dtheta, dphi, epoch) double *dtheta; /* Galactic longitude (l2) in degrees J2000 right ascension in degrees (returned) */ double *dphi; /* Galactic latitude (b2) in degrees J2000 declination in degrees (returned) */ double epoch; /* Besselian epoch in years */ { int i, j; double rtheta, rphi, v1[3], v2[3]; double t, eps0, r; double rmat[9]; /* Rotation matrix */ void v2s3(),s2v3(), fk5prec(), rotmat(); rtheta = degrad (*dtheta); rphi = degrad (*dphi); /* Convert RA,Dec to x,y,z */ r = 1.0; s2v3 (rtheta, rphi, r, v1); /* Interval between basic epoch J2000.0 and current epoch (JC) in centuries*/ t = (epoch - 2000.0) * 0.01; /* Mean obliquity */ eps0 = secrad ((84381.448 + (-46.8150 + (-0.00059 + 0.001813*t) * t) * t)); /* Form the equatorial to ecliptic rotation matrix (IAU 1980 theory). * References: Murray, C.A., Vectorial Astrometry, section 4.3. * The matrix is in the sense v[ecl] = rmat * v[equ]; the * equator, equinox and ecliptic are mean of date. */ rotmat (1, eps0, 0.0, 0.0, rmat); /* Multiply position vector by ecliptic to equatorial rotation matrix */ for (i = 0; i < 3; i++) { v2[i] = 0; for (j = 0; j < 3; j++) v2[i] = v2[i] + (rmat[3*j + i] * v1[j]); } /* Cartesian to spherical */ v2s3 (v2, &rtheta, &rphi, &r); /* Convert from radians to degrees */ *dtheta = raddeg (rtheta); *dphi = raddeg (rphi); if (epoch != 2000.0) fk5prec (epoch, 2000.0, dtheta, dphi); } /* The following routines are modified from Patrick Wallace's SLALIB */ /* Precess coordinates between epochs in FK4 */ void fk4prec (ep0, ep1, ra, dec) double ep0; /* Starting Besselian epoch */ double ep1; /* Ending Besselian epoch */ double *ra; /* RA in degrees mean equator & equinox of epoch ep0 mean equator & equinox of epoch ep1 (returned) */ double *dec; /* Dec in degrees mean equator & equinox of epoch ep0 mean equator & equinox of epoch ep1 (returned) */ /* ** Precession - FK4 (Bessel-Newcomb, pre-IAU1976) ** ** This routine will not correctly convert between FK4 and FK5 ** For output in FK5, precess to 1950.0 and use fk425() on result. ** ** Based on slaPreces(), P.T.Wallace Starlink 22 December 1993 */ { int i, j; double pm[9], *pmi, v1[3], v2[3], rra, rdec, r; void v2s3(),s2v3(), mprecfk4(); rra = degrad (*ra); rdec = degrad (*dec); r = 1.0; /* Generate appropriate precession matrix */ mprecfk4 ( ep0, ep1, pm ); /* Convert RA,Dec to x,y,z */ s2v3 (rra, rdec, r, v1); /* Multiply position vector by precession matrix */ pmi = pm; for (i = 0; i < 3; i++) { v2[i] = 0; for (j = 0; j < 3; j++) v2[i] = v2[i] + (*pmi++ * v1[j]); } /* Back to RA,Dec */ v2s3 (v2, &rra, &rdec, &r); /* Convert from radians to degrees */ *ra = raddeg (rra); *dec = raddeg (rdec); } void fk5prec (ep0, ep1, ra, dec) double ep0; /* Starting epoch */ double ep1; /* Ending epoch */ double *ra; /* RA in degrees mean equator & equinox of epoch ep0 mean equator & equinox of epoch ep1 (returned) */ double *dec; /* Dec in degrees mean equator & equinox of epoch ep0 mean equator & equinox of epoch ep1 (returned) */ /* ** Precession - FK5 (Fricke, post-IAU1976) ** ** This routine will not correctly convert between FK5 and FK4. ** For output in FK4, precess to 2000.0 and use fk524() on result. ** ** Based on slaPreces(), P.T.Wallace Starlink 22 December 1993 */ { int i, j; double pm[9], *pmi, v1[3], v2[3], rra, rdec, r; void v2s3(),s2v3(), mprecfk5(); rra = degrad (*ra); rdec = degrad (*dec); r = 1.0; /* Generate appropriate precession matrix */ mprecfk5 (ep0, ep1, pm); /* Convert RA,Dec to x,y,z */ s2v3 (rra, rdec, r, v1); /* Multiply position vector by precession matrix */ pmi = pm; for (i = 0; i < 3; i++) { v2[i] = 0; for (j = 0; j < 3; j++) v2[i] = v2[i] + ( v1[j] * *pmi++ ); } /* Back to RA,Dec */ v2s3 (v2, &rra, &rdec, &r); /* Convert from radians to degrees */ *ra = raddeg (rra); *dec = raddeg (rdec); return; } void mprecfk4 (bep0, bep1, rmatp) double bep0; /* Beginning Besselian epoch */ double bep1; /* Ending Besselian epoch */ double rmatp[9]; /* 3x3 Precession matrix (returned) */ /* ** Generate the matrix of precession between two epochs, ** using the old, pre-IAU1976, Bessel-Newcomb model, using ** Kinoshita's formulation (double precision) ** ** The matrix is in the sense v(bep1) = rmatp * v(bep0) ** ** Reference: ** Kinoshita, H. (1975) 'Formulas for precession', SAO Special ** Report No. 364, Smithsonian Institution Astrophysical ** Observatory, Cambridge, Massachusetts. ** ** Based on slaPrebn() by P.T.Wallace Starlink 30 October 1993 */ { double bigt, t, tas2r, w, zeta, z, theta; void rotmat(); /* Interval between basic epoch B1850.0 and beginning epoch in TC */ bigt = ( bep0 - 1850.0 ) / 100.0; /* Interval over which precession required, in tropical centuries */ t = ( bep1 - bep0 ) / 100.0; /* Euler angles */ tas2r = secrad (t); w = 2303.5548 + ( 1.39720 + 0.000059 * bigt ) * bigt; zeta = (w + ( 0.30242 - 0.000269 * bigt + 0.017996 * t ) * t ) * tas2r; z = (w + ( 1.09478 + 0.000387 * bigt + 0.018324 * t ) * t ) * tas2r; theta = ( 2005.1125 + ( - 0.85294 - 0.000365* bigt ) * bigt + ( - 0.42647 - 0.000365 * bigt - 0.041802 * t ) * t ) * tas2r; /* Rotation matrix */ rotmat (323, -zeta, theta, -z, rmatp); return; } void mprecfk5 (ep0, ep1, rmatp) double ep0; /* Beginning epoch */ double ep1; /* Ending epoch */ double rmatp[9]; /* 3x3 Precession matrix (returned) */ /* ** Form the matrix of precession between two epochs (IAU 1976, FK5). ** Notes: ** 1) The epochs are TDB (loosely ET) Julian epochs. ** 2) The matrix is in the sense v(ep1) = rmatp * v(ep0) . ** ** References: ** Lieske,J.H., 1979. Astron. Astrophys.,73,282. ** equations (6) & (7), p283. ** Kaplan,G.H., 1981. USNO circular no. 163, pa2. ** ** Based on slaPrec(), P.T.Wallace Starlink 31 October 1993 */ { double t0, t, tas2r, w, zeta, z, theta; void rotmat(); /* Interval between basic epoch J2000.0 and beginning epoch (JC) */ t0 = ( ep0 - 2000.0 ) / 100.0; /* Interval over which precession required (JC) */ t = ( ep1 - ep0 ) / 100.0; /* Euler angles */ tas2r = secrad (t); w = 2306.2181 + ( ( 1.39656 - ( 0.000139 * t0 ) ) * t0 ); zeta = (w + ( ( 0.30188 - 0.000344 * t0 ) + 0.017998 * t ) * t ) * tas2r; z = (w + ( ( 1.09468 + 0.000066 * t0 ) + 0.018203 * t ) * t ) * tas2r; theta = ( ( 2004.3109 + ( - 0.85330 - 0.000217 * t0 ) * t0 ) + ( ( -0.42665 - 0.000217 * t0 ) - 0.041833 * t ) * t ) * tas2r; /* Rotation matrix */ rotmat (323, -zeta, theta, -z, rmatp); return; } /* Make 3-D rotation matrix from up to three rotations */ void rotmat (axes, rot1, rot2, rot3, matrix) int axes; /* Axes about which coordinates are rotated (1=x, 2=y, 3=z) */ double rot1; /* First rotation in degrees */ double rot2; /* Second rotation in degrees */ double rot3; /* Third rotation in degrees */ double *matrix; /* 3x3 rotation matrix (returned) */ { int i, j, k, naxis, iaxes, iaxis; double rot[3], srot, crot, *mati, w, wm[9], *wmi, matn[9]; int axis[3]; /* Initial final rotation matrix */ mati = matrix; for (i = 0; i < 3; i++) { for (j=0; j < 3; j++) { if (i == j) *mati++ = 1.0; else *mati++ = 0.0; } } /* Separate digits of rotation axis string and count rotations */ naxis = 0; iaxes = axes; axis[0] = iaxes / 100; if (axis[0] > 0) { naxis++; iaxes = iaxes - (100 * axis[0]); } axis[naxis] = iaxes / 10; if (axis[naxis] > 0) { iaxes = iaxes - (10 * axis[naxis]); naxis++; } axis[naxis] = iaxes; if (axis[naxis] > 0) naxis++; /* Set up rotation angles */ rot[0] = rot1; rot[1] = rot2; rot[2] = rot3; /* For each digit of axis string, set up matrix */ for (iaxis = 0; iaxis < naxis; iaxis++) { /* Initialize current rotation matrix */ mati = matn; for (i = 0; i < 3; i++) { for (j=0; j < 3; j++) { if (i == j) *mati++ = 1.0; else *mati++ = 0.0; } } srot = sin (rot[iaxis]); crot = cos (rot[iaxis]); /* Matrix for rotation in X */ if (axis[iaxis] == 1) { matn[4] = crot; matn[5] = srot; matn[7] = -srot; matn[8] = crot; } /* Matrix for rotation in Y */ else if (axis[iaxis] == 2) { matn[0] = crot; matn[2] = -srot; matn[6] = srot; matn[8] = crot; } /* Matrix for rotation in Z */ else { matn[0] = crot; matn[1] = srot; matn[3] = -srot; matn[4] = crot; } /* Multiply existing rotation matrix by new rotation matrix */ for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { w = 0.0; for (k = 0; k < 3; k++) w+= matn[3*i + k] * matrix[3*k + j]; wm[3*i + j] = w; } } /* Update output matrix */ mati = matrix; wmi = wm; for (i = 0; i < 9; i++) { *mati++ = *wmi++; } } return; } /* The following routines are from Doug Mink's Fortran ephemeris library */ /* Convert right ascensiona and declination in degrees and distance to geocentric equatorial rectangular coordinates */ void d2v3 (rra,rdec,r,pos) double rra; /* Right ascension in degrees */ double rdec; /* Declination in degrees */ double r; /* Distance to object in same units as pos */ double pos[3]; /* x,y,z geocentric equatorial position of object (returned) */ { s2v3 (degrad (rra), degrad (rdec), r, pos); return; } /* Convert right ascension, declination, and distance to geocentric equatorial rectangular coordinates */ void s2v3 (rra,rdec,r,pos) double rra; /* Right ascension in radians */ double rdec; /* Declination in radians */ double r; /* Distance to object in same units as pos */ double pos[3]; /* x,y,z geocentric equatorial position of object (returned) */ { pos[0] = r * cos (rra) * cos (rdec); pos[1] = r * sin (rra) * cos (rdec); pos[2] = r * sin (rdec); return; } /* Convert geocentric equatorial rectangular coordinates to right ascension and declination in degrees and distance */ void v2d3 (pos,rra,rdec,r) double pos[3]; /* x,y,z geocentric equatorial position of object */ double *rra; /* Right ascension in degrees (returned) */ double *rdec; /* Declination in degrees (returned) */ double *r; /* Distance to object in same units as pos (returned) */ { v2s3 (pos, rra, rdec, r); *rra = raddeg (*rra); *rdec = raddeg (*rdec); return; } /* Convert geocentric equatorial rectangular coordinates to right ascension, declination, and distance */ void v2s3 (pos,rra,rdec,r) double pos[3]; /* x,y,z geocentric equatorial position of object */ double *rra; /* Right ascension in radians (returned) */ double *rdec; /* Declination in radians (returned) */ double *r; /* Distance to object in same units as pos (returned) */ { double x,y,z,rxy,rxy2,z2; x = pos[0]; y = pos[1]; z = pos[2]; *rra = atan2 (y, x); /* Keep RA within 0 to 2pi range */ if (*rra < 0.0) *rra = *rra + (2.0 * PI); if (*rra > 2.0 * PI) *rra = *rra - (2.0 * PI); rxy2 = x*x + y*y; rxy = sqrt (rxy2); *rdec = atan2 (z, rxy); z2 = z * z; *r = sqrt (rxy2 + z2); return; } /* * Nov 6 1995 Include stdlib.h instead of malloc.h * Apr 1 1996 Add arbitrary epoch precession * Apr 26 1996 Add FK4 <-> FK5 subroutines for use when epoch is known * Aug 6 1996 Clean up after lint * Nov 4 1996 Break SLA subroutines into separate file slasubs.c * Dec 9 1996 Change arguments to degrees in FK4 and FK5 precession programs * Dec 10 1996 All subroutine arguments are degrees except vector conversions * * Mar 20 1997 Drop unused variables after lint * * Apr 14 1998 Add ecliptic coordinate conversions and general conversion routines * Apr 23 1998 Add LINEAR coordinate system * Apr 28 1998 Change coordinate system flags to WCS_* * Apr 28 1998 Return -1 from wcscsys if not a legal coordinate system * May 7 1998 Keep theta within 0 to 2pi in ecl2fk5() * May 13 1998 Add wcsceq() * May 13 1998 Add equinox arguments to wcscon() * Jun 24 1998 Set J2000 from ICRS in wcscsys() * Jul 9 1998 Include stdio.h for fprintf() and sprintf() declarations * Sep 17 1998 Add wcscstr() to get coordinate string * Sep 21 1998 Fix bug in wcscstr() which returned B2000 instead of J2000 * Sep 21 1998 Add subroutine to convert proper motions, too. * Oct 21 1998 In wcscstr(), drop .00 from returned string * Nov 18 1998 Rename jpcop() v2s3() and jpcon() s2v3() (spherical to vector) * Dec 2 1998 Add PLANET coordinate system to wcscsys() and wcscstr() * * Mar 10 2000 Precess coordinates correctly from other than 1950.0 and 2000.0 * Mar 10 2000 Set coordinate system to J2000 or B1950 if string is numeric * Mar 14 2000 Clean up code in fk524m() and fk425m() * May 31 2000 Add proper motion correctly if proper motion precessed * Jun 26 2000 Add some support for WCS_XY image coordinates * Sep 14 2000 Return -1 from wcscsys if equinox is less than 1900.0 * Oct 31 2000 Add proper motion after fk425 or fk524 from system epoch * Oct 31 2000 Fix proper motion units in fk524p() and fk425p() * Nov 6 2000 Update fk425 and fk524 algorithms to include parallax and rv * * Jan 11 2001 Print all messages to stderr * Mar 21 2001 Move braces around bgal[] and jgal[] matrix initialization * * Feb 13 2002 Fix precession units problem in ecl2fk5() and fk52ecl() * * Apr 13 2005 Replace all sla_lib calls with local code * Nov 1 2005 Add WCS_ICRS, and unprecessable system * * Jan 5 2006 Fix bugs in precession subroutines mprecxxx() * May 3 2006 Drop declarations of unused variables suggested by Robert Lupton * Oct 6 2006 If pixel coordinates, set system to WCS_XY in wcscsys() * Oct 30 2006 Add LINEAR and ICRS to wcscstr() returns * * Aug 15 2007 Clean up code in rotmat() * Nov 8 2007 In wcsconp, make it clear that proper motion is in spherical coordinates * * Mar 29 2010 Fix bug in computing the magnitude of the e-terms in fk524() * Mar 30 2010 Drop ep1 assignment after line 178 in wcsconp() * * Jun 9 2016 Fix isnum() tests for added coloned times and dashed dates */ wcstools-3.9.5/libwcs/wcsinit.c0000664000016200001660000014067412733303651015601 0ustar minkoirsys/*** File libwcs/wcsinit.c *** July 24, 2016 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1998-2016 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: wcsinit.c (World Coordinate Systems) * Purpose: Convert FITS WCS to pixels and vice versa: * Subroutine: wcsinit (hstring) sets a WCS structure from an image header * Subroutine: wcsninit (hstring,lh) sets a WCS structure from fixed-length header * Subroutine: wcsinitn (hstring, name) sets a WCS structure for specified WCS * Subroutine: wcsninitn (hstring,lh, name) sets a WCS structure for specified WCS * Subroutine: wcsinitc (hstring, mchar) sets a WCS structure if multiple * Subroutine: wcsninitc (hstring,lh,mchar) sets a WCS structure if multiple * Subroutine: wcschar (hstring, name) returns suffix for specifed WCS * Subroutine: wcseq (hstring, wcs) set radecsys and equinox from image header * Subroutine: wcseqm (hstring, wcs, mchar) set radecsys and equinox if multiple */ #include /* strstr, NULL */ #include /* stderr */ #include #include "wcs.h" #ifndef VMS #include #endif static void wcseq(); static void wcseqm(); static void wcsioset(); void wcsrotset(); char wcschar(); /* set up a WCS structure from a FITS image header lhstring bytes long * for a specified WCS name */ struct WorldCoor * wcsninitn (hstring, lhstring, name) const char *hstring; /* character string containing FITS header information in the format = [/ ] */ int lhstring; /* Length of FITS header in bytes */ const char *name; /* character string with identifying name of WCS */ { hlength (hstring, lhstring); return (wcsinitn (hstring, name)); } /* set up a WCS structure from a FITS image header for specified WCSNAME */ struct WorldCoor * wcsinitn (hstring, name) const char *hstring; /* character string containing FITS header information in the format = [/ ] */ const char *name; /* character string with identifying name of WCS */ { char mchar; /* Suffix character for one of multiple WCS */ mchar = wcschar (hstring, name); if (mchar == '_') { fprintf (stderr, "WCSINITN: WCS name %s not matched in FITS header\n", name); return (NULL); } return (wcsinitc (hstring, &mchar)); } /* WCSCHAR -- Find the letter for a specific WCS conversion */ char wcschar (hstring, name) const char *hstring; /* character string containing FITS header information in the format = [/ ] */ const char *name; /* Name of WCS conversion to be matched (case-independent) */ { char *upname; char cwcs, charwcs; int iwcs; char keyword[12]; char *upval, value[72]; /* If no WCS character, return 0 */ if (name == NULL) return ((char) 0); /* Convert input name to upper case */ upname = uppercase (name); /* If single character name, return that character */ if (strlen (upname) == 1) return (upname[0]); /* Try to match input name to available WCSNAME names in header */ strcpy (keyword, "WCSNAME"); keyword[8] = (char) 0; charwcs = '_'; for (iwcs = 0; iwcs < 27; iwcs++) { if (iwcs > 0) cwcs = (char) (64 + iwcs); else cwcs = (char) 0; keyword[7] = cwcs; if (hgets (hstring, keyword, 72, value)) { upval = uppercase (value); if (!strcmp (upval, upname)) charwcs = cwcs; free (upval); } } free (upname); return (charwcs); } /* Make string of arbitrary case all uppercase */ char * uppercase (string) const char *string; { int lstring, i; char *upstring; lstring = strlen (string); upstring = (char *) calloc (1,lstring+1); for (i = 0; i < lstring; i++) { if (string[i] > 96 && string[i] < 123) upstring[i] = string[i] - 32; else upstring[i] = string[i]; } upstring[lstring] = (char) 0; return (upstring); } /* set up a WCS structure from a FITS image header lhstring bytes long */ struct WorldCoor * wcsninit (hstring, lhstring) const char *hstring; /* character string containing FITS header information in the format = [/ ] */ int lhstring; /* Length of FITS header in bytes */ { char mchar; /* Suffix character for one of multiple WCS */ mchar = (char) 0; hlength (hstring, lhstring); return (wcsinitc (hstring, &mchar)); } /* set up a WCS structure from a FITS image header lhstring bytes long */ struct WorldCoor * wcsninitc (hstring, lhstring, mchar) const char *hstring; /* character string containing FITS header information in the format = [/ ] */ int lhstring; /* Length of FITS header in bytes */ char *mchar; /* Suffix character for one of multiple WCS */ { hlength (hstring, lhstring); if (mchar[0] == ' ') mchar[0] = (char) 0; return (wcsinitc (hstring, mchar)); } /* set up a WCS structure from a FITS image header */ struct WorldCoor * wcsinit (hstring) const char *hstring; /* character string containing FITS header information in the format = [/ ] */ { char mchar; /* Suffix character for one of multiple WCS */ mchar = (char) 0; return (wcsinitc (hstring, &mchar)); } /* set up a WCS structure from a FITS image header for specified suffix */ struct WorldCoor * wcsinitc (hstring, wchar) const char *hstring; /* character string containing FITS header information in the format = [/ ] */ char *wchar; /* Suffix character for one of multiple WCS */ { struct WorldCoor *wcs, *depwcs; char ctype1[32], ctype2[32], tstring[32]; char pvkey1[8],pvkey2[8],pvkey3[8]; char *hcoeff; /* pointer to first coeff's in header */ char decsign; double rah,ram,ras, dsign,decd,decm,decs; double dec_deg,ra_hours, secpix, ra0, ra1, dec0, dec1, cvel; double cdelt1, cdelt2, cd[4], pc[81]; char keyword[16]; int ieq, i, j, k, naxes, cd11p, cd12p, cd21p, cd22p; int ilat; /* coordinate for latitude or declination */ /* int ix1, ix2, iy1, iy2, idx1, idx2, idy1, idy2; double dxrefpix, dyrefpix; */ char temp[80]; char wcsname[64]; /* Name of WCS depended on by current WCS */ char mchar; char cspace = (char) ' '; char cnull = (char) 0; double mjd; double rot; double ut; int nax; int twod; extern int tnxinit(); extern int zpxinit(); extern int platepos(); extern int dsspos(); void invert_wcs(); wcs = (struct WorldCoor *) calloc (1, sizeof(struct WorldCoor)); /* Set WCS character and name in structure */ mchar = wchar[0]; if (mchar == ' ') mchar = cnull; wcs->wcschar = mchar; if (hgetsc (hstring, "WCSNAME", &mchar, 63, wcsname)) { wcs->wcsname = (char *) calloc (strlen (wcsname)+2, 1); strcpy (wcs->wcsname, wcsname); } /* Set WCSLIB flags so that structures will be reinitialized */ wcs->cel.flag = 0; wcs->lin.flag = 0; wcs->wcsl.flag = 0; wcs->wcsl.cubeface = -1; /* Initialize to no plate fit */ wcs->ncoeff1 = 0; wcs->ncoeff2 = 0; /* Initialize to no CD matrix */ cdelt1 = 0.0; cdelt2 = 0.0; cd[0] = 0.0; cd[1] = 0.0; cd[2] = 0.0; cd[3] = 0.0; pc[0] = 0.0; wcs->rotmat = 0; wcs->rot = 0.0; /* Header parameters independent of projection */ naxes = 0; hgeti4c (hstring, "WCSAXES", &mchar, &naxes); if (naxes == 0) hgeti4 (hstring, "WCSAXES", &naxes); if (naxes == 0) hgeti4 (hstring, "NAXIS", &naxes); if (naxes == 0) hgeti4 (hstring, "WCSDIM", &naxes); if (naxes < 1) { setwcserr ("WCSINIT: No WCSAXES, NAXIS, or WCSDIM keyword"); wcsfree (wcs); return (NULL); } if (naxes > 2) naxes = 2; wcs->naxis = naxes; wcs->naxes = naxes; wcs->lin.naxis = naxes; wcs->nxpix = 0; hgetr8 (hstring, "NAXIS1", &wcs->nxpix); if (wcs->nxpix < 1) hgetr8 (hstring, "IMAGEW", &wcs->nxpix); if (wcs->nxpix < 1) { setwcserr ("WCSINIT: No NAXIS1 or IMAGEW keyword"); wcsfree (wcs); return (NULL); } wcs->nypix = 0; hgetr8 (hstring, "NAXIS2", &wcs->nypix); if (wcs->nypix < 1) hgetr8 (hstring, "IMAGEH", &wcs->nypix); if (naxes > 1 && wcs->nypix < 1) { setwcserr ("WCSINIT: No NAXIS2 or IMAGEH keyword"); wcsfree (wcs); return (NULL); } /* Reset number of axes to only those with dimension greater than one */ nax = 0; for (i = 0; i < naxes; i++) { /* Check for number of pixels in axis more than one */ strcpy (keyword, "NAXIS"); sprintf (temp, "%d", i+1); strcat (keyword, temp); if (!hgeti4 (hstring, keyword, &j)) { if (i == 0 && wcs->nxpix > 1) { /* fprintf (stderr,"WCSINIT: Missing keyword %s set to %.0f from IMAGEW\n", keyword, wcs->nxpix); */ j = wcs->nxpix; } else if (i == 1 && wcs->nypix > 1) { /* fprintf (stderr,"WCSINIT: Missing keyword %s set to %.0f from IMAGEH\n", keyword, wcs->nypix); */ j = wcs->nypix; } else fprintf (stderr,"WCSINIT: Missing keyword %s assumed 1\n",keyword); } /* Check for TAB WCS in axis */ strcpy (keyword, "CTYPE"); strcat (keyword, temp); if (hgets (hstring, keyword, 16, temp)) { if (strsrch (temp, "-TAB")) j = 0; } if (j > 1) nax = nax + 1; } naxes = nax; wcs->naxes = nax; wcs->naxis = nax; hgets (hstring, "INSTRUME", 16, wcs->instrument); hgeti4 (hstring, "DETECTOR", &wcs->detector); wcs->wcsproj = getdefwcs(); wcs->logwcs = 0; hgeti4 (hstring, "DC-FLAG", &wcs->logwcs); /* Initialize rotation matrices */ for (i = 0; i < 81; i++) wcs->pc[i] = 0.0; for (i = 0; i < 81; i++) pc[i] = 0.0; for (i = 0; i < naxes; i++) wcs->pc[(i*naxes)+i] = 1.0; for (i = 0; i < naxes; i++) pc[(i*naxes)+i] = 1.0; for (i = 0; i < 9; i++) wcs->cdelt[i] = 0.0; for (i = 0; i < naxes; i++) wcs->cdelt[i] = 1.0; /* If the current world coordinate system depends on another, set it now */ if (hgetsc (hstring, "WCSDEP",&mchar, 63, wcsname)) { if ((wcs->wcs = wcsinitn (hstring, wcsname)) == NULL) { setwcserr ("WCSINIT: depended on WCS could not be set"); wcsfree (wcs); return (NULL); } depwcs = wcs->wcs; depwcs->wcsdep = wcs; } else wcs->wcs = NULL; /* Read radial velocity from image header */ wcs->radvel = 0.0; wcs->zvel = 0.0; cvel = 299792.5; if (hgetr8c (hstring, "VSOURCE", &mchar, &wcs->radvel)) wcs->zvel = wcs->radvel / cvel; else if (hgetr8c (hstring, "ZSOURCE", &mchar, &wcs->zvel)) wcs->radvel = wcs->zvel * cvel; else if (hgetr8 (hstring, "VELOCITY", &wcs->radvel)) wcs->zvel = wcs->radvel / cvel; for (i = 0; i < 10; i++) { wcs->prj.p[i] = 0.0; } /* World coordinate system reference coordinate information */ if (hgetsc (hstring, "CTYPE1", &mchar, 16, ctype1)) { /* Read second coordinate type */ strcpy (ctype2, ctype1); if (!hgetsc (hstring, "CTYPE2", &mchar, 16, ctype2)) twod = 0; else twod = 1; strcpy (wcs->ctype[0], ctype1); strcpy (wcs->ctype[1], ctype2); if (strsrch (ctype2, "LAT") || strsrch (ctype2, "DEC")) ilat = 2; else ilat = 1; /* Read third and fourth coordinate types, if present */ strcpy (wcs->ctype[2], ""); hgetsc (hstring, "CTYPE3", &mchar, 9, wcs->ctype[2]); strcpy (wcs->ctype[3], ""); hgetsc (hstring, "CTYPE4", &mchar, 9, wcs->ctype[3]); /* Set projection type in WCS data structure */ if (wcstype (wcs, ctype1, ctype2)) { wcsfree (wcs); return (NULL); } /* Get units, if present, for linear coordinates */ if (wcs->prjcode == WCS_LIN) { if (!hgetsc (hstring, "CUNIT1", &mchar, 16, wcs->units[0])) { if (!mgetstr (hstring, "WAT1", "units", 16, wcs->units[0])) { wcs->units[0][0] = 0; } } if (!strcmp (wcs->units[0], "pixel")) wcs->prjcode = WCS_PIX; if (twod) { if (!hgetsc (hstring, "CUNIT2", &mchar, 16, wcs->units[1])) { if (!mgetstr (hstring, "WAT2", "units", 16, wcs->units[1])) { wcs->units[1][0] = 0; } } if (!strcmp (wcs->units[0], "pixel")) wcs->prjcode = WCS_PIX; } } /* Reference pixel coordinates and WCS value */ wcs->crpix[0] = 1.0; hgetr8c (hstring, "CRPIX1", &mchar, &wcs->crpix[0]); wcs->crpix[1] = 1.0; hgetr8c (hstring, "CRPIX2", &mchar, &wcs->crpix[1]); wcs->xrefpix = wcs->crpix[0]; wcs->yrefpix = wcs->crpix[1]; wcs->crval[0] = 0.0; hgetr8c (hstring, "CRVAL1", &mchar, &wcs->crval[0]); wcs->crval[1] = 0.0; hgetr8c (hstring, "CRVAL2", &mchar, &wcs->crval[1]); if (wcs->syswcs == WCS_NPOLE) wcs->crval[1] = 90.0 - wcs->crval[1]; if (wcs->syswcs == WCS_SPA) wcs->crval[1] = wcs->crval[1] - 90.0; wcs->xref = wcs->crval[0]; wcs->yref = wcs->crval[1]; if (wcs->coorflip) { wcs->cel.ref[0] = wcs->crval[1]; wcs->cel.ref[1] = wcs->crval[0]; } else { wcs->cel.ref[0] = wcs->crval[0]; wcs->cel.ref[1] = wcs->crval[1]; } wcs->longpole = 999.0; hgetr8c (hstring, "LONPOLE", &mchar, &wcs->longpole); wcs->cel.ref[2] = wcs->longpole; wcs->latpole = 999.0; hgetr8c (hstring, "LATPOLE", &mchar, &wcs->latpole); wcs->cel.ref[3] = wcs->latpole; wcs->lin.crpix = wcs->crpix; wcs->lin.cdelt = wcs->cdelt; wcs->lin.pc = wcs->pc; /* Projection constants (this should be projection-dependent */ wcs->prj.r0 = 0.0; hgetr8c (hstring, "PROJR0", &mchar, &wcs->prj.r0); /* FITS WCS interim proposal projection constants */ for (i = 0; i < 10; i++) { sprintf (keyword,"PROJP%d",i); hgetr8c (hstring, keyword, &mchar, &wcs->prj.p[i]); } sprintf (pvkey1, "PV%d_1", ilat); sprintf (pvkey2, "PV%d_2", ilat); sprintf (pvkey3, "PV%d_3", ilat); /* FITS WCS standard projection constants (projection-dependent) */ if (wcs->prjcode == WCS_AZP || wcs->prjcode == WCS_SIN || wcs->prjcode == WCS_COP || wcs->prjcode == WCS_COE || wcs->prjcode == WCS_COD || wcs->prjcode == WCS_COO) { hgetr8c (hstring, pvkey1, &mchar, &wcs->prj.p[1]); hgetr8c (hstring, pvkey2, &mchar, &wcs->prj.p[2]); } else if (wcs->prjcode == WCS_SZP) { hgetr8c (hstring, pvkey1, &mchar, &wcs->prj.p[1]); hgetr8c (hstring, pvkey2, &mchar, &wcs->prj.p[2]); if (wcs->prj.p[3] == 0.0) wcs->prj.p[3] = 90.0; hgetr8c (hstring, pvkey3, &mchar, &wcs->prj.p[3]); } else if (wcs->prjcode == WCS_CEA) { if (wcs->prj.p[1] == 0.0) wcs->prj.p[1] = 1.0; hgetr8c (hstring, pvkey1, &mchar, &wcs->prj.p[1]); } else if (wcs->prjcode == WCS_CYP) { if (wcs->prj.p[1] == 0.0) wcs->prj.p[1] = 1.0; hgetr8c (hstring, pvkey1, &mchar, &wcs->prj.p[1]); if (wcs->prj.p[2] == 0.0) wcs->prj.p[2] = 1.0; hgetr8c (hstring, pvkey2, &mchar, &wcs->prj.p[2]); } else if (wcs->prjcode == WCS_AIR) { if (wcs->prj.p[1] == 0.0) wcs->prj.p[1] = 90.0; hgetr8c (hstring, pvkey1, &mchar, &wcs->prj.p[1]); } else if (wcs->prjcode == WCS_BON) { hgetr8c (hstring, pvkey1, &mchar, &wcs->prj.p[1]); } else if (wcs->prjcode == WCS_ZPN) { for (i = 0; i < 10; i++) { sprintf (keyword,"PV%d_%d", ilat, i); hgetr8c (hstring, keyword, &mchar, &wcs->prj.p[i]); } } /* Initialize TNX, defaulting to TAN if there is a problem */ if (wcs->prjcode == WCS_TNX) { if (tnxinit (hstring, wcs)) { wcs->ctype[0][6] = 'A'; wcs->ctype[0][7] = 'N'; wcs->ctype[1][6] = 'A'; wcs->ctype[1][7] = 'N'; wcs->prjcode = WCS_TAN; } } /* Initialize ZPX, defaulting to ZPN if there is a problem */ if (wcs->prjcode == WCS_ZPX) { if (zpxinit (hstring, wcs)) { wcs->ctype[0][7] = 'N'; wcs->ctype[1][7] = 'N'; wcs->prjcode = WCS_ZPN; } } /* Set TPV to TAN as SCAMP coefficients will be added below */ if (wcs->prjcode == WCS_TPV) { wcs->ctype[0][6] = 'A'; wcs->ctype[0][7] = 'N'; wcs->ctype[1][6] = 'A'; wcs->ctype[1][7] = 'N'; wcs->prjcode = WCS_TAN; } /* Coordinate reference frame, equinox, and epoch */ if (wcs->wcsproj > 0) wcseqm (hstring, wcs, &mchar); wcsioset (wcs); /* Read distortion coefficients, if present */ distortinit (wcs, hstring); /* Use polynomial fit instead of projection, if present */ wcs->ncoeff1 = 0; wcs->ncoeff2 = 0; cd11p = hgetr8c (hstring, "CD1_1", &mchar, &cd[0]); cd12p = hgetr8c (hstring, "CD1_2", &mchar, &cd[1]); cd21p = hgetr8c (hstring, "CD2_1", &mchar, &cd[2]); cd22p = hgetr8c (hstring, "CD2_2", &mchar, &cd[3]); if (wcs->wcsproj != WCS_OLD && (hcoeff = ksearch (hstring,"CO1_1")) != NULL) { wcs->prjcode = WCS_PLT; (void)strcpy (wcs->ptype, "PLA"); for (i = 0; i < 20; i++) { sprintf (keyword,"CO1_%d", i+1); wcs->x_coeff[i] = 0.0; if (hgetr8 (hcoeff, keyword, &wcs->x_coeff[i])) wcs->ncoeff1 = i + 1; } hcoeff = ksearch (hstring,"CO2_1"); for (i = 0; i < 20; i++) { sprintf (keyword,"CO2_%d",i+1); wcs->y_coeff[i] = 0.0; if (hgetr8 (hcoeff, keyword, &wcs->y_coeff[i])) wcs->ncoeff2 = i + 1; } /* Compute a nominal scale factor */ platepos (wcs->crpix[0], wcs->crpix[1], wcs, &ra0, &dec0); platepos (wcs->crpix[0], wcs->crpix[1]+1.0, wcs, &ra1, &dec1); wcs->yinc = dec1 - dec0; wcs->xinc = -wcs->yinc; /* Compute image rotation angle */ wcs->wcson = 1; wcsrotset (wcs); rot = degrad (wcs->rot); /* Compute scale at reference pixel */ platepos (wcs->crpix[0], wcs->crpix[1], wcs, &ra0, &dec0); platepos (wcs->crpix[0]+cos(rot), wcs->crpix[1]+sin(rot), wcs, &ra1, &dec1); wcs->cdelt[0] = -wcsdist (ra0, dec0, ra1, dec1); wcs->xinc = wcs->cdelt[0]; platepos (wcs->crpix[0]+sin(rot), wcs->crpix[1]+cos(rot), wcs, &ra1, &dec1); wcs->cdelt[1] = wcsdist (ra0, dec0, ra1, dec1); wcs->yinc = wcs->cdelt[1]; /* Set CD matrix from header */ wcs->cd[0] = cd[0]; wcs->cd[1] = cd[1]; wcs->cd[2] = cd[2]; wcs->cd[3] = cd[3]; (void) matinv (2, wcs->cd, wcs->dc); } /* Else use CD matrix, if present */ else if (cd11p || cd12p || cd21p || cd22p) { wcs->rotmat = 1; wcscdset (wcs, cd); } /* Else get scaling from CDELT1 and CDELT2 */ else if (hgetr8c (hstring, "CDELT1", &mchar, &cdelt1) != 0) { hgetr8c (hstring, "CDELT2", &mchar, &cdelt2); /* If CDELT1 or CDELT2 is 0 or missing */ if (cdelt1 == 0.0 || (wcs->nypix > 1 && cdelt2 == 0.0)) { if (ksearch (hstring,"SECPIX") != NULL || ksearch (hstring,"PIXSCALE") != NULL || ksearch (hstring,"PIXSCAL1") != NULL || ksearch (hstring,"XPIXSIZE") != NULL || ksearch (hstring,"SECPIX1") != NULL) { secpix = 0.0; hgetr8 (hstring,"SECPIX",&secpix); if (secpix == 0.0) hgetr8 (hstring,"PIXSCALE",&secpix); if (secpix == 0.0) { hgetr8 (hstring,"SECPIX1",&secpix); if (secpix != 0.0) { if (cdelt1 == 0.0) cdelt1 = -secpix / 3600.0; if (cdelt2 == 0.0) { hgetr8 (hstring,"SECPIX2",&secpix); cdelt2 = secpix / 3600.0; } } else { hgetr8 (hstring,"XPIXSIZE",&secpix); if (secpix != 0.0) { if (cdelt1 == 0.0) cdelt1 = -secpix / 3600.0; if (cdelt2 == 0.0) { hgetr8 (hstring,"YPIXSIZE",&secpix); cdelt2 = secpix / 3600.0; } } else { hgetr8 (hstring,"PIXSCAL1",&secpix); if (secpix != 0.0 && cdelt1 == 0.0) cdelt1 = -secpix / 3600.0; if (cdelt2 == 0.0) { hgetr8 (hstring,"PIXSCAL2",&secpix); cdelt2 = secpix / 3600.0; } } } } else { if (cdelt1 == 0.0) cdelt1 = -secpix / 3600.0; if (cdelt2 == 0.0) cdelt2 = secpix / 3600.0; } } } if (cdelt2 == 0.0 && wcs->nypix > 1) cdelt2 = -cdelt1; wcs->cdelt[2] = 1.0; wcs->cdelt[3] = 1.0; /* Initialize rotation matrix */ for (i = 0; i < 81; i++) { pc[i] = 0.0; wcs->pc[i] = 0.0; } for (i = 0; i < naxes; i++) pc[(i*naxes)+i] = 1.0; /* Read FITS WCS interim rotation matrix */ if (!mchar && hgetr8 (hstring,"PC001001",&pc[0]) != 0) { k = 0; for (i = 0; i < naxes; i++) { for (j = 0; j < naxes; j++) { if (i == j) pc[k] = 1.0; else pc[k] = 0.0; sprintf (keyword, "PC00%1d00%1d", i+1, j+1); hgetr8 (hstring, keyword, &pc[k++]); } } wcspcset (wcs, cdelt1, cdelt2, pc); } /* Read FITS WCS standard rotation matrix */ else if (hgetr8c (hstring, "PC1_1", &mchar, &pc[0]) != 0) { k = 0; for (i = 0; i < naxes; i++) { for (j = 0; j < naxes; j++) { if (i == j) pc[k] = 1.0; else pc[k] = 0.0; sprintf (keyword, "PC%1d_%1d", i+1, j+1); hgetr8c (hstring, keyword, &mchar, &pc[k++]); } } wcspcset (wcs, cdelt1, cdelt2, pc); } /* Otherwise, use CROTAn */ else { rot = 0.0; if (ilat == 2) hgetr8c (hstring, "CROTA2", &mchar, &rot); else hgetr8c (hstring,"CROTA1", &mchar, &rot); wcsdeltset (wcs, cdelt1, cdelt2, rot); } } /* If no scaling is present, set to 1 per pixel, no rotation */ else { wcs->xinc = 1.0; wcs->yinc = 1.0; wcs->cdelt[0] = 1.0; wcs->cdelt[1] = 1.0; wcs->rot = 0.0; wcs->rotmat = 0; setwcserr ("WCSINIT: setting CDELT to 1"); } /* SCAMP convention */ if (wcs->prjcode == WCS_TAN && wcs->naxis == 2) { int n = 0; if (wcs->inv_x) { poly_end(wcs->inv_x); wcs->inv_x = NULL; } if (wcs->inv_y) { poly_end(wcs->inv_y); wcs->inv_y = NULL; } wcs->pvfail = 0; for (i = 0; i < (2*MAXPV); i++) { wcs->projppv[i] = 0.0; wcs->prj.ppv[i] = 0.0; } for (k = 0; k < 2; k++) { for (j = 0; j < MAXPV; j++) { sprintf(keyword, "PV%d_%d", k+1, j); if (hgetr8c(hstring, keyword,&mchar, &wcs->projppv[j+k*MAXPV]) == 0) { wcs->projppv[j+k*MAXPV] = 0.0; } else n++; } } /* If any PVi_j are set, add them in the structure if no SIRTF distortion*/ if (n > 0 && wcs->distcode != DISTORT_SIRTF) { n = 0; for (k = MAXPV; k >= 0; k--) { /* lat comes first for compatibility reasons */ wcs->prj.ppv[k] = wcs->projppv[k+wcs->wcsl.lat*MAXPV]; wcs->prj.ppv[k+MAXPV] = wcs->projppv[k+wcs->wcsl.lng*MAXPV]; if (!n && (wcs->prj.ppv[k] || wcs->prj.ppv[k+MAXPV])) { n = k+1; } } invert_wcs(wcs); /* Need to call tanset again */ wcs->cel.flag = 0; } } /* If linear or pixel WCS, print "degrees" */ if (!strncmp (wcs->ptype,"LIN",3) || !strncmp (wcs->ptype,"PIX",3)) { wcs->degout = -1; wcs->ndec = 5; } /* Epoch of image (from observation date, if possible) */ if (hgetr8 (hstring, "MJD-OBS", &mjd)) wcs->epoch = 1900.0 + (mjd - 15019.81352) / 365.242198781; else if (!hgetdate (hstring,"DATE-OBS",&wcs->epoch)) { if (!hgetdate (hstring,"DATE",&wcs->epoch)) { if (!hgetr8 (hstring,"EPOCH",&wcs->epoch)) wcs->epoch = wcs->equinox; } } /* Add time of day if not part of DATE-OBS string */ else { hgets (hstring,"DATE-OBS",32,tstring); if (!strchr (tstring,'T')) { if (hgetr8 (hstring, "UT",&ut)) wcs->epoch = wcs->epoch + (ut / (24.0 * 365.242198781)); else if (hgetr8 (hstring, "UTMID",&ut)) wcs->epoch = wcs->epoch + (ut / (24.0 * 365.242198781)); } } wcs->wcson = 1; } else if (mchar != cnull && mchar != cspace) { (void) sprintf (temp, "WCSINITC: No image scale for WCS %c", mchar); setwcserr (temp); wcsfree (wcs); return (NULL); } /* Plate solution coefficients */ else if (ksearch (hstring,"PLTRAH") != NULL) { wcs->prjcode = WCS_DSS; hcoeff = ksearch (hstring,"PLTRAH"); hgetr8 (hcoeff,"PLTRAH",&rah); hgetr8 (hcoeff,"PLTRAM",&ram); hgetr8 (hcoeff,"PLTRAS",&ras); ra_hours = rah + (ram / (double)60.0) + (ras / (double)3600.0); wcs->plate_ra = hrrad (ra_hours); decsign = '+'; hgets (hcoeff,"PLTDECSN", 1, &decsign); if (decsign == '-') dsign = -1.; else dsign = 1.; hgetr8 (hcoeff,"PLTDECD",&decd); hgetr8 (hcoeff,"PLTDECM",&decm); hgetr8 (hcoeff,"PLTDECS",&decs); dec_deg = dsign * (decd+(decm/(double)60.0)+(decs/(double)3600.0)); wcs->plate_dec = degrad (dec_deg); hgetr8 (hstring,"EQUINOX",&wcs->equinox); hgeti4 (hstring,"EQUINOX",&ieq); if (ieq == 1950) strcpy (wcs->radecsys,"FK4"); else strcpy (wcs->radecsys,"FK5"); wcs->epoch = wcs->equinox; hgetr8 (hstring,"EPOCH",&wcs->epoch); (void)sprintf (wcs->center,"%2.0f:%2.0f:%5.3f %c%2.0f:%2.0f:%5.3f %s", rah,ram,ras,decsign,decd,decm,decs,wcs->radecsys); hgetr8 (hstring,"PLTSCALE",&wcs->plate_scale); hgetr8 (hstring,"XPIXELSZ",&wcs->x_pixel_size); hgetr8 (hstring,"YPIXELSZ",&wcs->y_pixel_size); hgetr8 (hstring,"CNPIX1",&wcs->x_pixel_offset); hgetr8 (hstring,"CNPIX2",&wcs->y_pixel_offset); hcoeff = ksearch (hstring,"PPO1"); for (i = 0; i < 6; i++) { sprintf (keyword,"PPO%d", i+1); wcs->ppo_coeff[i] = 0.0; hgetr8 (hcoeff,keyword,&wcs->ppo_coeff[i]); } hcoeff = ksearch (hstring,"AMDX1"); for (i = 0; i < 20; i++) { sprintf (keyword,"AMDX%d", i+1); wcs->x_coeff[i] = 0.0; hgetr8 (hcoeff, keyword, &wcs->x_coeff[i]); } hcoeff = ksearch (hstring,"AMDY1"); for (i = 0; i < 20; i++) { sprintf (keyword,"AMDY%d",i+1); wcs->y_coeff[i] = 0.0; hgetr8 (hcoeff, keyword, &wcs->y_coeff[i]); } wcs->wcson = 1; (void)strcpy (wcs->c1type, "RA"); (void)strcpy (wcs->c2type, "DEC"); (void)strcpy (wcs->ptype, "DSS"); wcs->degout = 0; wcs->ndec = 3; /* Compute a nominal reference pixel at the image center */ strcpy (wcs->ctype[0], "RA---DSS"); strcpy (wcs->ctype[1], "DEC--DSS"); wcs->crpix[0] = 0.5 * wcs->nxpix; wcs->crpix[1] = 0.5 * wcs->nypix; wcs->xrefpix = wcs->crpix[0]; wcs->yrefpix = wcs->crpix[1]; dsspos (wcs->crpix[0], wcs->crpix[1], wcs, &ra0, &dec0); wcs->crval[0] = ra0; wcs->crval[1] = dec0; wcs->xref = wcs->crval[0]; wcs->yref = wcs->crval[1]; /* Compute a nominal scale factor */ dsspos (wcs->crpix[0], wcs->crpix[1]+1.0, wcs, &ra1, &dec1); wcs->yinc = dec1 - dec0; wcs->xinc = -wcs->yinc; wcsioset (wcs); /* Compute image rotation angle */ wcs->wcson = 1; wcsrotset (wcs); rot = degrad (wcs->rot); /* Compute image scale at center */ dsspos (wcs->crpix[0]+cos(rot), wcs->crpix[1]+sin(rot), wcs, &ra1, &dec1); wcs->cdelt[0] = -wcsdist (ra0, dec0, ra1, dec1); dsspos (wcs->crpix[0]+sin(rot), wcs->crpix[1]+cos(rot), wcs, &ra1, &dec1); wcs->cdelt[1] = wcsdist (ra0, dec0, ra1, dec1); /* Set all other image scale parameters */ wcsdeltset (wcs, wcs->cdelt[0], wcs->cdelt[1], wcs->rot); } /* Approximate world coordinate system if plate scale is known */ else if ((ksearch (hstring,"SECPIX") != NULL || ksearch (hstring,"PIXSCALE") != NULL || ksearch (hstring,"PIXSCAL1") != NULL || ksearch (hstring,"XPIXSIZE") != NULL || ksearch (hstring,"SECPIX1") != NULL)) { secpix = 0.0; hgetr8 (hstring,"SECPIX",&secpix); if (secpix == 0.0) hgetr8 (hstring,"PIXSCALE",&secpix); if (secpix == 0.0) { hgetr8 (hstring,"SECPIX1",&secpix); if (secpix != 0.0) { cdelt1 = -secpix / 3600.0; hgetr8 (hstring,"SECPIX2",&secpix); cdelt2 = secpix / 3600.0; } else { hgetr8 (hstring,"XPIXSIZE",&secpix); if (secpix != 0.0) { cdelt1 = -secpix / 3600.0; hgetr8 (hstring,"YPIXSIZE",&secpix); cdelt2 = secpix / 3600.0; } else { hgetr8 (hstring,"PIXSCAL1",&secpix); cdelt1 = -secpix / 3600.0; hgetr8 (hstring,"PIXSCAL2",&secpix); cdelt2 = secpix / 3600.0; } } } else { cdelt2 = secpix / 3600.0; cdelt1 = -cdelt2; } /* Get rotation angle from the header, if it's there */ rot = 0.0; hgetr8 (hstring,"CROTA1", &rot); if (wcs->rot == 0.) hgetr8 (hstring,"CROTA2", &rot); /* Set CD and PC matrices */ wcsdeltset (wcs, cdelt1, cdelt2, rot); /* By default, set reference pixel to center of image */ wcs->crpix[0] = 0.5 + (wcs->nxpix * 0.5); wcs->crpix[1] = 0.5 + (wcs->nypix * 0.5); /* Get reference pixel from the header, if it's there */ if (ksearch (hstring,"CRPIX1") != NULL) { hgetr8 (hstring,"CRPIX1",&wcs->crpix[0]); hgetr8 (hstring,"CRPIX2",&wcs->crpix[1]); } /* Use center of detector array as reference pixel else if (ksearch (hstring,"DETSIZE") != NULL || ksearch (hstring,"DETSEC") != NULL) { char *ic; hgets (hstring, "DETSIZE", 32, temp); ic = strchr (temp, ':'); if (ic != NULL) *ic = ' '; ic = strchr (temp, ','); if (ic != NULL) *ic = ' '; ic = strchr (temp, ':'); if (ic != NULL) *ic = ' '; ic = strchr (temp, ']'); if (ic != NULL) *ic = cnull; sscanf (temp, "%d %d %d %d", &idx1, &idx2, &idy1, &idy2); dxrefpix = 0.5 * (double) (idx1 + idx2 - 1); dyrefpix = 0.5 * (double) (idy1 + idy2 - 1); hgets (hstring, "DETSEC", 32, temp); ic = strchr (temp, ':'); if (ic != NULL) *ic = ' '; ic = strchr (temp, ','); if (ic != NULL) *ic = ' '; ic = strchr (temp, ':'); if (ic != NULL) *ic = ' '; ic = strchr (temp, ']'); if (ic != NULL) *ic = cnull; sscanf (temp, "%d %d %d %d", &ix1, &ix2, &iy1, &iy2); wcs->crpix[0] = dxrefpix - (double) (ix1 - 1); wcs->crpix[1] = dyrefpix - (double) (iy1 - 1); } */ wcs->xrefpix = wcs->crpix[0]; wcs->yrefpix = wcs->crpix[1]; wcs->crval[0] = -999.0; if (!hgetra (hstring,"RA",&wcs->crval[0])) { setwcserr ("WCSINIT: No RA with SECPIX, no WCS"); wcsfree (wcs); return (NULL); } wcs->crval[1] = -999.0; if (!hgetdec (hstring,"DEC",&wcs->crval[1])) { setwcserr ("WCSINIT No DEC with SECPIX, no WCS"); wcsfree (wcs); return (NULL); } wcs->xref = wcs->crval[0]; wcs->yref = wcs->crval[1]; wcs->coorflip = 0; wcs->cel.ref[0] = wcs->crval[0]; wcs->cel.ref[1] = wcs->crval[1]; wcs->cel.ref[2] = 999.0; if (!hgetr8 (hstring,"LONPOLE",&wcs->cel.ref[2])) hgetr8 (hstring,"LONGPOLE",&wcs->cel.ref[2]); wcs->cel.ref[3] = 999.0; hgetr8 (hstring,"LATPOLE",&wcs->cel.ref[3]); /* Epoch of image (from observation date, if possible) */ if (hgetr8 (hstring, "MJD-OBS", &mjd)) wcs->epoch = 1900.0 + (mjd - 15019.81352) / 365.242198781; else if (!hgetdate (hstring,"DATE-OBS",&wcs->epoch)) { if (!hgetdate (hstring,"DATE",&wcs->epoch)) { if (!hgetr8 (hstring,"EPOCH",&wcs->epoch)) wcs->epoch = wcs->equinox; } } /* Add time of day if not part of DATE-OBS string */ else { hgets (hstring,"DATE-OBS",32,tstring); if (!strchr (tstring,'T')) { if (hgetr8 (hstring, "UT",&ut)) wcs->epoch = wcs->epoch + (ut / (24.0 * 365.242198781)); else if (hgetr8 (hstring, "UTMID",&ut)) wcs->epoch = wcs->epoch + (ut / (24.0 * 365.242198781)); } } /* Coordinate reference frame and equinox */ (void) wcstype (wcs, "RA---TAN", "DEC--TAN"); wcs->coorflip = 0; wcseq (hstring,wcs); wcsioset (wcs); wcs->degout = 0; wcs->ndec = 3; wcs->wcson = 1; } else { setwcserr ("WCSINIT: No image scale"); wcsfree (wcs); return (NULL); } wcs->lin.crpix = wcs->crpix; wcs->lin.cdelt = wcs->cdelt; wcs->lin.pc = wcs->pc; wcs->printsys = 1; wcs->tabsys = 0; wcs->linmode = 0; /* Initialize special WCS commands */ setwcscom (wcs); return (wcs); } /******* invert_wcs *********************************************************** PROTO void invert_wcs(wcsstruct *wcs) PURPOSE Invert WCS projection mapping (using a polynomial). INPUT WCS structure. OUTPUT -. NOTES . AUTHOR E. Bertin (IAP) VERSION 06/11/2003 ***/ void invert_wcs( struct WorldCoor *wcs) { polystruct *poly; double pixin[NAXISPV],raw[NAXISPV],rawmin[NAXISPV]; double *outpos,*outpost, *lngpos,*lngpost; double *latpos,*latpost,lngstep,latstep, rawsize, epsilon; int group[] = {1,1}; /* Don't ask, this is needed by poly_init()! */ int i,j,lng,lat,deg, maxflag; char errstr[80]; double xmin; double ymin; double xmax; double ymax; double lngmin; double latmin; /* Check first that inversion is not straightforward */ lng = wcs->wcsl.lng; lat = wcs->wcsl.lat; if (wcs->naxis != NAXISPV) { return; } if (strcmp(wcs->wcsl.pcode, "TAN") != 0) { return; } if ((wcs->projppv[1+lng*MAXPV] == 0) && (wcs->projppv[1+lat*MAXPV] == 0)) { return; } if (wcs->wcs != NULL) { pix2wcs(wcs->wcs,0,0,&xmin,&ymin); pix2wcs(wcs->wcs,wcs->nxpix,wcs->nypix,&xmax,&ymax); } else { xmin = 0; ymin = 0; xmax = wcs->nxpix; ymax = wcs->nypix; } /* We define x as "longitude" and y as "latitude" projections */ /* We assume that PCxx cross-terms with additional dimensions are small */ /* Sample the whole image with a regular grid */ if (lng == 0) { lngstep = (xmax-xmin)/(WCS_NGRIDPOINTS-1.0); lngmin = xmin; latstep = (ymax-ymin)/(WCS_NGRIDPOINTS-1.0); latmin = ymin; } else { lngstep = (ymax-ymin)/(WCS_NGRIDPOINTS-1.0); lngmin = ymin; latstep = (xmax-xmin)/(WCS_NGRIDPOINTS-1.0); latmin = xmin; } outpos = (double *)calloc(2*WCS_NGRIDPOINTS2,sizeof(double)); lngpos = (double *)calloc(WCS_NGRIDPOINTS2,sizeof(double)); latpos = (double *)calloc(WCS_NGRIDPOINTS2,sizeof(double)); raw[lat] = rawmin[lat] = 0.5+latmin; raw[lng] = rawmin[lng] = 0.5+lngmin; outpost = outpos; lngpost = lngpos; latpost = latpos; for (j=WCS_NGRIDPOINTS; j--; raw[lat]+=latstep) { raw[lng] = rawmin[lng]; for (i=WCS_NGRIDPOINTS; i--; raw[lng]+=lngstep) { if (linrev(raw, &wcs->lin, pixin)) { sprintf (errstr,"*Error*: incorrect linear conversion in %s", wcs->wcsl.pcode); setwcserr (errstr); } *(lngpost++) = pixin[lng]; *(latpost++) = pixin[lat]; raw_to_pv (&wcs->prj,pixin[lng],pixin[lat], outpost, outpost+1); outpost += 2; } } /* Invert "longitude" */ /* Compute the extent of the pixel in reduced projected coordinates */ linrev(rawmin, &wcs->lin, pixin); pixin[lng] += S2D; linfwd(pixin, &wcs->lin, raw); rawsize = sqrt((raw[lng]-rawmin[lng])*(raw[lng]-rawmin[lng]) +(raw[lat]-rawmin[lat])*(raw[lat]-rawmin[lat]))*D2S; if (!rawsize) { sprintf (errstr,"*Error*: incorrect linear conversion in %s", wcs->wcsl.pcode); setwcserr (errstr); } epsilon = WCS_INVACCURACY/rawsize; /* Find the lowest degree polynom */ poly = NULL; /* to avoid gcc -Wall warnings */ maxflag = 1; for (deg=1; deg<=WCS_INVMAXDEG && maxflag; deg++) { if (deg>1) { poly_end(poly); } poly = poly_init(group, 2, °, 1); poly_fit(poly, outpos, lngpos, NULL, WCS_NGRIDPOINTS2, NULL); maxflag = 0; outpost = outpos; lngpost = lngpos; for (i=WCS_NGRIDPOINTS2; i--; outpost+=2) { if (fabs(poly_func(poly, outpost)-*(lngpost++))>epsilon) { maxflag = 1; break; } } } if (maxflag) { setwcserr ("WARNING: Significant inaccuracy likely to occur in projection"); wcs->pvfail = 1; } /* Now link the created structure */ wcs->prj.inv_x = wcs->inv_x = poly; /* Invert "latitude" */ /* Compute the extent of the pixel in reduced projected coordinates */ linrev(rawmin, &wcs->lin, pixin); pixin[lat] += S2D; linfwd(pixin, &wcs->lin, raw); rawsize = sqrt((raw[lng]-rawmin[lng])*(raw[lng]-rawmin[lng]) +(raw[lat]-rawmin[lat])*(raw[lat]-rawmin[lat]))*D2S; if (!rawsize) { sprintf (errstr,"*Error*: incorrect linear conversion in %s", wcs->wcsl.pcode); setwcserr (errstr); } epsilon = WCS_INVACCURACY/rawsize; /* Find the lowest degree polynom */ maxflag = 1; for (deg=1; deg<=WCS_INVMAXDEG && maxflag; deg++) { if (deg>1) poly_end(poly); poly = poly_init(group, 2, °, 1); poly_fit(poly, outpos, latpos, NULL, WCS_NGRIDPOINTS2, NULL); maxflag = 0; outpost = outpos; latpost = latpos; for (i=WCS_NGRIDPOINTS2; i--; outpost+=2) { if (fabs(poly_func(poly, outpost)-*(latpost++))>epsilon) { maxflag = 1; break; } } } if (maxflag) { setwcserr ("WARNING: Significant inaccuracy likely to occur in projection"); wcs->pvfail = 1; } /* Now link the created structure */ wcs->prj.inv_y = wcs->inv_y = poly; /* Free memory */ free(outpos); free(lngpos); free(latpos); return; } /* Set coordinate system of image, input, and output */ static void wcsioset (wcs) struct WorldCoor *wcs; { if (strlen (wcs->radecsys) == 0 || wcs->prjcode == WCS_LIN) strcpy (wcs->radecsys, "LINEAR"); if (wcs->prjcode == WCS_PIX) strcpy (wcs->radecsys, "PIXEL"); wcs->syswcs = wcscsys (wcs->radecsys); if (wcs->syswcs == WCS_B1950) strcpy (wcs->radecout, "FK4"); else if (wcs->syswcs == WCS_J2000) strcpy (wcs->radecout, "FK5"); else strcpy (wcs->radecout, wcs->radecsys); wcs->sysout = wcscsys (wcs->radecout); wcs->eqout = wcs->equinox; strcpy (wcs->radecin, wcs->radecsys); wcs->sysin = wcscsys (wcs->radecin); wcs->eqin = wcs->equinox; return; } static void wcseq (hstring, wcs) char *hstring; /* character string containing FITS header information in the format = [/ ] */ struct WorldCoor *wcs; /* World coordinate system data structure */ { char mchar; /* Suffix character for one of multiple WCS */ mchar = (char) 0; wcseqm (hstring, wcs, &mchar); return; } static void wcseqm (hstring, wcs, mchar) char *hstring; /* character string containing FITS header information in the format = [/ ] */ struct WorldCoor *wcs; /* World coordinate system data structure */ char *mchar; /* Suffix character for one of multiple WCS */ { int ieq = 0; int eqhead = 0; char systring[32], eqstring[32]; char radeckey[16], eqkey[16]; char tstring[32]; double ut; /* Set equinox from EQUINOX, EPOCH, or RADECSYS; default to 2000 */ systring[0] = 0; eqstring[0] = 0; if (mchar[0]) { sprintf (eqkey, "EQUINOX%c", mchar[0]); sprintf (radeckey, "RADECSYS%c", mchar[0]); } else { strcpy (eqkey, "EQUINOX"); sprintf (radeckey, "RADECSYS"); } if (!hgets (hstring, eqkey, 31, eqstring)) { if (hgets (hstring, "EQUINOX", 31, eqstring)) strcpy (eqkey, "EQUINOX"); } if (!hgets (hstring, radeckey, 31, systring)) { if (hgets (hstring, "RADECSYS", 31, systring)) sprintf (radeckey, "RADECSYS"); } if (eqstring[0] == 'J') { wcs->equinox = atof (eqstring+1); ieq = atoi (eqstring+1); strcpy (systring, "FK5"); } else if (eqstring[0] == 'B') { wcs->equinox = atof (eqstring+1); ieq = (int) atof (eqstring+1); strcpy (systring, "FK4"); } else if (hgeti4 (hstring, eqkey, &ieq)) { hgetr8 (hstring, eqkey, &wcs->equinox); eqhead = 1; } else if (hgeti4 (hstring,"EPOCH",&ieq)) { if (ieq == 0) { ieq = 1950; wcs->equinox = 1950.0; } else { hgetr8 (hstring,"EPOCH",&wcs->equinox); eqhead = 1; } } else if (systring[0] != (char)0) { if (!strncmp (systring,"FK4",3)) { wcs->equinox = 1950.0; ieq = 1950; } else if (!strncmp (systring,"ICRS",4)) { wcs->equinox = 2000.0; ieq = 2000; } else if (!strncmp (systring,"FK5",3)) { wcs->equinox = 2000.0; ieq = 2000; } else if (!strncmp (systring,"GAL",3)) { wcs->equinox = 2000.0; ieq = 2000; } else if (!strncmp (systring,"ECL",3)) { wcs->equinox = 2000.0; ieq = 2000; } } if (ieq == 0) { wcs->equinox = 2000.0; ieq = 2000; if (!strncmp (wcs->c1type, "RA",2) || !strncmp (wcs->c1type,"DEC",3)) strcpy (systring,"FK5"); } /* Epoch of image (from observation date, if possible) */ if (!hgetdate (hstring,"DATE-OBS",&wcs->epoch)) { if (!hgetdate (hstring,"DATE",&wcs->epoch)) { if (!hgetr8 (hstring,"EPOCH",&wcs->epoch)) wcs->epoch = wcs->equinox; } } /* Add time of day if not part of DATE-OBS string */ else { hgets (hstring,"DATE-OBS",32,tstring); if (!strchr (tstring,'T')) { if (hgetr8 (hstring, "UT",&ut)) wcs->epoch = wcs->epoch + (ut / (24.0 * 365.242198781)); else if (hgetr8 (hstring, "UTMID",&ut)) wcs->epoch = wcs->epoch + (ut / (24.0 * 365.242198781)); } } if (wcs->epoch == 0.0) wcs->epoch = wcs->equinox; /* Set coordinate system from keyword, if it is present */ if (systring[0] == (char) 0) hgets (hstring, radeckey, 31, systring); if (systring[0] != (char) 0) { strcpy (wcs->radecsys,systring); if (!eqhead) { if (!strncmp (wcs->radecsys,"FK4",3)) wcs->equinox = 1950.0; else if (!strncmp (wcs->radecsys,"FK5",3)) wcs->equinox = 2000.0; else if (!strncmp (wcs->radecsys,"ICRS",4)) wcs->equinox = 2000.0; else if (!strncmp (wcs->radecsys,"GAL",3) && ieq == 0) wcs->equinox = 2000.0; } } /* Otherwise set coordinate system from equinox */ /* Systemless coordinates cannot be translated using b, j, or g commands */ else if (wcs->syswcs != WCS_NPOLE) { if (ieq > 1980) strcpy (wcs->radecsys,"FK5"); else strcpy (wcs->radecsys,"FK4"); } /* Set galactic coordinates if GLON or GLAT are in C1TYPE */ if (wcs->c1type[0] == 'G') strcpy (wcs->radecsys,"GALACTIC"); else if (wcs->c1type[0] == 'E') strcpy (wcs->radecsys,"ECLIPTIC"); else if (wcs->c1type[0] == 'S') strcpy (wcs->radecsys,"SGALACTC"); else if (wcs->c1type[0] == 'H') strcpy (wcs->radecsys,"HELIOECL"); else if (wcs->c1type[0] == 'A') strcpy (wcs->radecsys,"ALTAZ"); else if (wcs->c1type[0] == 'L') strcpy (wcs->radecsys,"LINEAR"); wcs->syswcs = wcscsys (wcs->radecsys); return; } /* Jun 11 1998 Split off header-dependent WCS initialization from other subs * Jun 15 1998 Fix major bug in wcsinit() when synthesizing WCS from header * Jun 18 1998 Fix bug in CD initialization; split PC initialization off * Jun 18 1998 Split PC initialization off into subroutine wcspcset() * Jun 24 1998 Set equinox from RADECSYS only if EQUINOX and EPOCH not present * Jul 6 1998 Read third and fourth axis CTYPEs * Jul 7 1998 Initialize eqin and eqout to equinox, * Jul 9 1998 Initialize rotation matrices correctly * Jul 13 1998 Initialize rotation, scale for polynomial and DSS projections * Aug 6 1998 Fix CROTA computation for DSS projection * Sep 4 1998 Fix CROTA, CDELT computation for DSS and polynomial projections * Sep 14 1998 If DATE-OBS not found, check for DATE * Sep 14 1998 If B or J present in EQUINOX, use that info to set system * Sep 29 1998 Initialize additional WCS commands from the environment * Sep 29 1998 Fix bug which read DATE as number rather than formatted date * Dec 2 1998 Read projection constants from header (bug fix) * * Feb 9 1999 Set rotation angle correctly when using DSS projection * Feb 19 1999 Fill in CDELTs from scale keyword if absent or zero * Feb 19 1999 Add PIXSCALE as possible default arcseconds per pixel * Apr 7 1999 Add error checking for NAXIS and NAXIS1 keywords * Apr 7 1999 Do not set systring if epoch is 0 and not RA/Dec * Jul 8 1999 In RADECSYS, use FK5 and FK4 instead of J2000 and B1950 * Oct 15 1999 Free wcs using wcsfree() * Oct 20 1999 Add multiple WCS support using new subroutine names * Oct 21 1999 Delete unused variables after lint; declare dsspos() * Nov 9 1999 Add wcschar() to check WCSNAME keywords for desired WCS * Nov 9 1999 Check WCSPREx keyword to find out if chained WCS's * * Jan 6 1999 Add wcsinitn() to initialize from specific WCSNAME * Jan 24 2000 Set CD matrix from header even if using polynomial * Jan 27 2000 Fix MJD to epoch conversion for when MJD-OBS is the only date * Jan 28 2000 Set CD matrix for DSS projection, too * Jan 28 2000 Use wcsproj instead of oldwcs * Dec 18 2000 Fix error in hgets() call in wcschar() * Dec 29 2000 Compute inverse CD matrix even if polynomial solution * Dec 29 2000 Add PROJR0 keyword for WCSLIB projections * Dec 29 2000 Use CDi_j matrix if any elements are present * * Jan 31 2001 Fix to allow 1D WCS * Jan 31 2001 Treat single character WCS name as WCS character * Feb 20 2001 Implement WCSDEPx nested WCS's * Feb 23 2001 Initialize all 4 terms of CD matrix * Feb 28 2001 Fix bug which read CRPIX1 into CRPIX2 * Mar 20 2001 Compare mchar to (char)0, not null * Mar 21 2001 Move ic declaration into commented out code * Jul 12 2001 Read PROJPn constants into proj.p array instead of PVn * Sep 7 2001 Set system to galactic or ecliptic based on CTYPE, not RADECSYS * Oct 11 2001 Set ctype[0] as well as ctype[1] to TAN for TNX projections * Oct 19 2001 WCSDIM keyword overrides zero value of NAXIS * * Feb 19 2002 Add XPIXSIZE/YPIXSIZE (KPNO) as default image scale keywords * Mar 12 2002 Add LONPOLE as well as LONGPOLE for WCSLIB 2.8 * Apr 3 2002 Implement hget8c() and hgetsc() to simplify code * Apr 3 2002 Add PVj_n projection constants in addition to PROJPn * Apr 19 2002 Increase numeric keyword value length from 16 to 31 * Apr 19 2002 Fix bug which didn't set radecsys keyword name * Apr 24 2002 If no WCS present for specified letter, return null * Apr 26 2002 Implement WCSAXESa keyword as first choice for number of axes * Apr 26 2002 Add wcschar and wcsname to WCS structure * May 9 2002 Add radvel and zvel to WCS structure * May 13 2002 Free everything which is allocated * May 28 2002 Read 10 prj.p instead of maximum of 100 * May 31 2002 Fix bugs with PV reading * May 31 2002 Initialize syswcs, sysin, sysout in wcsioset() * Sep 25 2002 Fix subroutine calls for radvel and latpole * Dec 6 2002 Correctly compute pixel at center of image for default CRPIX * * Jan 2 2002 Do not reinitialize projection vector for PV input * Jan 3 2002 For ZPN, read PVi_0 to PVi_9, not PVi_1 to PVi_10 * Mar 27 2003 Clean up default center computation * Apr 3 2003 Add input for SIRTF distortion coefficients * May 8 2003 Change PROJP reading to start with 0 instead of 1 * May 22 2003 Add ZPX approximation, reading projpn from WATi * May 28 2003 Avoid reinitializing coefficients set by PROJP * Jun 26 2003 Initialize xref and yref to -999.0 * Sep 23 2003 Change mgets() to mgetstr() to avoid name collision at UCO Lick * Oct 1 2003 Rename wcs->naxes to wcs->naxis to match WCSLIB 3.2 * Nov 3 2003 Initialize distortion coefficients in distortinit() in distort.c * Dec 1 2003 Change p[0,1,2] initializations to p[1,2,3] * Dec 3 2003 Add back wcs->naxes for backward compatibility * Dec 3 2003 Remove unused variables j,m in wcsinitc() * Dec 12 2003 Fix call to setwcserr() with format in it * * Feb 26 2004 Add parameters for ZPX projection * * Jun 22 2005 Drop declaration of variable wcserrmsg which is not used * Nov 9 2005 Use CROTA1 if CTYPE1 is LAT/DEC, CROTA2 if CTYPE2 is LAT/DEC * * Mar 9 2006 Get Epoch of observation from MJD-OBS or DATE-OBS/UT unless DSS * Apr 24 2006 Initialize rotation matrices * Apr 25 2006 Ignore axes with dimension of one * May 19 2006 Initialize all of 9x9 PC matrix; read in loops * Aug 21 2006 Limit naxes to 2 everywhere; RA and DEC should always be 1st * Oct 6 2006 If units are pixels, projection type is PIXEL * Oct 30 2006 Initialize cube face to -1, not a cube projection * * Jan 4 2007 Drop declarations of wcsinitc() and wcsinitn() already in wcs.h * Jan 8 2007 Change WCS letter from char to char* * Feb 1 2007 Read IRAF log wavelength flag DC-FLAG to wcs.logwcs * Feb 15 2007 Check for wcs->wcsproj > 0 instead of CTYPEi != LINEAR or PIXEL * Mar 13 2007 Try for RA, DEC, SECPIX if WCS character is space or null * Apr 27 2007 Ignore axes with TAB WCS for now * Oct 17 2007 Fix bug testing &mchar instead of mchar in if statement * * May 9 2008 Initialize TNX projection when projection types first set * Jun 27 2008 If NAXIS1 and NAXIS2 not present, check for IMAGEW and IMAGEH * * Mar 24 2009 Fix dimension bug if NAXISi not present (fix from John Burns) * * Mar 11 2011 Add NOAO ZPX projection (Frank Valdes) * Mar 18 2011 Add invert_wcs() by Emmanuel Bertin for SCAMP * Mar 18 2011 Change Bertin's ARCSEC/DEG to S2D and DEG/ARCSEC to D2S * Sep 1 2011 Add TPV as TAN with SCAMP PVs * * Oct 19 2012 Drop unused variable iszpx; fix bug in latmin assignment * * Feb 1 2013 Externalize uppercase() * Feb 07 2013 Avoid SWARP distortion if SIRTF distortion is present * Jul 25 2013 Initialize n=0 when checking for SCAMP distortion terms (fix from Martin Kuemmel) * * Jun 24 2016 wcs->ptype contains only 3-letter projection code */ wcstools-3.9.5/libwcs/wcslib.c0000664000016200001660000012632012732575413015402 0ustar minkoirsys/*============================================================================= * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-2002, Mark Calabretta * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Correspondence concerning WCSLIB may be directed to: * Internet email: mcalabre@atnf.csiro.au * Postal address: Dr. Mark Calabretta, * Australia Telescope National Facility, * P.O. Box 76, * Epping, NSW, 2121, * AUSTRALIA * *============================================================================= * * C routines which implement the FITS World Coordinate System (WCS) * convention. * * Summary of routines * ------------------- * wcsfwd() and wcsrev() are high level driver routines for the WCS linear * transformation, spherical coordinate transformation, and spherical * projection routines. * * Given either the celestial longitude or latitude plus an element of the * pixel coordinate a hybrid routine, wcsmix(), iteratively solves for the * unknown elements. * * An initialization routine, wcsset(), computes indices from the ctype * array but need not be called explicitly - see the explanation of * wcs.flag below. * * * Initialization routine; wcsset() * -------------------------------- * Initializes elements of a wcsprm data structure which holds indices into * the coordinate arrays. Note that this routine need not be called directly; * it will be invoked by wcsfwd() and wcsrev() if the "flag" structure member * is anything other than a predefined magic value. * * Given: * naxis const int * Number of image axes. * ctype[][16] * const char * Coordinate axis types corresponding to the FITS * CTYPEn header cards. * * Returned: * wcs wcsprm* Indices for the celestial coordinates obtained * by parsing the ctype[] array (see below). * * Function return value: * int Error status * 0: Success. * 1: Inconsistent or unrecognized coordinate axis * types. * * * Forward transformation; wcsfwd() * -------------------------------- * Compute the pixel coordinate for given world coordinates. * * Given: * ctype[][16] * const char * Coordinate axis types corresponding to the FITS * CTYPEn header cards. * * Given or returned: * wcs wcsprm* Indices for the celestial coordinates obtained * by parsing the ctype[] array (see below). * * Given: * world const double[] * World coordinates. world[wcs->lng] and * world[wcs->lat] are the celestial longitude and * latitude, in degrees. * * Given: * crval const double[] * Coordinate reference values corresponding to the FITS * CRVALn header cards (see note 2). * * Given and returned: * cel celprm* Spherical coordinate transformation parameters (usage * is described in the prologue to "cel.c"). * * Returned: * phi, double* Longitude and latitude in the native coordinate * theta system of the projection, in degrees. * * Given and returned: * prj prjprm* Projection parameters (usage is described in the * prologue to "proj.c"). * * Returned: * imgcrd double[] Image coordinate. imgcrd[wcs->lng] and * imgcrd[wcs->lat] are the projected x-, and * y-coordinates, in "degrees". For quadcube * projections with a CUBEFACE axis the face number is * also returned in imgcrd[wcs->cubeface]. * * Given and returned: * lin linprm* Linear transformation parameters (usage is described * in the prologue to "lin.c"). * * Returned: * pixcrd double[] Pixel coordinate. * * Function return value: * int Error status * 0: Success. * 1: Invalid coordinate transformation parameters. * 2: Invalid projection parameters. * 3: Invalid world coordinate. * 4: Invalid linear transformation parameters. * * * Reverse transformation; wcsrev() * -------------------------------- * Compute world coordinates for a given pixel coordinate. * * Given: * ctype[][16] * const char * Coordinate axis types corresponding to the FITS * CTYPEn header cards. * * Given or returned: * wcs wcsprm* Indices for the celestial coordinates obtained * by parsing the ctype[] array (see below). * * Given: * pixcrd const double[] * Pixel coordinate. * * Given and returned: * lin linprm* Linear transformation parameters (usage is described * in the prologue to "lin.c"). * * Returned: * imgcrd double[] Image coordinate. imgcrd[wcs->lng] and * imgcrd[wcs->lat] are the projected x-, and * y-coordinates, in "degrees". * * Given and returned: * prj prjprm* Projection parameters (usage is described in the * prologue to "proj.c"). * * Returned: * phi, double* Longitude and latitude in the native coordinate * theta system of the projection, in degrees. * * Given: * crval const double[] * Coordinate reference values corresponding to the FITS * CRVALn header cards (see note 2). * * Given and returned: * cel celprm* Spherical coordinate transformation parameters * (usage is described in the prologue to "cel.c"). * * Returned: * world double[] World coordinates. world[wcs->lng] and * world[wcs->lat] are the celestial longitude and * latitude, in degrees. * * Function return value: * int Error status * 0: Success. * 1: Invalid coordinate transformation parameters. * 2: Invalid projection parameters. * 3: Invalid pixel coordinate. * 4: Invalid linear transformation parameters. * * * Hybrid transformation; wcsmix() * ------------------------------- * Given either the celestial longitude or latitude plus an element of the * pixel coordinate solve for the remaining elements by iterating on the * unknown celestial coordinate element using wcsfwd(). * * Given: * ctype[][16] * const char * Coordinate axis types corresponding to the FITS * CTYPEn header cards. * * Given or returned: * wcs wcsprm* Indices for the celestial coordinates obtained * by parsing the ctype[] array (see below). * * Given: * mixpix const int * Which element of the pixel coordinate is given. * mixcel const int * Which element of the celestial coordinate is * given: * 1: Celestial longitude is given in * world[wcs->lng], latitude returned in * world[wcs->lat]. * 2: Celestial latitude is given in * world[wcs->lat], longitude returned in * world[wcs->lng]. * vspan[2] const double * Solution interval for the celestial coordinate, in * degrees. The ordering of the two limits is * irrelevant. Longitude ranges may be specified with * any convenient normalization, for example [-120,+120] * is the same as [240,480], except that the solution * will be returned with the same normalization, i.e. * lie within the interval specified. * vstep const double * Step size for solution search, in degrees. If zero, * a sensible, although perhaps non-optimal default will * be used. * viter int * If a solution is not found then the step size will be * halved and the search recommenced. viter controls * how many times the step size is halved. The allowed * range is 5 - 10. * * Given and returned: * world double[] World coordinates. world[wcs->lng] and * world[wcs->lat] are the celestial longitude and * latitude, in degrees. Which is given and which * returned depends on the value of mixcel. All other * elements are given. * * Given: * crval const double[] * Coordinate reference values corresponding to the FITS * CRVALn header cards (see note 2). * * Given and returned: * cel celprm* Spherical coordinate transformation parameters * (usage is described in the prologue to "cel.c"). * * Returned: * phi, double* Longitude and latitude in the native coordinate * theta system of the projection, in degrees. * * Given and returned: * prj prjprm* Projection parameters (usage is described in the * prologue to "proj.c"). * * Returned: * imgcrd double[] Image coordinate. imgcrd[wcs->lng] and * imgcrd[wcs->lat] are the projected x-, and * y-coordinates, in "degrees". * * Given and returned: * lin linprm* Linear transformation parameters (usage is described * in the prologue to "lin.c"). * * Given and returned: * pixcrd double[] Pixel coordinate. The element indicated by mixpix is * given and the remaining elements are returned. * * Function return value: * int Error status * 0: Success. * 1: Invalid coordinate transformation parameters. * 2: Invalid projection parameters. * 3: Coordinate transformation error. * 4: Invalid linear transformation parameters. * 5: No solution found in the specified interval. * * * Notes * ----- * 1) The CTYPEn must in be upper case and there must be 0 or 1 pair of * matched celestial axis types. The ctype[][16] should be padded with * blanks on the right and null-terminated. * * 2) Elements of the crval[] array which correspond to celestial axes are * ignored, the reference coordinate values in cel->ref[0] and * cel->ref[1] are the ones used. * * 3) These functions recognize the NCP projection and convert it to the * equivalent SIN projection. * * They also recognize GLS as a synonym for SFL. * * 4) The quadcube projections (TSC, CSC, QSC) may be represented in FITS in * either of two ways: * * a) The six faces may be laid out in one plane and numbered as * follows: * * 0 * * 4 3 2 1 4 3 2 * * 5 * * Faces 2, 3 and 4 may appear on one side or the other (or both). * The forward routines map faces 2, 3 and 4 to the left but the * inverse routines accept them on either side. * * b) The "COBE" convention in which the six faces are stored in a * three-dimensional structure using a "CUBEFACE" axis indexed from * 0 to 5 as above. * * These routines support both methods; wcsset() determines which is * being used by the presence or absence of a CUBEFACE axis in ctype[]. * wcsfwd() and wcsrev() translate the CUBEFACE axis representation to * the single plane representation understood by the lower-level WCSLIB * projection routines. * * * WCS indexing parameters * ----------------------- * The wcsprm struct consists of the following: * * int flag * The wcsprm struct contains indexes and other information derived * from the CTYPEn. Whenever any of the ctype[] are set or changed * this flag must be set to zero to signal the initialization routine, * wcsset() to redetermine the indices. The flag is set to 999 if * there is no celestial axis pair in the CTYPEn. * * char pcode[4] * The WCS projection code. * * char lngtyp[5], lattyp[5] * WCS celestial axis types. * * int lng,lat * Indices into the imgcrd[], and world[] arrays as described above. * These may also serve as indices for the celestial longitude and * latitude axes in the pixcrd[] array provided that the PC matrix * does not transpose axes. * * int cubeface * Index into the pixcrd[] array for the CUBEFACE axis. This is * optionally used for the quadcube projections where each cube face is * stored on a separate axis. * * * wcsmix() algorithm * ------------------ * Initially the specified solution interval is checked to see if it's a * "crossing" interval. If it isn't, a search is made for a crossing * solution by iterating on the unknown celestial coordinate starting at * the upper limit of the solution interval and decrementing by the * specified step size. A crossing is indicated if the trial value of the * pixel coordinate steps through the value specified. If a crossing * interval is found then the solution is determined by a modified form of * "regula falsi" division of the crossing interval. If no crossing * interval was found within the specified solution interval then a search * is made for a "non-crossing" solution as may arise from a point of * tangency. The process is complicated by having to make allowance for * the discontinuities that occur in all map projections. * * Once one solution has been determined others may be found by subsequent * invokations of wcsmix() with suitably restricted solution intervals. * * Note the circumstance which arises when the solution point lies at a * native pole of a projection in which the pole is represented as a * finite curve, for example the zenithals and conics. In such cases two * or more valid solutions may exist but WCSMIX only ever returns one. * * Because of its generality wcsmix() is very compute-intensive. For * compute-limited applications more efficient special-case solvers could * be written for simple projections, for example non-oblique cylindrical * projections. * * Author: Mark Calabretta, Australia Telescope National Facility * $Id: wcs.c,v 2.23 2002/04/03 01:25:29 mcalabre Exp $ *===========================================================================*/ #include #include #include #include #include "wcslib.h" /* Map error number to error message for each function. */ const char *wcsset_errmsg[] = { 0, "Inconsistent or unrecognized coordinate axis types"}; const char *wcsfwd_errmsg[] = { 0, "Invalid coordinate transformation parameters", "Invalid projection parameters", "Invalid world coordinate", "Invalid linear transformation parameters"}; const char *wcsrev_errmsg[] = { 0, "Invalid coordinate transformation parameters", "Invalid projection parameters", "Invalid pixel coordinate", "Invalid linear transformation parameters"}; const char *wcsmix_errmsg[] = { 0, "Invalid coordinate transformation parameters", "Invalid projection parameters", "Coordinate transformation error", "Invalid linear transformation parameters", "No solution found in the specified interval"}; #define signb(X) ((X) < 0.0 ? 1 : 0) int wcsset (naxis, ctype, wcs) const int naxis; const char ctype[][16]; struct wcsprm *wcs; { int nalias = 2; char aliases [2][4] = {"NCP", "GLS"}; int j, k; int *ndx = NULL; char requir[16]; strcpy(wcs->pcode, ""); strcpy(requir, ""); wcs->lng = -1; wcs->lat = -1; wcs->cubeface = -1; for (j = 0; j < naxis; j++) { if (ctype[j][4] != '-') { if (strcmp(ctype[j], "CUBEFACE") == 0) { if (wcs->cubeface == -1) { wcs->cubeface = j; } else { /* Multiple CUBEFACE axes! */ return 1; } } continue; } /* Got an axis qualifier, is it a recognized WCS projection? */ for (k = 0; k < npcode; k++) { if (strncmp(&ctype[j][5], pcodes[k], 3) == 0) break; } if (k == npcode) { /* Maybe it's a projection alias. */ for (k = 0; k < nalias; k++) { if (strncmp(&ctype[j][5], aliases[k], 3) == 0) break; } /* Not recognized. */ if (k == nalias) { continue; } } /* Parse the celestial axis type. */ if (strcmp(wcs->pcode, "") == 0) { sprintf(wcs->pcode, "%.3s", &ctype[j][5]); if (strncmp(ctype[j], "RA--", 4) == 0) { wcs->lng = j; strcpy(wcs->lngtyp, "RA"); strcpy(wcs->lattyp, "DEC"); ndx = &wcs->lat; sprintf(requir, "DEC--%s", wcs->pcode); } else if (strncmp(ctype[j], "DEC-", 4) == 0) { wcs->lat = j; strcpy(wcs->lngtyp, "RA"); strcpy(wcs->lattyp, "DEC"); ndx = &wcs->lng; sprintf(requir, "RA---%s", wcs->pcode); } else if (strncmp(&ctype[j][1], "LON", 3) == 0) { wcs->lng = j; sprintf(wcs->lngtyp, "%cLON", ctype[j][0]); sprintf(wcs->lattyp, "%cLAT", ctype[j][0]); ndx = &wcs->lat; sprintf(requir, "%s-%s", wcs->lattyp, wcs->pcode); } else if (strncmp(&ctype[j][1], "LAT", 3) == 0) { wcs->lat = j; sprintf(wcs->lngtyp, "%cLON", ctype[j][0]); sprintf(wcs->lattyp, "%cLAT", ctype[j][0]); ndx = &wcs->lng; sprintf(requir, "%s-%s", wcs->lngtyp, wcs->pcode); } else if (strncmp(&ctype[j][2], "LN", 2) == 0) { wcs->lng = j; sprintf(wcs->lngtyp, "%c%cLN", ctype[j][0], ctype[j][1]); sprintf(wcs->lattyp, "%c%cLT", ctype[j][0], ctype[j][1]); ndx = &wcs->lat; sprintf(requir, "%s-%s", wcs->lattyp, wcs->pcode); } else if (strncmp(&ctype[j][2], "LT", 2) == 0) { wcs->lat = j; sprintf(wcs->lngtyp, "%c%cLN", ctype[j][0], ctype[j][1]); sprintf(wcs->lattyp, "%c%cLT", ctype[j][0], ctype[j][1]); ndx = &wcs->lng; sprintf(requir, "%s-%s", wcs->lngtyp, wcs->pcode); } else { /* Unrecognized celestial type. */ return 1; } } else { if (strncmp(ctype[j], requir, 8) != 0) { /* Inconsistent projection types. */ return 1; } if (ndx == NULL) return 1; *ndx = j; strcpy(requir, ""); } } if (strcmp(requir, "")) { /* Unmatched celestial axis. */ return 1; } /* Do simple alias translations. */ if (strncmp(wcs->pcode, "GLS", 3) == 0) { strcpy(wcs->pcode, "SFL"); } if (strcmp(wcs->pcode, "")) { wcs->flag = WCSSET; } else { /* Signal for no celestial axis pair. */ wcs->flag = 999; } return 0; } /*--------------------------------------------------------------------------*/ int wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd) const char ctype[][16]; struct wcsprm* wcs; const double world[]; const double crval[]; struct celprm *cel; double *phi, *theta; struct prjprm *prj; double imgcrd[]; struct linprm *lin; double pixcrd[]; { int err, j; double offset; /* Initialize if required. */ if (wcs->flag != WCSSET) { if (wcsset(lin->naxis, ctype, wcs)) return 1; } /* Convert to relative physical coordinates. */ for (j = 0; j < lin->naxis; j++) { if (j == wcs->lng) continue; if (j == wcs->lat) continue; imgcrd[j] = world[j] - crval[j]; } if (wcs->flag != 999) { /* Compute projected coordinates. */ if (strcmp(wcs->pcode, "NCP") == 0) { /* Convert NCP to SIN. */ if (cel->ref[1] == 0.0) { return 2; } strcpy(wcs->pcode, "SIN"); prj->p[1] = 0.0; prj->p[2] = cosdeg (cel->ref[1])/sindeg (cel->ref[1]); prj->flag = (prj->flag < 0) ? -1 : 0; } if ((err = celfwd(wcs->pcode, world[wcs->lng], world[wcs->lat], cel, phi, theta, prj, &imgcrd[wcs->lng], &imgcrd[wcs->lat]))) { return err; } /* Do we have a CUBEFACE axis? */ if (wcs->cubeface != -1) { /* Separation between faces. */ if (prj->r0 == 0.0) { offset = 90.0; } else { offset = prj->r0*PI/2.0; } /* Stack faces in a cube. */ if (imgcrd[wcs->lat] < -0.5*offset) { imgcrd[wcs->lat] += offset; imgcrd[wcs->cubeface] = 5.0; } else if (imgcrd[wcs->lat] > 0.5*offset) { imgcrd[wcs->lat] -= offset; imgcrd[wcs->cubeface] = 0.0; } else if (imgcrd[wcs->lng] > 2.5*offset) { imgcrd[wcs->lng] -= 3.0*offset; imgcrd[wcs->cubeface] = 4.0; } else if (imgcrd[wcs->lng] > 1.5*offset) { imgcrd[wcs->lng] -= 2.0*offset; imgcrd[wcs->cubeface] = 3.0; } else if (imgcrd[wcs->lng] > 0.5*offset) { imgcrd[wcs->lng] -= offset; imgcrd[wcs->cubeface] = 2.0; } else { imgcrd[wcs->cubeface] = 1.0; } } } /* Apply forward linear transformation. */ if (linfwd(imgcrd, lin, pixcrd)) { return 4; } return 0; } /*--------------------------------------------------------------------------*/ int wcsrev(ctype, wcs, pixcrd, lin, imgcrd, prj, phi, theta, crval, cel, world) const char ctype[][16]; struct wcsprm *wcs; const double pixcrd[]; struct linprm *lin; double imgcrd[]; struct prjprm *prj; double *phi, *theta; const double crval[]; struct celprm *cel; double world[]; { int err, face, j; double offset; /* Initialize if required. */ if (wcs->flag != WCSSET) { if (wcsset(lin->naxis, ctype, wcs)) return 1; } /* Apply reverse linear transformation. */ if (linrev(pixcrd, lin, imgcrd)) { return 4; } /* Convert to world coordinates. */ for (j = 0; j < lin->naxis; j++) { if (j == wcs->lng) continue; if (j == wcs->lat) continue; world[j] = imgcrd[j] + crval[j]; } if (wcs->flag != 999) { /* Do we have a CUBEFACE axis? */ if (wcs->cubeface != -1) { face = (int)(imgcrd[wcs->cubeface] + 0.5); if (fabs(imgcrd[wcs->cubeface]-face) > 1e-10) { return 3; } /* Separation between faces. */ if (prj->r0 == 0.0) { offset = 90.0; } else { offset = prj->r0*PI/2.0; } /* Lay out faces in a plane. */ switch (face) { case 0: imgcrd[wcs->lat] += offset; break; case 1: break; case 2: imgcrd[wcs->lng] += offset; break; case 3: imgcrd[wcs->lng] += offset*2; break; case 4: imgcrd[wcs->lng] += offset*3; break; case 5: imgcrd[wcs->lat] -= offset; break; default: return 3; } } /* Compute celestial coordinates. */ if (strcmp(wcs->pcode, "NCP") == 0) { /* Convert NCP to SIN. */ if (cel->ref[1] == 0.0) { return 2; } strcpy(wcs->pcode, "SIN"); prj->p[1] = 0.0; prj->p[2] = cosdeg (cel->ref[1])/sindeg (cel->ref[1]); prj->flag = (prj->flag < 0) ? -1 : 0; } if ((err = celrev(wcs->pcode, imgcrd[wcs->lng], imgcrd[wcs->lat], prj, phi, theta, cel, &world[wcs->lng], &world[wcs->lat]))) { return err; } } return 0; } /*--------------------------------------------------------------------------*/ int wcsmix(ctype, wcs, mixpix, mixcel, vspan, vstep, viter, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd) const char ctype[][16]; struct wcsprm *wcs; const int mixpix, mixcel; const double vspan[2], vstep; int viter; double world[]; const double crval[]; struct celprm *cel; double *phi, *theta; struct prjprm *prj; double imgcrd[]; struct linprm *lin; double pixcrd[]; { const int niter = 60; int crossed, err, istep, iter, j, k, nstep, retry; const double tol = 1.0e-10; const double tol2 = 100.0*tol; double lambda, span[2], step; double pixmix; double dlng, lng, lng0, lng0m, lng1, lng1m; double dlat, lat, lat0, lat0m, lat1, lat1m; double d, d0, d0m, d1, d1m; double dx = 0.0; double dabs, dmin, lmin; double dphi, phi0, phi1; struct celprm cel0; /* Initialize if required. */ if (wcs->flag != WCSSET) { if (wcsset(lin->naxis, ctype, wcs)) return 1; } /* Check vspan. */ if (vspan[0] <= vspan[1]) { span[0] = vspan[0]; span[1] = vspan[1]; } else { /* Swap them. */ span[0] = vspan[1]; span[1] = vspan[0]; } /* Check vstep. */ step = fabs(vstep); if (step == 0.0) { step = (span[1] - span[0])/10.0; if (step > 1.0 || step == 0.0) step = 1.0; } /* Check viter. */ nstep = viter; if (nstep < 5) { nstep = 5; } else if (nstep > 10) { nstep = 10; } /* Given pixel element. */ pixmix = pixcrd[mixpix]; /* Iterate on the step size. */ for (istep = 0; istep <= nstep; istep++) { if (istep) step /= 2.0; /* Iterate on the sky coordinate between the specified range. */ if (mixcel == 1) { /* Celestial longitude is given. */ /* Check whether the solution interval is a crossing interval. */ lat0 = span[0]; world[wcs->lat] = lat0; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d0 = pixcrd[mixpix] - pixmix; dabs = fabs(d0); if (dabs < tol) return 0; lat1 = span[1]; world[wcs->lat] = lat1; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d1 = pixcrd[mixpix] - pixmix; dabs = fabs(d1); if (dabs < tol) return 0; lmin = lat1; dmin = dabs; /* Check for a crossing point. */ if (signb(d0) != signb(d1)) { crossed = 1; dx = d1; } else { crossed = 0; lat0 = span[1]; } for (retry = 0; retry < 4; retry++) { /* Refine the solution interval. */ while (lat0 > span[0]) { lat0 -= step; if (lat0 < span[0]) lat0 = span[0]; world[wcs->lat] = lat0; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d0 = pixcrd[mixpix] - pixmix; /* Check for a solution. */ dabs = fabs(d0); if (dabs < tol) return 0; /* Record the point of closest approach. */ if (dabs < dmin) { lmin = lat0; dmin = dabs; } /* Check for a crossing point. */ if (signb(d0) != signb(d1)) { crossed = 2; dx = d0; break; } /* Advance to the next subinterval. */ lat1 = lat0; d1 = d0; } if (crossed) { /* A crossing point was found. */ for (iter = 0; iter < niter; iter++) { /* Use regula falsi division of the interval. */ lambda = d0/(d0-d1); if (lambda < 0.1) { lambda = 0.1; } else if (lambda > 0.9) { lambda = 0.9; } dlat = lat1 - lat0; lat = lat0 + lambda*dlat; world[wcs->lat] = lat; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } /* Check for a solution. */ d = pixcrd[mixpix] - pixmix; dabs = fabs(d); if (dabs < tol) return 0; if (dlat < tol) { /* An artifact of numerical imprecision. */ if (dabs < tol2) return 0; /* Must be a discontinuity. */ break; } /* Record the point of closest approach. */ if (dabs < dmin) { lmin = lat; dmin = dabs; } if (signb(d0) == signb(d)) { lat0 = lat; d0 = d; } else { lat1 = lat; d1 = d; } } /* No convergence, must have been a discontinuity. */ if (crossed == 1) lat0 = span[1]; lat1 = lat0; d1 = dx; crossed = 0; } else { /* No crossing point; look for a tangent point. */ if (lmin == span[0]) break; if (lmin == span[1]) break; lat = lmin; lat0 = lat - step; if (lat0 < span[0]) lat0 = span[0]; lat1 = lat + step; if (lat1 > span[1]) lat1 = span[1]; world[wcs->lat] = lat0; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d0 = fabs(pixcrd[mixpix] - pixmix); d = dmin; world[wcs->lat] = lat1; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d1 = fabs(pixcrd[mixpix] - pixmix); for (iter = 0; iter < niter; iter++) { lat0m = (lat0 + lat)/2.0; world[wcs->lat] = lat0m; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d0m = fabs(pixcrd[mixpix] - pixmix); if (d0m < tol) return 0; lat1m = (lat1 + lat)/2.0; world[wcs->lat] = lat1m; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d1m = fabs(pixcrd[mixpix] - pixmix); if (d1m < tol) return 0; if (d0m < d && d0m <= d1m) { lat1 = lat; d1 = d; lat = lat0m; d = d0m; } else if (d1m < d) { lat0 = lat; d0 = d; lat = lat1m; d = d1m; } else { lat0 = lat0m; d0 = d0m; lat1 = lat1m; d1 = d1m; } } } } } else { /* Celestial latitude is given. */ /* Check whether the solution interval is a crossing interval. */ lng0 = span[0]; world[wcs->lng] = lng0; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d0 = pixcrd[mixpix] - pixmix; dabs = fabs(d0); if (dabs < tol) return 0; lng1 = span[1]; world[wcs->lng] = lng1; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d1 = pixcrd[mixpix] - pixmix; dabs = fabs(d1); if (dabs < tol) return 0; lmin = lng1; dmin = dabs; /* Check for a crossing point. */ if (signb(d0) != signb(d1)) { crossed = 1; dx = d1; } else { crossed = 0; lng0 = span[1]; } for (retry = 0; retry < 4; retry++) { /* Refine the solution interval. */ while (lng0 > span[0]) { lng0 -= step; if (lng0 < span[0]) lng0 = span[0]; world[wcs->lng] = lng0; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d0 = pixcrd[mixpix] - pixmix; /* Check for a solution. */ dabs = fabs(d0); if (dabs < tol) return 0; /* Record the point of closest approach. */ if (dabs < dmin) { lmin = lng0; dmin = dabs; } /* Check for a crossing point. */ if (signb(d0) != signb(d1)) { crossed = 2; dx = d0; break; } /* Advance to the next subinterval. */ lng1 = lng0; d1 = d0; } if (crossed) { /* A crossing point was found. */ for (iter = 0; iter < niter; iter++) { /* Use regula falsi division of the interval. */ lambda = d0/(d0-d1); if (lambda < 0.1) { lambda = 0.1; } else if (lambda > 0.9) { lambda = 0.9; } dlng = lng1 - lng0; lng = lng0 + lambda*dlng; world[wcs->lng] = lng; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } /* Check for a solution. */ d = pixcrd[mixpix] - pixmix; dabs = fabs(d); if (dabs < tol) return 0; if (dlng < tol) { /* An artifact of numerical imprecision. */ if (dabs < tol2) return 0; /* Must be a discontinuity. */ break; } /* Record the point of closest approach. */ if (dabs < dmin) { lmin = lng; dmin = dabs; } if (signb(d0) == signb(d)) { lng0 = lng; d0 = d; } else { lng1 = lng; d1 = d; } } /* No convergence, must have been a discontinuity. */ if (crossed == 1) lng0 = span[1]; lng1 = lng0; d1 = dx; crossed = 0; } else { /* No crossing point; look for a tangent point. */ if (lmin == span[0]) break; if (lmin == span[1]) break; lng = lmin; lng0 = lng - step; if (lng0 < span[0]) lng0 = span[0]; lng1 = lng + step; if (lng1 > span[1]) lng1 = span[1]; world[wcs->lng] = lng0; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d0 = fabs(pixcrd[mixpix] - pixmix); d = dmin; world[wcs->lng] = lng1; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d1 = fabs(pixcrd[mixpix] - pixmix); for (iter = 0; iter < niter; iter++) { lng0m = (lng0 + lng)/2.0; world[wcs->lng] = lng0m; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d0m = fabs(pixcrd[mixpix] - pixmix); if (d0m < tol) return 0; lng1m = (lng1 + lng)/2.0; world[wcs->lng] = lng1m; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d1m = fabs(pixcrd[mixpix] - pixmix); if (d1m < tol) return 0; if (d0m < d && d0m <= d1m) { lng1 = lng; d1 = d; lng = lng0m; d = d0m; } else if (d1m < d) { lng0 = lng; d0 = d; lng = lng1m; d = d1m; } else { lng0 = lng0m; d0 = d0m; lng1 = lng1m; d1 = d1m; } } } } } } /* Set cel0 to the unity transformation. */ cel0.flag = CELSET; cel0.ref[0] = cel->ref[0]; cel0.ref[1] = cel->ref[1]; cel0.ref[2] = cel->ref[2]; cel0.ref[3] = cel->ref[3]; cel0.euler[0] = -90.0; cel0.euler[1] = 0.0; cel0.euler[2] = 90.0; cel0.euler[3] = 1.0; cel0.euler[4] = 0.0; /* No convergence, check for aberrant behaviour at a native pole. */ *theta = -90.0; for (j = 1; j <= 2; j++) { /* Could the celestial coordinate element map to a native pole? */ *theta = -*theta; err = sphrev(0.0, *theta, cel->euler, &lng, &lat); if (mixcel == 1) { if (fabs(fmod(world[wcs->lng]-lng,360.0)) > tol) continue; if (lat < span[0]) continue; if (lat > span[1]) continue; world[wcs->lat] = lat; } else { if (fabs(world[wcs->lat]-lat) > tol) continue; if (lng < span[0]) lng += 360.0; if (lng > span[1]) lng -= 360.0; if (lng < span[0]) continue; if (lng > span[1]) continue; world[wcs->lng] = lng; } /* Is there a solution for the given pixel coordinate element? */ lng = world[wcs->lng]; lat = world[wcs->lat]; /* Feed native coordinates to wcsfwd() with cel0 set to unity. */ world[wcs->lng] = -180.0; world[wcs->lat] = *theta; if ((err = wcsfwd(ctype, wcs, world, crval, &cel0, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d0 = pixcrd[mixpix] - pixmix; /* Check for a solution. */ if (fabs(d0) < tol) { /* Recall saved world coordinates. */ world[wcs->lng] = lng; world[wcs->lat] = lat; return 0; } /* Search for a crossing interval. */ phi0 = -180.0; for (k = -179; k <= 180; k++) { phi1 = (double) k; world[wcs->lng] = phi1; if ((err = wcsfwd(ctype, wcs, world, crval, &cel0, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d1 = pixcrd[mixpix] - pixmix; /* Check for a solution. */ dabs = fabs(d1); if (dabs < tol) { /* Recall saved world coordinates. */ world[wcs->lng] = lng; world[wcs->lat] = lat; return 0; } /* Is it a crossing interval? */ if (signb(d0) != signb(d1)) break; phi0 = phi1; d0 = d1; } for (iter = 1; iter <= niter; iter++) { /* Use regula falsi division of the interval. */ lambda = d0/(d0-d1); if (lambda < 0.1) { lambda = 0.1; } else if (lambda > 0.9) { lambda = 0.9; } dphi = phi1 - phi0; world[wcs->lng] = phi0 + lambda*dphi; if ((err = wcsfwd(ctype, wcs, world, crval, &cel0, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } /* Check for a solution. */ d = pixcrd[mixpix] - pixmix; dabs = fabs(d); if (dabs < tol || (dphi < tol && dabs < tol2)) { /* Recall saved world coordinates. */ world[wcs->lng] = lng; world[wcs->lat] = lat; return 0; } if (signb(d0) == signb(d)) { phi0 = world[wcs->lng]; d0 = d; } else { phi1 = world[wcs->lng]; d1 = d; } } } /* No solution. */ return 5; } /* Dec 20 1999 Doug Mink - Change signbit() to signb() and always define it * Dec 20 1999 Doug Mink - Include wcslib.h, which includes wcs.h, wcstrig.h * * Mar 20 2001 Doug Mink - Include stdio.h for sprintf() * Mar 20 2001 Doug Mink - Add () around err assignments in if statements * Sep 19 2001 Doug Mink - Add above changes to WCSLIB-2.7 version * * Mar 15 2002 Doug Mink - Add above changes to WCSLIB-2.8.2 * Apr 3 2002 Mark Calabretta - Fix bug in code checking section * * Jun 20 2006 Doug Mink - Initialized uninitialized variables * * Jun 22 2016 Jessica Mink - Increase CTYPE length to 16 */ wcstools-3.9.5/libwcs/wcstrig.c0000664000016200001660000001062311750060474015572 0ustar minkoirsys/*============================================================================ * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-2002, Mark Calabretta * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Correspondence concerning WCSLIB may be directed to: * Internet email: mcalabre@atnf.csiro.au * Postal address: Dr. Mark Calabretta, * Australia Telescope National Facility, * P.O. Box 76, * Epping, NSW, 2121, * AUSTRALIA * *============================================================================= * * The functions defined herein are trigonometric or inverse trigonometric * functions which take or return angular arguments in decimal degrees. * * $Id: wcstrig.c,v 2.8 2002/04/03 01:25:29 mcalabre Exp $ *---------------------------------------------------------------------------*/ #include #include "wcslib.h" const double d2r = PI / 180.0; const double r2d = 180.0 / PI; double cosdeg (angle) const double angle; { double resid; resid = fabs(fmod(angle,360.0)); if (resid == 0.0) { return 1.0; } else if (resid == 90.0) { return 0.0; } else if (resid == 180.0) { return -1.0; } else if (resid == 270.0) { return 0.0; } return cos(angle*d2r); } /*--------------------------------------------------------------------------*/ double sindeg (angle) const double angle; { double resid; resid = fmod(angle-90.0,360.0); if (resid == 0.0) { return 1.0; } else if (resid == 90.0) { return 0.0; } else if (resid == 180.0) { return -1.0; } else if (resid == 270.0) { return 0.0; } return sin(angle*d2r); } /*--------------------------------------------------------------------------*/ double tandeg (angle) const double angle; { double resid; resid = fmod(angle,360.0); if (resid == 0.0 || fabs(resid) == 180.0) { return 0.0; } else if (resid == 45.0 || resid == 225.0) { return 1.0; } else if (resid == -135.0 || resid == -315.0) { return -1.0; } return tan(angle*d2r); } /*--------------------------------------------------------------------------*/ double acosdeg(v) const double v; { if (v >= 1.0) { if (v-1.0 < WCSTRIG_TOL) return 0.0; } else if (v == 0.0) { return 90.0; } else if (v <= -1.0) { if (v+1.0 > -WCSTRIG_TOL) return 180.0; } return acos(v)*r2d; } /*--------------------------------------------------------------------------*/ double asindeg (v) const double v; { if (v <= -1.0) { if (v+1.0 > -WCSTRIG_TOL) return -90.0; } else if (v == 0.0) { return 0.0; } else if (v >= 1.0) { if (v-1.0 < WCSTRIG_TOL) return 90.0; } return asin(v)*r2d; } /*--------------------------------------------------------------------------*/ double atandeg (v) const double v; { if (v == -1.0) { return -45.0; } else if (v == 0.0) { return 0.0; } else if (v == 1.0) { return 45.0; } return atan(v)*r2d; } /*--------------------------------------------------------------------------*/ double atan2deg (y, x) const double x, y; { if (y == 0.0) { if (x >= 0.0) { return 0.0; } else if (x < 0.0) { return 180.0; } } else if (x == 0.0) { if (y > 0.0) { return 90.0; } else if (y < 0.0) { return -90.0; } } return atan2(y,x)*r2d; } /* Dec 20 1999 Doug Mink - Change cosd() and sind() to cosdeg() and sindeg() * Dec 20 1999 Doug Mink - Include wcslib.h, which includes wcstrig.h * Dec 20 1999 Doug Mink - Use PI from wcslib.h, not locally defined * * Sep 19 2001 Doug Mink - No change for WCSLIB 2.7 */ wcstools-3.9.5/libwcs/webread.c0000664000016200001660000007730712465245442015541 0ustar minkoirsys/*** File webread.c *** February 6, 2015 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** (http code from John Roll) *** Copyright (C) 2000-2015 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include #include #include "wcs.h" #include "fitsfile.h" #include "wcscat.h" #define CHUNK 8192 #define LINE 1024 #define MAXHOSTNAMELENGTH 256 #ifdef HAVE_FCNTL_H #include #else #include #endif #include #include /* for MinGW */ #ifdef MSWIN #include #else #include #include #include #endif /* static int FileINetParse (char *file,int port,struct sockaddr_in *adrinet);*/ static int FileINetParse(); static FILE *SokOpen(); #define XFREAD 1 #define XFWRITE 2 #define XFCREAT 4 #define File FILE * #define FileFd(fd) fileno(fd) static char newline = '\n'; /* WEBREAD -- Read a catalog over the web and return results */ int webread (caturl,refcatname,distsort,cra,cdec,dra,ddec,drad,dradi,sysout, eqout,epout,mag1,mag2,sortmag,nstarmax, unum,ura,udec,upra,updec,umag,utype,nlog) char *caturl; /* URL of search engine */ char *refcatname; /* Name of catalog (UAC, USAC, UAC2, USAC2) */ int distsort; /* 1 to sort stars by distance from center */ double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ double dradi; /* Inner edge of annulus in degrees (ignore if 0) */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 to nmag) */ int nstarmax; /* Maximum number of stars to be returned */ double *unum; /* Array of UA numbers (returned) */ double *ura; /* Array of right ascensions (returned) */ double *udec; /* Array of declinations (returned) */ double *upra; /* Array of right ascension proper motions (returned) */ double *updec; /* Array of declination proper motions (returned) */ double **umag; /* Array of magnitudes (returned) */ int *utype; /* Array of plate numbers (returned) */ int nlog; /* Logging interval (-1 to dump returned file) */ { char srchurl[LINE]; char temp[64]; struct TabTable *tabtable; double dtemp; int lurl; int nsmax; struct StarCat *starcat; char cstr[32]; double ra, dec; int nstar; if (nstarmax < 1) nlog = -1; /* Convert coordinate system to string */ wcscstr (cstr, sysout, eqout, epout); /* Set up search query from arguments */ lurl = strlen (caturl); /* Set up query for scat used as server */ if (!strncmp (caturl+lurl-4,"scat",4)) { /* Center coordinates of search */ sprintf (srchurl, "?catalog=%s&ra=%.7f&dec=%.7f&system=%s&format=tab", refcatname, cra, cdec, cstr); /* Search radius or box size */ if (drad != 0.0) { dtemp = drad * 3600.0; sprintf (temp, "&rad=%.3f",dtemp); strcat (srchurl, temp); if (dradi > 0.0) { dtemp = dradi * 3600.0; sprintf (temp, "&inrad=%.3f",dtemp); strcat (srchurl, temp); } } else { dtemp = dra * 3600.0; sprintf (temp, "&dra=%.3f",dtemp); strcat (srchurl, temp); dtemp = ddec * 3600.0; sprintf (temp, "&ddec=%.3f",dtemp); strcat (srchurl, temp); } /* Sort by magnitude or distance for cutoff */ if (sortmag > 0) { sprintf (temp,"&sort=m%d", sortmag); strcat (srchurl, temp); } if (distsort) strcat (srchurl, "&sort=distance"); /* Magnitude limits */ if (mag1 != mag2) { sprintf (temp, "&mag1=%.2f&mag=%.2f",mag1,mag2); strcat (srchurl, temp); } /* Epoch for coordinates */ if (epout != 0.0) { sprintf (temp, "&epoch=%.5f", epout); strcat (srchurl, temp); } /* Number of decimal places in RA seconds */ sprintf (temp, "&ndec=4"); /* Maximum number of stars to return */ if (nstarmax > 0) { sprintf (temp, "&nstar=%d", nstarmax); strcat (srchurl, temp); } if (nlog > 0) fprintf (stderr, "%s%s\n", caturl, srchurl); } /* Set up query for ESO GSC server */ else if (!strncmp (caturl+lurl-10,"gsc-server",10)) { ra = cra; dec = cdec; if (sysout != WCS_J2000) wcscon (sysout, WCS_J2000, eqout, 2000.0, &ra, &dec, epout); if (dec < 0.0) sprintf (srchurl, "?%.7f%.7f&", ra/15.0, dec); else sprintf (srchurl, "?%.7f+%.7f&", ra/15.0, dec); if (drad > 0.0) dtemp = drad * 60.0; else dtemp = 60.0 * sqrt (dra*dra + ddec*ddec); sprintf (temp, "r=0,%.3f&",dtemp); strcat (srchurl, temp); nstar = 100000; sprintf (temp, "nout=%d&f=8", nstar); strcat (srchurl, temp); if (nlog > 0) fprintf (stderr, "%s%s\n", caturl, srchurl); } /* Set up query for ESO USNO A server */ else if (!strncmp (caturl+lurl-12,"usnoa-server",12)) { ra = cra; dec = cdec; if (sysout != WCS_J2000) wcscon (sysout, WCS_J2000, eqout, 2000.0, &ra, &dec, epout); if (dec < 0.0) sprintf (srchurl, "?%.7f%.7f&", ra, dec); else sprintf (srchurl, "?%.7f+%.7f&", ra, dec); if (drad > 0.0) dtemp = drad * 60.0; else dtemp = 60.0 * sqrt (dra*dra + ddec*ddec); sprintf (temp, "radius=0,%.3f&", dtemp); strcat (srchurl, temp); if (mag1 != mag2) { sprintf (temp, "mag=%.2f,%.2f&", mag1, mag2); strcat (srchurl, temp); } if (sortmag == 2) sprintf (temp, "format=8&sort=mr&"); else sprintf (temp, "format=8&sort=m&"); strcat (srchurl, temp); nsmax = nstarmax * 4; sprintf (temp, "n=%d", nsmax); strcat (srchurl, temp); if (nlog > 0) fprintf (stderr,"%s%s\n", caturl, srchurl); } /* Run search across the web */ if ((tabtable = webopen (caturl, srchurl, nlog)) == NULL) { if (nlog > 0) fprintf (stderr, "WEBREAD: %s failed\n", srchurl); return (0); } /* Return if no data */ if (tabtable->tabdata == NULL || strlen (tabtable->tabdata) == 0) { if (nlog > 0) fprintf (stderr, "WEBREAD: No data returned\n"); return (0); } /* If scat, make sure that tab table has tabs */ if (!strncmp (caturl+lurl-4,"scat",4)) { } /* Dump returned file and stop */ if (nlog < 0) { (void) fwrite (tabtable->tabbuff, tabtable->lbuff, 1, stdout); exit (0); } /* Open returned Starbase table as a catalog */ if ((starcat = tabcatopen (caturl, tabtable, 0)) == NULL) { if (nlog > 0) fprintf (stderr, "WEBREAD: Could not open Starbase table as catalog\n"); return (0); } if (!strncmp (caturl+lurl-12,"usnoa-server",12)) { starcat->coorsys = WCS_J2000; starcat->epoch = 2000.0; starcat->equinox = 2000.0; starcat->nmag = 2; starcat->entmag[0] = 5; starcat->entmag[1] = 4; strcpy (starcat->keymag[0], "magb"); strcpy (starcat->keymag[1], "magr"); } /* Extract desired sources from catalog and return them */ return (tabread (caturl,distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nstarmax,&starcat, unum,ura,udec,upra,updec,umag,utype,NULL,nlog)); } int webrnum (caturl,refcatname,nnum,sysout,eqout,epout,match, unum,ura,udec,upra,updec,umag,utype,nlog) char *caturl; /* URL of search engine */ char *refcatname; /* Name of catalog (UAC, USAC, UAC2, USAC2) */ int nnum; /* Number of stars to find */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Proper motion epoch (0.0 for no proper motion) */ int match; /* 1 to match star number exactly, else sequence num */ double *unum; /* Array of UA numbers to find */ double *ura; /* Array of right ascensions (returned) */ double *udec; /* Array of declinations (returned) */ double *upra; /* Array of right ascensions proper motion (returned) */ double *updec; /* Array of declination proper motions (returned) */ double **umag; /* Array of magnitudes (returned) */ int *utype; /* Array of spectral types (returned) */ int nlog; /* Logging interval (-1 to dump returned file) */ { char srchurl[LINE]; char numlist[LINE]; char numstr[32]; char csys[32]; struct TabTable *tabtable; int i, refcat, nfld, nmag, mprop; int lurl; char title[64]; /* Description of catalog (returned) */ int syscat; /* Catalog coordinate system (returned) */ double eqcat; /* Equinox of catalog (returned) */ double epcat; /* Epoch of catalog (returned) */ int ireg, istar; char cstr[32]; char temp[64]; struct StarCat *starcat; /* Set up search query from arguments */ lurl = strlen (caturl); /* Set up query for scat used as server */ if (!strncmp (caturl+lurl-4,"scat",4)) { /* Make list of catalog numbers */ refcat = RefCat (refcatname,title,&syscat,&eqcat,&epcat,&mprop,&nmag); for (i = 0; i < nnum; i++) { nfld = CatNumLen (refcat, unum[i], 0); CatNum (refcat, -nfld, 0, unum[i], numstr); if (i > 0) { strcat (numlist, ","); strcat (numlist, numstr); } else strcpy (numlist, numstr); } /* Set up search query */ wcscstr (cstr, sysout, eqout, epout); sprintf (srchurl, "?catalog=%s&num=%s&ndec=4&outsys=%s",refcatname,numlist,csys); if (epout != 0.0) { sprintf (temp, "&epoch=%.5f", epout); strcat (srchurl, temp); } } /* Set up query for ESO GSC server */ else if (!strncmp (caturl+lurl-10,"gsc-server",10)) { ireg = (int) unum[0]; istar = (int) (10000.0 * (unum[0] - (double) ireg) + 0.5); sprintf (srchurl, "?object=GSC%05d%05d&nout=1&f=8", ireg, istar); if (nlog > 0) fprintf (stderr, "%s%s\n", caturl, srchurl); } /* Set up query for ESO USNO A server */ else if (!strncmp (caturl+lurl-12,"usnoa-server",12)) { ireg = (int) unum[0]; istar = (int) (100000000.0 * (unum[0] - (double) ireg) + 0.5); sprintf (srchurl, "?object=U%04d_%08d&n=1&format=8&", ireg, istar); if (nlog > 0) fprintf (stderr,"%s%s\n", caturl, srchurl); } /* Run search across the web */ if ((tabtable = webopen (caturl, srchurl, nlog)) == NULL) { if (nlog > 0) fprintf (stderr, "WEBRNUM: %s failed\n", srchurl); return (0); } /* Return if no data */ if (tabtable->tabdata == NULL || strlen (tabtable->tabdata) == 0) { if (nlog > 0) fprintf (stderr, "WEBRNUM: No data returned\n"); return (0); } /* Dump returned file and stop */ if (nlog < 0) { (void) fwrite (tabtable->tabbuff, tabtable->lbuff, 1, stdout); exit (0); } /* Open returned Starbase table as a catalog */ if ((starcat = tabcatopen (caturl, tabtable, 0)) == NULL) { if (nlog > 0) fprintf (stderr, "WEBRNUM: Could not open Starbase table as catalog\n"); return (0); } /* Extract desired sources from catalog and return them */ return (tabrnum (srchurl, nnum, sysout, eqout, epout, &starcat, match, unum, ura, udec, upra, updec, umag, utype, NULL, nlog)); } struct TabTable * webopen (caturl, srchpar, nlog) char *caturl; /* URL of search engine */ char *srchpar; /* Search engine parameters to append */ int nlog; /* 1 to print diagnostic messages */ { char *srchurl; int lsrch; char *tabbuff; int lbuff = 0; char *tabnew, *tabline, *lastline, *tempbuff, *tabold; int formfeed = (char) 12; struct TabTable *tabtable; int ltab, lname; int diag; int tabdiff; char *space2tab(); if (nlog == 1) diag = 1; else diag = 0; /* Combine catalog search engine URL and arguments */ lsrch = strlen (srchpar) + strlen (caturl) + 2; if ((srchurl = (char *) malloc (lsrch)) == NULL) return (NULL); strcpy (srchurl, caturl); strcat (srchurl, srchpar); /* Open port to HTTP server, send command, and fill buffer with return */ if ((tabbuff = webbuff (srchurl, diag, &lbuff)) == NULL) { fprintf (stderr,"WEBOPEN: cannot read URL %s\n", srchurl); free (srchurl); return (NULL); } if (!strchr (tabbuff, ' ') && !strchr (tabbuff, ',') && !strchr (tabbuff, '|')) { if (diag) { fprintf (stderr,"Message returned from %s\n", srchurl); fprintf (stderr,"%s\n", tabbuff); } free (srchurl); return (NULL); } /* Transform SDSS return into tab table */ if (strsrch (srchurl, "sdss")) { tempbuff = tabbuff; tabbuff = sdssc2t (tempbuff); lbuff = strlen (tabbuff); free (tempbuff); } /* Transform MAST GALEX GSC 2 return into tab table */ else if (strsrch (srchurl, "galex")) { tempbuff = tabbuff; tabbuff = gsc2c2t (tempbuff); lbuff = strlen (tabbuff); free (tempbuff); } /* Transform CASB GSC 2 return into tab table */ else if (strsrch (srchurl, "gsss")) { tempbuff = tabbuff; tabbuff = gsc2t2t (tempbuff); lbuff = strlen (tabbuff); free (tempbuff); } /* Transform SkyBot return into tab table */ else if (strsrch (srchurl, "skybot")) { tempbuff = tabbuff; tabbuff = skybot2tab (tempbuff); lbuff = strlen (tabbuff); free (tempbuff); } /* Make sure that scat data is tab-separated (3 tabs found) */ else if (strsrch (srchurl, "scat")) { tempbuff = strchr (tabbuff, '\t'); if (tempbuff != NULL) { tempbuff = strchr (tempbuff+1, '\t'); if (tempbuff != NULL) tempbuff = strchr (tempbuff+1, '\t'); } if (tempbuff == NULL) { tempbuff = tabbuff; tabbuff = space2tab (tempbuff); lbuff = strlen (tabbuff); free (tempbuff); } } /* Allocate tab table structure */ ltab = sizeof (struct TabTable); if ((tabtable = (struct TabTable *) calloc (1, ltab)) == NULL) { fprintf (stderr,"WEBOPEN: cannot allocate Tab Table structure for %s", srchurl); free (srchurl); return (NULL); } /* Save pointers to file contents */ tabtable->tabbuff = tabbuff; tabtable->tabheader = tabtable->tabbuff; tabtable->lbuff = lbuff; /* Allocate space for and save catalog URL as filename */ lname = strlen (caturl) + 2; if ((tabtable->filename = (char *) calloc (1, lname)) == NULL) { fprintf (stderr,"WEBOPEN: cannot allocate filename %s in structure", caturl); tabclose (tabtable); free (srchurl); return (NULL); } strcpy (tabtable->filename, caturl); /* Allocate space for and save search string as tabname */ lname = strlen (srchpar) + 2; if ((tabtable->tabname = (char *) calloc (1, lname)) == NULL) { fprintf (stderr,"WEBOPEN: cannot allocate tabname %s in structure", srchurl); tabclose (tabtable); free (srchurl); return (NULL); } strcpy (tabtable->tabname, srchpar); /* Find column headings and start of data */ tabline = tabtable->tabheader; lastline = NULL; while (*tabline != '-' && tabline < tabtable->tabbuff+lbuff) { lastline = tabline; tabline = strchr (tabline,newline) + 1; } if (*tabline != '-') { fprintf (stderr,"WEBOPEN: No - line in tab table %s",srchurl); tabclose (tabtable); free (srchurl); return (NULL); } tabtable->tabhead = lastline; tabtable->tabdata = strchr (tabline, newline) + 1; /* Extract positions of keywords we will want to use */ if (!tabparse (tabtable)) { fprintf (stderr,"TABOPEN: No columns in tab table %s\n",srchurl); tabclose (tabtable); free (srchurl); return (NULL); } /* Enumerate entries in tab table catalog by counting newlines */ tabnew = tabtable->tabdata; tabold = tabnew; tabdiff = 0; tabtable->nlines = 0; while ((tabnew = strchr (tabnew, newline)) != NULL) { tabdiff = tabnew - tabold; tabnew = tabnew + 1; tabtable->nlines = tabtable->nlines + 1; if (*tabnew == formfeed) break; if (!strncasecmp (tabnew, "[EOD]", 5)) break; tabold = tabnew; } if (tabdiff < 2 && tabtable->nlines > 0) tabtable->nlines = tabtable->nlines - 1; tabtable->tabline = tabtable->tabdata; tabtable->iline = 1; free (srchurl); return (tabtable); } /* WEBBUFF -- Return character buffer from given URL */ char * webbuff (url, diag, lbuff) char *url; /* URL to read */ int diag; /* 1 to print diagnostic messages */ int *lbuff; /* Length of buffer (returned) */ { File sok; char *server; char linebuff[LINE]; char *buff; char *tabbuff; char *newbuff; char *urlpath; char *servurl; char *port; int status; int lserver; int lread; int lchunk, lline; int lcbuff; int lb; int ltbuff; int lcom; int i; int chunked = 0; int nport = 80; int nbcont = 0; char *cbcont; char *newserver; char *sokptr; char *newpath; char *encodeURL(); char czero; *lbuff = 0; newbuff = NULL; diag = 0; czero = (char) 0; /* Extract server name and path from URL */ servurl = url; if (!strncmp(url, "http://", 7)) servurl = servurl + 7; urlpath = strchr (servurl, '/'); if (urlpath != NULL) { lserver = urlpath - servurl; if ((server = (char *) malloc (lserver+2)) == NULL) return (NULL); strncpy (server, servurl, lserver); server[lserver] = (char) 0; if ( port = strchr (servurl,':') ) { *port = '\0'; port++; nport = atoi (port); } } else { if ((server = (char *) malloc (4)) == NULL) return (NULL); server[0] = '/'; server[1] = '\0'; } /* Open port to HTTP server */ if ( !(sok = SokOpen (server, nport, XFREAD | XFWRITE)) ) { if (port != NULL) fprintf(stderr, "Can't read URL %s:%s\n", server, port); else fprintf(stderr, "Can't read URL %s\n", server); free (server); return (NULL); } /* Make sure that URL contains only legal characters */ /* newpath = encodeURL (urlpath); */ newpath = urlpath; /* Send HTTP GET command */ fprintf (sok, "GET %s HTTP/1.1\r\nHost: %s\n\n", newpath, server); fflush (sok); free (server); if (newpath != urlpath) { free (newpath); } for (i = 0; i < LINE; i++) linebuff[i] = czero; (void) fscanf(sok, "%*s %d %s\r\n", &status, linebuff); /* If Redirect code encounter, go to alternate URL at Location: */ if ( status == 301 || status == 302 || status == 303 || status == 307 ) { char redirect[LINE]; while ((servurl = fgets (redirect, LINE, sok))) { if (!(strncmp (redirect, "Location:", 9))) break; } (void) fclose (sok); if (servurl == NULL) { if (diag) fprintf (stderr,"WEBBUFF: No forward for HTTP Code %d\n", status); return (NULL); } if ((servurl = strsrch (servurl, "http://")) == NULL) { if (diag) fprintf (stderr,"WEBBUFF: No forward URL for HTTP Code %d\n", status); return (NULL); } servurl = servurl + 7; urlpath = strchr (servurl, '/'); lserver = urlpath - servurl; if ((server = (char *) malloc (lserver+2)) == NULL) { return (NULL); } strncpy (server, servurl, lserver); server[lserver] = (char) 0; if (diag) fprintf (stderr,"WEBBUFF: HTTP Code %d: Temporary Redirect to %s\n", status, server); /* Open port to HTTP server */ if ( (sok = SokOpen (server, 80, XFREAD | XFWRITE)) == NULL ) { free (server); return (NULL); } /* Make sure that URL contains only legal characters */ /* newpath = encodeURL (urlpath); */ newpath = urlpath; /* Send HTTP GET command (simbad forward fails if HTTP/1.1 included) */ fprintf(sok, "GET %s HTTP/1.1\r\nHost: %s\n\n", newpath, server); fflush (sok); free (server); if (newpath != urlpath) { free (newpath); } (void) fscanf(sok, "%*s %d %*s\r\n", &status); } /* Skip continue lines if (status == 100) { while (status == 100) fscanf(sok, "%*s %d %*s\n", &status); } */ /* If status is not 200 return without data */ if ( status != 200 ) { if (diag) fprintf (stderr,"HTTP Code %d from %s\n", status, server); return (NULL); } for (i = 0; i < LINE; i++) linebuff[i] = czero; /* Skip over http header of returned stuff */ while (fgets (linebuff, LINE, sok) ) { if (diag) fprintf (stderr, "%s", linebuff); if (strcsrch (linebuff, "chunked") != NULL) chunked = 1; if (strcsrch (linebuff, "Content-length") != NULL) { if ((cbcont = strchr (linebuff, ':')) != NULL) nbcont = atoi (cbcont+1); } if (*linebuff == '\n') break; if (*linebuff == '\r') break; for (i = 0; i < LINE; i++) linebuff[i] = czero; } /* Read table into buffer in memory a chunk at a time */ tabbuff = NULL; for (i = 0; i < LINE; i++) linebuff[i] = czero; lb = 0; if (chunked) { lchunk = 1; lline = 1; *lbuff = 0; ltbuff = 0; while (lline > 0) { (void) fgets (linebuff, LINE, sok); lline = strlen (linebuff); if (lline < 1) break; if (linebuff[lline-1] < 32) linebuff[lline-1] = (char) 0; if (linebuff[lline-2] < 32) linebuff[lline-2] = (char) 0; if (strlen (linebuff) <= 0) continue; lchunk = (int) strtol (linebuff, NULL, 16); if (lchunk < 1) break; /* else if (lchunk == 1) continue; */ if (diag) fprintf (stderr, "%s (=%d)\n", linebuff, lchunk); lcbuff = ltbuff; ltbuff = ltbuff + lchunk; /* Allocate buffer on first time through */ if (tabbuff == NULL) { lb = 10 * ltbuff; tabbuff = (char *) calloc ((size_t)lb, (size_t)1); buff = tabbuff; } /* Increase buffer size if this chunk will push it over current limit */ else if (ltbuff > lb) { lb = lb * 10; newbuff = (char *) calloc ((size_t)lb, (size_t)1); movebuff (tabbuff, newbuff, lcbuff, 0, 0); free (tabbuff); tabbuff = newbuff; buff = tabbuff + lcbuff; newbuff = NULL; } else { buff = tabbuff + lcbuff; } (void) fread (buff, 1, lchunk, sok); buff[lchunk] = (char) 0; if (diag) fprintf (stderr, "%s\n", buff); *lbuff = ltbuff; for (i = 0; i < LINE; i++) linebuff[i] = czero; } } /* Read table all at once if total length is passed */ else if (nbcont > 0) { tabbuff = (char *) calloc (1, nbcont+1); tabbuff[nbcont] = (char) 0; if ((lread = fread (tabbuff, 1, nbcont, sok)) <= 0) { free (tabbuff); tabbuff = NULL; } } /* Read table into buffer in memory a buffer-full at a time */ else { lchunk = 8192; *lbuff = 0; buff = (char *) calloc (1, lchunk+8); if (buff == NULL) { fprintf (stderr, "WEBBUFF: unable to allocate chunk buffer of %d bytes\n", lchunk + 8); return (NULL); } while ( (lread = fread (buff, 1, lchunk, sok)) > 0 ) { lcbuff = *lbuff; *lbuff = *lbuff + lread; if (tabbuff == NULL) { tabbuff = (char *) malloc (*lbuff+8); if (tabbuff == NULL) { fprintf (stderr, "WEBBUFF: unable to allocate buffer of %d bytes\n", *lbuff + 8); return (NULL); } movebuff (buff, tabbuff, lread, 0, 0); } else { newbuff = (char *) malloc (*lbuff+8); if (newbuff == NULL) { fprintf (stderr, "WEBBUFF: unable to allocate new buffer of %d bytes\n", *lbuff + 8); return (NULL); } movebuff (tabbuff, newbuff, lcbuff, 0, 0); free (tabbuff); tabbuff = newbuff; movebuff (buff, tabbuff, lread, 0, lcbuff); } if (diag) fprintf (stderr, "%s\n", buff); } free (buff); buff = NULL; } (void) fclose (sok); return (tabbuff); } /* sokFile.c * copyright 1991, 1993, 1995, 1999 John B. Roll jr. */ static FILE * SokOpen(name, port, mode) char *name; /* "host:port" socket to open */ int port; int mode; /* mode of socket to open */ { int xfd; /* socket descriptor */ int type; /* type returned from FileINetParse */ struct sockaddr_in adrinet; /* socket structure parsed from name */ int reuse_addr = 1; File f; /* returned file descriptor */ if (!(type = FileINetParse(name, port, &adrinet))) return NULL; if ( type == 1 || (mode & XFCREAT && mode & XFREAD && !(mode & XFWRITE)) ) { if ( ((xfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) || setsockopt(xfd, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse_addr, sizeof(reuse_addr)) < 0 || (bind(xfd, (struct sockaddr *) & adrinet ,sizeof(adrinet)) != 0) || listen(xfd, 5) ) { close(xfd); return NULL; } } else { if (((xfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) || (connect(xfd, (struct sockaddr *) & adrinet ,sizeof(adrinet)) != 0)) { close(xfd); return NULL; } } f = fdopen (xfd, "r+"); return f; } static int FileINetParse(file, port, adrinet) char *file; /* host/socket pair to parse? */ int port; struct sockaddr_in *adrinet; /* socket info structure to fill? */ { struct hostent *hp; /* -> hostent structure for host */ char hostname[MAXHOSTNAMELENGTH + 12]; /* name of host */ char *portstr; /* internet port number (ascii) */ int type = 2; /* return code */ extern int gethostname(); if ( !strncmp(file, "http://", 7) ) { file += 7; if ( port == -1 ) port = 80; } strcpy(hostname, file); #ifdef msdos /* This is a DOS disk discriptor, not a machine name */ if ((!(file[0] == '.')) && file[1] == ':') return 0; #endif if ( (portstr = strchr(hostname, '/')) ) { *portstr = '\0'; } if ( (portstr = strchr(hostname, ':')) ) { *portstr++ = '\0'; if ((port = strtol(portstr, NULL, 0)) == 0) { struct servent *service; if ((service = getservbyname(portstr, NULL)) == NULL) return 0; port = service->s_port; } } if ( port == -1 ) return 0; if (hostname[0] == '\0') type = 1; if (hostname[0] == '\0' || hostname[0] == '.') if (gethostname(hostname, MAXHOSTNAMELENGTH) == -1) return 0; if ((hp = gethostbyname(hostname)) == NULL) return 0; memset(adrinet, 0, sizeof(struct sockaddr_in)); adrinet->sin_family = AF_INET; adrinet->sin_port = htons(port); memcpy(&adrinet->sin_addr, hp->h_addr, hp->h_length); return type; } char * space2tab (tabbuff) char *tabbuff; /* Tab table filled with spaces */ { char *newbuff, *line0, *line1, *ic, *icn; char cspace, ctab, cdash; int lbuff; int alltab = 0; int notab = 0; cspace = ' '; cdash = '-'; ctab = '\t'; line0 = tabbuff; lbuff = strlen (tabbuff); newbuff = (char *) calloc (lbuff, 1); icn = newbuff; while ((line1 = strchr (line0, newline))) { if (alltab == 0 && *(line1+1) == cdash) { alltab = 1; } ic = line0; notab = 1; while (ic <= line1) { if (*ic != cspace) *icn++ = *ic++; else { if (alltab) { *icn++ = ctab; while (*ic++ == cspace) { } ic--; } else if (notab) { notab = 0; *icn++ = ctab; while (*ic++ == cspace) { } ic--; } else *icn++ = *ic++; } } line0 = line1 + 1; notab = 1; if (strlen (line0) < 1) { *icn++ = (char) 0; break; } } return (newbuff); } /* The following two subroutines are from Fred Bulback, who has put them * in the public domain. */ /* Converts an integer value to its hex character*/ char char2hex (char code) { static char hex[] = "0123456789ABCDEF"; return hex[code & 15]; } /* Returns a url-encoded version of str */ /* IMPORTANT: be sure to free() the returned string after use */ char *encodeURL (char *str) { char *pstr = str, *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf; while (*pstr) { if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~' || *pstr == '/' || *pstr == '?') *pbuf++ = *pstr; else if (*pstr == ' ') *pbuf++ = '+'; else *pbuf++ = '%', *pbuf++ = char2hex(*pstr >> 4), *pbuf++ = char2hex(*pstr & 15); pstr++; } *pbuf = '\0'; return buf; } /* Nov 29 2000 New subroutines * Dec 11 2000 Do not print messages unless nlog > 0 * Dec 12 2000 Fix problems with return if no stars * Dec 18 2000 Clean up code after lint * * Jan 2 2001 Set MAXHOSTNAMELENGTH to 256, bypassing system constant * Jan 3 2001 Include string.h, not strings.h * Mar 19 2001 Drop argument types from declaration * Mar 23 2001 Put number into argument list correctly in webrnum() * Jun 7 2001 Add proper motion flag and number of magnitudes to RefCat() * Jun 20 2001 Move webopen() declaration to wcscat.h * Jun 28 2001 When reading chunked data, loop until nothing is read or [EOD] * Jul 12 2001 Break out web access into subroutine webbuff() * Sep 7 2001 Free server in webbuff() * Sep 11 2001 Pass array of magnitude vectors * Sep 14 2001 Pass sort type, if distance or magnitude * Sep 14 2001 Add option to print entire returned file if nlog < 0 * Sep 21 2001 Debug searches of ESO USNO-A2.0 and GSC catalogs * * Apr 8 2002 Fix bug in ESO USNO-A2.0 server code * Aug 6 2002 Make starcat->entmag and starcat->keymag into vectors * Oct 3 2002 If nstarmax is less than 1, print results from web directly * * Jan 27 2003 Add maximum number of stars to be returned to webread() * Jan 28 2003 Add number of decimal places to webread() and webrnum() * Mar 12 2003 Fix bug in USNO-A2 server code * Aug 22 2003 Add radi argument for inner edge of search annulus * Nov 22 2003 Increase buffer size faster than reading in webbuff() * Dec 12 2003 Fix calls to CatNumLen() and tabcatopen() * * Jan 5 2004 Convert SDSS table from comma-separated to tab-separated in webopen(); initialize nbcont to 0 in webbuff() * Jan 14 2004 Return error if data but no objects returned in webopen() * Aug 30 2004 Send CR-LF termination to HTTP GET, not just LF * Sep 10 2004 Print server messages only if verbose flag is on * * Jan 9 2006 Multiply max number of stars for ESO search to get all * Apr 6 2006 Check for sdss in URL for Sloan parsing * Jun 20 2006 Cast most stream I/O calls to void * Oct 30 2006 Reset buffer length for SDSS tables * * Jan 10 2007 Add match to webrnum argument list for tabrnum() * Jan 11 2007 Include fitsfile.h * Mar 13 2007 Process CSV data from STScI MAST GALEX GSC2 catalog * Mar 13 2007 Caselessly search for header info * Apr 11 2007 Terminate buffer read as number of characters * Jul 13 2007 Add SkyBot data transformation to webopen() * Jul 17 2007 Change order of arguments in movebuff() so destination is first * Jul 18 2007 Fix bug in chunked data reading * Jul 19 2007 If last line of table has no content, drop it * Aug 24 2007 Fix tab tables filled with spaces * Aug 28 2007 Fix space2tab() declarations which passed on Solaris, not Linux * Dec 31 2007 Fix chunk reading code in webbuff() * * Jan 8 2008 Forward automatically if status=301|302|303|307 (code from Ed Los) * * Sep 25 2009 Reverse movebuff() source, destination arguments for compatibility * Sep 25 2009 Free allocated pointers before returning after Douglas Burke * * Oct 29 2010 Declare match int in webrnum() * * Sep 16 2011 Add winsock2.h include for MinGW MSWindows C * * Sep 29 2014 Translate characters in URL to those legal for web use using * http://geekhideout.com/urlcode.shtml * * Feb 6 2015 Drop URL encoding because GSC2 search fails when used. */ wcstools-3.9.5/libwcs/worldpos.c0000664000016200001660000005101511750060474015761 0ustar minkoirsys/* worldpos.c -- WCS Algorithms from Classic AIPS. * September 1, 2011 * Copyright (C) 1994-2011 * Associated Universities, Inc. Washington DC, USA. * With code added by Jessica Mink, Smithsonian Astrophysical Observatory * and Allan Brighton and Andreas Wicenec, ESO * and Frank Valdes, NOAO * Module: worldpos.c * Purpose: Perform forward and reverse WCS computations for 8 projections * Subroutine: worldpos() converts from pixel location to RA,Dec * Subroutine: worldpix() converts from RA,Dec to pixel location -=-=-=-=-=-=- This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning AIPS should be addressed as follows: Internet email: aipsmail@nrao.edu Postal address: AIPS Group National Radio Astronomy Observatory 520 Edgemont Road Charlottesville, VA 22903-2475 USA -=-=-=-=-=-=- These two ANSI C functions, worldpos() and worldpix(), perform forward and reverse WCS computations for 8 types of projective geometries ("-SIN", "-TAN", "-ARC", "-NCP", "-GLS" or "-SFL", "-MER", "-AIT", "-STG", "CAR", and "COE"): worldpos() converts from pixel location to RA,Dec worldpix() converts from RA,Dec to pixel location where "(RA,Dec)" are more generically (long,lat). These functions are based on the WCS implementation of Classic AIPS, an implementation which has been in production use for more than ten years. See the two memos by Eric Greisen ftp://fits.cv.nrao.edu/fits/documents/wcs/aips27.ps.Z ftp://fits.cv.nrao.edu/fits/documents/wcs/aips46.ps.Z for descriptions of the 8 projective geometries and the algorithms. Footnotes in these two documents describe the differences between these algorithms and the 1993-94 WCS draft proposal (see URL below). In particular, these algorithms support ordinary field rotation, but not skew geometries (CD or PC matrix cases). Also, the MER and AIT algorithms work correctly only for CRVALi=(0,0). Users should note that GLS projections with yref!=0 will behave differently in this code than in the draft WCS proposal. The NCP projection is now obsolete (it is a special case of SIN). WCS syntax and semantics for various advanced features is discussed in the draft WCS proposal by Greisen and Calabretta at: ftp://fits.cv.nrao.edu/fits/documents/wcs/wcs.all.ps.Z -=-=-=- The original version of this code was Emailed to D.Wells on Friday, 23 September by Bill Cotton , who described it as a "..more or less.. exact translation from the AIPSish..". Changes were made by Don Wells during the period October 11-13, 1994: 1) added GNU license and header comments 2) added testpos.c program to perform extensive circularity tests 3) changed float-->double to get more than 7 significant figures 4) testpos.c circularity test failed on MER and AIT. B.Cotton found that "..there were a couple of lines of code [in] the wrong place as a result of merging several Fortran routines." 5) testpos.c found 0h wraparound in worldpix() and worldpos(). 6) E.Greisen recommended removal of various redundant if-statements, and addition of a 360d difference test to MER case of worldpos(). 7) D.Mink changed input to data structure and implemented rotation matrix. */ #include #include #include #include "wcs.h" int worldpos (xpix, ypix, wcs, xpos, ypos) /* Routine to determine accurate position for pixel coordinates */ /* returns 0 if successful otherwise 1 = angle too large for projection; */ /* does: -SIN, -TAN, -ARC, -NCP, -GLS or -SFL, -MER, -AIT projections */ /* anything else is linear */ /* Input: */ double xpix; /* x pixel number (RA or long without rotation) */ double ypix; /* y pixel number (Dec or lat without rotation) */ struct WorldCoor *wcs; /* WCS parameter structure */ /* Output: */ double *xpos; /* x (RA) coordinate (deg) */ double *ypos; /* y (dec) coordinate (deg) */ { double cosr, sinr, dx, dy, dz, tx; double sins, coss, dt, l, m, mg, da, dd, cos0, sin0; double rat = 0.0; double dect = 0.0; double mt, a, y0, td, r2; /* allan: for COE */ double dec0, ra0, decout, raout; double geo1, geo2, geo3; double cond2r=1.745329252e-2; double twopi = 6.28318530717959; double deps = 1.0e-5; /* Structure elements */ double xref; /* X reference coordinate value (deg) */ double yref; /* Y reference coordinate value (deg) */ double xrefpix; /* X reference pixel */ double yrefpix; /* Y reference pixel */ double xinc; /* X coordinate increment (deg) */ double yinc; /* Y coordinate increment (deg) */ double rot; /* Optical axis rotation (deg) (N through E) */ int itype = wcs->prjcode; /* Set local projection parameters */ xref = wcs->xref; yref = wcs->yref; xrefpix = wcs->xrefpix; yrefpix = wcs->yrefpix; xinc = wcs->xinc; yinc = wcs->yinc; rot = degrad (wcs->rot); cosr = cos (rot); sinr = sin (rot); /* Offset from ref pixel */ dx = xpix - xrefpix; dy = ypix - yrefpix; /* Scale and rotate using CD matrix */ if (wcs->rotmat) { tx = dx * wcs->cd[0] + dy * wcs->cd[1]; dy = dx * wcs->cd[2] + dy * wcs->cd[3]; dx = tx; } /* Scale and rotate using CDELTn and CROTA2 */ else { /* Check axis increments - bail out if either 0 */ if ((xinc==0.0) || (yinc==0.0)) { *xpos=0.0; *ypos=0.0; return 2; } /* Scale using CDELT */ dx = dx * xinc; dy = dy * yinc; /* Take out rotation from CROTA */ if (rot != 0.0) { tx = dx * cosr - dy * sinr; dy = dx * sinr + dy * cosr; dx = tx; } } /* Flip coordinates if necessary */ if (wcs->coorflip) { tx = dx; dx = dy; dy = tx; } /* Default, linear result for error or pixel return */ *xpos = xref + dx; *ypos = yref + dy; if (itype <= 0) return 0; /* Convert to radians */ if (wcs->coorflip) { dec0 = degrad (xref); ra0 = degrad (yref); } else { ra0 = degrad (xref); dec0 = degrad (yref); } l = degrad (dx); m = degrad (dy); sins = l*l + m*m; decout = 0.0; raout = 0.0; cos0 = cos (dec0); sin0 = sin (dec0); /* Process by case */ switch (itype) { case WCS_CAR: /* -CAR Cartesian (was WCS_PIX pixel and WCS_LIN linear) */ rat = ra0 + l; dect = dec0 + m; break; case WCS_SIN: /* -SIN sin*/ if (sins>1.0) return 1; coss = sqrt (1.0 - sins); dt = sin0 * coss + cos0 * m; if ((dt>1.0) || (dt<-1.0)) return 1; dect = asin (dt); rat = cos0 * coss - sin0 * m; if ((rat==0.0) && (l==0.0)) return 1; rat = atan2 (l, rat) + ra0; break; case WCS_TAN: /* -TAN tan */ case WCS_TNX: /* -TNX tan with polynomial correction */ case WCS_TPV: /* -TPV tan with polynomial correction */ case WCS_ZPX: /* -ZPX zpn with polynomial correction */ if (sins>1.0) return 1; dect = cos0 - m * sin0; if (dect==0.0) return 1; rat = ra0 + atan2 (l, dect); dect = atan (cos(rat-ra0) * (m * cos0 + sin0) / dect); break; case WCS_ARC: /* -ARC Arc*/ if (sins>=twopi*twopi/4.0) return 1; sins = sqrt(sins); coss = cos (sins); if (sins!=0.0) sins = sin (sins) / sins; else sins = 1.0; dt = m * cos0 * sins + sin0 * coss; if ((dt>1.0) || (dt<-1.0)) return 1; dect = asin (dt); da = coss - dt * sin0; dt = l * sins * cos0; if ((da==0.0) && (dt==0.0)) return 1; rat = ra0 + atan2 (dt, da); break; case WCS_NCP: /* -NCP North celestial pole*/ dect = cos0 - m * sin0; if (dect==0.0) return 1; rat = ra0 + atan2 (l, dect); dt = cos (rat-ra0); if (dt==0.0) return 1; dect = dect / dt; if ((dect>1.0) || (dect<-1.0)) return 1; dect = acos (dect); if (dec0<0.0) dect = -dect; break; case WCS_GLS: /* -GLS global sinusoid */ case WCS_SFL: /* -SFL Samson-Flamsteed */ dect = dec0 + m; if (fabs(dect)>twopi/4.0) return 1; coss = cos (dect); if (fabs(l)>twopi*coss/2.0) return 1; rat = ra0; if (coss>deps) rat = rat + l / coss; break; case WCS_MER: /* -MER mercator*/ dt = yinc * cosr + xinc * sinr; if (dt==0.0) dt = 1.0; dy = degrad (yref/2.0 + 45.0); dx = dy + dt / 2.0 * cond2r; dy = log (tan (dy)); dx = log (tan (dx)); geo2 = degrad (dt) / (dx - dy); geo3 = geo2 * dy; geo1 = cos (degrad (yref)); if (geo1<=0.0) geo1 = 1.0; rat = l / geo1 + ra0; if (fabs(rat - ra0) > twopi) return 1; /* added 10/13/94 DCW/EWG */ dt = 0.0; if (geo2!=0.0) dt = (m + geo3) / geo2; dt = exp (dt); dect = 2.0 * atan (dt) - twopi / 4.0; break; case WCS_AIT: /* -AIT Aitoff*/ dt = yinc*cosr + xinc*sinr; if (dt==0.0) dt = 1.0; dt = degrad (dt); dy = degrad (yref); dx = sin(dy+dt)/sqrt((1.0+cos(dy+dt))/2.0) - sin(dy)/sqrt((1.0+cos(dy))/2.0); if (dx==0.0) dx = 1.0; geo2 = dt / dx; dt = xinc*cosr - yinc* sinr; if (dt==0.0) dt = 1.0; dt = degrad (dt); dx = 2.0 * cos(dy) * sin(dt/2.0); if (dx==0.0) dx = 1.0; geo1 = dt * sqrt((1.0+cos(dy)*cos(dt/2.0))/2.0) / dx; geo3 = geo2 * sin(dy) / sqrt((1.0+cos(dy))/2.0); rat = ra0; dect = dec0; if ((l==0.0) && (m==0.0)) break; dz = 4.0 - l*l/(4.0*geo1*geo1) - ((m+geo3)/geo2)*((m+geo3)/geo2) ; if ((dz>4.0) || (dz<2.0)) return 1;; dz = 0.5 * sqrt (dz); dd = (m+geo3) * dz / geo2; if (fabs(dd)>1.0) return 1;; dd = asin (dd); if (fabs(cos(dd))1.0) return 1;; da = asin (da); rat = ra0 + 2.0 * da; dect = dd; break; case WCS_STG: /* -STG Sterographic*/ dz = (4.0 - sins) / (4.0 + sins); if (fabs(dz)>1.0) return 1; dect = dz * sin0 + m * cos0 * (1.0+dz) / 2.0; if (fabs(dect)>1.0) return 1; dect = asin (dect); rat = cos(dect); if (fabs(rat)1.0) return 1; rat = asin (rat); mg = 1.0 + sin(dect) * sin0 + cos(dect) * cos0 * cos(rat); if (fabs(mg)deps) rat = twopi/2.0 - rat; rat = ra0 + rat; break; case WCS_COE: /* COE projection code from Andreas Wicenic, ESO */ td = tan (dec0); y0 = 1.0 / td; mt = y0 - m; if (dec0 < 0.) a = atan2 (l,-mt); else a = atan2 (l, mt); rat = ra0 - (a / sin0); r2 = (l * l) + (mt * mt); dect = asin (1.0 / (sin0 * 2.0) * (1.0 + sin0*sin0 * (1.0 - r2))); break; } /* Return RA in range */ raout = rat; decout = dect; if (raout-ra0>twopi/2.0) raout = raout - twopi; if (raout-ra0<-twopi/2.0) raout = raout + twopi; if (raout < 0.0) raout += twopi; /* added by DCW 10/12/94 */ /* Convert units back to degrees */ *xpos = raddeg (raout); *ypos = raddeg (decout); return 0; } /* End of worldpos */ int worldpix (xpos, ypos, wcs, xpix, ypix) /*-----------------------------------------------------------------------*/ /* routine to determine accurate pixel coordinates for an RA and Dec */ /* returns 0 if successful otherwise: */ /* 1 = angle too large for projection; */ /* 2 = bad values */ /* does: SIN, TAN, ARC, NCP, GLS or SFL, MER, AIT, STG, CAR, COE projections */ /* anything else is linear */ /* Input: */ double xpos; /* x (RA) coordinate (deg) */ double ypos; /* y (dec) coordinate (deg) */ struct WorldCoor *wcs; /* WCS parameter structure */ /* Output: */ double *xpix; /* x pixel number (RA or long without rotation) */ double *ypix; /* y pixel number (dec or lat without rotation) */ { double dx, dy, ra0, dec0, ra, dec, coss, sins, dt, da, dd, sint; double l, m, geo1, geo2, geo3, sinr, cosr, tx, x, a2, a3, a4; double rthea,gamby2,a,b,c,phi,an,rap,v,tthea,co1,co2,co3,co4,ansq; /* COE */ double cond2r=1.745329252e-2, deps=1.0e-5, twopi=6.28318530717959; /* Structure elements */ double xref; /* x reference coordinate value (deg) */ double yref; /* y reference coordinate value (deg) */ double xrefpix; /* x reference pixel */ double yrefpix; /* y reference pixel */ double xinc; /* x coordinate increment (deg) */ double yinc; /* y coordinate increment (deg) */ double rot; /* Optical axis rotation (deg) (from N through E) */ int itype; /* Set local projection parameters */ xref = wcs->xref; yref = wcs->yref; xrefpix = wcs->xrefpix; yrefpix = wcs->yrefpix; xinc = wcs->xinc; yinc = wcs->yinc; rot = degrad (wcs->rot); cosr = cos (rot); sinr = sin (rot); /* Projection type */ itype = wcs->prjcode; /* Nonlinear position */ if (itype > 0) { if (wcs->coorflip) { dec0 = degrad (xref); ra0 = degrad (yref); dt = xpos - yref; } else { ra0 = degrad (xref); dec0 = degrad (yref); dt = xpos - xref; } /* 0h wrap-around tests added by D.Wells 10/12/1994: */ /* Modified to exclude weird reference pixels by D.Mink 2/3/2004 */ if (xrefpix*xinc > 180.0 || xrefpix*xinc < -180.0) { if (dt > 360.0) xpos -= 360.0; if (dt < 0.0) xpos += 360.0; } else { if (dt > 180.0) xpos -= 360.0; if (dt < -180.0) xpos += 360.0; } /* NOTE: changing input argument xpos is OK (call-by-value in C!) */ ra = degrad (xpos); dec = degrad (ypos); /* Compute direction cosine */ coss = cos (dec); sins = sin (dec); l = sin(ra-ra0) * coss; sint = sins * sin(dec0) + coss * cos(dec0) * cos(ra-ra0); } else { l = 0.0; sint = 0.0; sins = 0.0; coss = 0.0; ra = 0.0; dec = 0.0; ra0 = 0.0; dec0 = 0.0; m = 0.0; } /* Process by case */ switch (itype) { case WCS_CAR: /* -CAR Cartesian */ l = ra - ra0; m = dec - dec0; break; case WCS_SIN: /* -SIN sin*/ if (sint<0.0) return 1; m = sins * cos(dec0) - coss * sin(dec0) * cos(ra-ra0); break; case WCS_TNX: /* -TNX tan with polynomial correction */ case WCS_TPV: /* -TPV tan with polynomial correction */ case WCS_ZPX: /* -ZPX zpn with polynomial correction */ case WCS_TAN: /* -TAN tan */ if (sint<=0.0) return 1; m = sins * sin(dec0) + coss * cos(dec0) * cos(ra-ra0); l = l / m; m = (sins * cos(dec0) - coss * sin(dec0) * cos(ra-ra0)) / m; break; case WCS_ARC: /* -ARC Arc*/ m = sins * sin(dec0) + coss * cos(dec0) * cos(ra-ra0); if (m<-1.0) m = -1.0; if (m>1.0) m = 1.0; m = acos (m); if (m!=0) m = m / sin(m); else m = 1.0; l = l * m; m = (sins * cos(dec0) - coss * sin(dec0) * cos(ra-ra0)) * m; break; case WCS_NCP: /* -NCP North celestial pole*/ if (dec0==0.0) return 1; /* can't stand the equator */ else m = (cos(dec0) - coss * cos(ra-ra0)) / sin(dec0); break; case WCS_GLS: /* -GLS global sinusoid */ case WCS_SFL: /* -SFL Samson-Flamsteed */ dt = ra - ra0; if (fabs(dec)>twopi/4.0) return 1; if (fabs(dec0)>twopi/4.0) return 1; m = dec - dec0; l = dt * coss; break; case WCS_MER: /* -MER mercator*/ dt = yinc * cosr + xinc * sinr; if (dt==0.0) dt = 1.0; dy = degrad (yref/2.0 + 45.0); dx = dy + dt / 2.0 * cond2r; dy = log (tan (dy)); dx = log (tan (dx)); geo2 = degrad (dt) / (dx - dy); geo3 = geo2 * dy; geo1 = cos (degrad (yref)); if (geo1<=0.0) geo1 = 1.0; dt = ra - ra0; l = geo1 * dt; dt = dec / 2.0 + twopi / 8.0; dt = tan (dt); if (dttwopi/4.0) return 1; dt = yinc*cosr + xinc*sinr; if (dt==0.0) dt = 1.0; dt = degrad (dt); dy = degrad (yref); dx = sin(dy+dt)/sqrt((1.0+cos(dy+dt))/2.0) - sin(dy)/sqrt((1.0+cos(dy))/2.0); if (dx==0.0) dx = 1.0; geo2 = dt / dx; dt = xinc*cosr - yinc* sinr; if (dt==0.0) dt = 1.0; dt = degrad (dt); dx = 2.0 * cos(dy) * sin(dt/2.0); if (dx==0.0) dx = 1.0; geo1 = dt * sqrt((1.0+cos(dy)*cos(dt/2.0))/2.0) / dx; geo3 = geo2 * sin(dy) / sqrt((1.0+cos(dy))/2.0); dt = sqrt ((1.0 + cos(dec) * cos(da))/2.0); if (fabs(dt)twopi/4.0) return 1; dd = 1.0 + sins * sin(dec0) + coss * cos(dec0) * cos(da); if (fabs(dd)rotmat) l = rap * an * (1.0 - ansq/6.0) * (wcs->cd[0] / fabs(wcs->cd[0])); else l = rap * an * (1.0 - ansq/6.0) * (xinc / fabs(xinc)); m = rthea - (rap * (1.0 - ansq/2.0)); break; } /* end of itype switch */ /* Convert back to degrees */ if (itype > 0) { dx = raddeg (l); dy = raddeg (m); } /* For linear or pixel projection */ else { dx = xpos - xref; dy = ypos - yref; } if (wcs->coorflip) { tx = dx; dx = dy; dy = tx; } /* Scale and rotate using CD matrix */ if (wcs->rotmat) { tx = dx * wcs->dc[0] + dy * wcs->dc[1]; dy = dx * wcs->dc[2] + dy * wcs->dc[3]; dx = tx; } /* Scale and rotate using CDELTn and CROTA2 */ else { /* Correct for rotation */ if (rot!=0.0) { tx = dx*cosr + dy*sinr; dy = dy*cosr - dx*sinr; dx = tx; } /* Scale using CDELT */ if (xinc != 0.) dx = dx / xinc; if (yinc != 0.) dy = dy / yinc; } /* Convert to pixels */ *xpix = dx + xrefpix; if (itype == WCS_CAR) { if (*xpix > wcs->nxpix) { x = *xpix - (360.0 / xinc); if (x > 0.0) *xpix = x; } else if (*xpix < 0) { x = *xpix + (360.0 / xinc); if (x <= wcs->nxpix) *xpix = x; } } *ypix = dy + yrefpix; return 0; } /* end worldpix */ /* Oct 26 1995 Fix bug which interchanged RA and Dec twice when coorflip * * Oct 31 1996 Fix CD matrix use in WORLDPIX * Nov 4 1996 Eliminate extra code for linear projection in WORLDPIX * Nov 5 1996 Add coordinate flip in WORLDPIX * * May 22 1997 Avoid angle wraparound when CTYPE is pixel * Jun 4 1997 Return without angle conversion from worldpos if type is PIXEL * * Oct 20 1997 Add chip rotation; compute rotation angle trig functions * Jan 23 1998 Change PCODE to PRJCODE * Jan 26 1998 Remove chip rotation code * Feb 5 1998 Make cd[] and dc[] vectors; use xinc, yinc, rot from init * Feb 23 1998 Add NOAO TNX projection as TAN * Apr 28 1998 Change projection flags to WCS_* * May 27 1998 Skip limit checking for linear projection * Jun 25 1998 Fix inverse for CAR projection * Aug 5 1998 Allan Brighton: Added COE projection (code from A. Wicenec, ESO) * Sep 30 1998 Fix bug in COE inverse code to get sign correct * * Oct 21 1999 Drop unused y from worldpix() * * Apr 3 2002 Use GLS and SFL interchangeably * * Feb 3 2004 Let ra be >180 in worldpix() if ref pixel is >180 deg away * * Jun 20 2006 Initialize uninitialized variables * * Mar 11 2011 Initialize ZPX * Sep 1 2011 Add TPV projection as TAN */ wcstools-3.9.5/libwcs/fitsfile1.h0000664000016200001660000012301611750060645016004 0ustar minkoirsys/*** File fitsfile.h FITS and IRAF file access subroutines *** January 5, 2007 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2007 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #ifndef fitsfile_h_ #define fitsfile_h_ #include "fitshead.h" /* FITS table keyword structure */ struct Keyword { char kname[10]; /* Keyword for table entry */ int lname; /* Length of keyword name */ int kn; /* Index of entry on line */ int kf; /* Index in line of first character of entry */ int kl; /* Length of entry value */ }; #define FITSBLOCK 2880 /* Declarations for subroutines in fitsfile.c, imhfile.c, imio.c, * fileutil.c, and dateutil.c */ /* FITS file access subroutines in fitsfile.c */ int fitsropen( /* Open a FITS file for reading, returning a FILE pointer */ char *inpath); /* Pathname for FITS tables file to read */ char *fitsrhead( /* Read a FITS header */ char *filename, /* Name of FITS image file */ int *lhead, /* Allocated length of FITS header in bytes (returned) */ int *nbhead); /* Number of bytes before start of data (returned) */ char *fitsrtail( /* Read FITS header appended to graphics file */ char *filename, /* Name of FITS image file */ int *lhead, /* Allocated length of FITS header in bytes (returned) */ int *nbhead); /* Number of bytes before start of data (returned) */ char *fitsrimage( /* Read a FITS image */ char *filename, /* Name of FITS image file */ int *nbhead), /* Actual length of image header(s) in bytes */ char *header, /* FITS header for image (previously read) */ char *fitsrfull( /* Read a FITS image of any dimension */ char *filename, /* Name of FITS image file */ int *nbhead), /* Actual length of image header(s) in bytes */ char *header, /* FITS header for image (previously read) */ char *fitsrsect( /* Read a piece of a FITS image, header */ char *filename, /* Name of FITS image file */ char *header, /* FITS header for image (previously read) */ int *nbhead, /* Actual length of image header(s) in bytes */ int x0, y0, /* FITS image coordinate of first pixel */ int nx, /* Number of columns to read (less than NAXIS1) */ int ny, /* Number of rows to read (less than NAXIS2) */ int nlog); /* Note progress mod this rows */ int fitswhead( /* Write FITS header; keep file open for further writing */ char *filename, /* Name of FITS image file */ char *header); /* FITS header for image (previously read) */ int fitswexhead( /* Write FITS header in place */ char *filename, /* Name of FITS image file */ char *header); /* FITS header for image */ int fitswext( /* Write FITS header and image as extension to a file */ char *filename, /* Name of FITS image file */ char *header, /* FITS image header */ char *image); /* FITS image pixels */ int fitswhdu( /* Write FITS head and image as extension */ int fd, /* File descriptor */ char *filename, /* Name of FITS image file */ char *header, /* FITS image header */ char *image); /* FITS image pixels */ int fitswimage( /* Write FITS header and image */ char *filename, /* Name of FITS image file */ char *header, /* FITS image header */ char *image); /* FITS image pixels */ int fitscimage( /* Write FITS header and copy FITS image */ char *filename, /* Name of output FITS image file */ char *header, /* FITS image header */ char *filename0); /* Name of input FITS image file */ int isfits( /* Return 1 if file is a FITS file */ char *filename); /* Name of file to check */ void fitserr(); /* Print FITS error message to stderr */ void setfitsinherit( /* Set flag to append primary data header */ int inh); /* 1 to inherit primary data header, else 0 */ int fitsheadsize( /* Return size of fitsheader in bytes */ char *header); /* FITS image header */ /* FITS table file access subroutines in fitsfile.c */ int fitsrtopen( /* Open FITS table file and fill structure with * pointers to selected keywords * Return file descriptor (-1 if unsuccessful) */ char *inpath, /* Pathname for FITS tables file to read */ int *nk, /* Number of keywords to use */ struct Keyword **kw, /* Structure for desired entries */ int *nrows, /* Number of rows in table (returned) */ int *nchar, /* Number of characters in one table row (returned) */ int *nbhead); /* Number of characters before table starts */ int fitsrthead( /* Read pointers to selected keywords * from FITS table header */ char *header, /* Header for FITS tables file */ int *nk, /* Number of keywords to use */ struct Keyword **kw, /* Structure for desired entries */ int *nrows, /* Number of rows in table (returned) */ int *nchar); /* Number of characters in one table row (returned) */ void fitsrtlset(); /* Reset FITS Table buffer limits from start of data */ int fitsrtline( /* Return specified line of FITS table */ int fd, /* File descriptor for FITS file */ int nbhead, /* Number of bytes in FITS header */ int lbuff, /* Number of bytes in table buffer */ char *tbuff, /* FITS table buffer */ int irow, /* Number of table row to read */ int nbline, /* Number of bytes to read for this line */ char *line); /* One line of FITS table (returned) */ short ftgeti2( /* Extract column for keyword from FITS table line * as short */ char *entry, /* Row or entry from table */ struct Keyword *kw); /* Table column information from FITS header */ int ftgeti4( /* Extract column for keyword from FITS table line * as int */ char *entry, /* Row or entry from table */ struct Keyword *kw); /* Table column information from FITS header */ float ftgetr4( /* Extract column for keyword from FITS table line * as float */ char *entry, /* Row or entry from table */ struct Keyword *kw); /* Table column information from FITS header */ double ftgetr8( /* Extract column for keyword from FITS table line * as double */ char *entry, /* Row or entry from table */ struct Keyword *kw); /* Table column information from FITS header */ int ftgetc( /* Extract column for keyword from FITS table line * as char string */ char *entry, /* Row or entry from table */ struct Keyword *kw, /* Table column information from FITS header */ char *string, /* Returned string */ int maxchar); /* Maximum number of characters in returned string */ /* IRAF file access subroutines in imhfile.c */ char *irafrhead( /* Read IRAF .imh header file and translate to FITS header */ char *filename, /* Name of IRAF header file */ int *lihead); /* Length of IRAF image header in bytes (returned) */ char *irafrimage( /* Read IRAF image pixels (call after irafrhead) */ char *fitsheader); /* FITS image header (filled) */ int irafwhead( /* Write IRAF .imh header file */ char *hdrname, /* Name of IRAF header file */ int lhead, /* Length of IRAF header */ char *irafheader, /* IRAF header */ char *fitsheader); /* FITS image header */ int irafwimage( /* Write IRAF .imh header file and .pix image file */ char *hdrname, /* Name of IRAF header file */ int lhead, /* Length of IRAF header */ char *irafheader, /* IRAF header */ char *fitsheader, /* FITS image header */ char *image); /* IRAF image */ int isiraf( /* return 1 if IRAF imh file, else 0 */ char *filename); /* Name of file to check */ char *iraf2fits( /* Convert IRAF image header to FITS image header, * returning FITS header */ char *hdrname, /* IRAF header file name (may be path) */ char *irafheader, /* IRAF image header */ int nbiraf, /* Number of bytes in IRAF header */ int *nbfits); /* Number of bytes in FITS header (returned) */ char *fits2iraf( /* Convert FITS image header to IRAF image header, * returning IRAF header */ char *fitsheader, /* FITS image header */ char *irafheader, /* IRAF image header (returned updated) */ int nbhead, /* Length of IRAF header */ int *nbiraf); /* Length of returned IRAF header */ /* Image pixel access subroutines in imio.c */ double getpix( /* Read one pixel from any data type 2-D array (0,0)*/ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel * 16 = short, -16 = unsigned short, 32 = int * -32 = float, -64 = double */ int w; /* Image width in pixels */ int h; /* Image height in pixels */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int x, /* Zero-based horizontal pixel number */ int y); /* Zero-based vertical pixel number */ double getpix1( /* Read one pixel from any data type 2-D array (1,1)*/ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ int w; /* Image width in pixels */ int h; /* Image height in pixels */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int x, /* One-based horizontal pixel number */ int y); /* One-based vertical pixel number */ double maxvec( /* Get maximum value in vector from a image */ char *image, /* Image array from which to extract vector */ int bitpix, /* Number of bits per pixel in image */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int pix1, /* Offset of first pixel to extract */ int npix); /* Number of pixels to extract */ void putpix( /* Write one pixel to any data type 2-D array (0,0)*/ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ int w; /* Image width in pixels */ int h; /* Image height in pixels */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int x, /* Zero-based horizontal pixel number */ int y, /* Zero-based vertical pixel number */ double dpix); /* Value to put into image pixel */ void putpix1( /* Write one pixel to any data type 2-D array (1,1) */ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ int w; /* Image width in pixels */ int h; /* Image height in pixels */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int x, /* One-based horizontal pixel number */ int y, /* One-based vertical pixel number */ double dpix); /* Value to put into image pixel */ void addpix( /* Add to one pixel in any data type 2-D array (0,0)*/ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ int w; /* Image width in pixels */ int h; /* Image height in pixels */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int x, /* Zero-based horizontal pixel number */ int y, /* Zero-based vertical pixel number */ double dpix); /* Value to add to image pixel */ void addpix1( /* Add to one pixel in any data type 2-D array (1,1)*/ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ int w; /* Image width in pixels */ int h; /* Image height in pixels */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int x, /* One-based horizontal pixel number */ int y, /* One-based vertical pixel number */ double dpix); /* Value to add to image pixel */ void movepix( /* Move one pixel value between two 2-D arrays (0,0) */ char *image1, /* Pointer to first pixel in input image */ int bitpix1, /* Bits per input pixel (FITS codes) */ int w1, /* Number of horizontal pixels in input image */ int x1, y1); /* Zero-based row and column for input pixel */ char *image2, /* Pointer to first pixel in output image */ int bitpix2, /* Bits per output pixel (FITS codes) */ int w2, /* Number of horizontal pixels in output image */ int x2, y2); /* Zero-based row and column for output pixel */ void movepix1( /* Move one pixel value between two 2-D arrays (1,1) */ char *image1, /* Pointer to first pixel in input image */ int bitpix1, /* Bits per input pixel (FITS codes) */ int w1, /* Number of horizontal pixels in input image */ int x1, y1); /* One-based row and column for input pixel */ char *image2, /* Pointer to first pixel in output image */ int bitpix2, /* Bits per output pixel (FITS codes) */ int w2, /* Number of horizontal pixels in output image */ int x2, y2); /* One-based row and column for output pixel */ /* Image vector processing subroutines in imio.c */ void addvec( /* Add constant to vector from 2-D array */ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int pix1, /* Offset of first pixel to which to add */ int npix, /* Number of pixels to which to add */ double dpix); /* Value to add to pixels */ void multvec( /* Multiply vector from 2-D array by a constant */ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int pix1, /* Offset of first pixel to multiply */ int npix, /* Number of pixels to multiply */ double dpix); /* Value to add to pixels */ void getvec( /* Read vector from 2-D array */ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int pix1, /* Offset of first pixel to extract */ int npix, /* Number of pixels to extract */ double *dvec0); /* Vector of pixels (returned) */ void putvec( /* Write vector into 2-D array */ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int pix1, /* Offset of first pixel to insert */ int npix, /* Number of pixels to insert */ double *dvec0); /* Vector of pixels to insert */ void fillvec( /* Write constant into a vector */ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int pix1, /* Zero-based offset of first pixel to multiply */ int npix, /* Number of pixels to multiply */ double dpix); /* Value to which to set pixels */ void fillvec1( /* Write constant into a vector */ char *image, /* Image array as 1-D vector */ int bitpix, /* FITS bits per pixel */ double bzero, /* Zero point for pixel scaling */ double bscale, /* Scale factor for pixel scaling */ int pix1, /* One-based offset of first pixel to multiply */ int npix, /* Number of pixels to multiply */ double dpix); /* Value to which to set pixels */ /* Image pixel byte-swapping subroutines in imio.c */ void imswap( /* Swap alternating bytes in a vector */ int bitpix, /* Number of bits per pixel */ char *string, /* Address of starting point of bytes to swap */ int nbytes); /* Number of bytes to swap */ void imswap2( /* Swap bytes in a vector of 2-byte (short) integers */ char *string, /* Address of starting point of bytes to swap */ int nbytes); /* Number of bytes to swap */ void imswap4( /* Reverse bytes in a vector of 4-byte numbers */ char *string, /* Address of starting point of bytes to swap */ int nbytes); /* Number of bytes to swap */ void imswap8( /* Reverse bytes in a vector of 8-byte numbers */ char *string, /* Address of starting point of bytes to swap */ int nbytes); /* Number of bytes to swap */ int imswapped(); /* Return 1 if machine byte order is not FITS order */ /* File utilities from fileutil.c */ int getfilelines( /* Return number of lines in an ASCII file */ char *filename); /* Name of file to check */ char *getfilebuff( /* Return entire file contents in a character string */ char *filename); /* Name of file to read */ int getfilesize( /* Return size of a binary or ASCII file */ char *filename); /* Name of file to check */ int isimlist( /* Return 1 if file is list of FITS or IRAF image files, else 0 */ char *filename); /* Name of file to check */ int isimlistd( /* Return 1 if file is list of FITS or IRAF image files, else 0 */ char *filename, /* Name of file to check */ char *rootdir); /* Name of root directory for files in list */ int isfilelist( /* Return 1 if list of readable files, else 0 */ char *filename); /* Name of file to check */ char *rootdir); /* Name of root directory for files in list */ int isfile( /* Return 1 if file is a readable file, else 0 */ char *filename); /* Name of file to check */ int istiff( /* Return 1 if TIFF image file, else 0 */ char *filename); /* Name of file to check */ int isjpeg( /* Return 1 if JPEG image file, else 0 */ char *filename); /* Name of file to check */ int isgif( /* Return 1 if GIF image file, else 0 */ char *filename); /* Name of file to check */ int first_token( /* Return first token from the next line of an ASCII file */ FILE *diskfile, /* File descriptor for ASCII file */ int ncmax, /* Maximum number of characters returned */ char *token); /* First token on next line (returned) */ int stc2s ( /* Replace character in string with space */ char spchar, /* Character to replace with spaces */ char *string); /* Character string to process */ int sts2c ( /* Replace spaces in string with character */ char spchar, /* Character with which to replace spaces */ char *string); /* Character string to process */ /* Subroutines for translating dates and times in dateutil.c */ /* Subroutines to convert from year and day of year */ void doy2dt( /* Year and day of year to yyyy.mmdd hh.mmss */ int year, /* Year */ double doy, /* Day of year with fraction */ double *date, /* Date as yyyy.mmdd (returned) */ double *time); /* Time as hh.mmssxxxx (returned) */ double doy2ep( /* Year and day of year to fractional year (epoch) */ int year, /* Year */ double doy); /* Day of year with fraction */ double doy2epb( /* year and day of year to Besselian epoch */ int year, /* Year */ double doy); /* Day of year with fraction */ double doy2epj( /* year and day of year to Julian epoch */ int year, /* Year */ double doy); /* Day of year with fraction */ char *doy2fd( /* year and day of year to FITS date */ int year, /* Year */ double doy); /* Day of year with fraction */ double doy2jd( /* year and day of year to Julian Day */ int year, /* Year */ double doy); /* Day of year with fraction */ double doy2mjd( /* year and day of year to Modified Julian Day */ int year, /* Year */ double doy); /* Day of year with fraction */ double doy2ts( /* year and day of year to seconds since 1950.0 */ int year, /* Year */ double doy); /* Day of year with fraction */ int doy2tsi( /* year and day of year to IRAF seconds since 1980-01-01 */ int year, /* Year */ double doy); /* Day of year with fraction */ time_t doy2tsu( /* year and day of year to Unix seconds since 1970-01-01 */ int year, /* Year */ double doy); /* Day of year with fraction */ /* Subroutines to convert from date and time */ void dt2doy( /* yyyy.mmdd hh.mmss to year and day of year */ double date, /* Date as yyyy.mmdd * yyyy = calendar year (e.g. 1973) * mm = calendar month (e.g. 04 = april) * dd = calendar day (e.g. 15) */ double time; /* Time as hh.mmssxxxx * if time<0, it is time as -(fraction of a day) * hh = hour of day (0 .le. hh .le. 23) * nn = minutes (0 .le. nn .le. 59) * ss = seconds (0 .le. ss .le. 59) * xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ int *year, /* Year (returned) */ double *doy); /* Day of year with fraction (returned) */ double dt2ep( /* yyyy.ddmm and hh.mmsss to fractional year (epoch) */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ double dt2epb( /* yyyy.ddmm and hh.mmsss to Besselian epoch */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ double dt2epj( /* yyyy.ddmm and hh.mmsss to Julian epoch */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ char *dt2fd( /* yyyy.ddmm and hh.mmsss to FITS date string */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ void dt2i( /* yyyy.ddmm and hh.mmsss to year, month, day, hrs, min, sec */ double date, /* Date as yyyy.mmdd */ double time, /* Time as hh.mmssxxxx */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ double dt2jd( /* yyyy.ddmm and hh.mmsss to Julian Day */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ double dt2mjd( /* yyyy.ddmm and hh.mmsss to Modified Julian Day */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ double dt2ts( /* yyyy.ddmm and hh.mmsss to seconds since 1950.0 */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ int dt2tsi( /* yyyy.ddmm and hh.mmsss to IRAF seconds since 1980-01-01 */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ time_t dt2tsu( /* yyyy.ddmm and hh.mmsss to Unix seconds since 1970-01-01 */ double date, /* Date as yyyy.mmdd */ double time); /* Time as hh.mmssxxxx */ /* Subroutines to convert from epoch (various types of fractional year) */ void ep2dt( /* Fractional year to yyyy.mmdd hh.mmssss */ double epoch, /* Date as fractional year */ double *date, /* Date as yyyy.mmdd (returned) */ double *time); /* Time as hh.mmssxxxx (returned) */ void epb2dt( /* Besselian epoch to yyyy.mmdd hh.mmssss */ double epoch, /* Besselian epoch (fractional 365.242198781-day years) */ double *date, /* Date as yyyy.mmdd (returned) */ double *time); /* Time as hh.mmssxxxx (returned) */ void epj2dt( /* Julian epoch to yyyy.mmdd hh.mmssss */ double epoch, /* Julian epoch (fractional 365.25-day years) */ double *date, /* Date as yyyy.mmdd (returned)*/ double *time); /* Time as hh.mmssxxxx (returned) */ char *ep2fd( /* Fractional year to FITS date string yyyy-mm-ddThh:mm:ss.ss */ double epoch); /* Date as fractional year */ char *epb2fd( /* Besselian epoch to FITS date string yyyy-mm-ddThh:mm:ss.ss */ double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ char *epj2fd( /* Julian epoch to FITS date string yyyy-mm-ddThh:mm:ss.ss */ double epoch); /* Julian epoch (fractional 365.25-day years) */ void ep2i( /* Fractional year to year, month, day, hours, min., sec. */ double epoch, /* Date as fractional year */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ void epb2i( /* Besselian epoch to year, month, day, hours, min., sec. */ double epoch, /* Besselian epoch (fractional 365.242198781-day years) */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ void epj2i( /* Julian epoch to year, month, day, hours, min., sec. */ double epoch, /* Julian epoch (fractional 365.25-day years) */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ double ep2jd( /* Fractional year to Julian Date */ double epoch); /* Date as fractional year */ double epb2jd( /* Besselian epoch to Julian Date */ double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ double epj2jd( /* Julian epoch to Julian Date */ double epoch); /* Julian epoch (fractional 365.25-day years) */ double ep2mjd( /* Fractional year to Modified Julian Date */ double epoch); /* Date as fractional year */ double epb2mjd( /* Besselian epoch to Modified Julian Date */ double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ double epj2mjd( /* Julian epoch to Modified Julian Date */ double epoch); /* Julian epoch (fractional 365.25-day years) */ double ep2epb( /* Fractional year to Besselian epoch */ double epoch); /* Date as fractional year */ double ep2epj( /* Fractional year to Julian epoch */ double epoch); /* Date as fractional year */ double epb2epj( /* Besselian epoch to Julian epoch */ double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ double epj2epb( /* Julian epoch to Besselian epoch */ double epoch); /* Julian epoch (fractional 365.25-day years) */ double epb2ep( /* Besselian epoch to fractional year */ double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ double epj2ep( /* Julian epoch to fractional year */ double epoch); /* Julian epoch (fractional 365.25-day years) */ double ep2ts( /* Fractional year to seconds since 1950.0 */ double epoch); /* Date as fractional year */ double epb2ts( /* Besselian epoch to seconds since 1950.0 */ double epoch); /* Besselian epoch (fractional 365.242198781-day years) */ double epj2ts( /* Julian epoch to seconds since 1950.0 */ double epoch); /* Julian epoch (fractional 365.25-day years) */ /* Convert from FITS standard date string */ void fd2dt( /* FITS standard date string to date and time */ char *string; /* FITS date string, which may be: * fractional year * dd/mm/yy (FITS standard before 2000) * dd-mm-yy (nonstandard use before 2000) * yyyy-mm-dd (FITS standard after 1999) * yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ double *date, /* Date as yyyy.mmdd (returned)*/ double *time); /* Time as hh.mmssxxxx (returned) */ void fd2doy( /* FITS standard date string to year, day of year */ char *string, /* FITS date string */ int *year, /* Year (returned) */ double *doy); /* Day of year with fraction (returned) */ double fd2ep( /* FITS standard date string to fractional year (epoch) */ char *string); /* FITS date string */ double fd2epb( /* FITS standard date string to Besselian epoch */ char *string); /* FITS date string */ double fd2epj( /* FITS standard date string to Julian epoch */ char *string); /* FITS date string */ char *fd2fd( /* Any FITS standard date string to ISO FITS date string */ char *string); /* FITS date string */ char *fd2of( /* Any FITS standard date string to old FITS date and time */ char *string); /* FITS date string */ char *fd2ofd( /* Any FITS standard date string to old FITS date string */ char *string); /* FITS date string */ char *fd2oft( /* Any FITS standard date string to old FITS time string */ char *string); /* FITS date string */ void fd2i( /* FITS standard date string to year, mon, day, hrs, min, sec */ char *string, /* FITS date string */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ double fd2jd( /* FITS standard date string to Julian Day */ char *string); /* FITS date string */ double fd2mjd( /* FITS standard date string to Modified Julian Day */ char *string); /* FITS date string */ double fd2ts( /* FITS standard date to seconds since 1950-01-01 */ char *string); /* FITS date string */ int fd2tsi( /* FITS standard date to IRAF seconds since 1980-01-01 */ char *string); /* FITS date string */ time_t fd2tsu( /* FITS standard date to Unix seconds since 1970-01-01 */ char *string); /* FITS date string */ /* Convert from Julian Day */ void jd2doy( /* Julian Day to year and day of year */ double dj, /* Julian Day */ int *year, /* Year (returned) */ double *doy); /* Day of year with fraction (returned) */ void jd2dt( /* Julian Day to yyyy.mmdd hh.mmssss */ double dj, /* Julian Day */ double *date, /* Date as yyyy.mmdd (returned)*/ double *time); /* Time as hh.mmssxxxx (returned) */ double jd2ep( /* Julian Day to fractional year */ double dj); /* Julian Day */ double jd2epb( /* Julian Day to Besselian epoch */ double dj); /* Julian Day */ double jd2epj( /* Julian Day to Julian epoch */ double dj); /* Julian Day */ char *jd2fd( /* Julian Day to FITS date string yyyy-mm-ddThh:mm:ss.ss */ double dj); /* Julian Day */ void jd2i( /* Julian Day to year, month, day, hours, min., sec. */ double dj, /* Julian Day */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ double jd2mjd( /* Julian Day to Modified Julian day */ double dj); /* Julian Day */ double jd2ts( /* Julian Day to seconds since 1950.0 */ double dj); /* Julian Day */ time_t jd2tsu( /* Julian Day to Unix seconds since 1970-01-01T00:00 */ double dj); /* Julian Day */ int jd2tsi( /* Julian Day to IRAF seconds since 1980-01-01T00:00 */ double dj); /* Julian Day */ /* Convert current local time to various formats */ void lt2dt( /* Current local time to date (yyyy.mmdd), time (hh.mmsss) */ double *date, /* Date as yyyy.mmdd (returned) */ double *time); /* Time as hh.mmssxxxx (returned) */ char *lt2fd(); /* Current local time to FITS ISO date string */ int lt2tsi(); /* Current local time to IRAF seconds since 1980-01-01T00:00 */ time_t lt2tsu(); /* Current local time to Unix seconds since 1970-01-01T00:00 */ double lt2ts(); /* Current local time to IRAF seconds since 1950-01-01T00:00 */ /* Convert from Modified Julian Day (JD - 2400000.5) */ void mjd2doy( /* Modified Julian Day to year and day of year */ double dj, /* Modified Julian Day */ int *year, /* Year (returned) */ double *doy); /* Day of year with fraction (returned) */ void mjd2dt( /* Modified Julian Day to yyyy.mmdd hh.mmssss */ double dj, /* Modified Julian Date */ double *date, /* Date as yyyy.mmdd (returned)*/ double *time); /* Time as hh.mmssxxxx (returned) */ double mjd2ep( /* Modified Julian Day to fractional year */ double dj); /* Modified Julian Date */ double mjd2epb( /* Modified Julian Day to Besselian epoch */ double dj); /* Modified Julian Date */ double mjd2epj( /* Modified Julian Day to Julian epoch */ double dj); /* Modified Julian Date */ char *mjd2fd( /* Modified Julian Day to FITS date yyyy-mm-ddThh:mm:ss.ss */ double dj); /* Modified Julian Date */ void mjd2i( /* Modified Julian Day to year, month, day, hours, min, sec */ double dj, /* Modified Julian Date */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ double mjd2jd( /* Modified Julian Day to Julian day */ double dj); /* Modified Julian Date */ double mjd2ts( /* Modified Julian Day to seconds since 1950.0 */ double dj); /* Modified Julian Date */ /* Convert from seconds since 1950-01-01 0:00 (JPL Ephemeris time) */ void ts2dt( /* Seconds since 1950.0 to yyyy.mmdd hh.mmssss */ double tsec, /* seconds since 1950.0 */ double *date, /* Date as yyyy.mmdd (returned)*/ double *time); /* Time as hh.mmssxxxx (returned) */ double ts2ep( /* Seconds since 1950.0 to fractional year */ double tsec); /* seconds since 1950.0 */ double ts2epb( /* Seconds since 1950.0 to Besselian epoch */ double tsec); /* seconds since 1950.0 */ double ts2epj( /* Seconds since 1950.0 to Julian epoch */ double tsec); /* seconds since 1950.0 */ char *ts2fd( /* Seconds since 1950.0 to FITS date, yyyy-mm-ddT00:00:00.000 */ double tsec); /* seconds since 1950.0 */ void ts2i( /* Seconds since 1950.0 to year, month, day, hours, min, sec */ double tsec, /* seconds since 1950.0 */ int *iyr, /* year (returned) */ int *imon, /* month (returned) */ int *iday, /* day (returned) */ int *ihr, /* hours (returned) */ int *imn, /* minutes (returned) */ double *sec, /* seconds (returned) */ int ndsec); /* Number of decimal places in seconds (0=int) */ double ts2jd( /* Seconds since 1950.0 to Julian Day */ double tsec); /* seconds since 1950.0 */ double ts2mjd( /* Seconds since 1950.0 to Modified Julian Day */ double tsec); /* seconds since 1950.0 */ /* Convert from IRAF time (seconds since 1980-01-01 0:00 UT) */ char *tsi2fd( /* Seconds since 1980-01-01 to FITS standard date string */ double tsi2ts( /* Seconds since 1980-01-01 to seconds since 1950-01-01 */ double tsi2ts( /* Seconds since 1980-01-01 to seconds since 1950-01-01 */ void tsi2dt( /* Seconds since 1980-01-01 to date yyyy.mmdd, time hh.mmssss */ /* Convert from Unix time (seconds since 1970-01-01 0:00 UT) */ void tsu2dt( /* Seconds since 1970-01-01 to date yyyy.ddmm, time hh.mmsss */ char *tsu2fd( /* Seconds since 1970-01-01 to FITS standard date string */ char *tsd2fd( /* Seconds since start of day to FITS standard time string */ double tsu2ts( /* Seconds since 1970-01-01 to seconds since 1950-01-01 */ int tsu2tsi( /* Seconds since 1970-01-01 to local seconds since 1980-01-01 */ /* Convert from current Universal Time */ void ut2dt( /* Current Universal Time to date (yyyy.mmdd), time (hh.mmsss) */ void ut2doy( /* Current Universal Time to year, day of year */ double ut2ep( /* Current Universal Time to fractional year */ double ut2epb( /* Current Universal Time to Besselian Epoch */ double ut2epj( /* Current Universal Time to Julian Epoch */ char *ut2fd( /* Current Universal Time to FITS ISO date string */ double ut2jd( /* Current Universal Time to Julian Date */ double ut2mjd( /* Current Universal Time to Modified Julian Date */ int ut2tsi( /* Current UT to IRAF seconds since 1980-01-01T00:00 */ time_t ut2tsu( /* Current UT to Unix seconds since 1970-01-01T00:00 */ double ut2ts( /* Current UT to IRAF seconds since 1950-01-01T00:00 */ double tsd2dt( /* Seconds since start of day to hh.mmsssss */ int isdate( /* Return 1 if string is FITS old or ISO date */ int sts2c( /* Replaces spaces in a string with a specified character */ int stc2s( /* Replaces a specified character in a string with spaces */ /* Ephemeris time conversions (ET, TT, and TDT) */ char *et2fd( /* ET (or TDT or TT) in FITS format to UT in FITS format */ char *string); /* Ephemeris Time as FITS date string (E not T) */ char *fd2et( /* UT in FITS format to ET (or TDT or TT) in FITS format */ char *string); /* FITS date string */ void dt2et( /* yyyy.ddmm and hh.mmsss to Ephemeris Time */ double *date, /* Date as yyyy.mmdd */ double *time); /* Time as hh.mmssxxxx *if time<0, it is time as -(fraction of a day) */ double jd2jed( /* Convert from Julian Date to Julian Ephemeris Date */ double dj); /* Julian Date */ double jed2jd( /* Convert from Julian Ephemeris Date to Julian Date */ double dj); /* Julian Ephemeris Date */ double ets2ts( /* ET in seconds since 1950-01-01 to UT in same format */ double tsec); /* ET in seconds since 1950-01-01 */ double ts2ets( /* UT in seconds since 1950-01-01 to ET in same format */ double tsec); /* UT in seconds since 1950-01-01 */ void edt2dt( /* yyyy.ddmm and hh.mmsss Ephemeris Time to UT */ double *date; /* Date as yyyy.mmdd */ double *time; /* Time as hh.mmssxxxx * If time<0, it is time as -(fraction of a day) */ double utdt( /* Compute difference between UT and dynamical time (ET-UT) */ double dj); /* Julian Date (UT) */ /* Sidereal Time conversions */ char *fd2gst( /* Convert from FITS UT date to Greenwich Sidereal Time */ char *string); /* FITS date string */ void dt2gst( /* Convert from UT as yyyy.mmdd hh.mmssss to Greenwich Sidereal Time */ double *date, /* Date as yyyy.mmdd */ double *time); /* Time as hh.mmssxxxx * If time<0, it is time as -(fraction of a day) */ double jd2gst( /* Calculate Greenwich Sidereal Time given Julian Date */ double dj); /* Julian Date (UT) */ double ts2gst( /* Calculate Greenwich Sidereal Time given Universal Time */ double tsec); /* Time since 1950.0 in UT seconds */ char *fd2lst( /* Convert from FITS UT date to Local Sidereal Time */ char *string); /* FITS date string */ void dt2lst( /* Convert from UT as yyyy.mmdd hh.mmssss to Local Sidereal Time */ double *date, /* Date as yyyy.mmdd */ double *time); /* Time as hh.mmssxxxx * If time<0, it is time as -(fraction of a day) */ double ts2lst( /* Calculate Local Sidereal Time given Universal Time */ double tsec); /* Time since 1950.0 in UT seconds */ double jd2lst( /* Calculate Local Sidereal Time given Julian Date */ double dj); /* Julian Date (UT) */ double eqeqnx( /* Compute equation of eqinoxes from Julian Date */ double dj); /* Julian Date (UT) */ char *fd2mst( /* Convert from FITS UT date to Mean Sidereal Time */ char *string); /* FITS date string */ double jd2mst( /* Convert from Julian Date to Mean Sidereal Time */ double dj); /* Julian Date (UT) */ double jd2mst2( /* Convert from Julian Date to Mean Sidereal Time */ double dj); /* Julian Date (UT) */ void dt2mst( /* Convert from UT as yyyy.mmdd hh.mmssss to Mean Sidereal Time */ double *date, /* Date as yyyy.mmdd */ double *time); /* Time as hh.mmssxxxx * If time<0, it is time as -(fraction of a day) */ double lst2dt( /* Calculate UT as hh.mmsss given UT date and * Local Sidereal Time */ double date0; /* UT date as yyyy.mmdd */ double time0; /* LST as hh.mmssss */ double lst2jd( /* Calculate UT as Julian Date given UT date and * Local Sidereal Time */ double sdj); /* Julian Date of desired day at 0:00 UT + sidereal time */ char *lst2fd( /* Calculate FITS UT date and time given UT date and * Local Sidereal Time */ char *string); /* UT Date, LST as yyyy-mm-ddShh:mm:ss.ss */ char *gst2fd( /* Calculate FITS UT date and time given Greenwich Sidereal Time */ char *string); /* UT Date, GST as yyyy-mm-ddShh:mm:ss.ss */ double gst2jd( /* Calculate FITS UT Julian Date given Greenwich Sidereal Time */ double sdj); /* UT Date, GST as Julian Date */ char *mst2fd( /* Calculate FITS UT date and time given Mean Sidereal Time */ char *string); /* UT Date, MST as yyyy-mm-ddShh:mm:ss.ss */ double mst2jd( /* Calculate FITS UT Julian Date given Mean Sidereal Time */ double sdj); /* UT Date, MST as Julian Date */ double ts2mst( /* Calculate Mean Sidereal Time given Universal Time */ double tsec); /* time since 1950.0 in UT seconds */ void setlongitude( /* Longitude for sidereal time in or out */ double longitude); /* longitude of observatory in degrees (+=west) */ void compnut( /* Compute nutation in longitude and obliquity and mean obliquity*/ double dj, /* TDB (loosely ET or TT) as Julian Date */ double *dpsi, /* Nutation in longitude in radians (returned) */ double *deps, /* Nutation in obliquity in radians (returned) */ double *eps0); /* Mean obliquity in radians (returned) */ /* Heliocentric Julian Date conversions */ double mjd2mhjd( /* Convert from Modified Julian Date to Heliocentric MJD */ double mjd, /* Julian date (geocentric) */ double ra, /* Right ascension (degrees) */ double dec, /* Declination (degrees) */ int sys); /* J2000, B1950, GALACTIC, ECLIPTIC */ double mjd2hjd( /* Convert from Modified Julian Date to Heliocentric JD */ double mjd, /* Julian date (geocentric) */ double ra, /* Right ascension (degrees) */ double dec, /* Declination (degrees) */ int sys); /* J2000, B1950, GALACTIC, ECLIPTIC */ double mhjd2mjd( /* Convert from Heliocentric Modified Julian Date to MJD */ double mhjd, /* Modified Heliocentric Julian date */ double ra, /* Right ascension (degrees) */ double dec, /* Declination (degrees) */ int sys); /* J2000, B1950, GALACTIC, ECLIPTIC */ double jd2hjd( /* Convert from Julian Date to Heliocentric Julian Date */ double dj, /* Julian date (geocentric) */ double ra, /* Right ascension (degrees) */ double dec, /* Declination (degrees) */ int sys); /* J2000, B1950, GALACTIC, ECLIPTIC */ double hjd2jd( /* Convert from Heliocentric Julian Date to Julian Date */ double dj, /* Heliocentric Julian date */ double ra, /* Right ascension (degrees) */ double dec, /* Declination (degrees) */ int sys); /* J2000, B1950, GALACTIC, ECLIPTIC */ void setdatedec( /* Set number of decimal places in FITS dates */ int nd); /* Number of decimal places in FITS dates */ wcstools-3.9.5/libwcs/wcscat1.h0000664000016200001660000025435111750060645015472 0ustar minkoirsys/*** File libwcs/wcscat.h *** January 10, 2007 *** By Jessica Mink, jmink@cfa.harvard.edu *** Copyright (C) 1998-2007 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #ifndef _wcscat_h_ #define _wcscat_h_ /* Data structure for SAO TDC ASCII and binary star catalog entries */ struct Star { float rdum; float xno; /* Catalog number */ double ra; /* Right Ascension (degrees) */ double dec; /* Declination (degrees) */ char isp[24]; /* Spectral type or other 2-char identifier */ short mag[11]; /* Up to 10 Magnitudes * 100 */ double rapm; /* RA proper motion (degrees per year) */ double decpm; /* Dec proper motion (degrees per year) */ double xmag[11]; /* Up to 10 Magnitudes */ double num; /* Actual star number */ int coorsys; /* Coordinate system (WCS_J2000, WCS_B1950,...) */ double equinox; /* Equinox of coordinate system as fractional year */ double epoch; /* Epoch of position as fractional year */ double parallax; /* Parallax in arcseconds */ double pxerror; /* Parallax error in arcseconds */ double radvel; /* Radial velocity in km/sec, positive away */ double dist; /* Distance from search center in arcseconds */ double size; /* Semi-major axis in arcseconds */ char *entry; /* Line copied from input catalog */ char objname[80]; /* Object name */ int peak; /* Peak flux per pixel in star image */ }; /* Catalog proper motion units */ #define PM_MASYR 1 /* milliarcseconds per year */ #define PM_ARCSECYR 2 /* arcseconds per year */ #define PM_DEGYR 3 /* degrees per year */ #define PM_RADYR 4 /* radians per year */ #define PM_TSECYR 5 /* seconds of time (RA) per century */ #define PM_ARCSECCEN 6 /* arcseconds per year */ #define PM_TSECCEN 7 /* seconds of time (RA) per century */ #define PM_MTSYR 8 /* milliseconds of time (RA) per year */ /* Data structure for SAO TDC ASCII and binary star catalogs */ struct StarCat { int star0; /* Subtract from star number for file sequence number */ int star1; /* First star number in file */ int nstars; /* Number of stars in file */ int stnum; /* Star number format in catalog file: <0: -stnum-character name at end instead of number 0: no star i.d. numbers 1: Real*4 star i.d. numbers 2: Integer*4 3: Integer*4 4: Integer*4 5: Character ID instead of number in ASCII files */ int mprop; /* 1 if proper motion is included */ /* 2 if radial velocity is included */ int nmag; /* Number of magnitudes present Negative for J2000 catalog */ int nbent; /* Number of bytes per star entry */ int rasorted; /* 1 if RA-sorted, else 0 */ int ignore; /* 1 if ignoring info after position and magnitude */ FILE *ifcat; /* File descriptor for catalog file */ char isfil[24]; /* Star catalog file name */ char isname[64]; /* Star catalog description */ int byteswapped; /* 1 if catalog is byte-reversed from CPU */ int refcat; /* Code for type of catalog (TXTCAT, BINCAT, etc.) */ int coorsys; /* Coordinate system B1950 J2000 Galactic Ecliptic */ double epoch; /* Epoch of catalog coordinates in years */ double equinox; /* Equinox of catalog coordinates in years */ char inform; /* Coordinate format (B>inary D>egrees H>MS T>able U>SNO) */ char incdir[128]; /* Catalog directory pathname */ char incfile[32]; /* Catalog file name */ int ncobj; /* Length of object name in binary star entry */ int nnfld; /* Length of star number */ int nndec; /* Number of decimal places in star number */ int nepoch; /* 1 if epoch of coordinates is present */ int sptype; /* 1 if spectral type is present in catalog */ int plate; /* 1 if plate or field number is present in catalog */ char *catbuff; /* Pointer to start of catalog */ char *catdata; /* Pointer to first entry in catalog */ char *catline; /* Pointer to current entry in catalog */ char *catlast; /* Pointer to one past end of last entry in catalog */ int istar; /* Number of current catalog entry */ struct TabTable *startab; /* Structure for tab table catalog */ int entid; /* Entry number for ID */ int entra; /* Entry number for right ascension */ int entdec; /* Entry number for declination */ int entmag[10]; /* Entry numbers for up to 10 magnitudes */ int entpeak; /* Entry number for peak counts */ int entepoch; /* Entry number for epoch of observation */ int entdate; /* Entry number for FITS-format date of observation */ int entname; /* Entry number for object name */ int entadd; /* Entry number for additional keyword */ int entrpm; /* Entry number for proper motion in right ascension */ int entdpm; /* Entry number for proper motion in declination */ int entpx; /* Entry number for parallax */ int entpxe; /* Entry number for parallax error */ int entrv; /* Entry number for radial velocity */ int enttype; /* Entry number for spectral type */ int entsize; /* Entry number for size of object */ int rpmunit; /* Units for RA proper motion (PM_x) */ int dpmunit; /* Units for DEC proper motion (PM_x) */ char *caturl; /* set if web search, else NULL */ char keyid[16]; /* Entry name for ID */ char keyra[16]; /* Entry name for right ascension */ char keydec[16]; /* Entry name for declination */ char keymag[10][16]; /* Entry name for up to 10 magnitudes */ char keyrpm[16]; /* Entry name for right ascension proper motion */ char keydpm[16]; /* Entry name for declination proper motion */ char keypeak[16]; /* Entry name for integer code */ char keytype[16]; /* Entry name for spectral type */ char keyrv[16]; /* Entry name for radial velocity */ char keyadd[16]; /* Entry name for additional keyword */ char keyepoch[16]; /* Entry name for epoch */ }; /* Data structure for tab table files */ struct TabTable { char *filename; /* Name of tab table file */ int nlines; /* Number of entries in table */ char *tabname; /* Name of this table or NULL */ char *tabbuff; /* Pointer to start of saved tab table in memory */ char *tabheader; /* Pointer to start of line containing table header */ char *tabhead; /* Pointer to start of line containing column heading */ char *tabdash; /* Pointer to start of line with dashes after column headings */ char *tabdata; /* Pointer to start of first line of table data */ int lhead; /* Number of bytes before first data line */ int iline; /* Number of current line (1=first) */ int lline; /* Length in bytes of line buffer */ char *tabline; /* Pointer to start of current line */ FILE *tcat; /* File descriptor for tab table file */ int ncols; /* Number of columns per table entry */ char **colname; /* Column names */ int *lcol; /* Lengths of column header names */ int *lcfld; /* Number of columns in field (hyphens) */ int lbuff; /* Number of bytes in entire tab table */ }; /* Source catalog flags and subroutines */ /* Source catalog flags returned from CatCode */ #define GSC 1 /* HST Guide Star Catalog */ #define UJC 2 /* USNO UJ Star Catalog */ #define UAC 3 /* USNO A Star Catalog */ #define USAC 4 /* USNO SA Star Catalog */ #define SAO 5 /* SAO Star Catalog */ #define IRAS 6 /* IRAS Point Source Catalog */ #define PPM 7 /* PPM Star Catalog */ #define TYCHO 8 /* Tycho Star Catalog */ #define UA1 9 /* USNO A-1.0 Star Catalog */ #define UA2 10 /* USNO A-2.0 Star Catalog */ #define USA1 11 /* USNO SA-1.0 Star Catalog */ #define USA2 12 /* USNO SA-2.0 Star Catalog */ #define HIP 13 /* Hipparcos Star Catalog */ #define ACT 14 /* USNO ACT Star Catalog */ #define BSC 15 /* Yale Bright Star Catalog */ #define TYCHO2 16 /* Tycho-2 Star Catalog */ #define USNO 17 /* USNO-format plate catalog */ #define TMPSC 18 /* 2MASS All-Sky Point Source Catalog */ #define GSCACT 19 /* GSC-ACT revised Guide Star Catalog */ #define GSC2 20 /* GSC II version 2.2 */ #define UB1 21 /* USNO B-1.0 Star Catalog */ #define UCAC1 22 /* USNO CCD Astrograph Catalog 1.0 */ #define UCAC2 23 /* USNO CCD Astrograph Catalog 2.0 */ #define TMIDR2 24 /* 2MASS IDR2 Point Source Catalog */ #define YB6 25 /* USNO YB6 Catalog */ #define SDSS 26 /* Sloan Digital Sky Survey Catalog */ #define TMXSC 27 /* 2MASS Extended Source Catalog */ #define TMPSCE 28 /* 2MASS Point Source Catalog with mag errors */ #define TYCHO2E 29 /* Tycho-2 Star Catalog with magnitude errors */ #define SKY2K 30 /* SKY2000 Master Catalog */ #define TABCAT -1 /* StarBase tab table catalog */ #define BINCAT -2 /* TDC binary catalog */ #define TXTCAT -3 /* TDC ASCII catalog */ #define WEBCAT -4 /* Tab catalog via the web */ #define NUMCAT 30 /* Number of predefined catalogs */ /* Structure for access to tokens within a string */ #define MAXTOKENS 1000 /* Maximum number of tokens to parse */ #define MAXWHITE 20 /* Maximum number of different whitespace characters */ struct Tokens { char *line; /* Line which has been parsed */ int lline; /* Number of characters in line */ int ntok; /* Number of tokens on line */ int nwhite; /* Number of whitespace characters */ char white[MAXWHITE]; /* Whitespace (separator) characters */ char *tok1[MAXTOKENS]; /* Pointers to start of tokens */ int ltok[MAXTOKENS]; /* Lengths of tokens */ int itok; /* Current token number */ }; #define EP_EP 1 /* Output epoch as fractional year */ #define EP_JD 2 /* Output epoch as Julian Date */ #define EP_MJD 3 /* Ouput epoch as Modified Julian Date */ #define EP_FD 4 /* Output epoch in FITS format (yyyy-mm-dd) */ #define EP_ISO 5 /* Output epoch in ISO format (yyyy-mm-ddThh:mm:ss) */ /* Structure for dealing with ranges */ #define MAXRANGE 20 struct Range { double first; /* Current minimum value */ double last; /* Current maximum value */ double step; /* Current step in value */ double value; /* Current value */ double ranges[MAXRANGE*3]; /* nranges sets of first, last, step */ int nvalues; /* Total number of values in all ranges */ int nranges; /* Number of ranges */ int irange; /* Index of current range */ }; /* Flags for sorting catalog search results */ #define SORT_UNSET -1 /* Catalog sort flag not set yet */ #define SORT_NONE 0 /* Do not sort catalog output */ #define SORT_MAG 1 /* Sort output by magnitude */ #define SORT_DIST 2 /* Sort output by distance from center */ #define SORT_RA 3 /* Sort output by right ascension */ #define SORT_DEC 4 /* Sort output by declination */ #define SORT_X 5 /* Sort output by image X coordinate */ #define SORT_Y 6 /* Sort output by image Y coordinate */ #define SORT_ID 7 /* Merge close catalog objects */ #define SORT_MERGE 8 /* Merge close catalog objects */ /* Shapes for SAOimage region file output */ #define WCS_CIRCLE 1 /* circle shape for SAOimage plotting */ #define WCS_SQUARE 2 /* square shape for SAOimage plotting */ #define WCS_DIAMOND 3 /* diamond shape for SAOimage plotting */ #define WCS_CROSS 4 /* cross shape for SAOimage plotting */ #define WCS_EX 5 /* x shape for SAOimage plotting */ #define WCS_VAR 6 /* variable (+ and x) shape for HSTGSC plotting */ #define WCS_PCIRCLE 11 /* pixel circle shape for SAOimage plotting */ #define WCS_PSQUARE 12 /* pixel square shape for SAOimage plotting */ #define WCS_PDIAMOND 13 /* pixel diamond shape for SAOimage plotting */ #define WCS_PCROSS 14 /* pixel cross shape for SAOimage plotting */ #define WCS_PEX 15 /* pixel ex shape for SAOimage plotting */ #define WCS_PVAR 16 /* pixel variable (+ and x) shape for HSTGSC plotting */ /* Subroutines for extracting sources from catalogs */ #ifdef __cplusplus extern "C" { #endif #ifdef __STDC__ /* Full ANSI prototypes */ /* Subroutines for reading any catalogs, including TDC ASCII catalogs */ int ctgread( /* Read sources by sky region from any catalog */ char *catfile, /* Name of reference star catalog file */ int refcat, /* Catalog code from wcscat.h */ int distsort, /* 1 to sort stars by distance from center */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nsmax, /* Maximum number of stars to be returned */ struct StarCat **starcat, /* Catalog data structure */ double *tnum, /* Array of ID numbers (returned) */ double *tra, /* Array of right ascensions (returned) */ double *tdec, /* Array of declinations (returned) */ double *tpra, /* Array of right ascension proper motions (returned) */ double *tpdec, /* Array of declination proper motions (returned) */ double **tmag, /* 2-D array of magnitudes (returned) */ int *tc, /* Array of fluxes (returned) */ char **tobj, /* Array of object names (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ctgrnum( /* Read sources by number from any catalog */ char *catfile, /* Name of reference star catalog file */ int refcat, /* Catalog code from wcscat.h */ int nnum, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ struct StarCat **starcat, /* Star catalog data structure */ int match, /* 1 to match star number exactly, else sequence num */ double *tnum, /* Array of source numbers to look for */ double *tra, /* Array of right ascensions (returned) */ double *tdec, /* Array of declinations (returned) */ double *tpra, /* Array of right ascension proper motions (returned) */ double *tpdec, /* Array of declination proper motions (returned) */ double **tmag, /* 2-D Array of magnitudes (returned) */ int *tpeak, /* Array of peak counts (returned) */ char **tkey, /* Array of values of additional keyword */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ctgrdate( /* Read sources by date from SAO TDC ASCII format catalog */ char *catfile, /* Name of reference star catalog file */ int refcat, /* Catalog code from wcscat.h */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ struct StarCat **starcat, /* Star catalog data structure */ double date1, /* Start time as Modified Julian Date or Julian Date */ double date2, /* End time as Modified Julian Date or Julian Date */ int nmax, /* Maximum number of stars to look for */ double *tnum, /* Array of source numbers (returned) */ double *tra, /* Array of right ascensions (returned) */ double *tdec, /* Array of declinations (returned) */ double *tpra, /* Array of right ascension proper motions (returned) */ double *tpdec, /* Array of declination proper motions (returned) */ double **tmag, /* 2-D Array of magnitudes (returned) */ int *tc, /* Array of fluxes (returned) */ char **tobj, /* Array of object names (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ctgbin( /* Bin sources from SAO TDC ASCII format catalog */ char *catfile, /* Name of reference star catalog file */ int refcat, /* Catalog code from wcscat.h */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude by which to sort (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ctgstar( /* Read one star entry from ASCII catalog, 0 if OK */ int istar, /* Star sequence number in ASCII catalog */ struct StarCat *sc, /* Star catalog data structure */ struct Star *st); /* Star data structure, updated on return */ int isacat( /* Return 1 if string is name of ASCII catalog file */ char *catpath); /* Path to file to check */ struct StarCat *ctgopen( /* Open a Starbase, TDC ASCII, or TDC binary catalog */ char *catfile, /* Name of reference star catalog file */ int refcat); /* Catalog code from wcscat.h */ void ctgclose( /* Close Starbase, TDC ASCII, or TDC binary catalog * and free data structures */ struct StarCat *sc); /* Star catalog data structure */ /* Subroutines for extracting sources from HST Guide Star Catalog */ int gscread( /* Read sources by sky region from HST Guide Star Catalog */ int refcat, /* Catalog code from wcscat.h (GSC or GSCACT) */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int nstarmax, /* Maximum number of stars to be returned */ double *gnum, /* Array of ID numbers (returned) */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int gscrnum( /* Read sources by ID number from HST Guide Star Catalog */ int refcat, /* Catalog code from wcscat.h (GSC or GSCACT) */ int nnum, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ int match, /* 1 to match star number exactly, else sequence num */ double *gnum, /* Array of source numbers to look for */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int gscbin( /* Bin sources from HST Guide Star Catalog */ int refcat, /* Catalog code from wcscat.h (GSC or GSCACT) */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ void setgsclass( /* Set GSC object class to return (<0=all) */ int class); /* Class of objects to return */ /* Subroutine to read GSC II catalog over the web */ int gsc2read( /* Read sources by sky region from GSC II Catalog */ char *refcatname, /* Name of catalog (GSC2 for 2.2; GSC2.3 for 2.3) */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *gnum, /* Array of ID numbers (returned) */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double *gpra, /* Array of right ascension proper motions (returned) */ double *gpdec, /* Array of declination proper motions (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ /* Subroutine to read SDSS catalog over the web */ int sdssread( /* Read sources by sky region from SDSS Catalog */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ char **gobj, /* Array of object IDs (too long for integer*4) */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ char *sdssc2t( /* Convert SDSS buffer from comma- to tab-separated */ char *csvbuff); /* Input comma-separated table */ /* Subroutines to read local copy of 2MASS Point Source Catalog */ int tmcread( /* Read sources by sky region from 2MASS Point Source Catalog */ int refcat, /* Catalog code from wcscat.h (TMPSC or TMXSC or TMPSCE) */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *gnum, /* Array of catalog numbers (returned) */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int tmcrnum( /* Read sources by ID number from 2MASS Point Source Catalog */ int refcat, /* Catalog code from wcscat.h (TMPSC or TMXSC or TMPSCE) */ int nstars, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *gnum, /* Array of source numbers to look for */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int tmcbin( /* Bin sources from 2MASS Point Source Catalog */ int refcat, /* Catalog code from wcscat.h (TMPSC or TMXSC or TMPSCE) */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude to use (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ /* Subroutines to read local copies of USNO catalogs */ int uacread( /* Read sources by sky region from USNO A or SA Catalog */ char *refcatname, /* Name of catalog (UAC, USAC, UAC2, USAC2) */ int distsort, /* 1 to sort stars by distance from center */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *unum, /* Array of catalog numbers (returned) */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *uplate, /* Array of plate numbers (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int uacrnum( /* Read sources by ID number from USNO A or SA Catalog */ char *refcatname, /* Name of catalog (UAC, USAC, UAC2, USAC2) */ int nnum, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *unum, /* Array of source numbers to look for */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *uplate, /* Array of plate numbers (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int uacbin( /* Bin sources from USNO A or SA Catalog */ char *refcatname, /* Name of catalog (UAC, USAC, UAC2, USAC2) */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude to use (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ void setuplate( /* Set USNO catalog plate number to search */ int xplate); /* If nonzero, use objects only from this plate */ int getuplate(void); /* Get USNO catalog plate number to search */ int ubcread( /* Read sources by sky region from USNO B Catalog */ char *refcatname, /* Name of catalog (UB1 only for now) */ int distsort, /* 1 to sort stars by distance from center */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *unum, /* Array of ID numbers (returned) */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double *upra, /* Array of right ascension proper motions (returned) */ double *updec, /* Array of declination proper motions (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *upmni, /* Array of number of ids and pm quality (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ubcrnum( /* Read sources by ID number from USNO B Catalog */ char *refcatname, /* Name of catalog (UB1 only for now) */ int nnum, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *unum, /* Array of source numbers to look for */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double *upra, /* Array of right ascension proper motions (returned) */ double *updec, /* Array of declination proper motions (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *upmni, /* Array of number of ids and pm quality (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ubcbin( /* Bin sources from USNO B Catalog */ char *refcatname, /* Name of catalog (UB1 only for now) */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude to use (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ucacread( /* Read sources by sky region from USNO UCAC 1 Catalog */ char *refcatname, /* Name of catalog (UCAC1 or UCAC2) */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *gnum, /* Array of ID numbers (returned) */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double *gpra, /* Array of right ascension proper motions (returned) */ double *gpdec, /* Array of declination proper motions (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ucacrnum( /* Read sources by ID number from USNO UCAC 1 Catalog */ char *refcatname, /* Name of catalog (UCAC1 or UCAC2) */ int nstars, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *gnum, /* Array of source numbers to look for */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double *gpra, /* Array of right ascension proper motions (returned) */ double *gpdec, /* Array of declination proper motions (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ucacbin( /* Bin sources from USNO UCAC 1 Catalog */ char *refcatname, /* Name of catalog (UCAC1 or UCAC2) */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude to use (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ujcread( /* Read sources by sky region from USNO J Catalog */ char *refcatname, /* Name of catalog (UJC, xxxxx.usno) */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int nstarmax, /* Maximum number of stars to be returned */ double *unum, /* Array of catalog numbers (returned) */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *uplate, /* Array of plate numbers (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ujcrnum( /* Read sources by ID number from USNO J Catalog */ char *refcatname, /* Name of catalog (UJC, xxxxx.usno) */ int nnum, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *unum, /* Array of source numbers to look for */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *uplate, /* Array of plate numbers (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ujcbin( /* Bin sources from USNO J Catalog */ char *refcatname, /* Name of catalog (UJC, xxxxx.usno) */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude to use (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ /* Subroutines to read a local copy of the Tycho-2 catalog */ int ty2read( /* Read sources by sky region from Tycho 2 Catalog */ int refcat, /* Catalog code from wcscat.h (TYCHO2 or TYCHO2E */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *gnum, /* Array of ID numbers (returned) */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double *gpra, /* Array of right ascension proper motions (returned) */ double *gpdec, /* Array of declination proper motions (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ty2rnum( /* Read sources by ID number from Tycho 2 Catalog */ int refcat, /* Catalog code from wcscat.h (TYCHO2 or TYCHO2E */ int nstars, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *gnum, /* Array of source numbers to look for */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double *gpra, /* Array of right ascension proper motions (returned) */ double *gpdec, /* Array of declination proper motions (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int ty2bin( /* Bin sources from Tycho 2 Catalog */ int refcat, /* Catalog code from wcscat.h (TYCHO2 or TYCHO2E */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude to use (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ /* Subroutines to read a local copy of the ACT catalog */ int actread( /* Read sources by sky region from USNO ACT Catalog */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int distsort, /* 1 to sort stars by distance from center */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *gnum, /* Array of ID numbers (returned) */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double *gpra, /* Array of right ascension proper motions (returned) */ double *gpdec, /* Array of declination proper motions (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int actrnum( /* Read sources by ID number from USNO ACT Catalog */ int nstars, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *gnum, /* Array of source numbers to look for */ double *gra, /* Array of right ascensions (returned) */ double *gdec, /* Array of declinations (returned) */ double *gpra, /* Array of right ascension proper motions (returned) */ double *gpdec, /* Array of declination proper motions (returned) */ double **gmag, /* 2-D array of magnitudes (returned) */ int *gtype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int actbin( /* Bin sources from USNO ACT Catalog */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude to use (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ /* Subroutines to read SAO-TDC binary format catalogs */ int binread( /* Read from sky region from SAO TDC binary format catalog */ char *bincat, /* Name of reference star catalog file */ int distsort, /* 1 to sort stars by distance from center */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ struct StarCat **starcat, /* Star catalog data structure */ double *tnum, /* Array of ID numbers (returned) */ double *tra, /* Array of right ascensions (returned) */ double *tdec, /* Array of declinations (returned) */ double *tpra, /* Array of right ascension proper motions (returned) */ double *tpdec, /* Array of declination proper motions (returned) */ double **tmag, /* 2-D array of magnitudes (returned) */ int *tpeak, /* Array of encoded spectral types (returned) */ char **tobj, /* Array of object names (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int binrnum( /* Read sources by ID number from SAO TDC binary format catalog */ char *bincat, /* Name of reference star catalog file */ int nstars, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ int match, /* If 1, match number exactly, else number is sequence*/ double *tnum, /* Array of source numbers to look for */ double *tra, /* Array of right ascensions (returned) */ double *tdec, /* Array of declinations (returned) */ double *tpra, /* Array of right ascension proper motions (returned) */ double *tpdec, /* Array of declination proper motions (returned) */ double **tmag, /* 2-D array of magnitudes (returned) */ int *tpeak, /* Array of encoded spectral types (returned) */ char **tobj, /* Array of object names (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int binbin( /* Bin sources from SAO TDC binary format catalog */ char *bincat, /* Name of reference star catalog file */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude to use (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int binstar( /* Read one star entry from binary catalog, 0 if OK */ struct StarCat *sc, /* Star catalog descriptor */ struct Star *st, /* Current star entry (returned) */ int istar); /* Star sequence number in binary catalog */ struct StarCat *binopen( /* Open binary catalog, returning number of entries */ char *bincat); /* Name of reference star catalog file */ void binclose( /* Close binary catalog */ struct StarCat *sc); /* Star catalog descriptor */ int isbin( /* Return 1 if TDC binary catalog file, else 0 */ char *filename); /* Name of file to check */ /* Subroutines for extracting tab table information (in tabread.c) */ int tabread( /* Read sources from tab table catalog */ char *tabcatname, /* Name of reference star catalog file */ int distsort, /* 1 to sort stars by distance from center */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude by which to sort (1 to nmag) */ int nstarmax, /* Maximum number of stars to be returned */ struct StarCat **starcat, /* Star catalog data structure */ double *tnum, /* Array of source numbers (returned) */ double *tra, /* Array of right ascensions (returned) */ double *tdec, /* Array of declinations (returned) */ double *tpra, /* Array of right ascension proper motions (returned) */ double *tpdec, /* Array of declination proper motions (returned) */ double **tmag, /* 2-D Array of magnitudes (returned) */ int *tpeak, /* Array of peak counts (returned) */ char **tkey, /* Array of values of additional keyword */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int tabrnum( /* Read sources from tab table catalog */ char *tabcatname, /* Name of reference star catalog file */ int nnum, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ struct StarCat **starcat, /* Star catalog data structure */ int match, /* 1 to match star number exactly, else sequence num */ double *tnum, /* Array of source numbers to look for */ double *tra, /* Array of right ascensions (returned) */ double *tdec, /* Array of declinations (returned) */ double *tpra, /* Array of right ascension proper motions (returned) */ double *tpdec, /* Array of declination proper motions (returned) */ double **tmag, /* 2-D Array of magnitudes (returned) */ int *tpeak, /* Array of peak counts (returned) */ char **tkey, /* Array of values of additional keyword */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int tabbin( /* Read sources from tab table catalog */ char *tabcatname, /* Name of reference star catalog file */ struct WorldCoor *wcs, /* World coordinate system for image */ char *header, /* FITS header for output image */ char *image, /* Output FITS image */ double mag1, /* Minimum (brightest) magnitude (no limits if equal) */ double mag2, /* Maximum (faintest) magnitude (no limits if equal) */ int sortmag, /* Magnitude by which to sort (1 to nmag) */ double magscale, /* Scaling factor for magnitude to pixel flux * (image of number of catalog objects per bin if 0) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int tabxyread( /* Read x, y, and magnitude from tab table star list */ char *tabcatname, /* Name of reference star catalog file */ double **xa, /* Array of x coordinates (returned) */ double **ya, /* Array of y coordinates (returned) */ double **ba, /* Array of magnitudes (returned) */ int **pa, /* Array of fluxes (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int tabrkey( /* Keyword values from tab table catalogs */ char *tabcatname, /* Name of reference star catalog file */ struct StarCat **starcat, /* Star catalog data structure */ int nnum, /* Number of stars to look for */ double *tnum, /* Array of source numbers to look for */ char *keyword, /* Keyword for which to return values */ char **tval); /* Returned values for specified keyword */ struct StarCat *tabcatopen( /* Open tab table catalog */ char *tabpath, /* Tab table catalog file pathname */ struct TabTable *tabtable, /* Tab table data structure */ int nbbuff); /* Number of bytes in buffer; 0=read whole file */ void tabcatclose( /* Close tab table catalog */ struct StarCat *sc); /* Source catalog data structure */ int tabstar( /* Read one star entry from tab table catalog, 0 if OK */ int istar, /* Source sequence number in tab table catalog */ struct StarCat *sc, /* Source catalog data structure */ struct Star *st, /* Star data structure, updated on return */ int verbose); /* 1 to print error messages */ struct TabTable *tabopen( /* Open tab table file */ char *tabfile, /* Tab table catalog file name */ int nbbuff); /* Number of bytes in buffer; 0=read whole file */ void tabclose( /* Free all arrays left open by tab table structure */ struct TabTable *tabtable); /* Tab table data structure */ char *gettabline( /* Find a specified line in a tab table */ struct TabTable *tabtable, /* Tab table data structure */ int iline); /* Line sequence number in tab table */ double tabgetra( /* Return right ascension in degrees from tab table*/ struct Tokens *tabtok, /* Line token structure */ int ientry); /* sequence of entry on line */ double tabgetdec( /* Return declination in degrees from tab table*/ struct Tokens *tabtok, /* Line token structure */ int ientry); /* sequence of entry on line */ double tabgetr8( /* Return double number from tab table line */ struct Tokens *tabtok, /* Line token structure */ int ientry); /* sequence of entry on line */ int tabgeti4( /* Return 4-byte integer from tab table line */ struct Tokens *tabtok, /* Line token structure */ int ientry); /* sequence of entry on line */ void settabkey( /* Set tab table keyword to read for object */ char *keyword); /* column header of desired value */ int tabgetk( /* Get tab table entries for named column */ struct TabTable *tabtable, /* Tab table data structure */ struct Tokens *tabtok, /* Line token structure */ char *keyword, /* column header of desired value */ char *string, /* character string (returned) */ int maxchar); /* Maximum number of characters in returned string */ int tabgetc( /* Get tab table entry for named column */ struct Tokens *tabtok, /* Line token structure */ int ientry, /* sequence of entry on line */ char *string, /* character string (returned) */ int maxchar); /* Maximum number of characters in returned string */ int tabparse( /* Aeturn column names and positions in tabtable */ struct TabTable *tabtable); /* Tab table data structure */ int tabcol( /* Find column for name */ struct TabTable *tabtable, /* Tab table data structure */ char *keyword); /* column header of desired value */ int istab( /* Return 1 if tab table file, else 0 */ char *filename); /* Name of file to check */ char *gettaberr(); /* Return most recent tab table error message */ int gettabndec(); /* Return number of decimal places in tab catalog ids */ /* Subroutines to read catalogs over the web, from SCAT, HST, ESO, or SDSS servers */ int webread( /* Read sources by sky region from WWW catalog */ char *caturl, /* URL of search engine */ char *refcatname, /* Name of catalog */ int distsort, /* 1 to sort stars by distance from center */ double cra, /* Search center J2000 right ascension in degrees */ double cdec, /* Search center J2000 declination in degrees */ double dra, /* Search half width in right ascension in degrees */ double ddec, /* Search half-width in declination in degrees */ double drad, /* Limiting separation in degrees (ignore if 0) */ double dradi, /* Inner edge of annulus in degrees (ignore if 0) */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double mag1, /* Limiting magnitudes (none if equal) */ double mag2, /* Limiting magnitudes (none if equal) */ int sortmag, /* Number of magnitude by which to limit and sort */ int nstarmax, /* Maximum number of stars to be returned */ double *unum, /* Array of ID numbers (returned) */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double *upra, /* Array of right ascension proper motions (returned) */ double *updec, /* Array of declination proper motions (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *utype, /* Array of integer catalog values (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ int webrnum( /* Read sources by ID number from WWW catalog */ char *caturl, /* URL of search engine */ char *refcatname, /* Name of catalog */ int nnum, /* Number of stars to look for */ int sysout, /* Search coordinate system */ double eqout, /* Search coordinate equinox */ double epout, /* Proper motion epoch (0.0 for no proper motion) */ double *unum, /* Array of source numbers to look for */ double *ura, /* Array of right ascensions (returned) */ double *udec, /* Array of declinations (returned) */ double *upra, /* Array of right ascension proper motions (returned) */ double *updec, /* Array of declination proper motions (returned) */ double **umag, /* 2-D array of magnitudes (returned) */ int *utype, /* Array of object types (returned) */ int nlog); /* Verbose mode if > 1, number of sources per log line */ char *webbuff( /* Read URL into buffer across the web */ char *url, /* URL to read */ int diag, /* 1 to print diagnostic messages */ int *lbuff); /* Length of buffer (returned) */ struct TabTable *webopen( /* Open tab table across the web */ char *caturl, /* URL of search engine */ char *srchpar, /* Search engine parameters to append */ int nlog); /* 1 to print diagnostic messages */ /* Subroutines to read DAOPHOT-style catalogs of sources found in an image */ int daoread( /* Read image source positions from x y mag file */ char *daocat, /* Name of DAOFIND catalog file */ double **xa, /* X and Y coordinates of stars, array returned */ double **ya, /* X and Y coordinates of stars, array returned */ double **ba, /* Instrumental magnitudes of stars, array returned */ int **pa, /* Peak counts of stars in counts, array returned */ int nlog); /* 1 to print each star's position */ int daoopen( /* Open image source position x y mag file */ char *daofile); /* DAOFIND catalog file name */ char *daoline( /* Read line from image source position x y mag file */ int iline, /* Star sequence number in DAOFIND catalog */ char *line); /* Pointer to iline'th entry (returned updated) */ /* Subroutines for sorting tables of star positions and magnitudes from sortstar.c */ void FluxSortStars( /* Sort image stars by decreasing flux */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double *sb, /* Brighness in counts */ int *sc, /* Other 4-byte information */ int ns); /* Number of stars to sort */ void MagSortStars( /* Sort image stars by increasing magnitude */ double *sn, /* Identifying number */ double *sra, /* Right Ascension */ double *sdec, /* Declination */ double *spra, /* Right Ascension proper motion */ double *spdec, /* Declination proper motion */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double **sm, /* Magnitudes */ int *sc, /* Other 4-byte information */ char **sobj, /* Object name */ int ns, /* Number of stars to sort */ int nm, /* Number of magnitudes per star */ int ms); /* Magnitude by which to sort (1 to nmag) */ void IDSortStars( /* Sort image stars by increasing ID Number value */ double *sn, /* Identifying number */ double *sra, /* Right Ascension */ double *sdec, /* Declination */ double *spra, /* Right Ascension proper motion */ double *spdec, /* Declination proper motion */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double **sm, /* Magnitudes */ int *sc, /* Other 4-byte information */ char **sobj, /* Object name */ int ns, /* Number of stars to sort */ int nm); /* Number of magnitudes per star */ void RASortStars( /* Sort image stars by increasing right ascension */ double *sn, /* Identifying number */ double *sra, /* Right Ascension */ double *sdec, /* Declination */ double *spra, /* Right Ascension proper motion */ double *spdec, /* Declination proper motion */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double **sm, /* Magnitudes */ int *sc, /* Other 4-byte information */ char **sobj, /* Object name */ int ns, /* Number of stars to sort */ int nm); /* Number of magnitudes per star */ void DecSortStars( /* Sort image stars by increasing declination */ double *sn, /* Identifying number */ double *sra, /* Right Ascension */ double *sdec, /* Declination */ double *spra, /* Right Ascension proper motion */ double *spdec, /* Declination proper motion */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double **sm, /* Magnitudes */ int *sc, /* Other 4-byte information */ char **sobj, /* Object name */ int ns, /* Number of stars to sort */ int nm); /* Number of magnitudes per star */ void XSortStars( /* Sort image stars by increasing image X value */ double *sn, /* Identifying number */ double *sra, /* Right Ascension */ double *sdec, /* Declination */ double *spra, /* Right Ascension proper motion */ double *spdec, /* Declination proper motion */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double **sm, /* Magnitudes */ int *sc, /* Other 4-byte information */ char **sobj, /* Object name */ int ns, /* Number of stars to sort */ int nm); /* Number of magnitudes per star */ void YSortStars( /* Sort image stars by increasing image Y value */ double *sn, /* Identifying number */ double *sra, /* Right Ascension */ double *sdec, /* Declination */ double *spra, /* Right Ascension proper motion */ double *spdec, /* Declination proper motion */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double **sm, /* Magnitudes */ int *sc, /* Other 4-byte information */ char **sobj, /* Object name */ int ns, /* Number of stars to sort */ int nm); /* Number of magnitudes per star */ int MergeStars( /* Merge multiple entries within given radius * return mean ra, dec, proper motion, and magnitude(s) */ double *sn, /* Identifying number */ double *sra, /* Right Ascension */ double *sdec, /* Declination */ double *spra, /* Right Ascension proper motion */ double *spdec, /* Declination proper motion */ double *sx, /* Image X coordinate */ double *sy, /* Image Y coordinate */ double **sm, /* Magnitudes */ int *sc, /* Other 4-byte information */ char **sobj, /* Object name */ int ns, /* Number of stars to sort */ int nm, /* Number of magnitudes per star */ double rad, /* Maximum separation in arcseconds to merge */ int log); /* If >0, log progress every time mod number written */ /* Catalog utility subroutines from catutil.c */ /* Subroutines for dealing with catalogs */ int RefCat( /* Return catalog type code, title, coord. system */ char *refcatname, /* Name of reference catalog */ char *title, /* Description of catalog (returned) */ int *syscat, /* Catalog coordinate system (returned) */ double *eqcat, /* Equinox of catalog (returned) */ double *epcat, /* Epoch of catalog (returned) */ int *catprop, /* 1 if proper motion in catalog (returned) */ int *nmag); /* Number of magnitudes in catalog (returned) */ int CatCode( /* Return catalog type code */ char *refcatname); /* Name of reference catalog */ char *CatName( /* Return catalog name given catalog type code */ int refcat, /* Catalog code */ char *refcatname); /* Name of reference catalog */ char *CatSource( /* Return catalog source description given catalog type code */ int refcat, /* Catalog code */ char *refcatname); /* Name of reference catalog */ void CatID( /* Return catalog ID keyword given catalog type code */ char *catid, /* Catalog ID (returned) */ int refcat); /* Catalog code */ double CatRad( /* Return default search radius for given catalog */ int refcat); /* Catalog code */ char *ProgName( /* Return program name given program path used */ char *progpath0); /* Pathname by which program is invoked */ char *ProgCat( /* Return catalog name given program name used */ char *progname); /* Program name which might contain catalog code */ void CatNum( /* Return formatted source number */ int refcat, /* Catalog code */ int nnfld, /* Number of characters in number (from CatNumLen) * Print leading zeroes if negative */ int nndec, /* Number of decimal places ( >= 0) * Omit leading spaces if negative */ double dnum, /* Catalog number of source */ char *numstr); /* Formatted number (returned) */ int CatNumLen( /* Return length of source numbers */ int refcat, /* Catalog code */ double maxnum, /* Maximum ID number * (Ignored for standard catalogs) */ int nndec); /* Number of decimal places ( >= 0) */ int CatNdec( /* Return number of decimal places in source numbers */ int refcat); /* Catalog code */ void CatMagName( /* Return name of specified magnitude */ int imag, /* Sequence number of magnitude */ int refcat, /* Catalog code */ char *magname); /* Name of magnitude, returned */ int CatMagNum( /* Returns number of magnitude specified by letter as int */ int imag, /* int of magnitude letter */ int refcat); /* Catalog code */ void CatTabHead ( /* Print heading for catalog search result table */ int refcat, /* Catalog being searched */ int sysout, /* Output coordinate system */ int nnfld, /* Number of characters in ID column */ int mprop, /* 1 if proper motion in catalog */ int nmag, /* Number of magnitudes */ char *ranges, /* Catalog numbers to print */ char *keyword, /* Column to add to tab table output */ int gcset, /* 1 if there are any values in gc[] */ int tabout, /* 1 if output is tab-delimited */ int classd, /* GSC object class to accept (-1=all) */ int printxy, /* 1 if X and Y included in output */ char **gobj1, /* Pointer to array of object names; NULL if none */ FILE *fd); /* Output file descriptor; none if NULL */ int StrNdec( /* Return number of decimal places in numeric string */ char *string); /* Numeric string */ int NumNdec( /* Return number of decimal places in a number */ double number); /* Floating point number */ void setdateform ( /* Set date format code */ int dateform0); /* Date format code */ char *DateString( /* Return string with epoch of position in desired format */ double epoch, /* Date as fraction of a year */ int tabout); /* 1 for tab-preceded output string, else space-preceded */ void setlimdeg( /* Limit output in degrees (1) or hh:mm:ss dd:mm:ss (0) */ int degout); /* 1 for fractional degrees, else sexagesimal hours, degrees */ void SearchLim( /* Compute limiting RA and Dec */ double cra, /* Longitude/Right Ascension of Center of search area in degrees */ double cdec, /* Latitude/Declination of search area in degrees */ double dra, /* Horizontal half-width in degrees */ double ddec, /* Vertical half-width in degrees */ int syscoor, /* Coordinate system */ double *ra1, /* Lower right ascension limit in degrees (returned) */ double *ra2, /* Upper right ascension limit in degrees (returned) */ double *dec1, /* Lower declination limit in degrees (returned) */ double *dec2, /* Upper declination limit in degrees (returned) */ int verbose); /* 1 to print limits, else 0 */ void RefLim( /* Compute limiting RA and Dec in new system */ double cra, /* Longitude/Right Ascension of Center of search area in degrees */ double cdec, /* Latitude/Declination of search area in degrees */ double dra, /* Horizontal half-width in degrees */ double ddec, /* Vertical half-width in degrees */ int sysc, /* System of search coordinates */ int sysr, /* System of reference catalog coordinates */ double eqc, /* Equinox of search coordinates in years */ double epr, /* Epoch of reference catalog coordinates in years */ double secmarg, /* Margin in arcsec/century to catch moving stars */ double *ramin, /* Lower right ascension limit in degrees (returned) */ double *ramax, /* Upper right ascension limit in degrees (returned) */ double *decmin, /* Lower declination limit in degrees (returned) */ double *decmax, /* Upper declination limit in degrees (returned) */ int verbose); /* 1 to print limits, else 0 */ /* Subroutines for dealing with ranges */ struct Range *RangeInit( /* Initialize range structure from string */ char *string, /* String containing numbers separated by , and - */ int ndef); /* Maximum allowable range value */ int isrange( /* Return 1 if string is a range of numbers, else 0 */ char *string); /* String which might be a range of numbers */ void rstart( /* Restart range */ struct Range *range); /* Range structure */ int rgetn( /* Return number of values in all ranges */ struct Range *range); /* Range structure */ int rgeti4( /* Return next number in range as integer */ struct Range *range); /* Range structure */ double rgetr8( /* Return next number in range as double */ struct Range *range); /* Range structure */ /* Subroutines for access to tokens within a string */ int setoken( /* Tokenize a string for easy decoding */ struct Tokens *tokens, /* Token structure returned */ char *string, /* character string to tokenize */ char *cwhite); /* additional whitespace characters * if = tab, disallow spaces and commas */ int nextoken( /* Get next token from tokenized string */ struct Tokens *tokens, /* Token structure returned */ char *token, /* token (returned) */ int maxchars); /* Maximum length of token */ int getoken( /* Get specified token from tokenized string */ struct Tokens *tokens, /* Token structure returned */ int itok, /* token sequence number of token * if <0, get whole string after token -itok * if =0, get whole string */ char *token, /* token (returned) */ int maxchars); /* Maximum length of token */ int ageti4( /* Extract int value from keyword= value in string */ char *string, /* character string containing = */ char *keyword, /* character string containing the name of the keyword * the value of which is returned. hget searches for a * line beginning with this string. if "[n]" or ",n" is * present, the n'th token in the value is returned. */ int *ival); /* Integer value, returned */ int agetr8( /* Extract double value from keyword= value in string */ char *string, /* character string containing = */ char *keyword, /* character string containing the name of the keyword */ double *dval); /* Double value, returned */ int agets( /* Extract value from keyword= value in string */ char *string, /* character string containing = */ char *keyword, /* character string containing the name of the keyword */ int lval, /* Size of value in characters * If negative, value ends at end of line */ char *value); /* String (returned) */ int tmcid( /* Return 1 if string is 2MASS ID, else 0 */ char *string, /* Character string to check */ double *ra, /* Right ascension (returned) */ double *dec); /* Declination (returned) */ /* Subroutines for VOTable output */ int vothead( /* Print heading for VOTable SCAT output */ int refcat, /* Catalog code */ char *refcatname, /* Name of catalog */ int mprop, /* Proper motion flag */ int typecol, /* Flag for spectral type */ int ns, /* Number of sources found in catalog */ double cra, /* Search center right ascension */ double cdec, /* Search center declination */ double drad); /* Radius to search in degrees */ void vottail(); /* Terminate VOTable SCAT output */ /* Subroutines for version/date string */ void setrevmsg( /* Set version/date string */ char *getrevmsg( /* Return version/date string */ /* Subroutines for fitting and evaluating polynomials */ void polfit( /* Fit polynomial coefficients */ double polcomp( /* Evaluate polynomial from polfit coefficients */ #else /* K&R prototypes */ /* Subroutines for reading TDC ASCII catalogs (ctgread.c) */ int ctgread(); /* Read sources by sky region from SAO TDC ASCII format catalog */ int ctgrnum(); /* Read sources by number from SAO TDC ASCII format catalog */ int ctgrdate(); /* Read sources by date range from SAO TDC ASCII format catalog */ int ctgbin(); /* Bin sources from SAO TDC ASCII format catalog */ int ctgstar(); /* Read one star entry from ASCII catalog, 0 if OK */ int isacat(); /* Return 1 if string is name of ASCII catalog file */ struct StarCat *ctgopen(); void ctgclose(); /* Subroutines for extracting sources from HST Guide Star Catalog */ int gscread(); /* Read sources by sky region from HST Guide Star Catalog */ int gscrnum(); /* Read sources by ID number from HST Guide Star Catalog */ int gscbin(); /* Bin sources from HST Guide Star Catalog */ void setgsclass(); /* Set GSC object class */ /* Subroutine to read GSC II catalog over the web (gsc2read.c) */ int gsc2read(); /* Read sources by sky region from GSC II Catalog */ /* Subroutine to read SDSS catalog over the web (sdssread.c) */ int sdssread(); /* Read sources by sky region from SDSS Catalog */ char *sdssc2t(); /* Convert SDSS buffer from comma- to tab-separated */ /* Subroutines to read local copy of 2MASS Point Source Catalog (tmcread.c) */ int tmcread(); /* Read sources by sky region from 2MASS Point Source Catalog */ int tmcrnum(); /* Read sources by ID number from 2MASS Point Source Catalog */ int tmcbin(); /* Bin sources from 2MASS Point Source Catalog */ /* Subroutines to read local copies of USNO A and SA catalogs (uacread.c) */ int uacread(); /* Read sources by sky region from USNO A or SA Catalog */ int uacrnum(); /* Read sources by ID number from USNO A or SA Catalog */ int uacbin(); /* Bin sources from USNO A or SA Catalog */ void setuplate(); /* Set USNO catalog plate number to search */ int getuplate(); /* Get USNO catalog plate number to search */ /* Subroutines to read local copies of USNO B catalogs (ubcread.c) */ int ubcread(); /* Read sources by sky region from USNO B Catalog */ int ubcrnum(); /* Read sources by ID number from USNO B Catalog */ int ubcbin(); /* Bin sources from USNO B Catalog */ /* Subroutines to read local copies of USNO UCAC catalogs (ucacread.c) */ int ucacread(); /* Read sources by sky region from USNO UCAC 1 Catalog */ int ucacrnum(); /* Read sources by ID number from USNO UCAC 1 Catalog */ int ucacbin(); /* Bin sources from USNO UCAC 1 Catalog */ /* Subroutines to read local copies of USNO UJ catalog (ucacread.c) */ int ujcread(); /* Read sources by sky region from USNO J Catalog */ int ujcrnum(); /* Read sources by ID number from USNO J Catalog */ int ujcbin(); /* Bin sources from USNO J Catalog */ /* Subroutines to read a local copy of the Tycho-2 catalog (ty2read.c) */ int ty2read(); /* Read sources by sky region from Tycho 2 Catalog */ int ty2rnum(); /* Read sources by ID number from Tycho 2 Catalog */ int ty2bin(); /* Bin sources from Tycho 2 Catalog */ /* Subroutines to read a local copy of the ACT catalog (actread.c) */ int actread(); /* Read sources by sky region from USNO ACT Catalog */ int actrnum(); /* Read sources by ID number from USNO ACT Catalog */ int actbin(); /* Bin sources from USNO ACT Catalog */ /* Subroutines to read SAO-TDC binary format catalogs (binread.c) */ int binread(); /* Read sources by sky region from SAO TDC binary format catalog */ int binrnum(); /* Read sources by ID number from SAO TDC binary format catalog */ int binbin(); /* Bin sources from SAO TDC binary format catalog */ int binstar(); /* Read one star entry from binary catalog, 0 if OK */ int isbin(); struct StarCat *binopen(); void binclose(); /* Subroutines for extracting tab table information (tabread.c) */ int tabread(); /* Read sources from tab table catalog */ int tabrnum(); /* Read sources from tab table catalog */ int tabbin(); /* Read sources from tab table catalog */ struct TabTable *tabopen(); /* Open tab table file */ struct StarCat *tabcatopen(); /* Open tab table catalog */ void tabcatclose(); /* Close tab table catalog */ int tabxyread(); /* Read x, y, and magnitude from tab table star list */ void settabkey(); /* Set tab table keyword to read for object */ char *gettabline(); /* Find a specified line in a tab table */ int tabrkey(); /* Keyword values from tab table catalogs */ int tabcol(); /* Find column for name */ int tabgetk(); /* Get tab table entries for named column */ int tabgetc(); /* Get tab table entry for named column */ int tabgeti4(); /* Return 4-byte integer from tab table line */ int tabparse(); /* Aeturn column names and positions in tabtable */ double tabgetra(); /* Return right ascension in degrees from tab table*/ double tabgetdec(); /* Return declination in degrees from tab table*/ double tabgetr8(); /* Return double number from tab table line */ void tabclose(); /* Free all arrays left open by tab table structure */ char *gettaberr(); /* Return most recent tab table error message */ int istab(); /* Return 1 if tab table file, else 0 */ int gettabndec(); /* Return number of decimal places in tab catalog ids */ /* Subroutines to read catalogs over the web, from SCAT, HST, ESO, or SDSS servers */ int webread(); /* Read sources by sky region from catalog on the World Wide Web */ int webrnum(); /* Read sources by ID number from catalog on the World Wide Web */ char *webbuff(); /* Read URL into buffer across the web */ struct TabTable *webopen(); /* Open tab table across the web */ /* Subroutines to read DAOPHOT-style catalogs of sources found in an image */ int daoread(); /* Read image source positions from x y mag file */ int daoopen(); /* Open image source position x y mag file */ char *daoline(); /* Read line from image source position x y mag file */ /* Subroutines for sorting tables of star positions and magnitudes from sortstar.c */ void FluxSortStars(); /* Sort image stars by decreasing flux */ void MagSortStars(); /* Sort image stars by increasing magnitude */ void IDSortStars(); /* Sort image stars by increasing ID Number value */ void RASortStars(); /* Sort image stars by increasing right ascension */ void DecSortStars(); /* Sort image stars by increasing declination */ void XSortStars(); /* Sort image stars by increasing image X value */ void YSortStars(); /* Sort image stars by increasing image Y value */ int MergeStars(); /* Merge multiple entries within given radius */ /* Catalog utility subroutines from catutil.c */ /* Subroutines for dealing with catalogs */ int CatCode(); /* Return catalog type code */ int RefCat(); /* Return catalog type code, title, coord. system */ char *CatName(); /* Return catalog name given catalog type code */ char *CatSource(); /* Return catalog source description given catalog type code */ char *ProgCat(); /* Return catalog name given program name used */ char *ProgName(); /* Return program name given program path used */ char *CatName(); /* Return catalog name given catalog type code */ void CatID(); /* Return catalog ID keyword given catalog type code */ void CatNum(); /* Return formatted source number */ int CatNumLen(); /* Return length of source numbers */ int CatNdec(); /* Return number of decimal places in source numbers */ void CatMagName(); /* Return name of specified magnitude */ int CatMagNum(); /* Returns number of magnitude specified by letter as int */ double CatRad(); /* Return default search radius for given catalog */ int tmcid(); /* Return 1 if string is 2MASS ID, else 0 */ int NumNdec(); /* Return number of decimal places in a number */ int StrNdec(); /* Return number of decimal places in numeric string */ void setdateform(); /* Set date format code */ void setlimdeg(); /* Limit output in degrees (1) or hh:mm:ss dd:mm:ss (0) */ char *DateString(); /* Convert epoch to output format */ void SearchLim(); /* Compute limiting RA and Dec */ void RefLim(); /* Compute limiting RA and Dec in new system */ int ageti4(); /* Extract int value from keyword= value in string */ int agetr8(); /* Extract double value from keyword= value in string */ int agets(); /* Extract value from keyword= value in string */ void bv2sp(); /* Approximate main sequence spectral type from B - V */ /* Subroutines for dealing with ranges */ struct Range *RangeInit(); /* Initialize range structure from string */ int isrange(); /* Return 1 if string is a range of numbers, else 0 */ int rgetn(); /* Return number of values in all ranges */ int rgeti4(); /* Return next number in range as integer */ double rgetr8(); /* Return next number in range as double */ void rstart(); /* Restart range */ /* Subroutines for access to tokens within a string */ int setoken(); /* Tokenize a string for easy decoding */ int nextoken(); /* Get next token from tokenized string */ int getoken(); /* Get specified token from tokenized string */ /* Subroutines for VOTable output */ int vothead(); /* Print heading for VOTable SCAT output */ void vottail(); /* Terminate VOTable SCAT output */ /* Subroutines for version/date string */ void setrevmsg(); /* Set version/date string */ char *getrevmsg(); /* Return version/date string */ /* Subroutines for fitting and evaluating polynomials */ void polfit(); /* Fit polynomial coefficients */ double polcomp(); /* Evaluate polynomial from polfit coefficients */ #endif /* __STDC__ */ #ifdef __cplusplus } #endif __cplusplus #endif /* _wcscat_h_ */ /* Sep 22 1998 New header file (star.h) * Oct 16 1998 Add more options for ASCII catalogs * Oct 20 1998 Add object name to binary files * Oct 21 1998 New file (wcscat.h) * Oct 26 1998 Combined wcscat.h and star.h * Oct 27 1998 Add SAOimage region shapes * Nov 9 1998 Add rasorted flag to catalog structure * Nov 20 1998 Add support for USNO A-2.0 and SA-2.0 catalogs * Dec 8 1998 Add support for the Hipparcos and ACT catalogs * * Jan 25 1999 Add declarations for tab table access * Jan 25 1999 Add declarations for dealing with ranges of numbers * Feb 2 1999 Add number of decimal places in star number to StarCat * Feb 11 1999 Add coordinate system info to star structure * Feb 11 1999 Change starcat.insys to starcat.coorsys for consistency * May 14 1999 Update Star and StarCat structure to cover tab tables * May 19 1999 Update StarCat structure to include epoch from catalog * June 4 1999 Add CatNumLen() * Jun 14 1999 Add SearchLim() * Jun 30 1999 Add isrange() * Jul 1 1999 Add declarations for date/time conversions in dateutil.c * Jul 2 1999 Add rstart() * Jul 26 1999 Add Yale Bright Star Catalog * Aug 16 1999 Add RefLim() to get converted search coordinates right * Aug 25 1999 Add ACT catalog * Sep 10 1999 Move special case setting from argument list to subroutines * Sep 13 1999 Add subroutines to access data structure for single stars * Oct 1 1999 Add structure and subroutines for tokenized strings * Oct 22 1999 Change cat*() to ctg*() to avoid system conflict * Oct 29 1999 Add tabget() subroutines * Nov 1 1999 Increase maximum number of tokens on a line from 20 to 100 * Nov 2 1999 Move date utilities to fitsfile.h * * Jan 10 2000 Add column names to catalog data structure * Jan 11 2000 Add gettabndec() * Feb 9 2000 Add proper motion entry information to star data structure * Feb 16 2000 Add gettaberr() to return tab table error message * Mar 1 2000 Add isfile() and agets() to help with ASCII files * Mar 8 2000 Add ProgCat() to return catalog name from program name used * Mar 8 2000 Add ProgName() to extract program name from path used * Mar 10 2000 Add PropCat() to tell whether a catalog has proper motions * Mar 27 2000 Add tabxyread() * Apr 3 2000 Add option in catalog structure to ignore extra info * May 22 2000 Add Tycho 2 support, bv2sp() * May 26 2000 Add separate pointer to header in tab table structure * May 26 2000 Add separate pointer to table name in tab table structure * Jul 12 2000 Add catalog type code to ctalog data structure * Sep 20 2000 Add isacat() to detect ASCII catalog files * Sep 25 2000 Add starcat.sptype to flag spectral type in catalog * Oct 23 2000 Add USNO plate catalog to catalog type table * Oct 26 2000 Add proper motion flags for seconds and arcseconds per century * Oct 31 2000 Add proper motion flags for milliseconds per year * Nov 2 2000 Add parallax and radial velocity to star structure * Nov 21 2000 Add WEBCAT catalog type for tab ctalogs returned from the Web * Nov 22 2000 Add webread() and webrnum() * Nov 28 2000 Add tabparse() * Nov 30 2000 Add spectral type to catalog header; make star->isp 4 char. * Dec 13 2000 Add StrNdec() to get number of decimal places in number strings * Dec 15 2000 Add CatNdec() to get number of decimal places in source numbers * Dec 18 2000 Drop PropCat(), a cludgy proper motion flag * * Mar 22 2001 Add web search flag in catalog data structure * Mar 27 2001 Add shapes in pixels to SAOimage region options * May 14 2001 Add 2MASS Point Source Catalog flags * May 22 2001 Add declination sorting * May 24 2001 Add 2MASS Point Source Catalog subroutines * May 29 2001 Add length of star number to catalog structure * May 30 2001 Add third magnitude for tab tables to catalog structure * Jun 15 2001 Add CatName() and CatID() * Jun 19 2001 Add parallax error to catalog and star structures * Jun 20 2001 Add webopen(), GSC2, fourth magnitude to star and starcat * Jul 12 2001 Add separate web access subroutine, webbuff() * Jul 23 2001 Add ageti4() and agetr8() * Jul 24 2001 Add polfit() and polcomp() * Aug 8 2001 Add keyrv and option to set mprop to 2 to include rv/cz * Sep 10 2001 Add entry line and distance from search center to Star * Sep 13 2001 Add YSortStars() and SORT_Y * Sep 14 2001 Add lbuff to TabTable structure * Sep 20 2001 Add CatMagName() * Sep 25 2001 Move isfile() to fitsfile.h * Oct 16 2001 Add tabdash pointer to tabtable data structure * * Apr 9 2002 Fix typo in gettaberr() declaration * Apr 10 2002 Add CatMagNum() * May 6 2002 Increase object name length from 31 to 79 characters * May 13 2002 Add NumNdec(), gsc2read(), and gsc2rnum() * Aug 6 2002 Make magnitude entries and positions vectors of 10 * Oct 30 2002 Add epoch keyword and FITS date to StarCat data structure * * Jan 16 2003 Add USNO-B1.0 catalog * Mar 24 2003 Add CatCde() to get only catalog code * Apr 3 2003 Add ubcread(), ubcrnum(), and FluxSortStars() * Apr 3 2003 Drop gsc2rnum() * Apr 14 2003 Add setrevmsg() and getrevmsg() * Apr 24 2003 Add UCAC1 and UCAC2, ucacread() and ucacrnum() * May 20 2003 Add TMIDR2 for 2MASS PSC Interim Data Release 2 * Sep 16 2003 Add SORT_MERGE for scat * Sep 25 2003 Add *bin() subroutines for catalog binning * Dec 3 2003 Add USNO YB6 catalog * * Jan 5 2004 Add SDSS catalog * Jan 12 2004 Add 2MASS Extended Source catalog and size to star structure * Jan 14 2004 Add CatSource() subroutine to simplify help message creation * Jan 22 2004 Add setlimdeg() to print limit coordinates in degrees * Mar 16 2004 Add MergeStars() * Apr 23 2004 Add ctgrdate() * Aug 31 2004 Increase MAXTOKENS from 100 to 200 * Sep 2 2004 Increase MAXTOKENS from 200 to 1000 * * Jul 27 2005 Add date format codes and DateString() * Aug 5 2005 Add Tycho-2 and 2MASS PSC with magnitude errors * * Jan 6 2006 Add CatRad() subroutine * Mar 17 2006 Make vothead() int as it now returns the number of fields * Apr 3 2006 Add tmcid() to check for 2MASS identifiers * Apr 3 2006 Add setdateform() to set output date format * Apr 12 2006 Add SORT_ID for scat to sort catalog entries by ID number * Jun 20 2006 Add IDSortStars() * * Jan 10 2006 Add ANSI C function prototypes */ wcstools-3.9.5/libwcs/imrotate1.c0000664000016200001660000004603111750060473016016 0ustar minkoirsys/*** File libwcs/imrotate.c *** June 30, 2008 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 1996-2008 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include #include "fitsfile.h" static void RotWCSFITS(); /* rotate all the C* fields */ /* Rotate an image by 90, 180, or 270 degrees, with an optional * reflection across the vertical or horizontal axis. * verbose generates extra info on stdout. * return NULL if successful or rotated image. */ char * RotFITS (pathname,header,image0,xshift,yshift,rotate,mirror,bitpix2,rotwcs, verbose) char *pathname; /* Name of file which is being changed */ char *header; /* FITS header */ char *image0; /* Unrotated image pixels */ int xshift; /* Number of pixels to shift image horizontally, +=right */ int yshift; /* Number of pixels to shift image vertically, +=right */ int rotate; /* Angle to by which to rotate image (90, 180, 270) */ int mirror; /* Reflect image around 1=vertical, 2=horizontal axis */ int bitpix2; /* Number of bits per pixel in output image */ int rotwcs; /* If not =0, rotate WCS keywords, else leave them */ int verbose; { int bitpix1, ny, nx, nax; int x1, y1, x2, y2, nbytes; char *rotimage; char *image; char history[128]; char *filename; double crpix; image = NULL; rotimage = NULL; if (rotate == 1) rotate = 90; else if (rotate == 2) rotate = 180; else if (rotate == 3) rotate = 270; else if (rotate < 0) rotate = rotate + 360; filename = strrchr (pathname,'/'); if (filename) filename = filename + 1; else filename = pathname; /* Get image size */ nax = 0; if (hgeti4 (header,"NAXIS",&nax) < 1) { if (verbose) printf ("RotFITS: Not an image (NAXIS=%d)\n",nax); return (NULL); } else { if (hgeti4 (header,"NAXIS1",&nx) < 1) { if (verbose) printf ("RotFITS: Not an image (NAXIS1=%d)\n",nx); return (NULL); } else { if (hgeti4 (header,"NAXIS2",&ny) < 1) { if (verbose) printf ("RotFITS: Not an image (NAXIS2=%d)\n",ny); return (NULL); } } } bitpix1 = 16; hgeti4 (header,"BITPIX", &bitpix1); if (bitpix2 == 0) bitpix2 = bitpix1; /* Shift WCS fields in header */ if (rotwcs && hgetr8 (header, "CRPIX1", &crpix)) { crpix = crpix + xshift; hputr8 (header, "CRPIX1", crpix); } if (rotwcs && hgetr8 (header, "CRPIX2", &crpix)) { crpix = crpix + yshift; hputr8 (header, "CRPIX2", crpix); } /* Rotate WCS fields in header */ if (rotwcs && (rotate != 0 || mirror)) RotWCSFITS (header, rotate, mirror, verbose); /* Compute size of image in bytes */ switch (bitpix2) { case 8: nbytes = nx * ny; break; case 16: nbytes = nx * ny * 2; break; case 32: nbytes = nx * ny * 4; break; case -16: nbytes = nx * ny * 2; break; case -32: nbytes = nx * ny * 4; break; case -64: nbytes = nx * ny * 8; break; default: if (verbose) printf ("RotFITS: Illegal BITPIX (%d)\n", bitpix2); return (NULL); } if (bitpix1 != bitpix2) { sprintf (history,"Copy of image %s bits per pixel %d -> %d", filename, bitpix1, bitpix2); hputc (header,"HISTORY",history); if (verbose) fprintf (stderr,"%s\n",history); } /* Shift image first */ if (xshift != 0 || yshift != 0) { /* Allocate buffer for shifted image */ image = (char *) calloc (nbytes, 1); if (image == NULL) { if (verbose) printf ("RotFITS: Cannot allocate %d bytes for shifted image\n", nbytes); return (NULL); } for (x1 = 0; x1 < nx; x1++) { x2 = x1 + xshift; for (y1 = 0; y1 < ny; y1++) { y2 = y1 + yshift; if (y2 < ny) movepix (image0,bitpix1,nx,x1,y1,image,bitpix2,nx,x2,y2); } } sprintf (history,"Copy of image %s shifted by dx=%d dy=%d", filename, xshift, yshift); hputc (header,"HISTORY",history); if (rotate == 0 && !mirror) return (image); } else image = image0; /* Allocate buffer for rotated image */ rotimage = (char *) calloc (nbytes, 1); if (rotimage == NULL) { if (verbose) printf ("RotFITS: Cannot allocate %d bytes for new image\n", nbytes); return (NULL); } /* Mirror image without rotation */ if (rotate < 45 && rotate > -45) { if (mirror == 1) { for (x1 = 0; x1 < nx; x1++) { x2 = nx - x1 - 1; for (y1 = 0; y1 < ny; y1++) { movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,nx,x2,y1); } } sprintf (history,"Copy of image %s reflected",filename); hputc (header,"HISTORY",history); } else if (mirror == 2) { for (y1 = 0; y1 < ny; y1++) { y2 = ny - y1 - 1; for (x1 = 0; x1 < nx; x1++) { movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,nx,x1,y2); } } sprintf (history,"Copy of image %s flipped",filename); hputc (header,"HISTORY",history); } else { for (y1 = 0; y1 < ny; y1++) { for (x1 = 0; x1 < nx; x1++) { movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,nx,x1,y1); } } } } /* Rotate by 90 degrees */ else if (rotate >= 45 && rotate < 135) { if (mirror == 1) { for (y1 = 0; y1 < ny; y1++) { x2 = ny - y1 - 1; for (x1 = 0; x1 < nx; x1++) { y2 = nx - x1 - 1; movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,ny,x2,y2); } } sprintf (history,"Copy of image %s reflected, rotated 90 degrees", filename); hputc (header,"HISTORY",history); } else if (mirror == 2) { for (y1 = 0; y1 < ny; y1++) { for (x1 = 0; x1 < nx; x1++) { movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,ny,y1,x1); } } sprintf (history,"Copy of image %s flipped, rotated 90 degrees", filename); hputc (header,"HISTORY",history); } else { for (y1 = 0; y1 < ny; y1++) { x2 = ny - y1 - 1; for (x1 = 0; x1 < nx; x1++) { y2 = x1; movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,ny,x2,y2); } } sprintf (history,"Copy of image %s rotated 90 degrees",filename); hputc (header,"HISTORY",history); } hputi4 (header,"NAXIS1",ny); hputi4 (header,"NAXIS2",nx); } /* Rotate by 180 degrees */ else if (rotate >= 135 && rotate < 225) { if (mirror == 1) { for (y1 = 0; y1 < ny; y1++) { y2 = ny - y1 - 1; for (x1 = 0; x1 < nx; x1++) { movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,nx,x1,y2); } } sprintf (history,"Copy of image %s reflected, rotated 180 degrees", filename); hputc (header,"HISTORY",history); } else if (mirror == 2) { for (x1 = 0; x1 < nx; x1++) { x2 = nx - x1 - 1; for (y1 = 0; y1 < ny; y1++) { movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,nx,x2,y1); } } sprintf (history,"Copy of image %s flipped, rotated 180 degrees", filename); hputc (header,"HISTORY",history); } else { for (y1 = 0; y1 < ny; y1++) { y2 = ny - y1 - 1; for (x1 = 0; x1 < nx; x1++) { x2 = nx - x1 - 1; movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,nx,x2,y2); } } sprintf (history,"Copy of image %s rotated 180 degrees",filename); hputc (header,"HISTORY",history); } } /* Rotate by 270 degrees */ else if (rotate >= 225 && rotate < 315) { if (mirror == 1) { for (y1 = 0; y1 < ny; y1++) { for (x1 = 0; x1 < nx; x1++) { movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,ny,y1,x1); } } sprintf (history,"Copy of image %s reflected, rotated 270 degrees", filename); hputc (header,"HISTORY",history); } else if (mirror == 2) { for (y1 = 0; y1 < ny; y1++) { x2 = ny - y1 - 1; for (x1 = 0; x1 < nx; x1++) { y2 = nx - x1 - 1; movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,ny,x2,y2); } } sprintf (history,"Copy of image %s flipped, rotated 270 degrees", filename); hputc (header,"HISTORY",history); } else { for (y1 = 0; y1 < ny; y1++) { x2 = y1; for (x1 = 0; x1 < nx; x1++) { y2 = nx - x1 - 1; movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,ny,x2,y2); } } sprintf (history,"Copy of image %s rotated 270 degrees",filename); hputc (header,"HISTORY",history); } hputi4 (header,"NAXIS1",ny); hputi4 (header,"NAXIS2",nx); } /* If rotating by more than 315 degrees, assume top-bottom reflection */ else if (rotate >= 315 && mirror) { for (y1 = 0; y1 < ny; y1++) { for (x1 = 0; x1 < nx; x1++) { x2 = y1; y2 = x1; movepix (image,bitpix1,nx,x1,y1,rotimage,bitpix2,ny,x2,y2); } } sprintf (history,"Copy of image %s reflected top to bottom",filename); hputc (header,"HISTORY",history); } if (verbose) fprintf (stderr,"%s\n",history); return (rotimage); } /* rotate all the C* fields. * return 0 if at least one such field is found, else -1. */ static void RotWCSFITS (header, angle, mirror, verbose) char *header; /* FITS header */ int angle; /* Angle to be rotated (0, 90, 180, 270) */ int mirror; /* Reflect image around 1=vertical, 2=horizontal axis */ int verbose; /* Print progress if 1 */ { static char flds[15][8]; char ctype1[16], ctype2[16]; double ctemp1, ctemp2, ctemp3, ctemp4, naxis1, naxis2; int i, n, ndec1, ndec2, ndec3, ndec4; strcpy (flds[0], "CTYPE1"); strcpy (flds[1], "CTYPE2"); strcpy (flds[2], "CRVAL1"); strcpy (flds[3], "CRVAL2"); strcpy (flds[4], "CDELT1"); strcpy (flds[5], "CDELT2"); strcpy (flds[6], "CRPIX1"); strcpy (flds[7], "CRPIX2"); strcpy (flds[8], "CROTA1"); strcpy (flds[9], "CROTA2"); strcpy (flds[10], "IMWCS"); strcpy (flds[11], "CD1_1"); strcpy (flds[12], "CD1_2"); strcpy (flds[13], "CD2_1"); strcpy (flds[14], "CD2_2"); n = 0; hgetr8 (header, "NAXIS1", &naxis1); hgetr8 (header, "NAXIS2", &naxis2); /* Find out if there any WCS keywords in this header */ for (i = 0; i < sizeof(flds)/sizeof(flds[0]); i++) { if (ksearch (header, flds[i]) != NULL) { n++; if (verbose) fprintf (stderr,"%s: found\n", flds[i]); } } /* Return if no WCS keywords to change */ if (n == 0) { if (verbose) fprintf (stderr,"RotWCSFITS: No WCS in header\n"); return; } /* Reset CROTAn and CD matrix if axes have been exchanged */ if (angle == 90) { if (hgetr8 (header, "CROTA1", &ctemp1)) { hgetndec (header, "CROTA1", &ndec1); hputnr8 (header, "CROTA1", ndec1, ctemp1+90.0); } if (hgetr8 (header, "CROTA2", &ctemp2)) { hgetndec (header, "CROTA2", &ndec2); hputnr8 (header, "CROTA2", ndec2, ctemp2+90.0); } } /* Negate rotation angle if mirrored or flipped */ if (mirror > 0) { if (hgetr8 (header, "CROTA1", &ctemp1)) { hgetndec (header, "CROTA1", &ndec1); hputnr8 (header, "CROTA1", ndec1, -ctemp1); } if (hgetr8 (header, "CROTA2", &ctemp2)) { hgetndec (header, "CROTA2", &ndec2); hputnr8 (header, "CROTA2", ndec2, -ctemp2); } if (hgetr8 (header, "LTM1_1", &ctemp1)) { hgetndec (header, "LTM1_1", &ndec1); hputnr8 (header, "LTM1_1", ndec1, -ctemp1); } if (mirror == 1) { if (hgetr8 (header, "CD1_1", &ctemp1)) hputr8 (header, "CD1_1", -ctemp1); } if (mirror == 2) { if (hgetr8 (header, "CD2_2", &ctemp1)) hputr8 (header, "CD2_2", -ctemp1); } if (hgetr8 (header, "CD1_2", &ctemp1)) hputr8 (header, "CD1_2", -ctemp1); if (hgetr8 (header, "CD2_1", &ctemp1)) hputr8 (header, "CD2_1", -ctemp1); } /* Unbin CRPIX and CD matrix */ if (hgetr8 (header, "LTM1_1", &ctemp1)) { if (ctemp1 != 1.0) { if (hgetr8 (header, "LTM2_2", &ctemp2)) { if (ctemp1 == ctemp2) { double ltv1 = 0.0; double ltv2 = 0.0; if (hgetr8 (header, "LTV1", <v1)) hdel (header, "LTV1"); if (hgetr8 (header, "LTV2", <v1)) hdel (header, "LTV2"); if (hgetr8 (header, "CRPIX1", &ctemp3)) hputr8 (header, "CRPIX1", (ctemp3-ltv1)/ctemp1); if (hgetr8 (header, "CRPIX2", &ctemp3)) hputr8 (header, "CRPIX2", (ctemp3-ltv2)/ctemp1); if (hgetr8 (header, "CD1_1", &ctemp3)) hputr8 (header, "CD1_1", ctemp3/ctemp1); if (hgetr8 (header, "CD1_2", &ctemp3)) hputr8 (header, "CD1_2", ctemp3/ctemp1); if (hgetr8 (header, "CD2_1", &ctemp3)) hputr8 (header, "CD2_1", ctemp3/ctemp1); if (hgetr8 (header, "CD2_2", &ctemp3)) hputr8 (header, "CD2_2", ctemp3/ctemp1); hdel (header, "LTM1_1"); hdel (header, "LTM2_2"); } } } } /* Reset CRPIXn */ if (hgetr8 (header, "CRPIX1", &ctemp1) && hgetr8 (header, "CRPIX2", &ctemp2)) { hgetndec (header, "CRPIX1", &ndec1); hgetndec (header, "CRPIX2", &ndec2); if (mirror) { if (angle == 0) hputnr8 (header, "CRPIX1", ndec1, naxis1-ctemp1); else if (angle == 90) { hputnr8 (header, "CRPIX1", ndec2, naxis2-ctemp2); hputnr8 (header, "CRPIX2", ndec1, naxis1-ctemp1); } else if (angle == 180) { hputnr8 (header, "CRPIX1", ndec1, ctemp1); hputnr8 (header, "CRPIX2", ndec2, naxis2-ctemp2); } else if (angle == 270) { hputnr8 (header, "CRPIX1", ndec2, ctemp2); hputnr8 (header, "CRPIX2", ndec1, ctemp1); } } else { if (angle == 90) { hputnr8 (header, "CRPIX1", ndec2, naxis2-ctemp2); hputnr8 (header, "CRPIX2", ndec1, ctemp1); } else if (angle == 180) { hputnr8 (header, "CRPIX1", ndec1, naxis1-ctemp1); hputnr8 (header, "CRPIX2", ndec2, naxis2-ctemp2); } else if (angle == 270) { hputnr8 (header, "CRPIX1", ndec2, ctemp2); hputnr8 (header, "CRPIX2", ndec1, naxis1-ctemp1); } } } /* Reset CDELTn (degrees per pixel) */ if (hgetr8 (header, "CDELT1", &ctemp1) && hgetr8 (header, "CDELT2", &ctemp2)) { hgetndec (header, "CDELT1", &ndec1); hgetndec (header, "CDELT2", &ndec2); if (mirror) { if (angle == 0) hputnr8 (header, "CDELT1", ndec1, -ctemp1); else if (angle == 90) { hputnr8 (header, "CDELT1", ndec2, -ctemp2); hputnr8 (header, "CDELT2", ndec1, -ctemp1); } else if (angle == 180) { hputnr8 (header, "CDELT1", ndec1, ctemp1); hputnr8 (header, "CDELT2", ndec2, -ctemp2); } else if (angle == 270) { hputnr8 (header, "CDELT1", ndec2, ctemp2); hputnr8 (header, "CDELT2", ndec1, ctemp1); } } else { if (angle == 90) { hputnr8 (header, "CDELT1", ndec2, -ctemp2); hputnr8 (header, "CDELT2", ndec1, ctemp1); } else if (angle == 180) { hputnr8 (header, "CDELT1", ndec1, -ctemp1); hputnr8 (header, "CDELT2", ndec2, -ctemp2); } else if (angle == 270) { hputnr8 (header, "CDELT1", ndec2, ctemp2); hputnr8 (header, "CDELT2", ndec1, -ctemp1); } } } /* Reset CD matrix, if present */ ctemp1 = 0.0; ctemp2 = 0.0; ctemp3 = 0.0; ctemp4 = 0.0; if (hgetr8 (header, "CD1_1", &ctemp1)) { hgetr8 (header, "CD1_2", &ctemp2); hgetr8 (header, "CD2_1", &ctemp3); hgetr8 (header, "CD2_2", &ctemp4); hgetndec (header, "CD1_1", &ndec1); hgetndec (header, "CD1_2", &ndec2); hgetndec (header, "CD2_1", &ndec3); hgetndec (header, "CD2_2", &ndec4); if (mirror == 1) { if (angle == 0) { hputnr8 (header, "CD1_2", ndec2, -ctemp2); hputnr8 (header, "CD2_1", ndec3, -ctemp3); } else if (angle == 90) { hputnr8 (header, "CD1_1", ndec4, -ctemp4); hputnr8 (header, "CD1_2", ndec3, -ctemp3); hputnr8 (header, "CD2_1", ndec2, -ctemp2); hputnr8 (header, "CD2_2", ndec1, -ctemp1); } else if (angle == 180) { hputnr8 (header, "CD1_1", ndec1, ctemp1); hputnr8 (header, "CD1_2", ndec2, ctemp2); hputnr8 (header, "CD2_1", ndec3, -ctemp3); hputnr8 (header, "CD2_2", ndec4, -ctemp4); } else if (angle == 270) { hputnr8 (header, "CD1_1", ndec4, ctemp4); hputnr8 (header, "CD1_2", ndec3, ctemp3); hputnr8 (header, "CD2_1", ndec2, ctemp2); hputnr8 (header, "CD2_2", ndec1, ctemp1); } } else { if (angle == 90) { hputnr8 (header, "CD1_1", ndec2, -ctemp2); hputnr8 (header, "CD1_2", ndec1, ctemp1); hputnr8 (header, "CD2_1", ndec4, -ctemp4); hputnr8 (header, "CD2_2", ndec3, ctemp3); } else if (angle == 180) { hputnr8 (header, "CD1_1", ndec1, -ctemp1); hputnr8 (header, "CD1_2", ndec2, -ctemp2); hputnr8 (header, "CD2_1", ndec3, -ctemp3); hputnr8 (header, "CD2_2", ndec4, -ctemp4); } else if (angle == 270) { hputnr8 (header, "CD1_1", ndec2, ctemp2); hputnr8 (header, "CD1_2", ndec1, -ctemp1); hputnr8 (header, "CD2_1", ndec4, ctemp4); hputnr8 (header, "CD2_2", ndec3, -ctemp3); } } } /* Delete any polynomial solution */ /* (These could maybe be switched, but I don't want to work them out yet */ if (ksearch (header, "CO1_1")) { int i; char keyword[16]; for (i = 1; i < 13; i++) { sprintf (keyword,"CO1_%d", i); hdel (header, keyword); } for (i = 1; i < 13; i++) { sprintf (keyword,"CO2_%d", i); hdel (header, keyword); } } return; } /* May 29 1996 Change name from rotFITS to RotFITS * Jun 4 1996 Fix bug when handling assymetrical images * Jun 5 1996 Print filename, not pathname, in history * Jun 10 1996 Remove unused variables after running lint * Jun 13 1996 Replace image with rotated image * Jun 18 1996 Fix formatting bug in history * * Jul 11 1997 If rotation is 360, flip top bottom if mirror flat is set * * Feb 23 1998 Do not delete WCS if image not rotated or mirrored * May 26 1998 Rotate WCS instead of deleting it * May 27 1998 Include imio.h * Jun 8 1999 Return new image pointer instead of flag; do not free old image * Jun 9 1999 Make history buffer 128 instead of 72 to avoid overflows * Jun 10 1999 Drop image0; use image * Oct 21 1999 Fix hputnr8() calls after lint * * Jan 11 2001 Print all messages to stderr * Jan 17 2001 Reset coordinate direction if image is mirrored * Jan 18 2001 Reset WCS scale if image is binned * Nov 27 2001 Add error messages for all null returns * Nov 27 2001 Add bitpix=8 * * Jan 28 2004 Add xshift and yshift arguments to shift image * Sep 15 2004 Fix bugs in calls to hgetr8 for crpix (found by Rob Creager) * * Aug 17 2005 Add mirror = 2 flag indicating a flip across x axis * * Jun 26 2008 Shift pixels if either xshift or yshift is not zero * Jun 30 2008 Correct WCS changes as suggested by Ed Los */ wcstools-3.9.5/libwcs/wcscon1.c0000664000016200001660000020741211750060474015471 0ustar minkoirsys/*** File wcscon.c *** November 29, 2006 *** Doug Mink, Harvard-Smithsonian Center for Astrophysics *** Some subroutines are based on Starlink subroutines by Patrick Wallace *** Copyright (C) 1995-2006 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA * Module: wcscon.c (World Coordinate System conversion) * Purpose: Convert between various sky coordinate systems * Subroutine: wcscon (sys1,sys2,eq1,eq2,theta,phi,epoch) * convert between coordinate systems * Subroutine: wcsconp (sys1,sys2,eq1,eq2,ep1,ep2,dtheta,dphi,ptheta,pphi) * convert coordinates and proper motion between coordinate systems * Subroutine: wcsconv (sys1,sys2,eq1,eq2,ep1,ep2,dtheta,dphi,ptheta,pphi,px,rv) * convert coordinates and proper motion between coordinate systems * Subroutine: wcscsys (cstring) returns code for coordinate system in string * Subroutine: wcsceq (wcstring) returns equinox in years from system string * Subroutine: wcscstr (sys,equinox,epoch) returns system string from equinox * Subroutine: fk524 (ra,dec) Convert J2000(FK5) to B1950(FK4) coordinates * Subroutine: fk524e (ra, dec, epoch) (more accurate for known position epoch) * Subroutine: fk524m (ra,dec,rapm,decpm) exact * Subroutine: fk524pv (ra,dec,rapm,decpm,parallax,rv) more exact * Subroutine: fk425 (ra,dec) Convert B1950(FK4) to J2000(FK5) coordinates * Subroutine: fk425e (ra, dec, epoch) (more accurate for known position epoch) * Subroutine: fk425m (ra, dec, rapm, decpm) exact * Subroutine: fk425pv (ra,dec,rapm,decpm,parallax,rv) more exact * Subroutine: fk42gal (dtheta,dphi) Convert B1950(FK4) to galactic coordinates * Subroutine: fk52gal (dtheta,dphi) Convert J2000(FK5) to galactic coordinates * Subroutine: gal2fk4 (dtheta,dphi) Convert galactic coordinates to B1950(FK4) * Subroutine: gal2fk5 (dtheta,dphi) Convert galactic coordinates to J2000 #ifndef VMS #include #endif #include /* for fprintf() and sprintf() */ #include #include #include "wcs.h" void fk524(), fk524e(), fk524m(), fk524pv(); void fk425(), fk425e(), fk425m(), fk425pv(); void fk42gal(), fk52gal(), gal2fk4(), gal2fk5(); void fk42ecl(), fk52ecl(), ecl2fk4(), ecl2fk5(); /* Convert from coordinate system sys1 to coordinate system sys2, converting proper motions, too, and adding them if an epoch is specified */ void wcsconp (sys1, sys2, eq1, eq2, ep1, ep2, dtheta, dphi, ptheta, pphi) int sys1; /* Input coordinate system (J2000, B1950, ECLIPTIC, GALACTIC */ int sys2; /* Output coordinate system (J2000, B1950, ECLIPTIC, GALACTIC */ double eq1; /* Input equinox (default of sys1 if 0.0) */ double eq2; /* Output equinox (default of sys2 if 0.0) */ double ep1; /* Input Besselian epoch in years (for proper motion) */ double ep2; /* Output Besselian epoch in years (for proper motion) */ double *dtheta; /* Longitude or right ascension in degrees Input in sys1, returned in sys2 */ double *dphi; /* Latitude or declination in degrees Input in sys1, returned in sys2 */ double *ptheta; /* Longitude or right ascension proper motion in degrees/year Input in sys1, returned in sys2 */ double *pphi; /* Latitude or declination proper motion in degrees/year Input in sys1, returned in sys2 */ { void fk5prec(), fk4prec(); /* Set equinoxes if 0.0 */ if (eq1 == 0.0) { if (sys1 == WCS_B1950) eq1 = 1950.0; else eq1 = 2000.0; } if (eq2 == 0.0) { if (sys2 == WCS_B1950) eq2 = 1950.0; else eq2 = 2000.0; } /* Set epochs if 0.0 */ if (ep1 == 0.0) { if (sys1 == WCS_B1950) ep1 = 1950.0; else ep1 = 2000.0; } if (ep2 == 0.0) { if (sys2 == WCS_B1950) ep2 = 1950.0; else ep2 = 2000.0; } if (sys1 == WCS_ICRS && sys2 == WCS_ICRS) eq2 = eq1; if (sys1 == WCS_J2000 && sys2 == WCS_ICRS && eq1 == 2000.0) { eq2 = eq1; sys1 = sys2; } /* Set systems and equinoxes so that ICRS coordinates are not precessed */ if (sys1 == WCS_ICRS && sys2 == WCS_J2000 && eq2 == 2000.0) { eq1 = eq2; sys1 = sys2; } /* If systems and equinoxes are the same, add proper motion and return */ if (sys2 == sys1 && eq1 == eq2) { if (ep1 != ep2) { if (sys1 == WCS_J2000) { *dtheta = *dtheta + ((ep2 - ep1) * *ptheta); *dphi = *dphi + ((ep2 - ep1) * *pphi); } else if (sys1 == WCS_B1950) { *dtheta = *dtheta + ((ep2 - ep1) * *ptheta); *dphi = *dphi + ((ep2 - ep1) * *pphi); } } if (eq1 != eq2) { if (sys1 == WCS_B1950) fk4prec (eq1, eq2, dtheta, dphi); if (sys1 == WCS_J2000) fk5prec (eq1, 2000.0, dtheta, dphi); } return; } /* Precess from input equinox to input system equinox, if necessary */ if (sys1 == WCS_B1950 && eq1 != 1950.0) fk4prec (eq1, 1950.0, dtheta, dphi); if (sys1 == WCS_J2000 && eq1 != 2000.0) fk5prec (eq1, 2000.0, dtheta, dphi); /* Convert to B1950 FK4 */ if (sys2 == WCS_B1950) { if (sys1 == WCS_J2000) { if (*ptheta != 0.0 || *pphi != 0.0) { fk524m (dtheta, dphi, ptheta, pphi); if (ep1 == 2000.0) ep1 = 1950.0; if (ep2 != 1950.0) { *dtheta = *dtheta + ((ep2 - 1950.0) * *ptheta); *dphi = *dphi + ((ep2 - 1950.0) * *pphi); } } else if (ep2 != 1950.0) fk524e (dtheta, dphi, ep2); else fk524 (dtheta, dphi); } else if (sys1 == WCS_GALACTIC) gal2fk4 (dtheta, dphi); else if (sys1 == WCS_ECLIPTIC) ecl2fk4 (dtheta, dphi, ep2); } else if (sys2 == WCS_J2000) { if (sys1 == WCS_B1950) { if (*ptheta != 0.0 || *pphi != 0.0) { fk425m (dtheta, dphi, ptheta, pphi); if (ep2 != 2000.0) { *dtheta = *dtheta + ((ep2 - 2000.0) * *ptheta); *dphi = *dphi + ((ep2 - 2000.0) * *pphi); } } else if (ep2 > 0.0) fk425e (dtheta, dphi, ep2); else fk425 (dtheta, dphi); } else if (sys1 == WCS_GALACTIC) gal2fk5 (dtheta, dphi); else if (sys1 == WCS_ECLIPTIC) ecl2fk5 (dtheta, dphi, ep2); } else if (sys2 == WCS_GALACTIC) { if (sys1 == WCS_B1950) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } fk42gal (dtheta, dphi); } else if (sys1 == WCS_J2000) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } fk52gal (dtheta, dphi); } else if (sys1 == WCS_ECLIPTIC) { ecl2fk5 (dtheta, dphi, ep2); fk52gal (dtheta, dphi); } } else if (sys2 == WCS_ECLIPTIC) { if (sys1 == WCS_B1950) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } if (ep2 > 0.0) fk42ecl (dtheta, dphi, ep2); else fk42ecl (dtheta, dphi, 1950.0); } else if (sys1 == WCS_J2000) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } fk52ecl (dtheta, dphi, ep2); } else if (sys1 == WCS_GALACTIC) { gal2fk5 (dtheta, dphi); fk52ecl (dtheta, dphi, ep2); } } /* Precess to desired equinox, if necessary */ if (sys2 == WCS_B1950 && eq2 != 1950.0) fk4prec (1950.0, eq2, dtheta, dphi); if (sys2 == WCS_J2000 && eq2 != 2000.0) fk5prec (2000.0, eq2, dtheta, dphi); /* Keep latitude/declination between +90 and -90 degrees */ if (*dphi > 90.0) { *dphi = 180.0 - *dphi; *dtheta = *dtheta + 180.0; } else if (*dphi < -90.0) { *dphi = -180.0 - *dphi; *dtheta = *dtheta + 180.0; } /* Keep longitude/right ascension between 0 and 360 degrees */ if (*dtheta > 360.0) *dtheta = *dtheta - 360.0; else if (*dtheta < 0.0) *dtheta = *dtheta + 360.0; return; } /* Convert from coordinate system sys1 to coordinate system sys2, converting proper motions, too, and adding them if an epoch is specified */ void wcsconv (sys1, sys2, eq1, eq2, ep1, ep2, dtheta, dphi, ptheta, pphi, px, rv) int sys1; /* Input coordinate system (J2000, B1950, ECLIPTIC, GALACTIC */ int sys2; /* Output coordinate system (J2000, B1950, ECLIPTIC, GALACTIC */ double eq1; /* Input equinox (default of sys1 if 0.0) */ double eq2; /* Output equinox (default of sys2 if 0.0) */ double ep1; /* Input Besselian epoch in years (for proper motion) */ double ep2; /* Output Besselian epoch in years (for proper motion) */ double *dtheta; /* Longitude or right ascension in degrees Input in sys1, returned in sys2 */ double *dphi; /* Latitude or declination in degrees Input in sys1, returned in sys2 */ double *ptheta; /* Longitude or right ascension proper motion in degrees/year Input in sys1, returned in sys2 */ double *pphi; /* Latitude or declination proper motion in degrees/year Input in sys1, returned in sys2 */ double *px; /* Parallax in arcseconds */ double *rv; /* Radial velocity in km/sec */ { void fk5prec(), fk4prec(); /* Set equinoxes if 0.0 */ if (eq1 == 0.0) { if (sys1 == WCS_B1950) eq1 = 1950.0; else eq1 = 2000.0; } if (eq2 == 0.0) { if (sys2 == WCS_B1950) eq2 = 1950.0; else eq2 = 2000.0; } /* Set epochs if 0.0 */ if (ep1 == 0.0) { if (sys1 == WCS_B1950) ep1 = 1950.0; else ep1 = 2000.0; } if (ep2 == 0.0) { if (sys2 == WCS_B1950) ep2 = 1950.0; else ep2 = 2000.0; } /* Set systems and equinoxes so that ICRS coordinates are not precessed */ if (sys1 == WCS_ICRS && sys2 == WCS_ICRS) eq2 = eq1; if (sys1 == WCS_J2000 && sys2 == WCS_ICRS && eq1 == 2000.0) { eq2 = eq1; sys1 = sys2; } if (sys1 == WCS_ICRS && sys2 == WCS_J2000 && eq2 == 2000.0) { eq1 = eq2; sys1 = sys2; } /* If systems and equinoxes are the same, add proper motion and return */ if (sys2 == sys1 && eq1 == eq2) { if (ep1 != ep2) { if (sys1 == WCS_J2000) { *dtheta = *dtheta + ((ep2 - ep1) * *ptheta); *dphi = *dphi + ((ep2 - ep1) * *pphi); } else if (sys1 == WCS_B1950) { *dtheta = *dtheta + ((ep2 - ep1) * *ptheta); *dphi = *dphi + ((ep2 - ep1) * *pphi); } } return; } /* Precess from input equinox to input system equinox, if necessary */ if (eq1 != eq2) { if (sys1 == WCS_B1950 && eq1 != 1950.0) fk4prec (eq1, 1950.0, dtheta, dphi); if (sys1 == WCS_J2000 && eq1 != 2000.0) fk5prec (eq1, 2000.0, dtheta, dphi); } /* Convert to B1950 FK4 */ if (sys2 == WCS_B1950) { if (sys1 == WCS_J2000) { if (*ptheta != 0.0 || *pphi != 0.0) { if (*px != 0.0 || *rv != 0.0) fk524pv (dtheta, dphi, ptheta, pphi, px, rv); else fk524m (dtheta, dphi, ptheta, pphi); if (ep1 == 2000.0) ep1 = 1950.0; if (ep2 != 1950.0) { *dtheta = *dtheta + ((ep2 - 1950.0) * *ptheta); *dphi = *dphi + ((ep2 - 1950.0) * *pphi); } } else if (ep2 != 1950.0) fk524e (dtheta, dphi, ep2); else fk524 (dtheta, dphi); } else if (sys1 == WCS_GALACTIC) gal2fk4 (dtheta, dphi); else if (sys1 == WCS_ECLIPTIC) ecl2fk4 (dtheta, dphi, ep2); } else if (sys2 == WCS_J2000) { if (sys1 == WCS_B1950) { if (*ptheta != 0.0 || *pphi != 0.0) { if (*px != 0.0 || *rv != 0.0) fk425pv (dtheta, dphi, ptheta, pphi, px, rv); else fk425m (dtheta, dphi, ptheta, pphi); if (ep2 != 2000.0) { *dtheta = *dtheta + ((ep2 - 2000.0) * *ptheta); *dphi = *dphi + ((ep2 - 2000.0) * *pphi); } } else if (ep2 > 0.0) fk425e (dtheta, dphi, ep2); else fk425 (dtheta, dphi); } else if (sys1 == WCS_GALACTIC) gal2fk5 (dtheta, dphi); else if (sys1 == WCS_ECLIPTIC) ecl2fk5 (dtheta, dphi, ep2); } else if (sys2 == WCS_GALACTIC) { if (sys1 == WCS_B1950) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } fk42gal (dtheta, dphi); } else if (sys1 == WCS_J2000) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } fk52gal (dtheta, dphi); } else if (sys1 == WCS_ECLIPTIC) { ecl2fk5 (dtheta, dphi, ep2); fk52gal (dtheta, dphi); } } else if (sys2 == WCS_ECLIPTIC) { if (sys1 == WCS_B1950) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } if (ep2 > 0.0) fk42ecl (dtheta, dphi, ep2); else fk42ecl (dtheta, dphi, 1950.0); } else if (sys1 == WCS_J2000) { if (ep2 != 0.0 && (*ptheta != 0.0 || *pphi != 0.0)) { *dtheta = *dtheta + (*ptheta * (ep2 - ep1)); *dphi = *dphi + (*pphi * (ep2 - ep1)); } fk52ecl (dtheta, dphi, ep2); } else if (sys1 == WCS_GALACTIC) { gal2fk5 (dtheta, dphi); fk52ecl (dtheta, dphi, ep2); } } /* Precess to desired equinox, if necessary */ if (eq1 != eq2) { if (sys2 == WCS_B1950 && eq2 != 1950.0) fk4prec (1950.0, eq2, dtheta, dphi); if (sys2 == WCS_J2000 && eq2 != 2000.0) fk5prec (2000.0, eq2, dtheta, dphi); } /* Keep latitude/declination between +90 and -90 degrees */ if (*dphi > 90.0) { *dphi = 180.0 - *dphi; *dtheta = *dtheta + 180.0; } else if (*dphi < -90.0) { *dphi = -180.0 - *dphi; *dtheta = *dtheta + 180.0; } /* Keep longitude/right ascension between 0 and 360 degrees */ if (*dtheta > 360.0) *dtheta = *dtheta - 360.0; else if (*dtheta < 0.0) *dtheta = *dtheta + 360.0; return; } /* Convert from coordinate system sys1 to coordinate system sys2 */ void wcscon (sys1, sys2, eq1, eq2, dtheta, dphi, epoch) int sys1; /* Input coordinate system (J2000, B1950, ECLIPTIC, GALACTIC */ int sys2; /* Output coordinate system (J2000, B1950, ECLIPTIC, GALACTIC */ double eq1; /* Input equinox (default of sys1 if 0.0) */ double eq2; /* Output equinox (default of sys2 if 0.0) */ double *dtheta; /* Longitude or right ascension in degrees Input in sys1, returned in sys2 */ double *dphi; /* Latitude or declination in degrees Input in sys1, returned in sys2 */ double epoch; /* Besselian epoch in years */ { void fk5prec(), fk4prec(); /* Set equinoxes if 0.0 */ if (eq1 == 0.0) { if (sys1 == WCS_B1950) eq1 = 1950.0; else eq1 = 2000.0; } if (eq2 == 0.0) { if (sys2 == WCS_B1950) eq2 = 1950.0; else eq2 = 2000.0; } /* Set systems and equinoxes so that ICRS coordinates are not precessed */ if (sys1 == WCS_ICRS && sys2 == WCS_ICRS) eq2 = eq1; if (sys1 == WCS_J2000 && sys2 == WCS_ICRS && eq1 == 2000.0) { eq2 = eq1; sys1 = sys2; } if (sys1 == WCS_ICRS && sys2 == WCS_J2000 && eq2 == 2000.0) { eq1 = eq2; sys1 = sys2; } /* If systems and equinoxes are the same, return */ if (sys2 == sys1 && eq1 == eq2) return; /* Precess from input equinox, if necessary */ if (eq1 != eq2) { if (sys1 == WCS_B1950 && eq1 != 1950.0) fk4prec (eq1, 1950.0, dtheta, dphi); if (sys1 == WCS_J2000 && eq1 != 2000.0) fk5prec (eq1, 2000.0, dtheta, dphi); } /* Convert to B1950 FK4 */ if (sys2 == WCS_B1950) { if (sys1 == WCS_J2000) { if (epoch > 0) fk524e (dtheta, dphi, epoch); else fk524 (dtheta, dphi); } else if (sys1 == WCS_GALACTIC) gal2fk4 (dtheta, dphi); else if (sys1 == WCS_ECLIPTIC) { if (epoch > 0) ecl2fk4 (dtheta, dphi, epoch); else ecl2fk4 (dtheta, dphi, 1950.0); } } else if (sys2 == WCS_J2000) { if (sys1 == WCS_B1950) { if (epoch > 0) fk425e (dtheta, dphi, epoch); else fk425 (dtheta, dphi); } else if (sys1 == WCS_GALACTIC) gal2fk5 (dtheta, dphi); else if (sys1 == WCS_ECLIPTIC) { if (epoch > 0) ecl2fk5 (dtheta, dphi, epoch); else ecl2fk5 (dtheta, dphi, 2000.0); } } else if (sys2 == WCS_GALACTIC) { if (sys1 == WCS_B1950) fk42gal (dtheta, dphi); else if (sys1 == WCS_J2000) fk52gal (dtheta, dphi); else if (sys1 == WCS_ECLIPTIC) { if (epoch > 0) ecl2fk5 (dtheta, dphi, epoch); else ecl2fk5 (dtheta, dphi, 2000.0); fk52gal (dtheta, dphi); } } else if (sys2 == WCS_ECLIPTIC) { if (sys1 == WCS_B1950) { if (epoch > 0) fk42ecl (dtheta, dphi, epoch); else fk42ecl (dtheta, dphi, 1950.0); } else if (sys1 == WCS_J2000) { if (epoch > 0) fk52ecl (dtheta, dphi, epoch); else fk52ecl (dtheta, dphi, 2000.0); } else if (sys1 == WCS_GALACTIC) { gal2fk5 (dtheta, dphi); if (epoch > 0) fk52ecl (dtheta, dphi, epoch); else fk52ecl (dtheta, dphi, 2000.0); } } /* Precess to desired equinox, if necessary */ if (eq1 != eq2) { if (sys2 == WCS_B1950 && eq2 != 1950.0) fk4prec (1950.0, eq2, dtheta, dphi); if (sys2 == WCS_J2000 && eq2 != 2000.0) fk5prec (2000.0, eq2, dtheta, dphi); } /* Keep latitude/declination between +90 and -90 degrees */ if (*dphi > 90.0) { *dphi = 180.0 - *dphi; *dtheta = *dtheta + 180.0; } else if (*dphi < -90.0) { *dphi = -180.0 - *dphi; *dtheta = *dtheta + 180.0; } /* Keep longitude/right ascension between 0 and 360 degrees */ if (*dtheta > 360.0) *dtheta = *dtheta - 360.0; else if (*dtheta < 0.0) *dtheta = *dtheta + 360.0; return; } /* Set coordinate system from string */ int wcscsys (wcstring) char *wcstring; /* Name of coordinate system */ { double equinox; if (wcstring[0] == 'J' || wcstring[0] == 'j' || !strcmp (wcstring,"2000") || !strcmp (wcstring, "2000.0") || !strcmp (wcstring,"ICRS") || !strcmp (wcstring, "icrs") || !strncmp (wcstring,"FK5",3) || !strncmp (wcstring, "fk5",3)) return WCS_J2000; if (wcstring[0] == 'B' || wcstring[0] == 'b' || !strcmp (wcstring,"1950") || !strcmp (wcstring, "1950.0") || !strncmp (wcstring,"FK4",3) || !strncmp (wcstring, "fk4",3)) return WCS_B1950; else if (wcstring[0] == 'I' || wcstring[0] == 'i' ) return WCS_ICRS; else if (wcstring[0] == 'G' || wcstring[0] == 'g' ) return WCS_GALACTIC; else if (wcstring[0] == 'E' || wcstring[0] == 'e' ) return WCS_ECLIPTIC; else if (wcstring[0] == 'A' || wcstring[0] == 'a' ) return WCS_ALTAZ; else if (wcstring[0] == 'N' || wcstring[0] == 'n' ) return WCS_NPOLE; else if (wcstring[0] == 'L' || wcstring[0] == 'l' ) return WCS_LINEAR; else if (!strncasecmp (wcstring, "pixel", 5)) return WCS_XY; else if (wcstring[0] == 'P' || wcstring[0] == 'p' ) return WCS_PLANET; else if (isnum (wcstring)) { equinox = atof (wcstring); if (equinox > 1980.0) return WCS_J2000; else if (equinox > 1900.0) return WCS_B1950; else return -1; } else return -1; } /* Set equinox from string (return 0.0 if not obvious) */ double wcsceq (wcstring) char *wcstring; /* Name of coordinate system */ { if (wcstring[0] == 'J' || wcstring[0] == 'j' || wcstring[0] == 'B' || wcstring[0] == 'b') return (atof (wcstring+1)); else if (!strncmp (wcstring, "FK4",3) || !strncmp (wcstring, "fk4",3)) return (1950.0); else if (!strncmp (wcstring, "FK5",3) || !strncmp (wcstring, "fk5",3)) return (2000.0); else if (!strncmp (wcstring, "ICRS",4) || !strncmp (wcstring, "icrs",4)) return (2000.0); else if (wcstring[0] == '1' || wcstring[0] == '2') return (atof (wcstring)); else return (0.0); } /* Set coordinate system type string from system and equinox */ void wcscstr (cstr, syswcs, equinox, epoch) char *cstr; /* Coordinate system string (returned) */ int syswcs; /* Coordinate system code */ double equinox; /* Equinox of coordinate system */ double epoch; /* Epoch of coordinate system */ { char *estr; if (syswcs == WCS_XY) { strcpy (cstr, "XY"); return; } /* Try to figure out coordinate system if it is not set */ if (epoch == 0.0) epoch = equinox; if (syswcs < 0) { if (equinox > 0.0) { if (equinox == 2000.0) syswcs = WCS_J2000; else if (equinox == 1950.0) syswcs = WCS_B1950; } else if (epoch > 0.0) { if (epoch > 1980.0) { syswcs = WCS_J2000; equinox = 2000.0; } else { syswcs = WCS_B1950; equinox = 1950.0; } } else syswcs = WCS_J2000; } /* Set coordinate system string from system flag and epoch */ if (syswcs == WCS_B1950) { if (epoch == 1950.0 || epoch == 0.0) strcpy (cstr, "B1950"); else sprintf (cstr, "B%7.2f", equinox); if ((estr = strsrch (cstr,".00")) != NULL) { estr[0] = (char) 0; estr[1] = (char) 0; estr[2] = (char) 0; } } else if (syswcs == WCS_GALACTIC) strcpy (cstr, "galactic"); else if (syswcs == WCS_ECLIPTIC) strcpy (cstr, "ecliptic"); else if (syswcs == WCS_J2000) { if (epoch == 2000.0 || epoch == 0.0) strcpy (cstr, "J2000"); else sprintf (cstr, "J%7.2f", equinox); if ((estr = strsrch (cstr,".00")) != NULL) { estr[0] = (char) 0; estr[1] = (char) 0; estr[2] = (char) 0; } } else if (syswcs == WCS_ICRS) { strcpy (cstr, "ICRS"); } else if (syswcs == WCS_PLANET) { strcpy (cstr, "PLANET"); } else if (syswcs == WCS_LINEAR || syswcs == WCS_XY) { strcpy (cstr, "LINEAR"); } return; } /* Constant vector and matrix (by columns) These values were obtained by inverting C.Hohenkerk's forward matrix (private communication), which agrees with the one given in reference 2 but which has one additional decimal place. */ static double a[3] = {-1.62557e-6, -0.31919e-6, -0.13843e-6}; static double ad[3] = {1.245e-3, -1.580e-3, -0.659e-3}; static double d2pi = 6.283185307179586476925287; /* two PI */ static double tiny = 1.e-30; /* small number to avoid arithmetic problems */ /* FK524 convert J2000 FK5 star data to B1950 FK4 based on Starlink sla_fk524 by P.T.Wallace 27 October 1987 */ static double emi[6][6] = { { 0.9999256795, /* emi[0][0] */ 0.0111814828, /* emi[0][1] */ 0.0048590039, /* emi[0][2] */ -0.00000242389840, /* emi[0][3] */ -0.00000002710544, /* emi[0][4] */ -0.00000001177742 }, /* emi[0][5] */ { -0.0111814828, /* emi[1][0] */ 0.9999374849, /* emi[1][1] */ -0.0000271771, /* emi[1][2] */ 0.00000002710544, /* emi[1][3] */ -0.00000242392702, /* emi[1][4] */ 0.00000000006585 }, /* emi[1][5] */ { -0.0048590040, /* emi[2][0] */ -0.0000271557, /* emi[2][1] */ 0.9999881946, /* emi[2][2] */ 0.00000001177742, /* emi[2][3] */ 0.00000000006585, /* emi[2][4] */ -0.00000242404995 }, /* emi[2][5] */ { -0.000551, /* emi[3][0] */ 0.238509, /* emi[3][1] */ -0.435614, /* emi[3][2] */ 0.99990432, /* emi[3][3] */ 0.01118145, /* emi[3][4] */ 0.00485852 }, /* emi[3][5] */ { -0.238560, /* emi[4][0] */ -0.002667, /* emi[4][1] */ 0.012254, /* emi[4][2] */ -0.01118145, /* emi[4][3] */ 0.99991613, /* emi[4][4] */ -0.00002717 }, /* emi[4][5] */ { 0.435730, /* emi[5][0] */ -0.008541, /* emi[5][1] */ 0.002117, /* emi[5][2] */ -0.00485852, /* emi[5][3] */ -0.00002716, /* emi[5][4] */ 0.99996684 } /* emi[5][5] */ }; void fk524 (ra,dec) double *ra; /* Right ascension in degrees (J2000 in, B1950 out) */ double *dec; /* Declination in degrees (J2000 in, B1950 out) */ { double rapm; /* Proper motion in right ascension */ double decpm; /* Proper motion in declination */ /* In: deg/jul.yr. Out: deg/trop.yr. */ rapm = (double) 0.0; decpm = (double) 0.0; fk524m (ra, dec, &rapm, &decpm); return; } void fk524e (ra, dec, epoch) double *ra; /* Right ascension in degrees (J2000 in, B1950 out) */ double *dec; /* Declination in degrees (J2000 in, B1950 out) */ double epoch; /* Besselian epoch in years */ { double rapm; /* Proper motion in right ascension */ double decpm; /* Proper motion in declination */ /* In: deg/jul.yr. Out: deg/trop.yr. */ rapm = (double) 0.0; decpm = (double) 0.0; fk524m (ra, dec, &rapm, &decpm); *ra = *ra + (rapm * (epoch - 1950.0)); *dec = *dec + (decpm * (epoch - 1950.0)); return; } void fk524m (ra,dec,rapm,decpm) double *ra; /* Right ascension in degrees (J2000 in, B1950 out) */ double *dec; /* Declination in degrees (J2000 in, B1950 out) */ double *rapm; /* Proper motion in right ascension */ double *decpm; /* Proper motion in declination */ /* In: ra/dec deg/jul.yr. Out: ra/dec deg/trop.yr. */ { double parallax = 0.0; double rv = 0.0; fk524pv (ra, dec, rapm, decpm, ¶llax, &rv); return; } void fk524pv (ra,dec,rapm,decpm, parallax, rv) double *ra; /* Right ascension in degrees (J2000 in, B1950 out) */ double *dec; /* Declination in degrees (J2000 in, B1950 out) */ double *rapm; /* Proper motion in right ascension */ double *decpm; /* Proper motion in declination * In: ra/dec degrees/Julian year (not ra*cos(dec)) * Out: ra/dec degrees/tropical year */ double *parallax; /* Parallax (arcsec) */ double *rv; /* Rradial velocity (km/s, +ve = moving away) */ /* This routine converts stars from the IAU 1976 FK5 Fricke system, to the old Bessel-Newcomb FK4 system, using Yallop's implementation (see ref 2) of a matrix method due to Standish (see ref 3). The numerical values of ref 2 are used canonically. * Conversion from other than Julian epoch 2000.0 to other than Besselian epoch 1950.0 will require use of the appropriate precession, proper motion, and e-terms routines before and/or after fk524 is called. * In the FK4 catalogue the proper motions of stars within 10 degrees of the poles do not embody the differential e-term effect and should, strictly speaking, be handled in a different manner from stars outside these regions. however, given the general lack of homogeneity of the star data available for routine astrometry, the difficulties of handling positions that may have been determined from astrometric fields spanning the polar and non-polar regions, the likelihood that the differential e-terms effect was not taken into account when allowing for proper motion in past astrometry, and the undesirability of a discontinuity in the algorithm, the decision has been made in this routine to include the effect of differential e-terms on the proper motions for all stars, whether polar or not, at epoch 2000, and measuring on the sky rather than in terms of dra, the errors resulting from this simplification are less than 1 milliarcsecond in position and 1 milliarcsecond per century in proper motion. References: 1 "Mean and apparent place computations in the new IAU System. I. The transformation of astrometric catalog systems to the equinox J2000.0." Smith, C.A.; Kaplan, G.H.; Hughes, J.A.; Seidelmann, P.K.; Yallop, B.D.; Hohenkerk, C.Y. Astronomical Journal vol. 97, Jan. 1989, p. 265-273. 2 "Mean and apparent place computations in the new IAU System. II. Transformation of mean star places from FK4 B1950.0 to FK5 J2000.0 using matrices in 6-space." Yallop, B.D.; Hohenkerk, C.Y.; Smith, C.A.; Kaplan, G.H.; Hughes, J.A.; Seidelmann, P.K.; Astronomical Journal vol. 97, Jan. 1989, p. 274-279. 3 Seidelmann, P.K. (ed), 1992. "Explanatory Supplement to the Astronomical Almanac", ISBN 0-935702-68-7. 4 "Conversion of positions and proper motions from B1950.0 to the IAU system at J2000.0", Standish, E.M. Astronomy and Astrophysics, vol. 115, no. 1, Nov. 1982, p. 20-22. P.T.Wallace Starlink 19 December 1993 Doug Mink Smithsonian Astrophysical Observatory 1 November 2000 */ { double r2000,d2000; /* J2000.0 ra,dec (radians) */ double r1950,d1950; /* B1950.0 ra,dec (rad) */ /* Miscellaneous */ double ur,ud; double sr, cr, sd, cd, x, y, z, w, wd; double v1[6],v2[6]; double xd,yd,zd; double rxyz, rxysq, rxy; double dra,ddec; int i,j; int diag = 0; /* Constants */ double zero = (double) 0.0; double vf = 21.095; /* Km per sec to AU per tropical century */ /* = 86400 * 36524.2198782 / 149597870 */ /* Convert J2000 RA and Dec from degrees to radians */ r2000 = degrad (*ra); d2000 = degrad (*dec); /* Convert J2000 RA and Dec proper motion from degrees/year to arcsec/tc */ ur = *rapm * 360000.0; ud = *decpm * 360000.0; /* Spherical to Cartesian */ sr = sin (r2000); cr = cos (r2000); sd = sin (d2000); cd = cos (d2000); x = cr * cd; y = sr * cd; z = sd; v1[0] = x; v1[1] = y; v1[2] = z; if (ur != zero || ud != zero) { v1[3] = -(ur*y) - (cr*sd*ud); v1[4] = (ur*x) - (sr*sd*ud); v1[5] = (cd*ud); } else { v1[3] = zero; v1[4] = zero; v1[5] = zero; } /* Convert position + velocity vector to bn system */ for (i = 0; i < 6; i++) { w = zero; for (j = 0; j < 6; j++) { w = w + emi[i][j] * v1[j]; } v2[i] = w; } /* Vector components */ x = v2[0]; y = v2[1]; z = v2[2]; rxyz = sqrt (x*x + y*y + z*z); /* Magnitude of position vector */ rxyz = sqrt (x*x + y*y + z*z); /* Apply e-terms to position */ w = (x * a[0]) + (y * a[1]) + (z * a[2]); x = x + (a[0] * rxyz) - (w * x); y = y + (a[1] * rxyz) - (w * z); z = z + (a[2] * rxyz) - (w * z); /* Recompute magnitude of position vector */ rxyz = sqrt (x*x + y*y + z*z); /* Apply e-terms to position and velocity */ x = v2[0]; y = v2[1]; z = v2[2]; w = (x * a[0]) + (y * a[1]) + (z * a[2]); wd = (x * ad[0]) + (y * ad[1]) + (z * ad[2]); x = x + (a[0] * rxyz) - (w * x); y = y + (a[1] * rxyz) - (w * y); z = z + (a[2] * rxyz) - (w * z); xd = v2[3] + (ad[0] * rxyz) - (wd * x); yd = v2[4] + (ad[1] * rxyz) - (wd * y); zd = v2[5] + (ad[2] * rxyz) - (wd * z); /* Convert to spherical */ rxysq = (x * x) + (y * y); rxy = sqrt (rxysq); /* Convert back to spherical coordinates */ if (x == zero && y == zero) r1950 = zero; else { r1950 = atan2 (y,x); if (r1950 < zero) r1950 = r1950 + d2pi; } d1950 = atan2 (z,rxy); if (rxy > tiny) { ur = (x*yd - y*xd) / rxysq; ud = (zd*rxysq - z * (x*xd + y*yd)) / ((rxysq + z*z) * rxy); } if (*parallax > tiny) { *rv = ((x * xd) + (y * yd) + (z * zd)) / (*parallax * vf * rxyz); *parallax = *parallax / rxyz; } /* Return results */ *ra = raddeg (r1950); *dec = raddeg (d1950); *rapm = ur / 360000.0; *decpm = ud / 360000.0; if (diag) { dra = 240.0 * raddeg (r1950 - r2000); ddec = 3600.0 * raddeg (d1950 - d2000); fprintf(stderr,"B1950-J2000: dra= %11.5f sec ddec= %f11.5f arcsec\n", dra, ddec); } return; } /* Convert B1950.0 FK4 star data to J2000.0 FK5 */ static double em[6][6] = { { 0.9999256782, /* em[0][0] */ -0.0111820611, /* em[0][1] */ -0.0048579477, /* em[0][2] */ 0.00000242395018, /* em[0][3] */ -0.00000002710663, /* em[0][4] */ -0.00000001177656 }, /* em[0][5] */ { 0.0111820610, /* em[1][0] */ 0.9999374784, /* em[1][1] */ -0.0000271765, /* em[1][2] */ 0.00000002710663, /* em[1][3] */ 0.00000242397878, /* em[1][4] */ -0.00000000006587 }, /* em[1][5] */ { 0.0048579479, /* em[2][0] */ -0.0000271474, /* em[2][1] */ 0.9999881997, /* em[2][2] */ 0.00000001177656, /* em[2][3] */ -0.00000000006582, /* em[2][4] */ 0.00000242410173 }, /* em[2][5] */ { -0.000551, /* em[3][0] */ -0.238565, /* em[3][1] */ 0.435739, /* em[3][2] */ 0.99994704, /* em[3][3] */ -0.01118251, /* em[3][4] */ -0.00485767 }, /* em[3][5] */ { 0.238514, /* em[4][0] */ -0.002667, /* em[4][1] */ -0.008541, /* em[4][2] */ 0.01118251, /* em[4][3] */ 0.99995883, /* em[4][4] */ -0.00002718 }, /* em[4][5] */ { -0.435623, /* em[5][0] */ 0.012254, /* em[5][1] */ 0.002117, /* em[5][2] */ 0.00485767, /* em[5][3] */ -0.00002714, /* em[5][4] */ 1.00000956 } /* em[5][5] */ }; void fk425 (ra, dec) double *ra; /* Right ascension in degrees (B1950 in, J2000 out) */ double *dec; /* Declination in degrees (B1950 in, J2000 out) */ { double rapm; /* Proper motion in right ascension */ double decpm; /* Proper motion in declination */ /* In: rad/trop.yr. Out: rad/jul.yr. */ rapm = (double) 0.0; decpm = (double) 0.0; fk425m (ra, dec, &rapm, &decpm); return; } void fk425e (ra, dec, epoch) double *ra; /* Right ascension in degrees (B1950 in, J2000 out) */ double *dec; /* Declination in degrees (B1950 in, J2000 out) */ double epoch; /* Besselian epoch in years */ { double rapm; /* Proper motion in right ascension */ double decpm; /* Proper motion in declination */ /* In: rad/trop.yr. Out: rad/jul.yr. */ rapm = (double) 0.0; decpm = (double) 0.0; fk425m (ra, dec, &rapm, &decpm); *ra = *ra + (rapm * (epoch - 2000.0)); *dec = *dec + (decpm * (epoch - 2000.0)); return; } void fk425m (ra, dec, rapm, decpm) double *ra, *dec; /* Right ascension and declination in degrees input: B1950.0,FK4 returned: J2000.0,FK5 */ double *rapm, *decpm; /* Proper motion in right ascension and declination input: B1950.0,FK4 returned: J2000.0,FK5 ra/dec deg/trop.yr. ra/dec deg/jul.yr. */ { double parallax = 0.0; double rv = 0.0; fk425pv (ra, dec, rapm, decpm, ¶llax, &rv); return; } void fk425pv (ra,dec,rapm,decpm, parallax, rv) double *ra; /* Right ascension in degrees (J2000 in, B1950 out) */ double *dec; /* Declination in degrees (J2000 in, B1950 out) */ double *rapm; /* Proper motion in right ascension */ double *decpm; /* Proper motion in declination * In: ra/dec degrees/Julian year (not ra*cos(dec)) * Out: ra/dec degrees/tropical year */ double *parallax; /* Parallax (arcsec) */ double *rv; /* Rradial velocity (km/s, +ve = moving away) */ /* This routine converts stars from the old Bessel-Newcomb FK4 system to the IAU 1976 FK5 Fricke system, using Yallop's implementation (see ref 2) of a matrix method due to Standish (see ref 3). The numerical values of ref 2 are used canonically. * Conversion from other than Besselian epoch 1950.0 to other than Julian epoch 2000.0 will require use of the appropriate precession, proper motion, and e-terms routines before and/or after fk425 is called. * In the FK4 catalogue the proper motions of stars within 10 degrees of the poles do not embody the differential e-term effect and should, strictly speaking, be handled in a different manner from stars outside these regions. however, given the general lack of homogeneity of the star data available for routine astrometry, the difficulties of handling positions that may have been determined from astrometric fields spanning the polar and non-polar regions, the likelihood that the differential e-terms effect was not taken into account when allowing for proper motion in past astrometry, and the undesirability of a discontinuity in the algorithm, the decision has been made in this routine to include the effect of differential e-terms on the proper motions for all stars, whether polar or not, at epoch 2000, and measuring on the sky rather than in terms of dra, the errors resulting from this simplification are less than 1 milliarcsecond in position and 1 milliarcsecond per century in proper motion. References: 1 "Mean and apparent place computations in the new IAU System. I. The transformation of astrometric catalog systems to the equinox J2000.0." Smith, C.A.; Kaplan, G.H.; Hughes, J.A.; Seidelmann, P.K.; Yallop, B.D.; Hohenkerk, C.Y. Astronomical Journal vol. 97, Jan. 1989, p. 265-273. 2 "Mean and apparent place computations in the new IAU System. II. Transformation of mean star places from FK4 B1950.0 to FK5 J2000.0 using matrices in 6-space." Yallop, B.D.; Hohenkerk, C.Y.; Smith, C.A.; Kaplan, G.H.; Hughes, J.A.; Seidelmann, P.K.; Astronomical Journal vol. 97, Jan. 1989, p. 274-279. 3 "Conversion of positions and proper motions from B1950.0 to the IAU system at J2000.0", Standish, E.M. Astronomy and Astrophysics, vol. 115, no. 1, Nov. 1982, p. 20-22. P.T.Wallace Starlink 20 December 1993 Doug Mink Smithsonian Astrophysical Observatory 7 June 1995 */ { double r1950,d1950; /* B1950.0 ra,dec (rad) */ double r2000,d2000; /* J2000.0 ra,dec (rad) */ /* Miscellaneous */ double ur,ud,sr,cr,sd,cd,w,wd; double x,y,z,xd,yd,zd, dra,ddec; double rxyz, rxysq, rxy, rxyzsq, spxy, spxyz; int i,j; int diag = 0; double r0[3],rd0[3]; /* star position and velocity vectors */ double v1[6],v2[6]; /* combined position and velocity vectors */ /* Constants */ double zero = (double) 0.0; double vf = 21.095; /* Km per sec to AU per tropical century */ /* = 86400 * 36524.2198782 / 149597870 */ /* Convert B1950 RA and Dec from degrees to radians */ r1950 = degrad (*ra); d1950 = degrad (*dec); /* Convert B1950 RA and Dec proper motion from degrees/year to arcsec/tc */ ur = *rapm * 360000.0; ud = *decpm * 360000.0; /* Convert direction to Cartesian */ sr = sin (r1950); cr = cos (r1950); sd = sin (d1950); cd = cos (d1950); r0[0] = cr * cd; r0[1] = sr * cd; r0[2] = sd; /* Convert motion to Cartesian */ w = vf * *rv * *parallax; if (ur != zero || ud != zero || (*rv != zero && *parallax != zero)) { rd0[0] = (-sr * cd * ur) - (cr * sd * ud) + (w * r0[0]); rd0[1] = (cr * cd * ur) - (sr * sd * ud) + (w * r0[1]); rd0[2] = (cd * ud) + (w * r0[2]); } else { rd0[0] = zero; rd0[1] = zero; rd0[2] = zero; } /* Remove e-terms from position and express as position+velocity 6-vector */ w = (r0[0] * a[0]) + (r0[1] * a[1]) + (r0[2] * a[2]); for (i = 0; i < 3; i++) v1[i] = r0[i] - a[i] + (w * r0[i]); /* Remove e-terms from proper motion and express as 6-vector */ wd = (r0[0] * ad[0]) + (r0[1] * ad[1]) + (r0[2] * ad[2]); for (i = 0; i < 3; i++) v1[i+3] = rd0[i] - ad[i] + (wd * r0[i]); /* Alternately: Put proper motion in 6-vector without adding e-terms for (i = 0; i < 3; i++) v1[i+3] = rd0[i]; */ /* Convert position + velocity vector to FK5 system */ for (i = 0; i < 6; i++) { w = zero; for (j = 0; j < 6; j++) { w += em[i][j] * v1[j]; } v2[i] = w; } /* Vector components */ x = v2[0]; y = v2[1]; z = v2[2]; xd = v2[3]; yd = v2[4]; zd = v2[5]; /* Magnitude of position vector */ rxysq = x*x + y*y; rxy = sqrt (rxysq); rxyzsq = rxysq + z*z; rxyz = sqrt (rxyzsq); spxy = (x * xd) + (y * yd); spxyz = spxy + (z * zd); /* Convert back to spherical coordinates */ if (x == zero && y == zero) r2000 = zero; else { r2000 = atan2 (y,x); if (r2000 < zero) r2000 = r2000 + d2pi; } d2000 = atan2 (z,rxy); if (rxy > tiny) { ur = ((x * yd) - (y * xd)) / rxysq; ud = ((zd * rxysq) - (z * spxy)) / (rxyzsq * rxy); } if (*parallax > tiny) { *rv = spxyz / (*parallax * rxyz * vf); *parallax = *parallax / rxyz; } /* Return results */ *ra = raddeg (r2000); *dec = raddeg (d2000); *rapm = ur / 360000.0; *decpm = ud / 360000.0; if (diag) { dra = 240.0 * raddeg (r2000 - r1950); ddec = 3600.0 * raddeg (d2000 - d1950); fprintf(stderr,"J2000-B1950: dra= %11.5f sec ddec= %f11.5f arcsec\n", dra, ddec); } return; } int idg=0; /* l2,b2 system of galactic coordinates * p = 192.25 ra of galactic north pole (mean b1950.0) * q = 62.6 inclination of galactic to mean b1950.0 equator * r = 33 longitude of ascending node * p,q,r are degrees * Equatorial to galactic rotation matrix (The Eulerian angles are p, q, 90-r) +cp.cq.sr-sp.cr +sp.cq.sr+cp.cr -sq.sr -cp.cq.cr-sp.sr -sp.cq.cr+cp.sr +sq.cr cp.sq +sp.sq +cq */ static double bgal[3][3] = {{-0.066988739415,-0.872755765852,-0.483538914632}, {0.492728466075,-0.450346958020, 0.744584633283}, {-0.867600811151,-0.188374601723, 0.460199784784}}; /*--- Transform B1950.0 FK4 equatorial coordinates to * IAU 1958 galactic coordinates */ void fk42gal (dtheta,dphi) double *dtheta; /* B1950.0 FK4 right ascension in degrees Galactic longitude (l2) in degrees (returned) */ double *dphi; /* B1950.0 FK4 declination in degrees Galactic latitude (b2) in degrees (returned) */ /* Input equatorial coordinates are B1950 FK4. Use fk52gal() to convert from j2000.0 coordinates. Reference: Blaauw et al, MNRAS,121,123 (1960) */ { double pos[3],pos1[3],r,dl,db,rl,rb,rra,rdec,dra,ddec; void v2s3(),s2v3(); int i; char *eqcoor, *eqstrn(); dra = *dtheta; ddec = *dphi; rra = degrad (dra); rdec = degrad (ddec); /* remove e-terms */ /* call jpabe (rra,rdec,-1,idg) */ /* Spherical to Cartesian */ r = 1.; s2v3 (rra,rdec,r,pos); /* rotate to galactic */ for (i = 0; i<3; i++) { pos1[i] = pos[0]*bgal[i][0] + pos[1]*bgal[i][1] + pos[2]*bgal[i][2]; } /* Cartesian to spherical */ v2s3 (pos1,&rl,&rb,&r); dl = raddeg (rl); db = raddeg (rb); *dtheta = dl; *dphi = db; /* Print result if in diagnostic mode */ if (idg) { eqcoor = eqstrn (dra,ddec); fprintf (stderr,"FK42GAL: B1950 RA,Dec= %s\n",eqcoor); fprintf (stderr,"FK42GAL: long = %.5f lat = %.5f\n",dl,db); free (eqcoor); } return; } /*--- Transform IAU 1958 galactic coordinates to B1950.0 'FK4' * equatorial coordinates */ void gal2fk4 (dtheta,dphi) double *dtheta; /* Galactic longitude (l2) in degrees B1950 FK4 RA in degrees (returned) */ double *dphi; /* Galactic latitude (b2) in degrees B1950 FK4 Dec in degrees (returned) */ /* Output equatorial coordinates are B1950.0 FK4. Use gal2fk5() to convert to J2000 coordinates. Reference: Blaauw et al, MNRAS,121,123 (1960) */ { double pos[3],pos1[3],r,dl,db,rl,rb,rra,rdec,dra,ddec; void v2s3(),s2v3(); char *eqcoor, *eqstrn(); int i; /* spherical to cartesian */ dl = *dtheta; db = *dphi; rl = degrad (dl); rb = degrad (db); r = 1.0; s2v3 (rl,rb,r,pos); /* rotate to equatorial coordinates */ for (i = 0; i < 3; i++) { pos1[i] = pos[0]*bgal[0][i] + pos[1]*bgal[1][i] + pos[2]*bgal[2][i]; } /* cartesian to spherical */ v2s3 (pos1,&rra,&rdec,&r); /* introduce e-terms */ /* jpabe (rra,rdec,-1,idg); */ dra = raddeg (rra); ddec = raddeg (rdec); *dtheta = dra; *dphi = ddec; /* print result if in diagnostic mode */ if (idg) { fprintf (stderr,"GAL2FK4: long = %.5f lat = %.5f\n",dl,db); eqcoor = eqstrn (dra,ddec); fprintf (stderr,"GAL2FK4: B1950 RA,Dec= %s\n",eqcoor); free (eqcoor); } return; } /* l2,b2 system of galactic coordinates p = 192.25 ra of galactic north pole (mean b1950.0) q = 62.6 inclination of galactic to mean b1950.0 equator r = 33 longitude of ascending node p,q,r are degrees */ /* Equatorial to galactic rotation matrix The eulerian angles are p, q, 90-r +cp.cq.sr-sp.cr +sp.cq.sr+cp.cr -sq.sr -cp.cq.cr-sp.sr -sp.cq.cr+cp.sr +sq.cr +cp.sq +sp.sq +cq */ static double jgal[3][3] = {{-0.054875539726,-0.873437108010,-0.483834985808}, {0.494109453312,-0.444829589425, 0.746982251810}, {-0.867666135858,-0.198076386122, 0.455983795705}}; /* Transform J2000 equatorial coordinates to IAU 1958 galactic coordinates */ void fk52gal (dtheta,dphi) double *dtheta; /* J2000 right ascension in degrees Galactic longitude (l2) in degrees (returned) */ double *dphi; /* J2000 declination in degrees Galactic latitude (b2) in degrees (returned) */ /* Rotation matrices by P.T.Wallace, Starlink eqgal and galeq, March 1986 */ /* Input equatorial coordinates are J2000 FK5. Use gal2fk4() if converting from B1950 FK4 coordinates. Reference: Blaauw et al, MNRAS,121,123 (1960) */ { double pos[3],pos1[3],r,dl,db,rl,rb,rra,rdec,dra,ddec; void v2s3(),s2v3(); char *eqcoor, *eqstrn(); int i; /* Spherical to cartesian */ dra = *dtheta; ddec = *dphi; rra = degrad (dra); rdec = degrad (ddec); r = 1.0; (void)s2v3 (rra,rdec,r,pos); /* Rotate to galactic */ for (i = 0; i < 3; i++) { pos1[i] = pos[0]*jgal[i][0] + pos[1]*jgal[i][1] + pos[2]*jgal[i][2]; } /* Cartesian to spherical */ v2s3 (pos1,&rl,&rb,&r); dl = raddeg (rl); db = raddeg (rb); *dtheta = dl; *dphi = db; /* Print result if in diagnostic mode */ if (idg) { eqcoor = eqstrn (dra,ddec); fprintf (stderr,"FK52GAL: J2000 RA,Dec= %s\n",eqcoor); fprintf (stderr,"FK52GAL: long = %.5f lat = %.5f\n",dl,db); free (eqcoor); } return; } /*--- Transform IAU 1958 galactic coordinates to J2000 equatorial coordinates */ void gal2fk5 (dtheta,dphi) double *dtheta; /* Galactic longitude (l2) in degrees J2000.0 ra in degrees (returned) */ double *dphi; /* Galactic latitude (b2) in degrees J2000.0 dec in degrees (returned) */ /* Output equatorial coordinates are J2000. Use gal2fk4() to convert to B1950 coordinates. Reference: Blaauw et al, MNRAS,121,123 (1960) */ { double pos[3],pos1[3],r,dl,db,rl,rb,rra,rdec,dra,ddec; void v2s3(),s2v3(); int i; char *eqcoor, *eqstrn(); /* Spherical to Cartesian */ dl = *dtheta; db = *dphi; rl = degrad (dl); rb = degrad (db); r = 1.0; s2v3 (rl,rb,r,pos); /* Rotate to equatorial coordinates */ for (i = 0; i < 3; i++) { pos1[i] = pos[0]*jgal[0][i] + pos[1]*jgal[1][i] + pos[2]*jgal[2][i]; } /* Cartesian to Spherical */ v2s3 (pos1,&rra,&rdec,&r); dra = raddeg (rra); ddec = raddeg (rdec); *dtheta = dra; *dphi = ddec; /* Print result if in diagnostic mode */ if (idg) { fprintf (stderr,"GAL2FK5: long = %.5f lat = %.5f\n",dl,db); eqcoor = eqstrn (dra,ddec); fprintf (stderr,"GAL2FK5: J2000 RA,Dec= %s\n",eqcoor); free (eqcoor); } return; } /* Return string with right ascension in hours and declination in degrees */ char *eqstrn (dra, ddec) double dra; /* Right ascension in degrees */ double ddec; /* Declination in degrees */ { char *eqcoor; /* ASCII character string of position (returned) */ char decp; int rah,irm,decd,decm; double xpos,ypos,xp,yp,ras,decs; /* Right ascension to hours, minutes, and seconds */ xpos = dra / 15.0; rah = (int) xpos; xp = (double) 60.0 * (xpos - (double) rah); irm = (int) xp; ras = (double) 60.0 * (xp - (double) irm); /* Declination to degrees, minutes, seconds */ if (ddec < 0) { ypos = -ddec; decp = '-'; } else { decp = '+'; ypos = ddec; } decd = (int) ypos; yp = (double) 60.0 * (ypos - (double) decd); decm = (int) yp; decs = (double) 60.0 * (yp - (double) decm); eqcoor = malloc (32); (void)sprintf (eqcoor,"%02d:%02d:%06.3f %c%02d:%02d:%05.2f", rah,irm,ras,decp,decd,decm,decs); if (eqcoor[6] == ' ') eqcoor[6] = '0'; if (eqcoor[20] == ' ') eqcoor[20] = '0'; return (eqcoor); } /* Convert geocentric equatorial rectangular coordinates to right ascension and declination, and distance */ /* These routines are based on similar ones in Pat Wallace's slalib package */ /* Convert B1950 right ascension and declination to ecliptic coordinates */ void fk42ecl (dtheta, dphi, epoch) double *dtheta; /* B1950 right ascension in degrees Galactic longitude (l2) in degrees (returned) */ double *dphi; /* B1950 declination in degrees Galactic latitude (b2) in degrees (returned) */ double epoch; /* Besselian epoch in years */ { void fk425e(), fk52ecl(); /* Convert from B1950 to J2000 coordinates */ fk425e (dtheta, dphi, epoch); /* Convert from J2000 to ecliptic coordinates */ fk52ecl (dtheta, dphi, epoch); return; } /* Convert J2000 right ascension and declination to ecliptic coordinates */ void fk52ecl (dtheta, dphi, epoch) double *dtheta; /* J2000 right ascension in degrees Galactic longitude (l2) in degrees (returned) */ double *dphi; /* J2000 declination in degrees Galactic latitude (b2) in degrees (returned) */ double epoch; /* Besselian epoch in years */ { int i, j; double t, eps0, rphi, rtheta; double v1[3], v2[3], r; double rmat[9], *rmati; /* Rotation matrix */ void rotmat(), v2s3(), s2v3(), fk5prec(); /* Precess coordinates from J2000 to epoch */ if (epoch != 2000.0) fk5prec (2000.0, epoch, dtheta, dphi); /* Convert from degrees to radians */ rtheta = degrad (*dtheta); rphi = degrad (*dphi); /* Convert RA,Dec to x,y,z */ r = 1.0; s2v3 (rtheta, rphi, r, v1); /* Interval between basic epoch J2000.0 and current epoch (JC) in centuries*/ t = (epoch - 2000.0) * 0.01; /* Mean obliquity */ eps0 = secrad ((84381.448 + (-46.8150 + (-0.00059 + 0.001813*t) * t) * t)); /* Form the equatorial to ecliptic rotation matrix (IAU 1980 theory). * References: Murray, C.A., Vectorial Astrometry, section 4.3. * The matrix is in the sense v[ecl] = rmat * v[equ]; the * equator, equinox and ecliptic are mean of date. */ rotmat (1, eps0, 0.0, 0.0, rmat); /* Multiply position vector by equatoria to eccliptic rotation matrix */ rmati = rmat; for (i = 0; i < 3; i++) { v2[i] = 0; for (j = 0; j < 3; j++) v2[i] = v2[i] + (*rmati++ * v1[j]); } /* Convert x,y,z to latitude, longitude */ v2s3 (v2, &rtheta, &rphi, &r); /* Convert from radians to degrees */ *dtheta = raddeg (rtheta); *dphi = raddeg (rphi); } /* Convert ecliptic coordinates to B1950 right ascension and declination */ void ecl2fk4 (dtheta, dphi, epoch) double *dtheta; /* Galactic longitude (l2) in degrees B1950 right ascension in degrees (returned) */ double *dphi; /* Galactic latitude (b2) in degrees B1950 declination in degrees (returned) */ double epoch; /* Besselian epoch in years */ { void ecl2fk5(), fk524e(); /* Convert from ecliptic to J2000 coordinates */ ecl2fk5 (dtheta, dphi, epoch); /* Convert from J2000 to B1950 coordinates */ fk524e (dtheta, dphi, epoch); return; } /* Convert ecliptic coordinates to J2000 right ascension and declination */ void ecl2fk5 (dtheta, dphi, epoch) double *dtheta; /* Galactic longitude (l2) in degrees J2000 right ascension in degrees (returned) */ double *dphi; /* Galactic latitude (b2) in degrees J2000 declination in degrees (returned) */ double epoch; /* Besselian epoch in years */ { int i, j; double rtheta, rphi, v1[3], v2[3]; double t, eps0, r; double rmat[9]; /* Rotation matrix */ void v2s3(),s2v3(), fk5prec(), rotmat(); rtheta = degrad (*dtheta); rphi = degrad (*dphi); /* Convert RA,Dec to x,y,z */ r = 1.0; s2v3 (rtheta, rphi, r, v1); /* Interval between basic epoch J2000.0 and current epoch (JC) in centuries*/ t = (epoch - 2000.0) * 0.01; /* Mean obliquity */ eps0 = secrad ((84381.448 + (-46.8150 + (-0.00059 + 0.001813*t) * t) * t)); /* Form the equatorial to ecliptic rotation matrix (IAU 1980 theory). * References: Murray, C.A., Vectorial Astrometry, section 4.3. * The matrix is in the sense v[ecl] = rmat * v[equ]; the * equator, equinox and ecliptic are mean of date. */ rotmat (1, eps0, 0.0, 0.0, rmat); /* Multiply position vector by ecliptic to equatorial rotation matrix */ for (i = 0; i < 3; i++) { v2[i] = 0; for (j = 0; j < 3; j++) v2[i] = v2[i] + (rmat[3*j + i] * v1[j]); } /* Cartesian to spherical */ v2s3 (v2, &rtheta, &rphi, &r); /* Convert from radians to degrees */ *dtheta = raddeg (rtheta); *dphi = raddeg (rphi); if (epoch != 2000.0) fk5prec (epoch, 2000.0, dtheta, dphi); } /* The following routines are modified from Patrick Wallace's SLALIB */ /* Precess coordinates between epochs in FK4 */ void fk4prec (ep0, ep1, ra, dec) double ep0; /* Starting Besselian epoch */ double ep1; /* Ending Besselian epoch */ double *ra; /* RA in degrees mean equator & equinox of epoch ep0 mean equator & equinox of epoch ep1 (returned) */ double *dec; /* Dec in degrees mean equator & equinox of epoch ep0 mean equator & equinox of epoch ep1 (returned) */ /* ** Precession - FK4 (Bessel-Newcomb, pre-IAU1976) ** ** This routine will not correctly convert between FK4 and FK5 ** For output in FK5, precess to 1950.0 and use fk425() on result. ** ** Based on slaPreces(), P.T.Wallace Starlink 22 December 1993 */ { int i, j; double pm[9], *pmi, v1[3], v2[3], rra, rdec, r; void v2s3(),s2v3(), mprecfk4(); rra = degrad (*ra); rdec = degrad (*dec); r = 1.0; /* Generate appropriate precession matrix */ mprecfk4 ( ep0, ep1, pm ); /* Convert RA,Dec to x,y,z */ s2v3 (rra, rdec, r, v1); /* Multiply position vector by precession matrix */ pmi = pm; for (i = 0; i < 3; i++) { v2[i] = 0; for (j = 0; j < 3; j++) v2[i] = v2[i] + (*pmi++ * v1[j]); } /* Back to RA,Dec */ v2s3 (v2, &rra, &rdec, &r); /* Convert from radians to degrees */ *ra = raddeg (rra); *dec = raddeg (rdec); } void fk5prec (ep0, ep1, ra, dec) double ep0; /* Starting epoch */ double ep1; /* Ending epoch */ double *ra; /* RA in degrees mean equator & equinox of epoch ep0 mean equator & equinox of epoch ep1 (returned) */ double *dec; /* Dec in degrees mean equator & equinox of epoch ep0 mean equator & equinox of epoch ep1 (returned) */ /* ** Precession - FK5 (Fricke, post-IAU2000) ** ** This routine will not correctly convert between FK5 and FK4. ** For output in FK4, precess to 2000.0 and use fk524() on result. */ { void fk5ep2j(), fk5j2ep(); fk5ep2j (ep0, ra, dec); fk5j2ep (ep1, ra, dec); return; } void mprecfk4 (bep0, bep1, rmatp) double bep0; /* Beginning Besselian epoch */ double bep1; /* Ending Besselian epoch */ double rmatp[9]; /* 3x3 Precession matrix (returned) */ /* ** Generate the matrix of precession between two epochs, ** using the old, pre-IAU1976, Bessel-Newcomb model, using ** Kinoshita's formulation (double precision) ** ** The matrix is in the sense v(bep1) = rmatp * v(bep0) ** ** Reference: ** Kinoshita, H. (1975) 'Formulas for precession', SAO Special ** Report No. 364, Smithsonian Institution Astrophysical ** Observatory, Cambridge, Massachusetts. ** ** Based on slaPrebn() by P.T.Wallace Starlink 30 October 1993 */ { double bigt, t, tas2r, w, zeta, z, theta; void rotmat(); /* Interval between basic epoch B1850.0 and beginning epoch in TC */ bigt = ( bep0 - 1850.0 ) / 100.0; /* Interval over which precession required, in tropical centuries */ t = ( bep1 - bep0 ) / 100.0; /* Euler angles */ tas2r = secrad (t); w = 2303.5548 + ( 1.39720 + 0.000059 * bigt ) * bigt; zeta = (w + ( 0.30242 - 0.000269 * bigt + 0.017996 * t ) * t ) * tas2r; z = (w + ( 1.09478 + 0.000387 * bigt + 0.018324 * t ) * t ) * tas2r; theta = ( 2005.1125 + ( - 0.85294 - 0.000365* bigt ) * bigt + ( - 0.42647 - 0.000365 * bigt - 0.041802 * t ) * t ) * tas2r; /* Rotation matrix */ rotmat (323, -zeta, theta, -z, rmatp); return; } void mprecfk5 (ep0, ep1, rmatp) double ep0; /* Beginning epoch */ double ep1; /* Ending epoch */ double rmatp[9]; /* 3x3 Precession matrix (returned) */ /* ** Form the matrix of precession between two epochs (IAU 1976, FK5). ** Notes: ** 1) The epochs are TDB (loosely ET) Julian epochs. ** 2) The matrix is in the sense v(ep1) = rmatp * v(ep0) . ** ** References: ** Lieske,J.H., 1979. Astron. Astrophys.,73,282. ** equations (6) & (7), p283. ** Kaplan,G.H., 1981. USNO circular no. 163, pa2. ** ** Based on slaPrec(), P.T.Wallace Starlink 31 October 1993 */ { double t0, t, tas2r, w, zeta, z, theta; void rotmat(); /* Interval in Julian centuries between J2000.0 and beginning epoch */ t0 = ( ep0 - 2000.0 ) / 100.0; /* Interval over which precession required (JC) */ t = ( ep1 - ep0 ) / 100.0; /* Euler angles */ tas2r = secrad (t); w = 2306.2181 + ( ( 1.39656 - ( 0.000139 * t0 ) ) * t0 ); zeta = (w + ( ( 0.30188 - 0.000344 * t0 ) + 0.017998 * t ) * t ) * tas2r; z = (w + ( ( 1.09468 + 0.000066 * t0 ) + 0.018203 * t ) * t ) * tas2r; theta = ( ( 2004.3109 + ( - 0.85330 - 0.000217 * t0 ) * t0 ) + ( ( -0.42665 - 0.000217 * t0 ) - 0.041833 * t ) * t ) * tas2r; /* Rotation matrix */ rotmat (323, -zeta, theta, -z, rmatp); return; } /* Precess coordinates to J2000 in FK5 */ void fk5ep2j (ep, ra, dec) double ep; /* Starting Julian epoch */ double *ra; /* RA in degrees mean equator & equinox of epoch ep0 mean equator & equinox of epoch ep1 (returned) */ double *dec; /* Dec in degrees mean equator & equinox of epoch ep0 mean equator & equinox of epoch ep1 (returned) */ /* ** Precession - FK5 (Fricke, post-IAU2000) ** ** This routine will not correctly convert between FK5 and FK4. ** For output in FK4, precess to 2000.0 and use fk524() on result. ** ** Based on slaPreces(), P.T.Wallace Starlink 22 December 1993 */ { int i, j; double pm[9], pmt[9], *pmi, v1[3], v2[3], rra, rdec, r; void v2s3(),s2v3(), mfk5j2ep(); rra = degrad (*ra); rdec = degrad (*dec); r = 1.0; /* Convert RA,Dec to x,y,z */ s2v3 (rra, rdec, r, v1); /* Generate and transpose precession matrix */ mfk5j2ep ( ep, pm ); for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { pmt[i+(j*3)] = pm[j+(i*3)]; } } /* Multiply position vector by precession matrix */ pmi = pmt; for (i = 0; i < 3; i++) { v2[i] = 0; for (j = 0; j < 3; j++) v2[i] = v2[i] + (*pmi++ * v1[j]); } /* Back to RA,Dec */ v2s3 (v2, &rra, &rdec, &r); /* Convert from radians to degrees */ *ra = raddeg (rra); *dec = raddeg (rdec); } /* Precess coordinates from J2000 in FK5 */ void fk5j2ep (ep, ra, dec) double ep; /* Starting Julian epoch */ double *ra; /* RA in degrees mean equator & equinox of epoch ep0 mean equator & equinox of epoch ep1 (returned) */ double *dec; /* Dec in degrees mean equator & equinox of epoch ep0 mean equator & equinox of epoch ep1 (returned) */ /* ** Precession - FK5 (Fricke, post-IAU2000) ** ** This routine will not correctly convert between FK5 and FK4. ** For output in FK4, precess to 2000.0 and use fk524() on result. ** ** Based on slaPreces(), P.T.Wallace Starlink 22 December 1993 */ { int i, j; double pm[9], *pmi, v1[3], v2[3], rra, rdec, r; void v2s3(), s2v3(), mfk5j2ep(); rra = degrad (*ra); rdec = degrad (*dec); r = 1.0; /* Convert RA,Dec to x,y,z */ s2v3 (rra, rdec, r, v1); /* Generate precession matrix */ mfk5j2ep ( ep, pm ); /* Multiply position vector by precession matrix */ pmi = pm; for (i = 0; i < 3; i++) { v2[i] = 0; for (j = 0; j < 3; j++) v2[i] = v2[i] + (*pmi++ * v1[j]); } /* Back to RA,Dec */ v2s3 (v2, &rra, &rdec, &r); /* Convert from radians to degrees */ *ra = raddeg (rra); *dec = raddeg (rdec); } void mfk5j2ep (ep, rmatp) double ep; /* Beginning epoch */ double rmatp[9]; /* 3x3 Precession matrix (returned) */ /* ** Form the matrix of precession between two epochs (IAU 2000, FK5). ** Notes: ** 1) The epochs are TDB (loosely ET) Julian epochs. ** 2) The matrix is in the sense v(ep) = rmatp * v(J2000) . ** ** References: ** Lieske,J.H., 1979. Astron. Astrophys.,73,282. ** equations (6) & (7), p283. ** Kaplan,G.H., 2005. USNO circular no. 179, p. 44. ** ** Based on slaPrec(), P.T.Wallace Starlink 31 October 1993 */ { double t, t2, t3, t4, tas2r, zeta, z, theta; void rotmat(); /* Interval in Julian centuries between J2000.0 and beginning epoch */ t = ( ep - 2000.0 ) / 100.0; t2 = t * t; t3 = t2 * t; t4 = t3 * t; /* Euler angles */ tas2r = secrad (t); zeta = 2.65045 + (2306.083227 + (0.2988499 * t) + (0.01801828 * t2) - (0.000005971 * t3) - (0.0000003173 * t4)) * tas2r; z = -2.650545 + (2306.077181 + (1.0927348 * t) + (0.01801828 * t2) - (0.000005971 * t3) - (0.0000003173 * t4)) * tas2r; theta = (2004.191903 - (0.4294934 * t) - (0.04182264 * t2) - (0.000007089 * t3) - (0.0000001274 * t4)) * tas2r; /* Rotation matrix */ rotmat (323, -z, theta, -zeta, rmatp); return; } /* Make 3-D rotation matrix from up to three rotations */ void rotmat (axes, rot1, rot2, rot3, matrix) int axes; /* Axes about which coordinates are rotated (1=x, 2=y, 3=z) */ double rot1; /* First rotation in degrees */ double rot2; /* Second rotation in degrees */ double rot3; /* Third rotation in degrees */ double *matrix; /* 3x3 rotation matrix (returned) */ { int i, j, k, naxis, iaxes, iaxis; double rot, srot, crot, *mati, w, wm[9], *wmi, matn[9]; int axis[3]; /* Initial final rotation matrix */ mati = matrix; for (i = 0; i < 3; i++) { for (j=0; j < 3; j++) { if (i == j) *mati++ = 1.0; else *mati++ = 0.0; } } /* Separate digits of rotation axis string and count rotations */ naxis = 0; iaxes = axes; axis[0] = iaxes / 100; if (axis[0] > 0) { naxis++; iaxes = iaxes - (100 * axis[0]); } axis[naxis] = iaxes / 10; if (axis[naxis] > 0) { iaxes = iaxes - (10 * axis[naxis]); naxis++; } axis[naxis] = iaxes; if (axis[naxis] > 0) naxis++; /* For each digit of axis string, set up matrix */ for (iaxis = 0; iaxis < naxis; iaxis++) { /* Initialize current rotation matrix */ mati = matn; for (i = 0; i < 3; i++) { for (j=0; j < 3; j++) { if (i == j) *mati++ = 1.0; else *mati++ = 0.0; } } /* Select rotation angle from argument list */ if (axis[iaxis] == 1) rot = rot1; else if (axis[iaxis] == 2) rot = rot2; else rot = rot3; srot = sin (rot); crot = cos (rot); /* Matrix for rotation in X */ if (axis[iaxis] == 1) { matn[4] = crot; matn[5] = srot; matn[7] = -srot; matn[8] = crot; } /* Matrix for rotation in Y */ else if (axis[iaxis] == 2) { matn[0] = crot; matn[2] = -srot; matn[6] = srot; matn[8] = crot; } /* Matrix for rotation in Z */ else { matn[0] = crot; matn[1] = srot; matn[3] = -srot; matn[4] = crot; } /* Multiply existing rotation matrix by new rotation matrix */ for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { w = 0.0; for (k = 0; k < 3; k++) w+= matn[3*i + k] * matrix[3*k + j]; wm[3*i + j] = w; } } /* Update output matrix */ mati = matrix; wmi = wm; for (i = 0; i < 9; i++) { *mati++ = *wmi++; } } return; } /* The following routines are from Doug Mink's Fortran ephemeris library */ /* Convert right ascension, declination, and distance to geocentric equatorial rectangular coordinates */ void s2v3 (rra,rdec,r,pos) double rra; /* Right ascension in radians */ double rdec; /* Declination in radians */ double r; /* Distance to object in same units as pos */ double pos[3]; /* x,y,z geocentric equatorial position of object (returned) */ { pos[0] = r * cos (rra) * cos (rdec); pos[1] = r * sin (rra) * cos (rdec); pos[2] = r * sin (rdec); return; } /* Convert geocentric equatorial rectangular coordinates to right ascension, declination, and distance */ void v2s3 (pos,rra,rdec,r) double pos[3]; /* x,y,z geocentric equatorial position of object */ double *rra; /* Right ascension in radians (returned) */ double *rdec; /* Declination in radians (returned) */ double *r; /* Distance to object in same units as pos (returned) */ { double x,y,z,rxy,rxy2,z2; x = pos[0]; y = pos[1]; z = pos[2]; *rra = atan2 (y, x); /* Keep RA within 0 to 2pi range */ if (*rra < 0.0) *rra = *rra + (2.0 * PI); if (*rra > 2.0 * PI) *rra = *rra - (2.0 * PI); rxy2 = x*x + y*y; rxy = sqrt (rxy2); *rdec = atan2 (z, rxy); z2 = z * z; *r = sqrt (rxy2 + z2); return; } /* * Nov 6 1995 Include stdlib.h instead of malloc.h * Apr 1 1996 Add arbitrary epoch precession * Apr 26 1996 Add FK4 <-> FK5 subroutines for use when epoch is known * Aug 6 1996 Clean up after lint * Nov 4 1996 Break SLA subroutines into separate file slasubs.c * Dec 9 1996 Change arguments to degrees in FK4 and FK5 precession programs * Dec 10 1996 All subroutine arguments are degrees except vector conversions * * Mar 20 1997 Drop unused variables after lint * * Apr 14 1998 Add ecliptic coordinate conversions and general conversion routines * Apr 23 1998 Add LINEAR coordinate system * Apr 28 1998 Change coordinate system flags to WCS_* * Apr 28 1998 Return -1 from wcscsys if not a legal coordinate system * May 7 1998 Keep theta within 0 to 2pi in ecl2fk5() * May 13 1998 Add wcsceq() * May 13 1998 Add equinox arguments to wcscon() * Jun 24 1998 Set J2000 from ICRS in wcscsys() * Jul 9 1998 Include stdio.h for fprintf() and sprintf() declarations * Sep 17 1998 Add wcscstr() to get coordinate string * Sep 21 1998 Fix bug in wcscstr() which returned B2000 instead of J2000 * Sep 21 1998 Add subroutine to convert proper motions, too. * Oct 21 1998 In wcscstr(), drop .00 from returned string * Nov 18 1998 Rename jpcop() v2s3() and jpcon() s2v3() (spherical to vector) * Dec 2 1998 Add PLANET coordinate system to wcscsys() and wcscstr() * * Mar 10 2000 Precess coordinates correctly from other than 1950.0 and 2000.0 * Mar 10 2000 Set coordinate system to J2000 or B1950 if string is numeric * Mar 14 2000 Clean up code in fk524m() and fk425m() * May 31 2000 Add proper motion correctly if proper motion precessed * Jun 26 2000 Add some support for WCS_XY image coordinates * Sep 14 2000 Return -1 from wcscsys if equinox is less than 1900.0 * Oct 31 2000 Add proper motion after fk425 or fk524 from system epoch * Oct 31 2000 Fix proper motion units in fk524p() and fk425p() * Nov 6 2000 Update fk425 and fk524 algorithms to include parallax and rv * * Jan 11 2001 Print all messages to stderr * Mar 21 2001 Move braces around bgal[] and jgal[] matrix initialization * * Feb 13 2002 Fix precession units problem in ecl2fk5() and fk52ecl() * * Apr 13 2005 Replace all sla_lib calls with local code * Nov 1 2005 Add WCS_ICRS, and unprecessable system * * Jan 5 2006 Fix bugs in precession subroutines mprecxxx() * May 3 2006 Drop declarations of unused variables suggested by Robert Lupton * Oct 6 2006 If pixel coordinates, set system to WCS_XY in wcscsys() * Oct 30 2006 Add LINEAR and ICRS to wcscstr() returns * Nov 29 2006 Rewrite FK5 precession subroutines to IAU 2000 standard */ wcstools-3.9.5/libwcs/str2dcpp.c0000664000016200001660000000711211750060474015650 0ustar minkoirsys// // strtod.c // // Convert string to double // // Copyright (C) 2002 Michael Ringgaard. All rights reserved. // http://www.jbox.dk/sanos/source/lib/strtod.c.html // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // 3. Neither the name of the project nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE. // #include #include #include #include #include double strtod(const char *str, char **endptr) { double number; int exponent; int negative; char *p = (char *) str; double p10; int n; int num_digits; int num_decimals; // Skip leading whitespace while (isspace(*p)) p++; // Handle optional sign negative = 0; switch (*p) { case '-': negative = 1; // Fall through to increment position case '+': p++; } number = 0.; exponent = 0; num_digits = 0; num_decimals = 0; // Process string of digits while (isdigit(*p)) { number = number * 10. + (*p - '0'); p++; num_digits++; } // Process decimal part if (*p == '.') { p++; while (isdigit(*p)) { number = number * 10. + (*p - '0'); p++; num_digits++; num_decimals++; } exponent -= num_decimals; } if (num_digits == 0) { errno = ERANGE; return 0.0; } // Correct for sign if (negative) number = -number; // Process an exponent string if (*p == 'e' || *p == 'E') { // Handle optional sign negative = 0; switch(*++p) { case '-': negative = 1; // Fall through to increment pos case '+': p++; } // Process string of digits n = 0; while (isdigit(*p)) { n = n * 10 + (*p - '0'); p++; } if (negative) exponent -= n; else exponent += n; } if (exponent < DBL_MIN_EXP || exponent > DBL_MAX_EXP) { errno = ERANGE; return HUGE_VAL; } // Scale the result p10 = 10.; n = exponent; if (n < 0) n = -n; while (n) { if (n & 1) { if (exponent < 0) number /= p10; else number *= p10; } n >>= 1; p10 *= p10; } if (number == HUGE_VAL) errno = ERANGE; if (endptr) *endptr = p; return number; } double atof(const char *str) { return strtod(str, NULL); } wcstools-3.9.5/libwcs/skybotread.c0000664000016200001660000003150111750060474016255 0ustar minkoirsys/*** File libwcs/skybotread.c *** May 5, 2009 *** By Jessica Mink, jmink@cfa.harvard.edu *** Harvard-Smithsonian Center for Astrophysics *** Copyright (C) 2004-2009 *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Correspondence concerning WCSTools should be addressed as follows: Internet email: jmink@cfa.harvard.edu Postal address: Jessica Mink Smithsonian Astrophysical Observatory 60 Garden St. Cambridge, MA 02138 USA */ #include #include #include #include #include #include #include "fitsfile.h" #include "wcs.h" #include "wcscat.h" #define ABS(a) ((a) < 0 ? (-(a)) : (a)) #define LINE 1024 static int obscode = 801; /* Default to Harvard Observatory, Oak Ridge */ void setobs(newobs) int newobs; {obscode = newobs; return; } static char tabhead[500]; /* Starbase header for returned data */ void setobsname (obsname) char *obsname; { if (strcsrch (obsname, "mmt")) obscode = 696; /* Whipple Observatory, Mt. Hopkins */ else if (strcsrch (obsname, "whip")) obscode = 696; /* Whipple Observatory, Mt. Hopkins */ else if (strcsrch (obsname, "flw")) obscode = 696; /* Whipple Observatory, Mt. Hopkins */ else if (strcsrch (obsname, "oak")) obscode = 801; /* Harvard Observatory, Oak Ridge */ else if (strcsrch (obsname, "hco")) obscode = 802; /* Harvard Observatory, Cambridge */ else if (strcsrch (obsname, "boy")) obscode = 074; /* Boyden Observatory, Bloemfontein */ else if (strcsrch (obsname, "are")) obscode = 800; /* Harvard Observatory, Arequipa */ else obscode = 500; /* Geocenter */ return; } char * getobsname (code) int code; { char *obsname; obsname = (char *) calloc (64, 1); if (code == 696) strcpy (obsname, "FLWO Whipple Observatory, Mt. Hopkins"); else if (code == 801) strcpy (obsname, "HCO Oak Ridge"); else if (code == 802) strcpy (obsname, "HCO Cambridge"); else if (code == 074) strcpy (obsname, "Boyden Observatory, Bloemfontein"); else if (code == 800) strcpy (obsname, "HCO Arequipa, Peru"); else if (code == 500) strcpy (obsname, "Geocenter"); else sprintf (obsname, "IAU %d", obscode); return (obsname); } /* SkyBot search engine URL */ static char skyboturl[128]="http://www.imcce.fr/webservices/skybot/skybot_query.php"; /* skybotread -- Read IMCCE SkyBot server astroids over the web */ int skybotread (cra,cdec,dra,ddec,drad,distsort,sysout,eqout,epout,mag1,mag2, sortmag,nstarmax,gnum,gobj,gra,gdec,gpra,gpdec,gmag,gtype,nlog) double cra; /* Search center J2000 right ascension in degrees */ double cdec; /* Search center J2000 declination in degrees */ double dra; /* Search half width in right ascension in degrees */ double ddec; /* Search half-width in declination in degrees */ double drad; /* Limiting separation in degrees (ignore if 0) */ int distsort; /* 1 to sort asteroids by distance from center */ int sysout; /* Search coordinate system */ double eqout; /* Search coordinate equinox */ double epout; /* Julian date for positions (current time if zero) */ double mag1,mag2; /* Limiting magnitudes (none if equal) */ int sortmag; /* Magnitude by which to sort (1 to nmag) */ int nstarmax; /* Maximum number of stars to be returned */ double *gnum; /* Array of asteroid numbers (returned) */ char **gobj; /* Array of object IDs (too long for integer*4) */ double *gra; /* Array of right ascensions (returned) */ double *gdec; /* Array of declinations (returned) */ double *gpra; /* Array of right ascension motions (returned) */ double *gpdec; /* Array of declination motions (returned) */ double **gmag; /* 2-D array of magnitudes and other info (returned) */ int *gtype; /* Array of object classes (returned) */ int nlog; /* 1 for diagnostics */ { char srchurl[LINE]; char cmag; char *obs; char *dstr; struct TabTable *tabtable; struct StarCat *starcat; /* Star catalog data structure */ double dtemp, jdout; int nstar, nlog0; double ra, dec, mag, dradi, dradx; char rastr[32], decstr[32], temp[256], tstr[80]; /* Set up header for returned Starbase table */ strcpy (tabhead, "catalog\tSkyBot\n"); strcat (tabhead, "equinox\t2000.0\n"); strcat (tabhead, "radecsys\tFK5\n"); obs = getobsname (obscode); sprintf (tstr, "obs\t%s\n", obs); strcpy (tabhead, tstr); dradi = 0.0; nlog0 = nlog; if (nstarmax < 1) nlog = -1; /* mag1 is always the smallest magnitude */ if (mag2 < mag1) { mag = mag2; mag2 = mag1; mag1 = mag; } if (mag1 < 0) mag1 = 0.0; /* Set up query for SkyBot server */ ra = cra; dec = cdec; if (sysout != WCS_J2000) wcscon (sysout, WCS_J2000, eqout, 2000.0, &ra, &dec, epout); /* Epoch for positions */ jdout = ep2jd (epout); sprintf (srchurl, "?-ep=%.5f&", jdout); dstr = jd2fd (jdout); sprintf (tstr, "epoch\t%s\n",dstr); strcat (tabhead, tstr); /* Search center */ sprintf (temp, "-ra=%.5f&-dec=%.5f&", ra, dec); strcat (srchurl, temp); deg2str (rastr, 32, ra, 5); deg2str (decstr, 32, dec, 5); sprintf (tstr, "sra\t%s\n",rastr); strcat (tabhead, tstr); sprintf (tstr, "sdec\t%s\n",decstr); strcat (tabhead, tstr); /* Radius in degrees */ if (drad != 0.0) { if (drad < 0.0) { dradx = -drad * sqrt (2.0); if (dradx > 10.0) dradx = 10.0; sprintf (temp, "-rd=%.5f&", dradx); sprintf (tstr, "dra\t%.5f\n", -drad); strcat (tabhead, tstr); sprintf (tstr, "ddec\t%.5f\n", -drad); strcat (tabhead, tstr); } else { if (drad > 10.0) dradx = 10.0; else dradx = drad; sprintf (temp, "-rd=%.5f&", dradx); sprintf (tstr, "rad\t%.5f\n", dradx); strcat (tabhead, tstr); } } /* Box size in degrees */ else { dradx = sqrt ((dra * dra) + (ddec * ddec)); sprintf (temp, "-rd=%.5f&", dradx); sprintf (tstr, "dra\t%.6f\n", dra); strcat (tabhead, tstr); sprintf (tstr, "ddec\t%.6f\n", ddec); strcat (tabhead, tstr); } /* Units for motion on the sky */ strcat (tabhead, "rpmunit\tarcsec/hour\n"); strcat (tabhead, "dpmunit\tarcsec/hour\n"); strcat (srchurl, temp); /* Output type */ strcat (srchurl, "-mime=text&"); /* IAU observatory code*/ sprintf (temp, "loc=%03d&", obscode); strcat (srchurl, temp); /* Drop comets to save time */ strcat (srchurl, "-objFilter=110&"); /* Drop planets to save time (unused) strcat (srchurl, "-objFilter=100&"); */ /* Source of search */ strcat (srchurl, "-from=WCSTools"); if (nlog0 > 0) fprintf (stderr,"%s%s\n", skyboturl, srchurl); /* Run search across the web */ if ((tabtable = webopen (skyboturl, srchurl, nlog)) == NULL) { if (nlog > 0) fprintf (stderr, "SKYBOTREAD: %s failed\n", srchurl); return (0); } /* Return if no data */ if (tabtable->tabdata == NULL || strlen (tabtable->tabdata) == 0 || !strncasecmp (tabtable->tabdata, "[EOD]", 5)) { if (nlog > 0) fprintf (stderr, "SKYBOTREAD: No data returned\n"); return (0); } /* Dump returned file and stop */ if (nlog < 0) { (void) fwrite (tabtable->tabbuff, tabtable->lbuff, 1, stdout); exit (0); } /* Open returned Starbase table as a catalog */ if ((starcat = tabcatopen (skyboturl, tabtable,0)) == NULL) { if (nlog > 0) fprintf (stderr, "SKYBOTREAD: Could not open Starbase table as catalog\n"); return (0); } /* Set reference frame, epoch, and equinox of catalog */ starcat->coorsys = WCS_J2000; starcat->epoch = 2000.0; starcat->equinox = 2000.0; starcat->nmag = 3; /* Extract desired sources from catalog and return them */ nstar = tabread (skyboturl,distsort,cra,cdec,dra,ddec,drad,dradi, sysout,eqout,epout,mag1,mag2,sortmag,nstarmax,&starcat, gnum,gra,gdec,gpra,gpdec,gmag,gtype,gobj,nlog); tabcatclose (starcat); starcat = NULL; return (nstar); } char * skybot2tab (skybuff) char *skybuff; /* Input comma-separated table */ { char *heading; char *colhead; char *colsep; char *tabbuff; /* Output tab-separated table */ char *tbuff; char *databuff; char *dbuff; char *buffer; char *lastbuff; char *endhead; char *colend; char *chead; char *head; char *tbuffi; char temp[16], format[16]; int lbuff, i, lra, icol; int lhead, ldata; int addname; int lobj; char cbuff; char *buff; char cbar = '|'; char ccom = ','; char cminus = '-'; char cspace = ' '; char ctab = (char) 9; char clf = (char) 10; double ra; /* Skip first two lines of returned header */ buffer = strchr (skybuff, '\n') + 1; buffer = strchr (buffer, '\n') + 1; /* Skip header line as it is recreated */ buffer = strchr (buffer, '\n') + 1; /* Allocate starbase table for output */ lbuff = strlen (skybuff) + strlen (tabhead) + 200; tabbuff = (char *) calloc (lbuff, 1); /* Add metadata */ strcpy (tabbuff, tabhead); /* Set up tabbed column headings */ i = 0; lhead = 0; colhead = tabbuff + strlen (tabbuff); /* Combine number and name into first column */ strcpy (colhead, "object "); strcat (colhead,"\t"); /* Fix heading for RA column, which will be degrees, not hours */ strcat (colhead, "ra "); strcat (colhead,"\t"); /* Fix colheading for Dec column */ strcat (colhead, "dec "); strcat (colhead,"\t"); strcat (colhead, "class "); strcat (colhead,"\t"); strcat (colhead, "vmag "); strcat (colhead,"\t"); strcat (colhead, "poserr"); strcat (colhead,"\t"); strcat (colhead, "offset"); strcat (colhead,"\t"); strcat (colhead, "rapm "); strcat (colhead,"\t"); strcat (colhead, "decpm "); strcat (colhead,"\t"); strcat (colhead, "gdist "); strcat (colhead,"\t"); strcat (colhead, "hdist "); strcat (colhead,"\n"); lhead = strlen (colhead); /* Set up tabbed separator line */ colsep = colhead + lhead; for (i = 0; i < lhead; i++) { cbuff = colhead[i]; if (cbuff == ctab) colsep[i] = ctab; else if (cbuff == (char) 10) colsep[i] = (char) 10; else colsep[i] = '-'; } /* Copy input through final linefeed */ lastbuff = strrchr (buffer, '\n') + 1; /* Copy data to output buffer, dropping leading and trailing spaces and converting vertical bars in table to tabs */ dbuff = buffer; tbuff = tabbuff + strlen (tabbuff); icol = 0; while (dbuff < lastbuff) { /* Drop out if blank line encountered */ if (icol == 0 && *dbuff == clf) break; /* Combine ID and name in first column */ if (icol == 0) { tbuffi = tbuff; while (*dbuff == cspace) dbuff++; if (*dbuff == cminus) { addname = 0; dbuff++; } else addname = 1; while (*dbuff != cbar) { if (*dbuff != cspace) *tbuff++ = *dbuff; dbuff++; } if (*dbuff == cbar) { icol++; dbuff++; } if (addname) *tbuff++ = '('; while (*dbuff != cbar) { if (*dbuff != cspace) *tbuff++ = *dbuff; dbuff++; } if (addname) *tbuff++ = ')'; lobj = tbuff - tbuffi; if (lobj < 16) { for (i = lobj; i < 16; i++) *tbuff++ = ' '; } } if (*dbuff == cbar) { *tbuff++ = ctab; icol++; dbuff++; /* Convert RA from fractional hours to fractional degrees */ if (icol == 2) { ra = atof (dbuff) * 15.0; colend = strchr (dbuff, cbar) - 1; lra = colend - dbuff; sprintf (format,"%%%d.%df",lra,lra-4); sprintf (temp, format, ra); for (i = 0; i < lra; i++) dbuff[i] = temp[i]; dbuff--; } /* Shorten "Satellite" to Sat */ if (icol == 4) { if (!strncmp (dbuff, " Sat", 4)) { *tbuff++ = 'S'; *tbuff++ = 'a'; *tbuff++ = 't'; dbuff = dbuff + 9; } else dbuff--; } } else if (*dbuff == clf) { *tbuff++ = *dbuff; icol = 0; } else if (*dbuff != cspace) *tbuff++ = *dbuff; dbuff++; } return (tabbuff); } /* Jul 26 2004 New program * * May 5 2009 Add -objFilter=110 to drop comets (someday, this might be optional) */ wcstools-3.9.5/libwcs/str2dsun.c0000664000016200001660000001347611750060474015705 0ustar minkoirsys/* * strtod.c -- * * Source code for the "strtod" library procedure. * * Copyright (c) 1988-1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * https://svn.greensocs.com/public/packages/tcl/tcl8.5.0/compat/strtod.c * * RCS: @(#) $Id: strtod.c,v 1.8 2007/04/16 13:36:34 dkf Exp $ */ #include "tclInt.h" #include #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifndef NULL #define NULL 0 #endif static int maxExponent = 511; /* Largest possible base 10 exponent. Any * exponent larger than this will already * produce underflow or overflow, so there's * no need to worry about additional digits. */ static double powersOf10[] = { /* Table giving binary powers of 10. Entry */ 10., /* is 10^2^i. Used to convert decimal */ 100., /* exponents into floating-point numbers. */ 1.0e4, 1.0e8, 1.0e16, 1.0e32, 1.0e64, 1.0e128, 1.0e256 }; /* *---------------------------------------------------------------------- * * strtod -- * * This procedure converts a floating-point number from an ASCII * decimal representation to internal double-precision format. * * Results: * The return value is the double-precision floating-point * representation of the characters in string. If endPtr isn't * NULL, then *endPtr is filled in with the address of the * next character after the last one that was part of the * floating-point number. * * Side effects: * None. * *---------------------------------------------------------------------- */ double strtod( CONST char *string, /* A decimal ASCII floating-point number, * optionally preceded by white space. Must * have form "-I.FE-X", where I is the integer * part of the mantissa, F is the fractional * part of the mantissa, and X is the * exponent. Either of the signs may be "+", * "-", or omitted. Either I or F may be * omitted, or both. The decimal point isn't * necessary unless F is present. The "E" may * actually be an "e". E and X may both be * omitted (but not just one). */ char **endPtr) /* If non-NULL, store terminating character's * address here. */ { int sign, expSign = FALSE; double fraction, dblExp, *d; register CONST char *p; register int c; int exp = 0; /* Exponent read from "EX" field. */ int fracExp = 0; /* Exponent that derives from the fractional * part. Under normal circumstatnces, it is * the negative of the number of digits in F. * However, if I is very long, the last digits * of I get dropped (otherwise a long I with a * large negative exponent could cause an * unnecessary overflow on I alone). In this * case, fracExp is incremented one for each * dropped digit. */ int mantSize; /* Number of digits in mantissa. */ int decPt; /* Number of mantissa digits BEFORE decimal * point. */ CONST char *pExp; /* Temporarily holds location of exponent in * string. */ /* * Strip off leading blanks and check for a sign. */ p = string; while (isspace(UCHAR(*p))) { p += 1; } if (*p == '-') { sign = TRUE; p += 1; } else { if (*p == '+') { p += 1; } sign = FALSE; } /* * Count the number of digits in the mantissa (including the decimal * point), and also locate the decimal point. */ decPt = -1; for (mantSize = 0; ; mantSize += 1) { c = *p; if (!isdigit(c)) { if ((c != '.') || (decPt >= 0)) { break; } decPt = mantSize; } p += 1; } /* * Now suck up the digits in the mantissa. Use two integers to collect 9 * digits each (this is faster than using floating-point). If the mantissa * has more than 18 digits, ignore the extras, since they can't affect the * value anyway. */ pExp = p; p -= mantSize; if (decPt < 0) { decPt = mantSize; } else { mantSize -= 1; /* One of the digits was the point. */ } if (mantSize > 18) { fracExp = decPt - 18; mantSize = 18; } else { fracExp = decPt - mantSize; } if (mantSize == 0) { fraction = 0.0; p = string; goto done; } else { int frac1, frac2; frac1 = 0; for ( ; mantSize > 9; mantSize -= 1) { c = *p; p += 1; if (c == '.') { c = *p; p += 1; } frac1 = 10*frac1 + (c - '0'); } frac2 = 0; for (; mantSize > 0; mantSize -= 1) { c = *p; p += 1; if (c == '.') { c = *p; p += 1; } frac2 = 10*frac2 + (c - '0'); } fraction = (1.0e9 * frac1) + frac2; } /* * Skim off the exponent. */ p = pExp; if ((*p == 'E') || (*p == 'e')) { p += 1; if (*p == '-') { expSign = TRUE; p += 1; } else { if (*p == '+') { p += 1; } expSign = FALSE; } if (!isdigit(UCHAR(*p))) { p = pExp; goto done; } while (isdigit(UCHAR(*p))) { exp = exp * 10 + (*p - '0'); p += 1; } } if (expSign) { exp = fracExp - exp; } else { exp = fracExp + exp; } /* * Generate a floating-point number that represents the exponent. Do this * by processing the exponent one bit at a time to combine many powers of * 2 of 10. Then combine the exponent with the fraction. */ if (exp < 0) { expSign = TRUE; exp = -exp; } else { expSign = FALSE; } if (exp > maxExponent) { exp = maxExponent; errno = ERANGE; } dblExp = 1.0; for (d = powersOf10; exp != 0; exp >>= 1, d += 1) { if (exp & 01) { dblExp *= *d; } } if (expSign) { fraction /= dblExp; } else { fraction *= dblExp; } done: if (endPtr != NULL) { *endPtr = (char *) p; } if (sign) { return -fraction; } return fraction; } wcstools-3.9.5/libwcs/Update.sao0000764000016200001660000000054611537520473015701 0ustar minkoirsyscp -p \ wcs.h \ wcsinit.c \ wcs.c \ wcscon.c \ worldpos.c \ platepos.c \ dsspos.c \ tnxpos.c \ zpxpos.c \ poly.c \ fitshead.h \ hget.c \ iget.c \ hput.c \ wcslib.h \ wcslib.c \ lin.c \ cel.c \ proj.c \ sph.c \ wcstrig.c \ fitsfile.h \ fitsfile.c \ imhfile.c \ dateutil.c \ fileutil.c \ imio.h \ imio.c \ distort.c \ NEWS \ Files \ ../../Saoimage/Src/wcssubs wcstools-3.9.5/libwcs/poly.c0000664000016200001660000005500712733325726015106 0ustar minkoirsys /* poly.c *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * Part of: A program using Polynomials * * Author: E.BERTIN (IAP) * * Contents: Polynomial fitting * * Last modify: 08/03/2005 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "wcslib.h" #define QCALLOC(ptr, typ, nel) \ {if (!(ptr = (typ *)calloc((size_t)(nel),sizeof(typ)))) \ qerror("Not enough memory for ", \ #ptr " (" #nel " elements) !");;} #define QMALLOC(ptr, typ, nel) \ {if (!(ptr = (typ *)malloc((size_t)(nel)*sizeof(typ)))) \ qerror("Not enough memory for ", \ #ptr " (" #nel " elements) !");;} /********************************* qerror ************************************/ /* I hope it will never be used! */ void qerror(char *msg1, char *msg2) { fprintf(stderr, "\n> %s%s\n\n",msg1,msg2); abort(); } /****** poly_init ************************************************************ PROTO polystruct *poly_init(int *group, int ndim, int *degree, int ngroup) PURPOSE Allocate and initialize a polynom structure. INPUT 1D array containing the group for each parameter, number of dimensions (parameters), 1D array with the polynomial degree for each group, number of groups. OUTPUT polystruct pointer. NOTES -. AUTHOR E. Bertin (IAP) VERSION 08/03/2003 ***/ polystruct *poly_init(int *group, int ndim, int *degree, int ngroup) { void qerror(char *msg1, char *msg2); polystruct *poly; char str[512]; int nd[POLY_MAXDIM]; int *groupt, d,g,n,num,den; QCALLOC(poly, polystruct, 1); if ((poly->ndim=ndim) > POLY_MAXDIM) { sprintf(str, "The dimensionality of the polynom (%d) exceeds the maximum\n" "allowed one (%d)", ndim, POLY_MAXDIM); qerror("*Error*: ", str); } if (ndim) QMALLOC(poly->group, int, poly->ndim); for (groupt=poly->group, d=ndim; d--;) *(groupt++) = *(group++)-1; poly->ngroup = ngroup; if (ngroup) { group = poly->group; /* Forget the original *group */ QMALLOC(poly->degree, int, poly->ngroup); /*-- Compute the number of context parameters for each group */ memset(nd, 0, ngroup*sizeof(int)); for (d=0; d=ngroup) qerror("*Error*: polynomial GROUP out of range", ""); nd[g]++; } } /* Compute the total number of coefficients */ poly->ncoeff = 1; for (g=0; gdegree[g]=*(degree++))>POLY_MAXDEGREE) { sprintf(str, "The degree of the polynom (%d) exceeds the maximum\n" "allowed one (%d)", poly->degree[g], POLY_MAXDEGREE); qerror("*Error*: ", str); } /*-- There are (n+d)!/(n!d!) coeffs per group, that is Prod_(i<=d) (n+i)/i */ for (num=den=1, n=nd[g]; d; num*=(n+d), den*=d--); poly->ncoeff *= num/den; } QMALLOC(poly->basis, double, poly->ncoeff); QCALLOC(poly->coeff, double, poly->ncoeff); return poly; } /****** poly_end ************************************************************* PROTO void poly_end(polystruct *poly) PURPOSE Free a polynom structure and everything it contains. INPUT polystruct pointer. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP, Leiden observatory & ESO) VERSION 09/04/2000 ***/ void poly_end(polystruct *poly) { if (poly) { free(poly->coeff); free(poly->basis); free(poly->degree); free(poly->group); free(poly); } } /****** poly_func ************************************************************ PROTO double poly_func(polystruct *poly, double *pos) PURPOSE Evaluate a multidimensional polynom. INPUT polystruct pointer, pointer to the 1D array of input vector data. OUTPUT Polynom value. NOTES Values of the basis functions are updated in poly->basis. AUTHOR E. Bertin (IAP) VERSION 03/03/2004 ***/ double poly_func(polystruct *poly, double *pos) { double xpol[POLY_MAXDIM+1]; double *post, *xpolt, *basis, *coeff, xval; long double val; int expo[POLY_MAXDIM+1], gexpo[POLY_MAXDIM+1]; int *expot, *degree,*degreet, *group,*groupt, *gexpot, d,g,t, ndim; /* Prepare the vectors and counters */ ndim = poly->ndim; basis = poly->basis; coeff = poly->coeff; group = poly->group; degree = poly->degree; if (ndim) { for (xpolt=xpol, expot=expo, post=pos, d=ndim; --d;) { *(++xpolt) = 1.0; *(++expot) = 0; } for (gexpot=gexpo, degreet=degree, g=poly->ngroup; g--;) *(gexpot++) = *(degreet++); if (gexpo[*group]) gexpo[*group]--; } /* The constant term is handled separately */ val = *(coeff++); *(basis++) = 1.0; *expo = 1; *xpol = *pos; /* Compute the rest of the polynom */ for (t=poly->ncoeff; --t; ) { /*-- xpol[0] contains the current product of the x^n's */ val += (*(basis++)=*xpol)**(coeff++); /*-- A complex recursion between terms of the polynom speeds up computations */ /*-- Not too good for roundoff errors (prefer Horner's), but much easier for */ /*-- multivariate polynomials: this is why we use a long double accumulator */ post = pos; groupt = group; expot = expo; xpolt = xpol; for (d=0; dncoeff; ndim = poly->ndim; matsize = ncoeff*ncoeff; basis = poly->basis; extbasist = extbasis; QCALLOC(alpha, double, matsize); QCALLOC(beta, double, ncoeff); /* Subtract an average offset to maintain precision (droped for now ) */ /* if (x) { for (d=0; dcoeff; for (j=ncoeff; j--;) *(coeff++) = *(betat++); /* poly_addcste(poly, offset); */ free(beta); return; } /****** poly_addcste ********************************************************* PROTO void poly_addcste(polystruct *poly, double *cste) PURPOSE Modify matrix coefficients to mimick the effect of adding a cst to the input of a polynomial. INPUT Pointer to the polynomial structure, Pointer to the vector of cst. OUTPUT -. NOTES Requires quadruple-precision. **For the time beeing, this function returns completely wrong results!!** AUTHOR E. Bertin (IAP) VERSION 03/03/2004 ***/ void poly_addcste(polystruct *poly, double *cste) { long double *acoeff; double *coeff,*mcoeff,*mcoefft, val; int *mpowers,*powers,*powerst,*powerst2, i,j,n,p, denum, flag, maxdegree, ncoeff, ndim; ncoeff = poly->ncoeff; ndim = poly->ndim; maxdegree = 0; for (j=0; jngroup; j++) if (maxdegree < poly->degree[j]) maxdegree = poly->degree[j]; maxdegree++; /* Actually we need maxdegree+1 terms */ QCALLOC(acoeff, long double, ncoeff); QCALLOC(mcoeff, double, ndim*maxdegree); QCALLOC(mpowers, int, ndim); mcoefft = mcoeff; /* To avoid gcc -Wall warnings */ powerst = powers = poly_powers(poly); coeff = poly->coeff; for (i=0; i