pax_global_header00006660000000000000000000000064140043066730014515gustar00rootroot0000000000000052 comment=5c927e8a9312576b8618bf2480be1b9867d2483c swarp-2.41.5/000077500000000000000000000000001400430667300127425ustar00rootroot00000000000000swarp-2.41.5/AUTHORS000066400000000000000000000001431400430667300140100ustar00rootroot00000000000000Emmanuel Bertin : SWarp code, FITS library, TNX support, and documentation. swarp-2.41.5/BUGS000066400000000000000000000000011400430667300134140ustar00rootroot00000000000000 swarp-2.41.5/COPYRIGHT000066400000000000000000000012531400430667300142360ustar00rootroot00000000000000Copyright 2010 IAP - CNRS / Universite P.&M.Curie Author: Emmanuel Bertin SWarp 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 3 of the License, or (at your option) any later version. SWarp 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 SWarp. If not, see . swarp-2.41.5/ChangeLog000066400000000000000000001074641400430667300145300ustar00rootroot00000000000000# # ChangeLog # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # # This file part of: SWarp # # Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC # # License: GNU General Public License # # SWarp 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 3 of the License, or # (at your option) any later version. # SWarp 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 SWarp. If not, see . # # Last modified: 26/10/2010 # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ------------------------------------------------------------------------ r95 | bertin | 2010-09-01 11:39:26 +0200 (Wed, 01 Sep 2010) | 3 lines Added MJD-OBS (start of observations) to output FITS headers. Pushed version number to 2.19.1. ------------------------------------------------------------------------ r94 | bertin | 2010-08-26 00:19:37 +0200 (Thu, 26 Aug 2010) | 7 lines Rewrote astrometric flux rescaling code to solve problem with manual background subtraction (thanks to D.G.Bonfield for reporting). Expect slight changes at the 1e-5 level for background-subtracted resampled pixels. The displayed background values are now those of the original image. Added RESCALE_WEIGHTS configuration switch (defaulted to Y). Setting RESCALE_WEIGHTS to N turns off automatic weight and variance rescaling based on the actual noise level measured in the image (thanks to J.Mohr and C.Mancone for the suggestion). Fixed (once again) the automatic centering and framing algorithm (thanks to D.Murphy for reporting). Updated links in README, ChangeLog and man page. Increased default values for the MEM_MAX and COMBINE_BUFSIZE memory parameters to 256MB. Pushed version number to 2.19.0. ------------------------------------------------------------------------ r93 | bertin | 2010-07-20 13:23:20 +0200 (Tue, 20 Jul 2010) | 2 lines Fixed TFORM error message in fitshead.c (thanks to S.Guieu). ------------------------------------------------------------------------ r92 | bertin | 2010-07-02 14:34:23 +0200 (Fri, 02 Jul 2010) | 2 lines Removed redundant update_tab() calls. ------------------------------------------------------------------------ r91 | bertin | 2010-07-02 11:54:17 +0200 (Fri, 02 Jul 2010) | 2 lines Fixed comment copy issue for slashes within strings (thanks to F.Schuller). ------------------------------------------------------------------------ r90 | bertin | 2010-05-21 16:23:28 +0200 (Fri, 21 May 2010) | 2 lines Fixed syntax message (thanks to J.-B. Marquette). ------------------------------------------------------------------------ r89 | bertin | 2010-04-20 17:39:38 +0200 (Tue, 20 Apr 2010) | 2 lines Added LICENSE to the .spec.in file, too. ------------------------------------------------------------------------ r88 | bertin | 2010-04-20 17:37:35 +0200 (Tue, 20 Apr 2010) | 2 lines Added LICENSE to the list of EXTRA_DIST files. ------------------------------------------------------------------------ r87 | bertin | 2010-04-20 17:34:48 +0200 (Tue, 20 Apr 2010) | 2 lines Added CeCILL version 2 license text and update COPYRIGHT information. ------------------------------------------------------------------------ r86 | bertin | 2010-02-22 14:54:59 +0100 (Mon, 22 Feb 2010) | 2 lines Deactivated subtraction of the median background from saturation level if the result is negative. ------------------------------------------------------------------------ r85 | bertin | 2009-09-10 19:32:33 +0200 (Thu, 10 Sep 2009) | 6 lines Added --enable-auto-flags. Added --enable-best-link configure option. Added rpm-best option in Makefile.am. Cleaned up configure file. Pushed version number to 2.18.0. ------------------------------------------------------------------------ r84 | bertin | 2009-05-22 14:31:31 +0200 (Fri, 22 May 2009) | 3 lines Added filtering of non-numerical characters for floating-point FITS keywords (thanks to D.G. Bonfield for the suggestion). Included Chiara's MissFITS fix in fitspick(). ------------------------------------------------------------------------ r83 | bertin | 2009-04-28 19:27:03 +0200 (Tue, 28 Apr 2009) | 2 lines Fixed bug in make_kernel() test bug (thanks to R.Owen). ------------------------------------------------------------------------ r81 | bertin | 2009-04-09 15:55:32 +0200 (Thu, 09 Apr 2009) | 3 lines Fixed references to COPYRIGHT file. Pushed version number to 2.17.6. ------------------------------------------------------------------------ r80 | bertin | 2009-04-01 18:48:34 +0200 (Wed, 01 Apr 2009) | 4 lines Fixed icc 11 compilations options on x86-64 architecture. Cleaned up obsolete references. Added favicon to XSLT filter. ------------------------------------------------------------------------ r79 | bertin | 2009-04-01 14:42:31 +0200 (Wed, 01 Apr 2009) | 2 lines Updated XSLT filter (AstrOmatic theme). ------------------------------------------------------------------------ r77 | bertin | 2009-03-23 18:20:20 +0100 (Mon, 23 Mar 2009) | 7 lines Cleaned up Makefile.am RPM options. Fixed rpm build issue on Fedora Core 10. Fixed display of max thread number in configure help. Updated icc compilation flags to 11.0 syntax. Set the license string to CeCILL in the .spec file. Pushed version number to 2.17.5. ------------------------------------------------------------------------ r76 | bertin | 2009-02-20 18:22:43 +0100 (Fri, 20 Feb 2009) | 3 lines Fixed bug which would cause the mapping to depend on the ordering of PVs. Pushed version number to 2.17.4 ------------------------------------------------------------------------ r75 | bertin | 2009-01-12 17:55:07 +0100 (Mon, 12 Jan 2009) | 2 lines Set doc to correct mime-type. ------------------------------------------------------------------------ r73 | root | 2009-01-09 17:25:25 +0100 (Fri, 09 Jan 2009) | 1 line Changed trunk directory name ------------------------------------------------------------------------ r72 | bertin | 2008-12-16 19:23:32 +0100 (Tue, 16 Dec 2008) | 2 lines Fixed version numbering issue. ------------------------------------------------------------------------ r71 | bertin | 2008-12-16 19:19:30 +0100 (Tue, 16 Dec 2008) | 2 lines Added versioning of resampled filenames for duplicated input filenames (reported by J.Mohr). ------------------------------------------------------------------------ r70 | bertin | 2008-12-05 10:30:36 +0100 (Fri, 05 Dec 2008) | 4 lines Increased MAXINFIELD (max.number of input images) to 200,000 (was 100,000) Increased MAXLIST (number arguments per option) to MAXINFIELD (was 256!) Increased MAXLISTSIZE to (100*MAXLIST). ------------------------------------------------------------------------ r69 | bertin | 2008-12-02 12:16:19 +0100 (Tue, 02 Dec 2008) | 3 lines Fixed image framing and flux scaling problem when mixing different lng and lat axes (thanks to David G. Bonfield). Pushed version number to 2.17.3. ------------------------------------------------------------------------ r68 | bertin | 2008-10-27 13:29:07 +0100 (Mon, 27 Oct 2008) | 2 lines Fixed asymmetry of background filtering at image boundaries (thanks to P.Astier and D.Hardin). ------------------------------------------------------------------------ r67 | bertin | 2008-10-01 19:09:35 +0200 (Wed, 01 Oct 2008) | 2 lines Updated FITS library to the latest version. ------------------------------------------------------------------------ r66 | bertin | 2008-10-01 18:04:59 +0200 (Wed, 01 Oct 2008) | 3 lines Fixed superfluous -static-intel LDFLAGS in new compiler optimization script. Removed swarp-mp spec file (merged now with swarp.spec). ------------------------------------------------------------------------ r65 | bertin | 2008-10-01 16:45:42 +0200 (Wed, 01 Oct 2008) | 5 lines Updated compiler autoconfiguration script. Updated .spec RPM script. Added rpm-icc target. Version is now 2.17.2. ------------------------------------------------------------------------ r64 | bertin | 2008-02-06 15:20:53 +0100 (Wed, 06 Feb 2008) | 2 lines Fixed issue with missing "@"lists (reported by H.J. McCracken). ------------------------------------------------------------------------ r63 | bertin | 2008-01-10 17:33:04 +0100 (Thu, 10 Jan 2008) | 2 lines Fixed error in the y^2.x^4 PV monomial (found by R.Haigron & J.Guibert). ------------------------------------------------------------------------ r62 | bertin | 2008-01-08 12:20:00 +0100 (Tue, 08 Jan 2008) | 3 lines Fixed issue with multiple input files (only one would be considered). Version number pushed to 2.17.1. ------------------------------------------------------------------------ r61 | bertin | 2008-01-07 15:46:53 +0100 (Mon, 07 Jan 2008) | 3 lines Added description of FSCALASTRO_TYPE and @ syntax to doc. Added sincos() support in interpolate_pix() (much faster with gcc, slightly slower with icc). ------------------------------------------------------------------------ r60 | bertin | 2008-01-04 19:16:46 +0100 (Fri, 04 Jan 2008) | 4 lines Fixed weighting in FSCALASTRO_TYPE VARIABLE mode. Fixed CD transformation matrix in precessions. Optimized the computation of interpolation kernels for Lanczos3 (speed +30%) and Lanczos3 (speed +40%) using trigonometric polynomials. ------------------------------------------------------------------------ r59 | bertin | 2008-01-03 20:00:04 +0100 (Thu, 03 Jan 2008) | 4 lines Added FSCALASTRO_TYPE VARIABLE mode to compensate for variable pixel scale on exposures corrected for illumination. Cleaned up code in FITSWCS library. Version number pushed to 2.17.0. ------------------------------------------------------------------------ r58 | bertin | 2007-11-18 15:26:51 +0100 (Sun, 18 Nov 2007) | 5 lines Added support for reading selected FITS extensions for all input images/maps (e.g. image.fits[3] a la CFITSIO). Added @lists support in all config-file and command-line arguments. Removed .svn directories from source archive. Pushed version number to 2.16.6. ------------------------------------------------------------------------ r57 | marmo | 2007-08-09 17:35:41 +0200 (Thu, 09 Aug 2007) | 1 line headflag inherited by the output field. ------------------------------------------------------------------------ r56 | marmo | 2007-08-08 20:22:51 +0200 (Wed, 08 Aug 2007) | 1 line XSLT style-sheet updated. ------------------------------------------------------------------------ r55 | bertin | 2007-07-17 12:39:40 +0200 (Tue, 17 Jul 2007) | 3 lines Upgraded to the latest version of the FITS library. Updated the THANKS. ------------------------------------------------------------------------ r54 | bertin | 2007-07-16 19:44:31 +0200 (Mon, 16 Jul 2007) | 3 lines FITS cleanup bug (http://astromatic.net/forum/showthread.php?tid=236) fixed. Effective gain is now computed properly when FSCALEASTRO_TYPE is FIXED (http://astromatic.net/forum/showthread.php?tid=129). ------------------------------------------------------------------------ r53 | bertin | 2007-07-13 22:00:26 +0200 (Fri, 13 Jul 2007) | 5 lines Temptative fix of the FITS cleanup bug (see http://astromatic.net/forum/showthread.php?tid=236). Updated doc. Updated THANKS. Hid GAIN and SATLEVEL config parameters. ------------------------------------------------------------------------ r52 | bertin | 2007-07-13 20:32:00 +0200 (Fri, 13 Jul 2007) | 5 lines Fixed update date and a few details. Included missing acx_urbi_resolve_dir.m4. Removed acx_mpi.m4. Updated to the last FITS library version. ------------------------------------------------------------------------ r51 | marmo | 2007-06-25 19:04:46 +0200 (Mon, 25 Jun 2007) | 1 line computation of saturation level added. ------------------------------------------------------------------------ r50 | marmo | 2007-06-19 20:31:34 +0200 (Tue, 19 Jun 2007) | 1 line rpm building generalised. ------------------------------------------------------------------------ r49 | marmo | 2007-06-19 19:19:15 +0200 (Tue, 19 Jun 2007) | 1 line Akim Demaille macro for solving the issue added ------------------------------------------------------------------------ r48 | bertin | 2007-06-08 16:12:01 +0200 (Fri, 08 Jun 2007) | 2 lines Updated the documentation (about XML now written by default and image list support). ------------------------------------------------------------------------ r47 | bertin | 2007-06-08 15:53:25 +0200 (Fri, 08 Jun 2007) | 2 lines Added Akim Demaille's fix for absolute paths. ------------------------------------------------------------------------ r46 | marmo | 2007-06-08 15:34:19 +0200 (Fri, 08 Jun 2007) | 1 line Error notification added ------------------------------------------------------------------------ r45 | bertin | 2007-06-08 15:05:30 +0200 (Fri, 08 Jun 2007) | 4 lines Updated fits library modules to the latest version. Updated release info files. Pushed version number to 2.16.3 (release version). ------------------------------------------------------------------------ r44 | bertin | 2007-06-08 14:54:44 +0200 (Fri, 08 Jun 2007) | 3 lines Added support for pseudo-3D image cubes (e.g. ISSA maps). Added internal functions for future astrometric improvements. ------------------------------------------------------------------------ r43 | marmo | 2007-05-30 14:44:35 +0200 (Wed, 30 May 2007) | 1 line all tables in xml file are now displayed. ------------------------------------------------------------------------ r42 | bertin | 2007-05-17 18:00:30 +0200 (Thu, 17 May 2007) | 2 lines Fixed issue with ZPN and other projections by using the right latitude axis. ------------------------------------------------------------------------ r41 | bertin | 2007-04-03 17:59:05 +0200 (Tue, 03 Apr 2007) | 2 lines Fixed swapping of CTYPEs for mixed longitude and latitude indices. ------------------------------------------------------------------------ r40 | bertin | 2007-04-03 14:31:36 +0200 (Tue, 03 Apr 2007) | 2 lines Dirty-fixed ${datarootdir} issue in configure. ------------------------------------------------------------------------ r39 | bertin | 2007-04-02 19:00:00 +0200 (Mon, 02 Apr 2007) | 2 lines Fixed issue occurring when longitude and latitude axes are mixed. ------------------------------------------------------------------------ r38 | marmo | 2007-03-28 15:09:03 +0200 (Wed, 28 Mar 2007) | 1 line basic xslt stylesheet imported ------------------------------------------------------------------------ r37 | bertin | 2007-03-26 14:41:33 +0200 (Mon, 26 Mar 2007) | 6 lines Added XSLT filter file (currently copied from the SCAMP XSLT filter). Fixed XSLT filter path problem with RPM versions. Added External_Header flag FIELD to XML-VOTable output. Improved configure summary display. Pushed version number to 2.16.1. ------------------------------------------------------------------------ r36 | bertin | 2007-03-08 09:58:16 +0100 (Thu, 08 Mar 2007) | 2 lines Removed forgotten debug display, ------------------------------------------------------------------------ r35 | bertin | 2007-02-18 09:24:48 +0100 (Sun, 18 Feb 2007) | 2 lines Fixed bug occuring while picking up integers in headers. ------------------------------------------------------------------------ r34 | bertin | 2007-02-08 21:04:16 +0100 (Thu, 08 Feb 2007) | 3 lines Added new celsys_to_eq() and eq_to_celsys() functions to fitswcs library. Fixed issue with automatic centering with galactic (or anything else) inputs and equatorial outputs. ------------------------------------------------------------------------ r33 | bertin | 2007-01-17 18:03:46 +0100 (Wed, 17 Jan 2007) | 2 lines Added options for compiling with icc (Intel compiler). ------------------------------------------------------------------------ r32 | bertin | 2006-10-29 21:07:01 +0100 (Sun, 29 Oct 2006) | 3 lines Applied patch by Sergio Pascual for configuring the path to the XSL file. Updated the TODO section. ------------------------------------------------------------------------ r31 | bertin | 2006-10-26 18:08:24 +0200 (Thu, 26 Oct 2006) | 4 lines Updated FITS library to the latest version. Fixed UCDs in XML output. Finalized support for file lists. ------------------------------------------------------------------------ r30 | marmo | 2006-10-25 18:59:54 +0200 (Wed, 25 Oct 2006) | 1 line input as image list enabled ------------------------------------------------------------------------ r29 | bertin | 2006-09-19 15:29:39 +0200 (Tue, 19 Sep 2006) | 2 lines Removed residual debugging info. ------------------------------------------------------------------------ r28 | bertin | 2006-09-19 15:27:21 +0200 (Tue, 19 Sep 2006) | 2 lines Fixed bug with COPY_KEYWORDS option on some specific headers. ------------------------------------------------------------------------ r27 | bertin | 2006-08-10 18:40:17 +0200 (Thu, 10 Aug 2006) | 3 lines Typo in preference list fixed. This is the 2.16 release. ------------------------------------------------------------------------ r26 | bertin | 2006-08-09 20:12:58 +0200 (Wed, 09 Aug 2006) | 5 lines Added Equinox and COOSYS FIELDs to VOTable output. Fixed various issues in the propagation of astrometric and photometric metadata. Updated the documentation. Changed the version number to 2.16: we are go for the release! ------------------------------------------------------------------------ r25 | bertin | 2006-08-08 20:17:11 +0200 (Tue, 08 Aug 2006) | 4 lines Fixed graph matrix overflow in image combine routine. Removed counting of more than one extension per file in the displayed number of overlaps. Added estimate of maximum exposure time and maximum effective gain in FITS and XML meta-data outputs. ------------------------------------------------------------------------ r24 | bertin | 2006-08-05 20:06:24 +0200 (Sat, 05 Aug 2006) | 2 lines Optimized the COMBINE buffer allocation by finding the real maximal clique by using the recursive algorithm of Bron & Kerbosch (1971): typical gain ~ 50%. ------------------------------------------------------------------------ r23 | bertin | 2006-08-02 22:04:55 +0200 (Wed, 02 Aug 2006) | 3 lines Fixed serious co-addition bug for framed output FOVs. Removed useless access to images outside the output frame during co-addition. ------------------------------------------------------------------------ r22 | bertin | 2006-08-01 23:00:44 +0200 (Tue, 01 Aug 2006) | 3 lines Fixed issues with image combining with RESAMPLE N. Fixed (invisible) floating exception occuring during image combining. ------------------------------------------------------------------------ r21 | bertin | 2006-07-27 21:29:03 +0200 (Thu, 27 Jul 2006) | 6 lines Added/Fixed several elements in XML output. Added BLANK_BADPIXELS option to blank output pixels with a weight of zero. Added "naive" total exposure time calculation. Increased background buffer size to 8MB. Doc: added BLANK_BADPIXELS keyword description and fixed typos in gain computation. ------------------------------------------------------------------------ r20 | bertin | 2006-07-26 20:29:05 +0200 (Wed, 26 Jul 2006) | 5 lines XML VOTable output implementation now complete (checked validity and compliance). Added stdout output of XML using XML_NAME STDOUT option. Pushed the limit for keyword length to 32 chars. Doc: Updated to 2.16, with info about XML output options. ------------------------------------------------------------------------ r19 | bertin | 2006-07-26 11:47:29 +0200 (Wed, 26 Jul 2006) | 2 lines Corrected a typo that would prevent the code to compile on Macs. ------------------------------------------------------------------------ r18 | bertin | 2006-07-25 22:52:52 +0200 (Tue, 25 Jul 2006) | 2 lines Further progress with the XML-Votable output (note: "ct" units replaced with "adu" units). ------------------------------------------------------------------------ r17 | bertin | 2006-07-25 16:00:31 +0200 (Tue, 25 Jul 2006) | 2 lines Added automatic detection of the number of CPUs on BSD, HP/UX and IRIX systems. ------------------------------------------------------------------------ r16 | bertin | 2006-07-24 20:47:56 +0200 (Mon, 24 Jul 2006) | 2 lines Further progress on the XML metadata config dump. ------------------------------------------------------------------------ r15 | bertin | 2006-07-21 21:09:26 +0200 (Fri, 21 Jul 2006) | 3 lines Further progress on the XML output. Added a follow-up of celestial types through field structures. ------------------------------------------------------------------------ r14 | bertin | 2006-07-20 22:01:53 +0200 (Thu, 20 Jul 2006) | 5 lines Cleaned up configure.ac (removed obsolete options). Added XML VOTable output support files. Added error catching routines. Added XML VOTable support (not finished, deactivated for now). ------------------------------------------------------------------------ r13 | bertin | 2006-07-19 19:41:42 +0200 (Wed, 19 Jul 2006) | 3 lines Added CELESTIAL_TYPE SUPERGALACTIC option. Cleaned up default configuration file dump. ------------------------------------------------------------------------ r12 | bertin | 2006-07-19 18:14:38 +0200 (Wed, 19 Jul 2006) | 5 lines Updated ChangeLog. Relaxed binary table identification checks. Fixed coordinate system transformation bug (detected on Gal<->Eq). Added support for supergalactic coordinate system. ------------------------------------------------------------------------ r11 | baillard | 2006-07-18 13:55:53 +0200 (Tue, 18 Jul 2006) | 2 lines Move swarp to public repository ------------------------------------------------------------------------ r10 | bertin | 2006-07-17 20:02:20 +0200 (Mon, 17 Jul 2006) | 4 lines Added ICRS support (but no conversion to older systems yet). Updated the FITS library to the latest version (adds warning history, error catching and fixes pointer aliasing compilation warnings). Updated WCS routines to the latest version (TNX multithreading and polynomial bugfixes). ------------------------------------------------------------------------ r9 | bertin | 2006-06-08 17:32:31 +0200 (Thu, 08 Jun 2006) | 2 lines Fixed a bug that would make config arguments limited to 496 chars (see http://astromatic.net/forum/showthread.php?tid=14). ------------------------------------------------------------------------ r8 | bertin | 2006-03-12 18:56:52 +0100 (Sun, 12 Mar 2006) | 2 lines Updated ChangeLog and HISTORY files. ------------------------------------------------------------------------ r7 | bertin | 2006-03-12 18:36:29 +0100 (Sun, 12 Mar 2006) | 2 lines Replaced make with make -j to speed up the RPM building process. ------------------------------------------------------------------------ r6 | bertin | 2006-03-11 22:41:55 +0100 (Sat, 11 Mar 2006) | 3 lines Fixed segfault with too long arguments. Version number pushed to 2.15.7. ------------------------------------------------------------------------ r5 | bertin | 2006-01-31 17:13:07 +0100 (Tue, 31 Jan 2006) | 2 lines Removed a forgotten 'printf("coucou\n")' in fitscleanup.c ... ------------------------------------------------------------------------ r4 | bertin | 2006-01-31 17:10:52 +0100 (Tue, 31 Jan 2006) | 2 lines Added additional checks to resampling boundaries to prevent crash in case of buggy astrometric solutions. ------------------------------------------------------------------------ r3 | marmo | 2005-11-12 19:11:47 +0100 (Sat, 12 Nov 2005) | 1 line fixed the bug on single weight image mode ------------------------------------------------------------------------ r2 | bertin | 2005-10-17 16:53:55 +0200 (Mon, 17 Oct 2005) | 1 line -------------------------------- old ChangeLog -------------------------------- Who When Where(mostly) What EB 13/03/2001 useprefs() Allow Weighting when input weight-maps are missing. EB 15/03/2001 coadd_pix() Provide a specific handling of the weights when n=2 in COMBINE_TYPE MEDIAN mode. EB 09/04/2001 make_back() Fixed a bug with weight-maps in large-image mode. EB 01/08/2001 coadd_pix() Fixed a weighting bug in MEDIAN mode. EB 06/08/2001 - Reorganize files and directories on the MissFITS model. EB 10/08/2001 - Added support for header_only and resample_only modes. EB 13/08/2001 write_wcs() Fixed a small bug that would cause the RADECSYS keyword to be written twice in the header. header.c Added read/write support for COMIN and COMAX custom FITS keywords. EB 07/03/2002 makeit() Make the identification of non-image FITS data more strict for ambiguous headers. EB 16/03/2002 resample.c New module extracted from coadd.c resample.h New include for resample.c EB 18/03/2002 - Added multithreading to resampling routine (compile with -DUSE_THREADS option). EB 08/06/2002 printinfo_field() Astrom/Photom displayed flux scale was inversed. EB 09/06/2002 read_aschead() Make header parsing less strict. resample_field() frame_wcs() Fixed problem with images outside the output frame. EB 11/06/2002 resample_field() Fixed pthread_mutex_destroy() bug on Alpha. field.c New display of external header info. EB 13/06/2002 - Removed config.h from define.h and included explicitely in all sources EB 14/06/2002 - Added off_t type explicitely in fseek()s and ftell()s. KINGSIZE_T type added in the fits library to support large files. EB 15/06/2002 coadd_fields() Fixed memory bug for images completely outside the output frame. EB 17/07/2002 fitswcs.c Added wcs_dist() function and field radius measurement (copied from SAM). EB 24/07/2002 wcs_dist() Fixed a units bug. EB 29/09/2002 load_weight() Fixed WEIGHT_FROMRMSMAP bug. coadd_fields() Removed normalization of output weights. EB 08/10/2002 init_field() Make the sign of longitude increment negative in automatic framing. writefitsinfo_field() Fixed FITS header bug in WRITE_FILEINFO mode with input weight-maps main() Changed banner. EB 28/11/2002 init_field() Fixed bad propagation of longitude increment sign. define.h COPYRIGHT Slightly modified. configure.in Allow NTHREADS>1 in monothreaded build. use_prefs() Warning added. EB 10/01/2003 interpolate_pix() linecount[n] was not initialized. EB 18/01/2003 range_wcs() Fixed scaling sign bug for non-spherical projections EB 10/04/2003 coadd_pix() fast_median() Activate a faster version of the median for co-addition. EB 17/04/2003 resample.c New multithreaded code. EB 18/04/2003 init_field() Handled properly case with CENTER_TYPE MANUAL and IMAGE_SIZE 0. make_kernel() Optimized Lanczos kernel computations. EB 19/04/2003 fast_median() Optimized further. EB 20/04/2003 prefs.h Fixed missing galactic coord support. load_field() init_field() Added support for PIXEL celestial type. EB 21/04/2003 - Added propagation of FITS keywords. addkeywordto_head() Fixed bug when adding COMMENTs fitswrite() fitspick() Improved handling of H_STRINGS comments EB 28/04/2003 coadd_pix() Optimized code. - Added opt. support for INTEL math lib. resample_field() Changed temp. weight naming convention. EB 03/07/2003 threads.c New modules with macro functions to make multithreading easier. EB 09/07/2003 coadd.c Completely rewrote the co-addition code. Better optimisation and multi- threading added. EB 09/07/2003 lin.c Replaced the include with an EB 04/08/2003 threads.c Made code compilation optional. EB 15/08/2003 - Small fixes to avoid gcc -Wall warnings. addhistoryto_cat() date in HISTORY has now dd/mm/YYYY format EB 16/08/2003 - Added HAVE_GETENV configure flag. header.c Replaced getpwuid() with getenv("LOGNAME") main() Produce a more concise --version output. EB 18/08/2003 coadd_fields() Weight-map corruption bug fixed. EB 20/08/2003 field.c Removed obsolete #includes. EB 17/10/2003 - Made COPYSIGN and SIGNBIT conditions the default in wcslib. EB 20/10/2003 - Removed additional gcc -Wall warnings. EB 21/10/2003 coadd_line() Set output pixel to one of the input values when all input weights are zero. EB 26/10/2003 range_wcs() invert_wcs() Fixed bug in step increment. fitswcs.* Updated to the latest SCAMP version. EB 28/10/2003 write_wcs() Fixed bug when writing PVs. EB 05/11/2003 read_body() read_fitsbasic() interpolate_pix() backstat() convert_data() Added support for BLANKed pixels. EB 06/11/2003 invert_wcs() range_wcs() Extended the automatic min and max WCS limits of a field to pixel borders. read_body() Fixed NaN detection. EB 09/11/2003 convert_data() read_fitsbasic() backstat() Fixed BLANKing bugs in WEIGHTED mode. EB 16/11/2003 - Added PROJECTION_ERR keyword and new "approximated astrometry" mode. EB 19/11/2003 init_field() Positioned headerflag for output field. EB 20/11/2003 fitswcs.c makeit() init_field() Added support for heterogeneous axis labeling. EB 21/11/2003 makeit() load_field() load_weight() Reduced memory usage with MEFs. projapp_init() Removed warning for small images. EB 22/11/2003 coadd_movewdata() Copy first pixel value in output image if all weights are 0. EB 24/11/2003 warp_line() Fixed a HUGE bug in resampling!!! EB 28/11/2003 tnx.c Broken TNX support rehabilitated. EB 20/12/2003 warp_line() Fixed projection bug with oversampling. EB 04/01/2004 raw_to_pv() Fixed bug for polynoms >= 4th degree. EB 06/02/2004 coadd_line() Fixed bug with COADD_CHI2. EB 28/04/2004 scale_field() Fixed BZERO scaling bug. EB 06/11/2004 range_wcs() Fixed auto-limits with all-sky images. EB 17/11/2004 fitsutil.c Update + replaced %e by %E format. makeit() main() Improved display (time, # of threads..) read_aschead() Fixed header corruption bugs with crippled .head lines. read_prefs() Added automatic NTHREADS on systems with sysconf(_SC_NPROCESSORS_ONLN). EB 18/11/2004 read_aschead() Removed debug info left by mistake Improved robustness of header reading configure.ac Removed icc/gcc duplicated options. EB 05/12/2004 swarp.tex Fixed a few confusing equations. EB 09/12/2004 makeit() Fixed a long standing bug: weights were not scaled with the flux scale. EB 10/12/2004 - New .spec files and rpm handling (cross-compiling now possible on x86_64). back.c back.h Replaced long's by int's. EB 26/04/2005 FITS library Upgraded to the latest version. EB 27/04/2005 makeit() Fixed segfault with Nextensions > 8182. EB 28/04/2005 coadd_line() Added support for summation. EB 20/06/2005 fitswcs.c Upgraded to the latest version. EB 21/06/2005 coadd.c Fixed segfault and positioning pb in RESAMPLE N mode. EB 22/06/2005 init_field() Force sexagedecimal input order to lng,lat EB 24/06/2005 makeit() Dropped reaxe_wcs() for lng>lat EB 19/07/2005 init_field() Fixed non-integer CRPIXs in automatic IMAGE_SIZE mode. dumpprefs() Added support for "deep dump". EB 20/07/2005 makeit() Fixed a huge bug introduced while axing reaxe_wcs()... - Replace Postscript version of doc with PDF file. EB 15/09/2005 pthread_nextline() Fixed long-standing line-swapping bug in multi-threaded mode. CM 12/11/2005 useprefs() Propagate duplicate weight-map in case of multiple input images. EB 31/01/2006 interpolate_pix() Added additional boundary check to prevent bogus astrometric solutions from crashing SWarp. EB 11/03/2006 prefs.c Allow very long arrays of strings to be given as arguments to swarp. swarp-2.41.5/HISTORY000066400000000000000000000031771400430667300140360ustar00rootroot00000000000000V2.17 (2008-01-07) Improved performance. Improved XSLT filter. Variable pixel-scale flux correction is now supported. Both GAIN and SATLEVEL keywords are now propagated. Many bugfixes. V2.16 (2006-08-09) XML-VOTable meta-data output added. Many bugfixes. Updated documentation V2.15.7 (2006-03-12) Single weight bug fixed. Weighting all images with one single weight is now allowed. Very long arguments to the swarp command are now supported. V2.15.5 (2005-07-20) Mostly bugfixes. V2.0 (2003-08-18) Image combination section completely rewritten, with support for multithreading and multidimensional data. It is now 2-4 times faster. Image resampling optimized: about twice faster now. Various portability issues fixed. Documentation updated. V1.41 (2003-04-21) New COPY_KEYWORDS option to propagate selected FITS keywords New CELESTIAL_TYPE PIXEL to boost processing speed when astronometry is not a concern. Many bugfixes. Update doc. V1.40 (2003-04-17) Fixed Multithreaded code (now with load-balancing). V1.38 (2002-11-28) Bugfixes V1.37 (2002-10-08) Bugfixes. Longitude axis is now reversed by default. V1.36 (2002-06-15) Support for large files. Bugfixes V1.35 (2002-06-11) Bugfixes V1.34 (2002-05-09) First "GNU-style" release. V1.27 (2002-03=17) Multi-threading and resample/coadd-only options added V1.18 (2001-03-11) Public release with full documentation V1.14 (2001-01-14) Support for galactic and equatorial coordinates V1.6 (2000-08-21) Public pre-release. Interpolation engine rewritten V1.5 (2000-07-??) Support for IRAF's TNX astrometric format added V1.4 (2000-05-??) First working version. swarp-2.41.5/INSTALL000066400000000000000000000034711400430667300140000ustar00rootroot00000000000000Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. 2. Type `make' to compile the package. 3. Type `make install' to install the programs and any data files and documentation. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for variables by setting them in the environment. You can do that on the command line like this: ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. swarp-2.41.5/LICENSE000066400000000000000000001045131400430667300137530ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, 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 them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program 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 3 of the License, or (at your option) any later version. This program 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 this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . swarp-2.41.5/Makefile.am000066400000000000000000000045151400430667300150030ustar00rootroot00000000000000# # Makefile.am # # Main Makefile. Process this file with automake to generate a Makefile # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # # This file part of: SWarp # # Copyright: (C) 2002-2019 IAP/CNRS/SorbonneU # # SWarp 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 3 of the License, or # (at your option) any later version. # SWarp 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 SWarp. If not, see . # # Last modified: 09/12/2019 # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = foreign no-dependencies SUBDIRS = src man doc debian dist_pkgdata_DATA = xsl/swarp.xsl EXTRA_DIST = autogen.sh AUTHORS BUGS ChangeLog COPYRIGHT \ HISTORY INSTALL LICENSE README.md THANKS RPM_ROOTDIR = `rpmbuild --nobuild -E %_topdir` RPM_SRCDIR = $(RPM_ROOTDIR)/SOURCES DEB_SRCDIR = ~/DEBIAN/SOURCES dist-hook: rm -rf `find $(distdir) -type d \( -name .svn -o -name .git \)` rpm: dist cp -f $(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.gz $(RPM_SRCDIR) rpmbuild -ba --clean --nodeps $(PACKAGE_TARNAME).spec rpm-icc: dist cp -f $(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.gz $(RPM_SRCDIR) USE_ICC="1" rpmbuild -ba --clean --nodeps $(PACKAGE_TARNAME).spec rpm-best: dist cp -f $(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.gz $(RPM_SRCDIR) USE_BEST="1" rpmbuild -ba --clean --nodeps $(PACKAGE_TARNAME).spec deb: dist mkdir -p $(DEB_SRCDIR) tar -xvf $(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.gz -C $(DEB_SRCDIR) cd $(DEB_SRCDIR)/$(PACKAGE_TARNAME)-$(PACKAGE_VERSION) debuild --set-envvar=PACKAGE_RELEASE=$(PACKAGE_RELEASE) -j4 -b -us -uc deb-best: dist mkdir -p $(DEB_SRCDIR) tar -xvf $(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.gz -C $(DEB_SRCDIR) cd $(DEB_SRCDIR)/$(PACKAGE_TARNAME)-$(PACKAGE_VERSION) debuild --set-envvar=PACKAGE_RELEASE=$(PACKAGE_RELEASE) --set-envvar=USE_BEST=1 --preserve-env --preserve-envvar=PATH -j4 -b -us -uc swarp-2.41.5/README.md000066400000000000000000000015011400430667300142160ustar00rootroot00000000000000# SWarp [![Build Status](https://travis-ci.org/astromatic/swarp.svg?branch=master)](https://travis-ci.org/astromatic/swarp [![Coverity Scan Build Status](https://scan.coverity.com/projects/swarp/badge.svg)](https://scan.coverity.com/projects/swarp "Coverity Badge") [![Documentation Status](https://readthedocs.org/projects/swarp/badge/?version=latest)](http://swarp.readthedocs.io/en/latest/?badge=latest) [Swarp] resamples and coadds FITS images to an arbitrary astrometric projection Check out the on-line [documentation], the [official web page], and the [user forum]. [SWarp]: http://astromatic.net/software/swarp [documentation]: https://www.astromatic.net/pubsvn/software/swarp/trunk/doc/swarp.pdf [official web page]: http://astromatic.net/software/swarp [user forum]: http://astromatic.net/forum/forumdisplay.php?fid=5 swarp-2.41.5/THANKS000066400000000000000000000034371400430667300136640ustar00rootroot00000000000000Mark Calabretta SWarp makes extensive use of his nice WCS library Nicolas Devillard Enlightening discussions about interpolation engines, fast medians and pthread portability issues. See http://ndevilla.free.fr/ Ville Laurikari For his VL_PROG_CC_WARNINGS (modified to ACX_PROG_CC_OPTIM) Steven G. Johnson For his acx_pthread.m4 Akim Demaille for solving the $datarootdir issue and providing the URBI_RESOLVE_DIR() function. Chiara Marmo for adding the computation of saturation levels and fixing several bugs. Julian Taylor for his patch to limit the number of files opened during image combination. Eduardo Amores Pierre Astier John Blakeslee Oliver Czoke Mireille Dantel-Fort Shantanu Desai Erik Deul Joerg P. Dietrich Laurent Domisse Thomas Erben Dafydd Wyn Evans Norman Grogin Stephen Gwyn Delphine Hardin Jan Kohnert Vincent Lebrun Frederic Magnard Henry-Joy McCracken Joe Mohr Mario Radovich Roeland Rengelink Armin Rest Chris Sabbey Roy Williams Help in discovering bugs or bringing suggestions Institut d'Astrophysique de Paris TERAPIX project Financial and technical support swarp-2.41.5/TODO000066400000000000000000000005521400430667300134340ustar00rootroot00000000000000Correct the small (10^-4) jittering due to kernel aliasing in Lanczos mode. Add support for compressed input images. Improve the quality of background subtraction, and make it multithreaded. Add support for PV/DV parameters according to the final WCS documents (when they are released!). Add "Drizzle-like" RESAMPLING_TYPE (square top-hat with width < 1 pixel). swarp-2.41.5/autogen.sh000077500000000000000000001344321400430667300147520ustar00rootroot00000000000000#!/bin/sh # a u t o g e n . s h # # Copyright (c) 2005-2009 United States Government as represented by # the U.S. Army Research Laboratory. # # 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. The name of the author may not be used to endorse or promote # products derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. # ### # # Script for automatically preparing the sources for compilation by # performing the myriad of necessary steps. The script attempts to # detect proper version support, and outputs warnings about particular # systems that have autotool peculiarities. # # Basically, if everything is set up and installed correctly, the # script will validate that minimum versions of the GNU Build System # tools are installed, account for several common configuration # issues, and then simply run autoreconf for you. # # If autoreconf fails, which can happen for many valid configurations, # this script proceeds to run manual preparation steps effectively # providing a POSIX shell script (mostly complete) reimplementation of # autoreconf. # # The AUTORECONF, AUTOCONF, AUTOMAKE, LIBTOOLIZE, ACLOCAL, AUTOHEADER # environment variables and corresponding _OPTIONS variables (e.g. # AUTORECONF_OPTIONS) may be used to override the default automatic # detection behaviors. Similarly the _VERSION variables will override # the minimum required version numbers. # # Examples: # # To obtain help on usage: # ./autogen.sh --help # # To obtain verbose output: # ./autogen.sh --verbose # # To skip autoreconf and prepare manually: # AUTORECONF=false ./autogen.sh # # To verbosely try running with an older (unsupported) autoconf: # AUTOCONF_VERSION=2.50 ./autogen.sh --verbose # # Author: # Christopher Sean Morrison # # Patches: # Sebastian Pipping # ###################################################################### # set to minimum acceptable version of autoconf if [ "x$AUTOCONF_VERSION" = "x" ] ; then AUTOCONF_VERSION=2.52 fi # set to minimum acceptable version of automake if [ "x$AUTOMAKE_VERSION" = "x" ] ; then AUTOMAKE_VERSION=1.6.0 fi # set to minimum acceptable version of libtool if [ "x$LIBTOOL_VERSION" = "x" ] ; then LIBTOOL_VERSION=1.4.2 fi ################## # ident function # ################## ident ( ) { # extract copyright from header __copyright="`grep Copyright $AUTOGEN_SH | head -${HEAD_N}1 | awk '{print $4}'`" if [ "x$__copyright" = "x" ] ; then __copyright="`date +%Y`" fi # extract version from CVS Id string __id="$Id: autogen.sh 33925 2009-03-01 23:27:06Z brlcad $" __version="`echo $__id | sed 's/.*\([0-9][0-9][0-9][0-9]\)[-\/]\([0-9][0-9]\)[-\/]\([0-9][0-9]\).*/\1\2\3/'`" if [ "x$__version" = "x" ] ; then __version="" fi echo "autogen.sh build preparation script by Christopher Sean Morrison" echo " + config.guess download patch by Sebastian Pipping (2008-12-03)" echo "revised 3-clause BSD-style license, copyright (c) $__copyright" echo "script version $__version, ISO/IEC 9945 POSIX shell script" } ################## # USAGE FUNCTION # ################## usage ( ) { echo "Usage: $AUTOGEN_SH [-h|--help] [-v|--verbose] [-q|--quiet] [-d|--download] [--version]" echo " --help Help on $NAME_OF_AUTOGEN usage" echo " --verbose Verbose progress output" echo " --quiet Quiet suppressed progress output" echo " --download Download the latest config.guess from gnulib" echo " --version Only perform GNU Build System version checks" echo echo "Description: This script will validate that minimum versions of the" echo "GNU Build System tools are installed and then run autoreconf for you." echo "Should autoreconf fail, manual preparation steps will be run" echo "potentially accounting for several common preparation issues. The" echo "AUTORECONF, AUTOCONF, AUTOMAKE, LIBTOOLIZE, ACLOCAL, AUTOHEADER," echo "PROJECT, & CONFIGURE environment variables and corresponding _OPTIONS" echo "variables (e.g. AUTORECONF_OPTIONS) may be used to override the" echo "default automatic detection behavior." echo ident return 0 } ########################## # VERSION_ERROR FUNCTION # ########################## version_error ( ) { if [ "x$1" = "x" ] ; then echo "INTERNAL ERROR: version_error was not provided a version" exit 1 fi if [ "x$2" = "x" ] ; then echo "INTERNAL ERROR: version_error was not provided an application name" exit 1 fi $ECHO $ECHO "ERROR: To prepare the ${PROJECT} build system from scratch," $ECHO " at least version $1 of $2 must be installed." $ECHO $ECHO "$NAME_OF_AUTOGEN does not need to be run on the same machine that will" $ECHO "run configure or make. Either the GNU Autotools will need to be installed" $ECHO "or upgraded on this system, or $NAME_OF_AUTOGEN must be run on the source" $ECHO "code on another system and then transferred to here. -- Cheers!" $ECHO } ########################## # VERSION_CHECK FUNCTION # ########################## version_check ( ) { if [ "x$1" = "x" ] ; then echo "INTERNAL ERROR: version_check was not provided a minimum version" exit 1 fi _min="$1" if [ "x$2" = "x" ] ; then echo "INTERNAL ERROR: version check was not provided a comparison version" exit 1 fi _cur="$2" # needed to handle versions like 1.10 and 1.4-p6 _min="`echo ${_min}. | sed 's/[^0-9]/./g' | sed 's/\.\././g'`" _cur="`echo ${_cur}. | sed 's/[^0-9]/./g' | sed 's/\.\././g'`" _min_major="`echo $_min | cut -d. -f1`" _min_minor="`echo $_min | cut -d. -f2`" _min_patch="`echo $_min | cut -d. -f3`" _cur_major="`echo $_cur | cut -d. -f1`" _cur_minor="`echo $_cur | cut -d. -f2`" _cur_patch="`echo $_cur | cut -d. -f3`" if [ "x$_min_major" = "x" ] ; then _min_major=0 fi if [ "x$_min_minor" = "x" ] ; then _min_minor=0 fi if [ "x$_min_patch" = "x" ] ; then _min_patch=0 fi if [ "x$_cur_minor" = "x" ] ; then _cur_major=0 fi if [ "x$_cur_minor" = "x" ] ; then _cur_minor=0 fi if [ "x$_cur_patch" = "x" ] ; then _cur_patch=0 fi $VERBOSE_ECHO "Checking if ${_cur_major}.${_cur_minor}.${_cur_patch} is greater than ${_min_major}.${_min_minor}.${_min_patch}" if [ $_min_major -lt $_cur_major ] ; then return 0 elif [ $_min_major -eq $_cur_major ] ; then if [ $_min_minor -lt $_cur_minor ] ; then return 0 elif [ $_min_minor -eq $_cur_minor ] ; then if [ $_min_patch -lt $_cur_patch ] ; then return 0 elif [ $_min_patch -eq $_cur_patch ] ; then return 0 fi fi fi return 1 } ###################################### # LOCATE_CONFIGURE_TEMPLATE FUNCTION # ###################################### locate_configure_template ( ) { _pwd="`pwd`" if test -f "./configure.ac" ; then echo "./configure.ac" elif test -f "./configure.in" ; then echo "./configure.in" elif test -f "$_pwd/configure.ac" ; then echo "$_pwd/configure.ac" elif test -f "$_pwd/configure.in" ; then echo "$_pwd/configure.in" elif test -f "$PATH_TO_AUTOGEN/configure.ac" ; then echo "$PATH_TO_AUTOGEN/configure.ac" elif test -f "$PATH_TO_AUTOGEN/configure.in" ; then echo "$PATH_TO_AUTOGEN/configure.in" fi } ################## # argument check # ################## ARGS="$*" PATH_TO_AUTOGEN="`dirname $0`" NAME_OF_AUTOGEN="`basename $0`" AUTOGEN_SH="$PATH_TO_AUTOGEN/$NAME_OF_AUTOGEN" LIBTOOL_M4="${PATH_TO_AUTOGEN}/misc/libtool.m4" if [ "x$HELP" = "x" ] ; then HELP=no fi if [ "x$QUIET" = "x" ] ; then QUIET=no fi if [ "x$VERBOSE" = "x" ] ; then VERBOSE=no fi if [ "x$VERSION_ONLY" = "x" ] ; then VERSION_ONLY=no fi if [ "x$DOWNLOAD" = "x" ] ; then DOWNLOAD=no fi if [ "x$AUTORECONF_OPTIONS" = "x" ] ; then AUTORECONF_OPTIONS="-i -f" fi if [ "x$AUTOCONF_OPTIONS" = "x" ] ; then AUTOCONF_OPTIONS="-f" fi if [ "x$AUTOMAKE_OPTIONS" = "x" ] ; then AUTOMAKE_OPTIONS="-a -c -f" fi ALT_AUTOMAKE_OPTIONS="-a -c" if [ "x$LIBTOOLIZE_OPTIONS" = "x" ] ; then LIBTOOLIZE_OPTIONS="--automake -c -f" fi ALT_LIBTOOLIZE_OPTIONS="--automake --copy --force" if [ "x$ACLOCAL_OPTIONS" = "x" ] ; then ACLOCAL_OPTIONS="" fi if [ "x$AUTOHEADER_OPTIONS" = "x" ] ; then AUTOHEADER_OPTIONS="" fi if [ "x$CONFIG_GUESS_URL" = "x" ] ; then CONFIG_GUESS_URL="http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob_plain;f=build-aux/config.guess;hb=HEAD" fi for arg in $ARGS ; do case "x$arg" in x--help) HELP=yes ;; x-[hH]) HELP=yes ;; x--quiet) QUIET=yes ;; x-[qQ]) QUIET=yes ;; x--verbose) VERBOSE=yes ;; x-[dD]) DOWNLOAD=yes ;; x--download) DOWNLOAD=yes ;; x-[vV]) VERBOSE=yes ;; x--version) VERSION_ONLY=yes ;; *) echo "Unknown option: $arg" echo usage exit 1 ;; esac done ##################### # environment check # ##################### # sanity check before recursions potentially begin if [ ! -f "$AUTOGEN_SH" ] ; then echo "INTERNAL ERROR: $AUTOGEN_SH does not exist" if [ ! "x$0" = "x$AUTOGEN_SH" ] ; then echo "INTERNAL ERROR: dirname/basename inconsistency: $0 != $AUTOGEN_SH" fi exit 1 fi # force locale setting to C so things like date output as expected LC_ALL=C # commands that this script expects for __cmd in echo head tail pwd ; do echo "test" | $__cmd > /dev/null 2>&1 if [ $? != 0 ] ; then echo "INTERNAL ERROR: '${__cmd}' command is required" exit 2 fi done echo "test" | grep "test" > /dev/null 2>&1 if test ! x$? = x0 ; then echo "INTERNAL ERROR: grep command is required" exit 1 fi echo "test" | sed "s/test/test/" > /dev/null 2>&1 if test ! x$? = x0 ; then echo "INTERNAL ERROR: sed command is required" exit 1 fi # determine the behavior of echo case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac # determine the behavior of head case "x`echo 'head' | head -n 1 2>&1`" in *xhead*) HEAD_N="n " ;; *) HEAD_N="" ;; esac # determine the behavior of tail case "x`echo 'tail' | tail -n 1 2>&1`" in *xtail*) TAIL_N="n " ;; *) TAIL_N="" ;; esac VERBOSE_ECHO=: ECHO=: if [ "x$QUIET" = "xyes" ] ; then if [ "x$VERBOSE" = "xyes" ] ; then echo "Verbose output quelled by quiet option. Further output disabled." fi else ECHO=echo if [ "x$VERBOSE" = "xyes" ] ; then echo "Verbose output enabled" VERBOSE_ECHO=echo fi fi # allow a recursive run to disable further recursions if [ "x$RUN_RECURSIVE" = "x" ] ; then RUN_RECURSIVE=yes fi ################################################ # check for help arg and bypass version checks # ################################################ if [ "x`echo $ARGS | sed 's/.*[hH][eE][lL][pP].*/help/'`" = "xhelp" ] ; then HELP=yes fi if [ "x$HELP" = "xyes" ] ; then usage $ECHO "---" $ECHO "Help was requested. No preparation or configuration will be performed." exit 0 fi ####################### # set up signal traps # ####################### untrap_abnormal ( ) { for sig in 1 2 13 15; do trap - $sig done } # do this cleanup whenever we exit. trap ' # start from the root if test -d "$START_PATH" ; then cd "$START_PATH" fi # restore/delete backup files if test "x$PFC_INIT" = "x1" ; then recursive_restore fi ' 0 # trap SIGHUP (1), SIGINT (2), SIGPIPE (13), SIGTERM (15) for sig in 1 2 13 15; do trap ' $ECHO "" $ECHO "Aborting $NAME_OF_AUTOGEN: caught signal '$sig'" # start from the root if test -d "$START_PATH" ; then cd "$START_PATH" fi # clean up on abnormal exit $VERBOSE_ECHO "rm -rf autom4te.cache" rm -rf autom4te.cache if test -f "acinclude.m4.$$.backup" ; then $VERBOSE_ECHO "cat acinclude.m4.$$.backup > acinclude.m4" chmod u+w acinclude.m4 cat acinclude.m4.$$.backup > acinclude.m4 $VERBOSE_ECHO "rm -f acinclude.m4.$$.backup" rm -f acinclude.m4.$$.backup fi { (exit 1); exit 1; } ' $sig done ############################# # look for a configure file # ############################# if [ "x$CONFIGURE" = "x" ] ; then CONFIGURE="`locate_configure_template`" if [ ! "x$CONFIGURE" = "x" ] ; then $VERBOSE_ECHO "Found a configure template: $CONFIGURE" fi else $ECHO "Using CONFIGURE environment variable override: $CONFIGURE" fi if [ "x$CONFIGURE" = "x" ] ; then if [ "x$VERSION_ONLY" = "xyes" ] ; then CONFIGURE=/dev/null else $ECHO $ECHO "A configure.ac or configure.in file could not be located implying" $ECHO "that the GNU Build System is at least not used in this directory. In" $ECHO "any case, there is nothing to do here without one of those files." $ECHO $ECHO "ERROR: No configure.in or configure.ac file found in `pwd`" exit 1 fi fi #################### # get project name # #################### if [ "x$PROJECT" = "x" ] ; then PROJECT="`grep AC_INIT $CONFIGURE | grep -v '.*#.*AC_INIT' | tail -${TAIL_N}1 | sed 's/^[ ]*AC_INIT(\([^,)]*\).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" if [ "x$PROJECT" = "xAC_INIT" ] ; then # projects might be using the older/deprecated arg-less AC_INIT .. look for AM_INIT_AUTOMAKE instead PROJECT="`grep AM_INIT_AUTOMAKE $CONFIGURE | grep -v '.*#.*AM_INIT_AUTOMAKE' | tail -${TAIL_N}1 | sed 's/^[ ]*AM_INIT_AUTOMAKE(\([^,)]*\).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" fi if [ "x$PROJECT" = "xAM_INIT_AUTOMAKE" ] ; then PROJECT="project" fi if [ "x$PROJECT" = "x" ] ; then PROJECT="project" fi else $ECHO "Using PROJECT environment variable override: $PROJECT" fi $ECHO "Preparing the $PROJECT build system...please wait" $ECHO ######################## # check for autoreconf # ######################## HAVE_AUTORECONF=no if [ "x$AUTORECONF" = "x" ] ; then for AUTORECONF in autoreconf ; do $VERBOSE_ECHO "Checking autoreconf version: $AUTORECONF --version" $AUTORECONF --version > /dev/null 2>&1 if [ $? = 0 ] ; then HAVE_AUTORECONF=yes break fi done else HAVE_AUTORECONF=yes $ECHO "Using AUTORECONF environment variable override: $AUTORECONF" fi ########################## # autoconf version check # ########################## _acfound=no if [ "x$AUTOCONF" = "x" ] ; then for AUTOCONF in autoconf ; do $VERBOSE_ECHO "Checking autoconf version: $AUTOCONF --version" $AUTOCONF --version > /dev/null 2>&1 if [ $? = 0 ] ; then _acfound=yes break fi done else _acfound=yes $ECHO "Using AUTOCONF environment variable override: $AUTOCONF" fi _report_error=no if [ ! "x$_acfound" = "xyes" ] ; then $ECHO "ERROR: Unable to locate GNU Autoconf." _report_error=yes else _version="`$AUTOCONF --version | head -${HEAD_N}1 | sed 's/[^0-9]*\([0-9\.][0-9\.]*\)/\1/'`" if [ "x$_version" = "x" ] ; then _version="0.0.0" fi $ECHO "Found GNU Autoconf version $_version" version_check "$AUTOCONF_VERSION" "$_version" if [ $? -ne 0 ] ; then _report_error=yes fi fi if [ "x$_report_error" = "xyes" ] ; then version_error "$AUTOCONF_VERSION" "GNU Autoconf" exit 1 fi ########################## # automake version check # ########################## _amfound=no if [ "x$AUTOMAKE" = "x" ] ; then for AUTOMAKE in automake ; do $VERBOSE_ECHO "Checking automake version: $AUTOMAKE --version" $AUTOMAKE --version > /dev/null 2>&1 if [ $? = 0 ] ; then _amfound=yes break fi done else _amfound=yes $ECHO "Using AUTOMAKE environment variable override: $AUTOMAKE" fi _report_error=no if [ ! "x$_amfound" = "xyes" ] ; then $ECHO $ECHO "ERROR: Unable to locate GNU Automake." _report_error=yes else _version="`$AUTOMAKE --version | head -${HEAD_N}1 | sed 's/[^0-9]*\([0-9\.][0-9\.]*\)/\1/'`" if [ "x$_version" = "x" ] ; then _version="0.0.0" fi $ECHO "Found GNU Automake version $_version" version_check "$AUTOMAKE_VERSION" "$_version" if [ $? -ne 0 ] ; then _report_error=yes fi fi if [ "x$_report_error" = "xyes" ] ; then version_error "$AUTOMAKE_VERSION" "GNU Automake" exit 1 fi ######################## # check for libtoolize # ######################## HAVE_LIBTOOLIZE=yes HAVE_ALT_LIBTOOLIZE=no _ltfound=no if [ "x$LIBTOOLIZE" = "x" ] ; then LIBTOOLIZE=libtoolize $VERBOSE_ECHO "Checking libtoolize version: $LIBTOOLIZE --version" $LIBTOOLIZE --version > /dev/null 2>&1 if [ ! $? = 0 ] ; then HAVE_LIBTOOLIZE=no $ECHO if [ "x$HAVE_AUTORECONF" = "xno" ] ; then $ECHO "Warning: libtoolize does not appear to be available." else $ECHO "Warning: libtoolize does not appear to be available. This means that" $ECHO "the automatic build preparation via autoreconf will probably not work." $ECHO "Preparing the build by running each step individually, however, should" $ECHO "work and will be done automatically for you if autoreconf fails." fi # look for some alternates for tool in glibtoolize libtoolize15 libtoolize14 libtoolize13 ; do $VERBOSE_ECHO "Checking libtoolize alternate: $tool --version" _glibtoolize="`$tool --version > /dev/null 2>&1`" if [ $? = 0 ] ; then $VERBOSE_ECHO "Found $tool --version" _glti="`which $tool`" if [ "x$_glti" = "x" ] ; then $VERBOSE_ECHO "Cannot find $tool with which" continue; fi if test ! -f "$_glti" ; then $VERBOSE_ECHO "Cannot use $tool, $_glti is not a file" continue; fi _gltidir="`dirname $_glti`" if [ "x$_gltidir" = "x" ] ; then $VERBOSE_ECHO "Cannot find $tool path with dirname of $_glti" continue; fi if test ! -d "$_gltidir" ; then $VERBOSE_ECHO "Cannot use $tool, $_gltidir is not a directory" continue; fi HAVE_ALT_LIBTOOLIZE=yes LIBTOOLIZE="$tool" $ECHO $ECHO "Fortunately, $tool was found which means that your system may simply" $ECHO "have a non-standard or incomplete GNU Autotools install. If you have" $ECHO "sufficient system access, it may be possible to quell this warning by" $ECHO "running:" $ECHO sudo -V > /dev/null 2>&1 if [ $? = 0 ] ; then $ECHO " sudo ln -s $_glti $_gltidir/libtoolize" $ECHO else $ECHO " ln -s $_glti $_gltidir/libtoolize" $ECHO $ECHO "Run that as root or with proper permissions to the $_gltidir directory" $ECHO fi _ltfound=yes break fi done else _ltfound=yes fi else _ltfound=yes $ECHO "Using LIBTOOLIZE environment variable override: $LIBTOOLIZE" fi ############################ # libtoolize version check # ############################ _report_error=no if [ ! "x$_ltfound" = "xyes" ] ; then $ECHO $ECHO "ERROR: Unable to locate GNU Libtool." _report_error=yes else _version="`$LIBTOOLIZE --version | head -${HEAD_N}1 | sed 's/[^0-9]*\([0-9\.][0-9\.]*\)/\1/'`" if [ "x$_version" = "x" ] ; then _version="0.0.0" fi $ECHO "Found GNU Libtool version $_version" version_check "$LIBTOOL_VERSION" "$_version" if [ $? -ne 0 ] ; then _report_error=yes fi fi if [ "x$_report_error" = "xyes" ] ; then version_error "$LIBTOOL_VERSION" "GNU Libtool" exit 1 fi ##################### # check for aclocal # ##################### if [ "x$ACLOCAL" = "x" ] ; then for ACLOCAL in aclocal ; do $VERBOSE_ECHO "Checking aclocal version: $ACLOCAL --version" $ACLOCAL --version > /dev/null 2>&1 if [ $? = 0 ] ; then break fi done else $ECHO "Using ACLOCAL environment variable override: $ACLOCAL" fi ######################## # check for autoheader # ######################## if [ "x$AUTOHEADER" = "x" ] ; then for AUTOHEADER in autoheader ; do $VERBOSE_ECHO "Checking autoheader version: $AUTOHEADER --version" $AUTOHEADER --version > /dev/null 2>&1 if [ $? = 0 ] ; then break fi done else $ECHO "Using AUTOHEADER environment variable override: $AUTOHEADER" fi ######################### # check if version only # ######################### $VERBOSE_ECHO "Checking whether to only output version information" if [ "x$VERSION_ONLY" = "xyes" ] ; then $ECHO ident $ECHO "---" $ECHO "Version requested. No preparation or configuration will be performed." exit 0 fi ################################# # PROTECT_FROM_CLOBBER FUNCTION # ################################# protect_from_clobber ( ) { PFC_INIT=1 # protect COPYING & INSTALL from overwrite by automake. the # automake force option will (inappropriately) ignore the existing # contents of a COPYING and/or INSTALL files (depending on the # version) instead of just forcing *missing* files like it does # for AUTHORS, NEWS, and README. this is broken but extremely # prevalent behavior, so we protect against it by keeping a backup # of the file that can later be restored. for file in COPYING INSTALL ; do if test -f ${file} ; then if test -f ${file}.$$.protect_from_automake.backup ; then $VERBOSE_ECHO "Already backed up ${file} in `pwd`" else $VERBOSE_ECHO "Backing up ${file} in `pwd`" $VERBOSE_ECHO "cp -p ${file} ${file}.$$.protect_from_automake.backup" cp -p ${file} ${file}.$$.protect_from_automake.backup fi fi done } ############################## # RECURSIVE_PROTECT FUNCTION # ############################## recursive_protect ( ) { # for projects using recursive configure, run the build # preparation steps for the subdirectories. this function assumes # START_PATH was set to pwd before recursion begins so that # relative paths work. # git 'r done, protect COPYING and INSTALL from being clobbered protect_from_clobber if test -d autom4te.cache ; then $VERBOSE_ECHO "Found an autom4te.cache directory, deleting it" $VERBOSE_ECHO "rm -rf autom4te.cache" rm -rf autom4te.cache fi # find configure template _configure="`locate_configure_template`" if [ "x$_configure" = "x" ] ; then return fi # $VERBOSE_ECHO "Looking for configure template found `pwd`/$_configure" # look for subdirs # $VERBOSE_ECHO "Looking for subdirs in `pwd`" _det_config_subdirs="`grep AC_CONFIG_SUBDIRS $_configure | grep -v '.*#.*AC_CONFIG_SUBDIRS' | sed 's/^[ ]*AC_CONFIG_SUBDIRS(\(.*\)).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" CHECK_DIRS="" for dir in $_det_config_subdirs ; do if test -d "`pwd`/$dir" ; then CHECK_DIRS="$CHECK_DIRS \"`pwd`/$dir\"" fi done # process subdirs if [ ! "x$CHECK_DIRS" = "x" ] ; then $VERBOSE_ECHO "Recursively scanning the following directories:" $VERBOSE_ECHO " $CHECK_DIRS" for dir in $CHECK_DIRS ; do $VERBOSE_ECHO "Protecting files from automake in $dir" cd "$START_PATH" eval "cd $dir" # recursively git 'r done recursive_protect done fi } # end of recursive_protect ############################# # RESTORE_CLOBBERED FUNCION # ############################# restore_clobbered ( ) { # The automake (and autoreconf by extension) -f/--force-missing # option may overwrite COPYING and INSTALL even if they do exist. # Here we restore the files if necessary. spacer=no for file in COPYING INSTALL ; do if test -f ${file}.$$.protect_from_automake.backup ; then if test -f ${file} ; then # compare entire content, restore if needed if test "x`cat ${file}`" != "x`cat ${file}.$$.protect_from_automake.backup`" ; then if test "x$spacer" = "xno" ; then $VERBOSE_ECHO spacer=yes fi # restore the backup $VERBOSE_ECHO "Restoring ${file} from backup (automake -f likely clobbered it)" $VERBOSE_ECHO "rm -f ${file}" rm -f ${file} $VERBOSE_ECHO "mv ${file}.$$.protect_from_automake.backup ${file}" mv ${file}.$$.protect_from_automake.backup ${file} fi # check contents elif test -f ${file}.$$.protect_from_automake.backup ; then $VERBOSE_ECHO "mv ${file}.$$.protect_from_automake.backup ${file}" mv ${file}.$$.protect_from_automake.backup ${file} fi # -f ${file} # just in case $VERBOSE_ECHO "rm -f ${file}.$$.protect_from_automake.backup" rm -f ${file}.$$.protect_from_automake.backup fi # -f ${file}.$$.protect_from_automake.backup done CONFIGURE="`locate_configure_template`" if [ "x$CONFIGURE" = "x" ] ; then return fi _aux_dir="`grep AC_CONFIG_AUX_DIR $CONFIGURE | grep -v '.*#.*AC_CONFIG_AUX_DIR' | tail -${TAIL_N}1 | sed 's/^[ ]*AC_CONFIG_AUX_DIR(\(.*\)).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" if test ! -d "$_aux_dir" ; then _aux_dir=. fi for file in config.guess config.sub ltmain.sh ; do if test -f "${_aux_dir}/${file}" ; then $VERBOSE_ECHO "rm -f \"${_aux_dir}/${file}.backup\"" rm -f "${_aux_dir}/${file}.backup" fi done } # end of restore_clobbered ############################## # RECURSIVE_RESTORE FUNCTION # ############################## recursive_restore ( ) { # restore COPYING and INSTALL from backup if they were clobbered # for each directory recursively. # git 'r undone restore_clobbered # find configure template _configure="`locate_configure_template`" if [ "x$_configure" = "x" ] ; then return fi # look for subdirs _det_config_subdirs="`grep AC_CONFIG_SUBDIRS $_configure | grep -v '.*#.*AC_CONFIG_SUBDIRS' | sed 's/^[ ]*AC_CONFIG_SUBDIRS(\(.*\)).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" CHECK_DIRS="" for dir in $_det_config_subdirs ; do if test -d "`pwd`/$dir" ; then CHECK_DIRS="$CHECK_DIRS \"`pwd`/$dir\"" fi done # process subdirs if [ ! "x$CHECK_DIRS" = "x" ] ; then $VERBOSE_ECHO "Recursively scanning the following directories:" $VERBOSE_ECHO " $CHECK_DIRS" for dir in $CHECK_DIRS ; do $VERBOSE_ECHO "Checking files for automake damage in $dir" cd "$START_PATH" eval "cd $dir" # recursively git 'r undone recursive_restore done fi } # end of recursive_restore ####################### # INITIALIZE FUNCTION # ####################### initialize ( ) { # this routine performs a variety of directory-specific # initializations. some are sanity checks, some are preventive, # and some are necessary setup detection. # # this function sets: # CONFIGURE # SEARCH_DIRS # CONFIG_SUBDIRS ################################## # check for a configure template # ################################## CONFIGURE="`locate_configure_template`" if [ "x$CONFIGURE" = "x" ] ; then $ECHO $ECHO "A configure.ac or configure.in file could not be located implying" $ECHO "that the GNU Build System is at least not used in this directory. In" $ECHO "any case, there is nothing to do here without one of those files." $ECHO $ECHO "ERROR: No configure.in or configure.ac file found in `pwd`" exit 1 fi ##################### # detect an aux dir # ##################### _aux_dir="`grep AC_CONFIG_AUX_DIR $CONFIGURE | grep -v '.*#.*AC_CONFIG_AUX_DIR' | tail -${TAIL_N}1 | sed 's/^[ ]*AC_CONFIG_AUX_DIR(\(.*\)).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" if test ! -d "$_aux_dir" ; then _aux_dir=. else $VERBOSE_ECHO "Detected auxillary directory: $_aux_dir" fi ################################ # detect a recursive configure # ################################ CONFIG_SUBDIRS="" _det_config_subdirs="`grep AC_CONFIG_SUBDIRS $CONFIGURE | grep -v '.*#.*AC_CONFIG_SUBDIRS' | sed 's/^[ ]*AC_CONFIG_SUBDIRS(\(.*\)).*/\1/' | sed 's/.*\[\(.*\)\].*/\1/'`" for dir in $_det_config_subdirs ; do if test -d "`pwd`/$dir" ; then $VERBOSE_ECHO "Detected recursive configure directory: `pwd`/$dir" CONFIG_SUBDIRS="$CONFIG_SUBDIRS `pwd`/$dir" fi done ########################################################### # make sure certain required files exist for GNU projects # ########################################################### _marker_found="" _marker_found_message_intro='Detected non-GNU marker "' _marker_found_message_mid='" in ' for marker in foreign cygnus ; do _marker_found_message=${_marker_found_message_intro}${marker}${_marker_found_message_mid} _marker_found="`grep 'AM_INIT_AUTOMAKE.*'${marker} $CONFIGURE`" if [ ! "x$_marker_found" = "x" ] ; then $VERBOSE_ECHO "${_marker_found_message}`basename \"$CONFIGURE\"`" break fi if test -f "`dirname \"$CONFIGURE\"/Makefile.am`" ; then _marker_found="`grep 'AUTOMAKE_OPTIONS.*'${marker} Makefile.am`" if [ ! "x$_marker_found" = "x" ] ; then $VERBOSE_ECHO "${_marker_found_message}Makefile.am" break fi fi done if [ "x${_marker_found}" = "x" ] ; then _suggest_foreign=no for file in AUTHORS COPYING ChangeLog INSTALL NEWS README ; do if [ ! -f $file ] ; then $VERBOSE_ECHO "Touching ${file} since it does not exist" _suggest_foreign=yes touch $file fi done if [ "x${_suggest_foreign}" = "xyes" ] ; then $ECHO $ECHO "Warning: Several files expected of projects that conform to the GNU" $ECHO "coding standards were not found. The files were automatically added" $ECHO "for you since you do not have a 'foreign' declaration specified." $ECHO $ECHO "Considered adding 'foreign' to AM_INIT_AUTOMAKE in `basename \"$CONFIGURE\"`" if test -f "`dirname \"$CONFIGURE\"/Makefile.am`" ; then $ECHO "or to AUTOMAKE_OPTIONS in your top-level Makefile.am file." fi $ECHO fi fi ################################################## # make sure certain generated files do not exist # ################################################## for file in config.guess config.sub ltmain.sh ; do if test -f "${_aux_dir}/${file}" ; then $VERBOSE_ECHO "mv -f \"${_aux_dir}/${file}\" \"${_aux_dir}/${file}.backup\"" mv -f "${_aux_dir}/${file}" "${_aux_dir}/${file}.backup" fi done ############################ # search alternate m4 dirs # ############################ SEARCH_DIRS="" for dir in m4 ; do if [ -d $dir ] ; then $VERBOSE_ECHO "Found extra aclocal search directory: $dir" SEARCH_DIRS="$SEARCH_DIRS -I $dir" fi done ###################################### # remove any previous build products # ###################################### if test -d autom4te.cache ; then $VERBOSE_ECHO "Found an autom4te.cache directory, deleting it" $VERBOSE_ECHO "rm -rf autom4te.cache" rm -rf autom4te.cache fi # tcl/tk (and probably others) have a customized aclocal.m4, so can't delete it # if test -f aclocal.m4 ; then # $VERBOSE_ECHO "Found an aclocal.m4 file, deleting it" # $VERBOSE_ECHO "rm -f aclocal.m4" # rm -f aclocal.m4 # fi } # end of initialize() ############## # initialize # ############## # stash path START_PATH="`pwd`" # Before running autoreconf or manual steps, some prep detection work # is necessary or useful. Only needs to occur once per directory, but # does need to traverse the entire subconfigure hierarchy to protect # files from being clobbered even by autoreconf. recursive_protect # start from where we started cd "$START_PATH" # get ready to process initialize ######################################### # DOWNLOAD_GNULIB_CONFIG_GUESS FUNCTION # ######################################### # TODO - should make sure wget/curl exist and/or work before trying to # use them. download_gnulib_config_guess () { # abuse gitweb to download gnulib's latest config.guess via HTTP config_guess_temp="config.guess.$$.download" ret=1 for __cmd in wget curl fetch ; do $VERBOSE_ECHO "Checking for command ${__cmd}" ${__cmd} --version > /dev/null 2>&1 ret=$? if [ ! $ret = 0 ] ; then continue fi __cmd_version=`${__cmd} --version | head -n 1 | sed -e 's/^[^0-9]\+//' -e 's/ .*//'` $VERBOSE_ECHO "Found ${__cmd} ${__cmd_version}" opts="" case ${__cmd} in wget) opts="-O" ;; curl) opts="-o" ;; fetch) opts="-t 5 -f" ;; esac $VERBOSE_ECHO "Running $__cmd \"${CONFIG_GUESS_URL}\" $opts \"${config_guess_temp}\"" eval "$__cmd \"${CONFIG_GUESS_URL}\" $opts \"${config_guess_temp}\"" > /dev/null 2>&1 if [ $? = 0 ] ; then mv -f "${config_guess_temp}" ${_aux_dir}/config.guess ret=0 break fi done if [ ! $ret = 0 ] ; then $ECHO "Warning: config.guess download failed from: $CONFIG_GUESS_URL" rm -f "${config_guess_temp}" fi } ############################## # LIBTOOLIZE_NEEDED FUNCTION # ############################## libtoolize_needed () { ret=1 # means no, don't need libtoolize for feature in AC_PROG_LIBTOOL AM_PROG_LIBTOOL LT_INIT ; do $VERBOSE_ECHO "Searching for $feature in $CONFIGURE" found="`grep \"^$feature.*\" $CONFIGURE`" if [ ! "x$found" = "x" ] ; then ret=0 # means yes, need to run libtoolize break fi done return ${ret} } ############################################ # prepare build via autoreconf or manually # ############################################ reconfigure_manually=no if [ "x$HAVE_AUTORECONF" = "xyes" ] ; then $ECHO $ECHO $ECHO_N "Automatically preparing build ... $ECHO_C" $VERBOSE_ECHO "$AUTORECONF $SEARCH_DIRS $AUTORECONF_OPTIONS" autoreconf_output="`$AUTORECONF $SEARCH_DIRS $AUTORECONF_OPTIONS 2>&1`" ret=$? $VERBOSE_ECHO "$autoreconf_output" if [ ! $ret = 0 ] ; then if [ "x$HAVE_ALT_LIBTOOLIZE" = "xyes" ] ; then if [ ! "x`echo \"$autoreconf_output\" | grep libtoolize | grep \"No such file or directory\"`" = "x" ] ; then $ECHO $ECHO "Warning: autoreconf failed but due to what is usually a common libtool" $ECHO "misconfiguration issue. This problem is encountered on systems that" $ECHO "have installed libtoolize under a different name without providing a" $ECHO "symbolic link or without setting the LIBTOOLIZE environment variable." $ECHO $ECHO "Restarting the preparation steps with LIBTOOLIZE set to $LIBTOOLIZE" export LIBTOOLIZE RUN_RECURSIVE=no export RUN_RECURSIVE untrap_abnormal $VERBOSE_ECHO sh $AUTOGEN_SH "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" sh "$AUTOGEN_SH" "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" exit $? fi fi $ECHO "Warning: $AUTORECONF failed" if test -f ltmain.sh ; then $ECHO "libtoolize being run by autoreconf is not creating ltmain.sh in the auxillary directory like it should" fi $ECHO "Attempting to run the preparation steps individually" reconfigure_manually=yes else if [ "x$DOWNLOAD" = "xyes" ] ; then if libtoolize_needed ; then download_gnulib_config_guess fi fi fi else reconfigure_manually=yes fi ############################ # LIBTOOL_FAILURE FUNCTION # ############################ libtool_failure ( ) { # libtool is rather error-prone in comparison to the other # autotools and this routine attempts to compensate for some # common failures. the output after a libtoolize failure is # parsed for an error related to AC_PROG_LIBTOOL and if found, we # attempt to inject a project-provided libtool.m4 file. _autoconf_output="$1" if [ "x$RUN_RECURSIVE" = "xno" ] ; then # we already tried the libtool.m4, don't try again return 1 fi if test -f "$LIBTOOL_M4" ; then found_libtool="`$ECHO $_autoconf_output | grep AC_PROG_LIBTOOL`" if test ! "x$found_libtool" = "x" ; then if test -f acinclude.m4 ; then rm -f acinclude.m4.$$.backup $VERBOSE_ECHO "cat acinclude.m4 > acinclude.m4.$$.backup" cat acinclude.m4 > acinclude.m4.$$.backup fi $VERBOSE_ECHO "cat \"$LIBTOOL_M4\" >> acinclude.m4" chmod u+w acinclude.m4 cat "$LIBTOOL_M4" >> acinclude.m4 # don't keep doing this RUN_RECURSIVE=no export RUN_RECURSIVE untrap_abnormal $ECHO $ECHO "Restarting the preparation steps with libtool macros in acinclude.m4" $VERBOSE_ECHO sh $AUTOGEN_SH "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" sh "$AUTOGEN_SH" "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" exit $? fi fi } ########################### # MANUAL_AUTOGEN FUNCTION # ########################### manual_autogen ( ) { ################################################## # Manual preparation steps taken are as follows: # # aclocal [-I m4] # # libtoolize --automake -c -f # # aclocal [-I m4] # # autoconf -f # # autoheader # # automake -a -c -f # ################################################## ########### # aclocal # ########### $VERBOSE_ECHO "$ACLOCAL $SEARCH_DIRS $ACLOCAL_OPTIONS" aclocal_output="`$ACLOCAL $SEARCH_DIRS $ACLOCAL_OPTIONS 2>&1`" ret=$? $VERBOSE_ECHO "$aclocal_output" if [ ! $ret = 0 ] ; then $ECHO "ERROR: $ACLOCAL failed" && exit 2 ; fi ############## # libtoolize # ############## if libtoolize_needed ; then if [ "x$HAVE_LIBTOOLIZE" = "xyes" ] ; then $VERBOSE_ECHO "$LIBTOOLIZE $LIBTOOLIZE_OPTIONS" libtoolize_output="`$LIBTOOLIZE $LIBTOOLIZE_OPTIONS 2>&1`" ret=$? $VERBOSE_ECHO "$libtoolize_output" if [ ! $ret = 0 ] ; then $ECHO "ERROR: $LIBTOOLIZE failed" && exit 2 ; fi else if [ "x$HAVE_ALT_LIBTOOLIZE" = "xyes" ] ; then $VERBOSE_ECHO "$LIBTOOLIZE $ALT_LIBTOOLIZE_OPTIONS" libtoolize_output="`$LIBTOOLIZE $ALT_LIBTOOLIZE_OPTIONS 2>&1`" ret=$? $VERBOSE_ECHO "$libtoolize_output" if [ ! $ret = 0 ] ; then $ECHO "ERROR: $LIBTOOLIZE failed" && exit 2 ; fi fi fi ########### # aclocal # ########### # re-run again as instructed by libtoolize $VERBOSE_ECHO "$ACLOCAL $SEARCH_DIRS $ACLOCAL_OPTIONS" aclocal_output="`$ACLOCAL $SEARCH_DIRS $ACLOCAL_OPTIONS 2>&1`" ret=$? $VERBOSE_ECHO "$aclocal_output" # libtoolize might put ltmain.sh in the wrong place if test -f ltmain.sh ; then if test ! -f "${_aux_dir}/ltmain.sh" ; then $ECHO $ECHO "Warning: $LIBTOOLIZE is creating ltmain.sh in the wrong directory" $ECHO $ECHO "Fortunately, the problem can be worked around by simply copying the" $ECHO "file to the appropriate location (${_aux_dir}/). This has been done for you." $ECHO $VERBOSE_ECHO "cp -p ltmain.sh \"${_aux_dir}/ltmain.sh\"" cp -p ltmain.sh "${_aux_dir}/ltmain.sh" $ECHO $ECHO_N "Continuing build preparation ... $ECHO_C" fi fi # ltmain.sh if [ "x$DOWNLOAD" = "xyes" ] ; then download_gnulib_config_guess fi fi # libtoolize_needed ############ # autoconf # ############ $VERBOSE_ECHO $VERBOSE_ECHO "$AUTOCONF $AUTOCONF_OPTIONS" autoconf_output="`$AUTOCONF $AUTOCONF_OPTIONS 2>&1`" ret=$? $VERBOSE_ECHO "$autoconf_output" if [ ! $ret = 0 ] ; then # retry without the -f and check for usage of macros that are too new ac2_59_macros="AC_C_RESTRICT AC_INCLUDES_DEFAULT AC_LANG_ASSERT AC_LANG_WERROR AS_SET_CATFILE" ac2_55_macros="AC_COMPILER_IFELSE AC_FUNC_MBRTOWC AC_HEADER_STDBOOL AC_LANG_CONFTEST AC_LANG_SOURCE AC_LANG_PROGRAM AC_LANG_CALL AC_LANG_FUNC_TRY_LINK AC_MSG_FAILURE AC_PREPROC_IFELSE" ac2_54_macros="AC_C_BACKSLASH_A AC_CONFIG_LIBOBJ_DIR AC_GNU_SOURCE AC_PROG_EGREP AC_PROG_FGREP AC_REPLACE_FNMATCH AC_FUNC_FNMATCH_GNU AC_FUNC_REALLOC AC_TYPE_MBSTATE_T" macros_to_search="" ac_major="`echo ${AUTOCONF_VERSION}. | cut -d. -f1 | sed 's/[^0-9]//g'`" ac_minor="`echo ${AUTOCONF_VERSION}. | cut -d. -f2 | sed 's/[^0-9]//g'`" if [ $ac_major -lt 2 ] ; then macros_to_search="$ac2_59_macros $ac2_55_macros $ac2_54_macros" else if [ $ac_minor -lt 54 ] ; then macros_to_search="$ac2_59_macros $ac2_55_macros $ac2_54_macros" elif [ $ac_minor -lt 55 ] ; then macros_to_search="$ac2_59_macros $ac2_55_macros" elif [ $ac_minor -lt 59 ] ; then macros_to_search="$ac2_59_macros" fi fi configure_ac_macros=__none__ for feature in $macros_to_search ; do $VERBOSE_ECHO "Searching for $feature in $CONFIGURE" found="`grep \"^$feature.*\" $CONFIGURE`" if [ ! "x$found" = "x" ] ; then if [ "x$configure_ac_macros" = "x__none__" ] ; then configure_ac_macros="$feature" else configure_ac_macros="$feature $configure_ac_macros" fi fi done if [ ! "x$configure_ac_macros" = "x__none__" ] ; then $ECHO $ECHO "Warning: Unsupported macros were found in $CONFIGURE" $ECHO $ECHO "The `basename \"$CONFIGURE\"` file was scanned in order to determine if any" $ECHO "unsupported macros are used that exceed the minimum version" $ECHO "settings specified within this file. As such, the following macros" $ECHO "should be removed from configure.ac or the version numbers in this" $ECHO "file should be increased:" $ECHO $ECHO "$configure_ac_macros" $ECHO $ECHO $ECHO_N "Ignorantly continuing build preparation ... $ECHO_C" fi ################### # autoconf, retry # ################### $VERBOSE_ECHO $VERBOSE_ECHO "$AUTOCONF" autoconf_output="`$AUTOCONF 2>&1`" ret=$? $VERBOSE_ECHO "$autoconf_output" if [ ! $ret = 0 ] ; then # test if libtool is busted libtool_failure "$autoconf_output" # let the user know what went wrong cat <. # # Last modified: 27/01/2021 # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # First, disable the annoying config.cache define([AC_CACHE_LOAD],) define([AC_CACHE_SAVE],) # This is your standard Bertin source code... AC_INIT(SWarp, 2.41.5, [astromatic@astromatic.net], swarp, [http://astromatic.net/software/swarp]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR(autoconf) AC_CONFIG_SRCDIR(src/makeit.c) AC_CONFIG_HEADERS(config.h) AM_INIT_AUTOMAKE date=`date +%Y-%m-%d` date1=`date -R` date2=`date +"%a %b %d %Y"` date3=`date +"%B %Y"` AC_DEFINE_UNQUOTED(DATE, "$date", [Archive creation date]) AC_SUBST(PACKAGER, "AstrOmatic") AC_SUBST(DATE1, "$date1") AC_SUBST(DATE2, "$date2") AC_SUBST(DATE3, "$date3") # Include macros sinclude(acx_cfitsio.m4) sinclude(acx_prog_cc_optim.m4) sinclude(acx_pthread.m4) sinclude(acx_urbi_resolve_dir.m4) # Provide a special option for setting the package release number AC_ARG_WITH(release, [AS_HELP_STRING([--with-release=], [set the package release number (default = 1)])], [], [with_release="no"]) if test "$with_release" = "no"; then with_release=1 fi AC_SUBST(PACKAGE_RELEASE, "$with_release") # Display pakage and version number AC_MSG_RESULT([******** Configuring: $PACKAGE_NAME $PACKAGE_VERSION - $PACKAGE_RELEASE ($date) ********]) # Provide special option for choosing automatically the compilation flags. AC_MSG_CHECKING([if compilation flags are set automatically]) AC_ARG_ENABLE(auto-flags, [AS_HELP_STRING([--enable-auto-flags], [Let the configure script choose the compilation flags (default = no)])], AC_MSG_RESULT([yes]), AC_MSG_RESULT([no])) # Provide special option for the Linux Intel C compiler AC_MSG_CHECKING([whether the INTEL compiler is enabled]) AC_ARG_ENABLE(icc, [AS_HELP_STRING([--enable-icc], [Use the Intel compiler (default = no)])], CC="icc" AC_MSG_RESULT([yes]), AC_MSG_RESULT([no])) # Checks for programs. AC_LANG(C) AC_SEARCH_LIBS([strerror],[cposix]) if test "$enable_auto_flags" = "yes"; then CFLAGS="" LDFLAGS="" ACX_PROG_CC_OPTIM fi LT_INIT AC_PROG_INSTALL # Checks for libraries. AC_CHECK_LIB(m, sin) # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(malloc.h unistd.h sys/mman.h) if test "$enable_icc" = "yes"; then AC_CHECK_HEADERS(mathimf.h) fi # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_OFF_T AC_TYPE_SIZE_T AC_TYPE_LONG_LONG_INT AC_TYPE_UNSIGNED_LONG_LONG_INT AC_STRUCT_TM AC_TYPE_UID_T # Checks for library functions. AC_FUNC_ERROR_AT_LINE AC_FUNC_MMAP AC_TYPE_SIGNAL AC_FUNC_STRFTIME AC_CHECK_FUNCS([atexit getenv gethostname memcpy memmove memset mmap strstr \ getrlimit]) AC_CHECK_FUNCS([cosd sind tand acosd asind atand atan2d sincos]) AC_CHECK_FUNC([isnan], AC_DEFINE_UNQUOTED([HAVE_ISNAN2], 1, [Second isnan check])) # Check support for large files AC_SYS_LARGEFILE AC_FUNC_FSEEKO # Provide special options for CFITSIO AC_ARG_WITH(cfitsio, [Link with the CFITSIO library]) AC_ARG_WITH(cfitsio-libdir, [AS_HELP_STRING([--with-cfitsio-libdir=], [Provide an alternative path to the CFITSIO library])]) AC_ARG_WITH(cfitsio-incdir, [AS_HELP_STRING([--with-cfitsio-incdir=], [Provide an alternative path to the CFITSIO include directory])]) # Provide a special option for the default XSLT URL with_xsl_url="file://"$(URBI_RESOLVE_DIR([$datadir]))"/$PACKAGE_TARNAME/$PACKAGE_TARNAME.xsl" AC_ARG_WITH(xsl_url, [AS_HELP_STRING([--with-xsl_url=], [Provide an alternative default URL of the XSLT filter])]) AC_DEFINE_UNQUOTED([XSL_URL], "$with_xsl_url",[Default URL of the XSLT filter]) # Set flags for multithreading n_pthreads=1024 AC_ARG_ENABLE(threads, [AS_HELP_STRING([--enable-threads@<:@=@:>@], [Enable multhreading (on with up to 1024 threads by default)])], if test "$enableval" = "no"; then use_pthreads="no" else use_pthreads="yes" if test "$enableval" != "yes"; then n_pthreads=$enableval fi fi, use_pthreads=yes ) # Provide special option for profiling AC_MSG_CHECKING([for profiler mode]) AC_ARG_ENABLE(profiling, [AS_HELP_STRING([--enable-profiling], [Enable special mode for profiling (default = no)])] AC_MSG_RESULT([yes]), AC_MSG_RESULT([no])) # Enable linking options for making the executable as portable as possible. AC_MSG_CHECKING([best linking option]) AC_ARG_ENABLE(best-link, [AS_HELP_STRING([--enable-best-link], [Choose the right combination of static and dynamic linking to make \ the executable as portable as possible (default = no)])], AC_MSG_RESULT([yes]), AC_MSG_RESULT([no])) ################# Actions to complete in case of multhreading ################ AC_DEFINE_UNQUOTED(THREADS_NMAX, $n_pthreads,[Maximum number of POSIX threads]) if test "$use_pthreads" = "yes"; then AC_MSG_CHECKING([for multithreading]) AC_MSG_RESULT([maximum of $n_pthreads thread(s)]) AC_DEFINE(USE_THREADS, 1, [Triggers multhreading]) # CC, CFLAGS and LIBS are system and compiler-dependent ACX_PTHREAD CC="$PTHREAD_CC" [AM_CFLAGS="$AM_CFLAGS $PTHREAD_CFLAGS -D_REENTRANT"] LIBS="$LIBS $PTHREAD_LIBS" fi AM_CONDITIONAL(USE_THREADS, test $use_pthreads = "yes") ########################## handle the CFITSIO library ######################## if test "$with_cfitsio" != "no"; then ACX_CFITSIO($with_cfitsio_libdir, $with_cfitsio_incdir, [LIBS="$CFITSIO_LIBS $LIBS"] if test "$CFITSIO_WARN" != ""; then AC_MSG_WARN([$CFITSIO_WARN]) fi, AC_MSG_ERROR([$CFITSIO_ERROR Exiting.])) fi # Compile with profiling option if test "$enable_profiling" = "yes"; then if test "$enable_icc" = "yes"; then AM_CFLAGS="$AM_CFLAGS -pq" else AM_CFLAGS="$AM_CFLAGS -pg" fi enable_best_link="no" fi # "Best" linking option if test "$enable_best_link" = "yes"; then if test "$enable_icc" = "yes"; then AM_LDFLAGS="-static-intel -qopenmp-link static -shared-libgcc \ -static-libtool-libs -no-intel-extensions -avoid-version $AM_LDFLAGS" else AM_LDFLAGS="-shared-libgcc -static-libtool-libs -avoid-version $AM_LDFLAGS" fi fi AC_SUBST(AM_CFLAGS) AC_SUBST(AM_CPPFLAGS) AC_SUBST(AM_LDFLAGS) # Display compiler and linker flags AC_MSG_RESULT([***************************************************************]) AC_MSG_RESULT([Compile cmdline: $CC $AM_CPPFLAGS $CPPFLAGS $AM_CFLAGS $CFLAGS]) AC_MSG_RESULT([Link cmdline: $CC $AM_LDFLAGS $LDFLAGS $LIBS]) AC_MSG_RESULT([Default XSLT URL: $xsl_url]) AC_MSG_RESULT([***************************************************************]) AC_CONFIG_FILES([ Makefile swarp.spec debian/Makefile debian/changelog doc/Makefile doc/src/conf.py man/Makefile man/swarp.1 src/Makefile src/fits/Makefile src/wcs/Makefile ]) AC_OUTPUT swarp-2.41.5/debian/000077500000000000000000000000001400430667300141645ustar00rootroot00000000000000swarp-2.41.5/debian/Makefile.am000066400000000000000000000021171400430667300162210ustar00rootroot00000000000000# # Makefile.am # # Main Makefile. Process this file with automake to generate a Makefile # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # # This file part of: an AstrOmatic package # # Copyright: (C) 2017 IAP/CNRS/UPMC # # License: GNU General Public License # # AstrOmatic software 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 3 of the License, or # (at your option) any later version. # AstrOmatic software 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 AstrOmatic software. If not, see # . # # Last modified: 13/06/2017 # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% EXTRA_DIST = compat control rules swarp-2.41.5/debian/README000066400000000000000000000003751400430667300150510ustar00rootroot00000000000000The files in that subdirectory are for building custom, optimized binary Debian packages with the command make deb (using gcc) or make deb-best (using icc/MKL). They are not meant to be used for building packages of the official Debian/Ubuntu distros. swarp-2.41.5/debian/changelog.in000066400000000000000000000002371400430667300164450ustar00rootroot00000000000000@PACKAGE_TARNAME@ (@PACKAGE_VERSION@-@PACKAGE_RELEASE@) UNRELEASED; urgency=low * Automatic Debian release. -- @PACKAGER@ <@PACKAGE_BUGREPORT@> @DATE1@ swarp-2.41.5/debian/compat000066400000000000000000000000021400430667300153620ustar00rootroot000000000000009 swarp-2.41.5/debian/control000066400000000000000000000024601400430667300155710ustar00rootroot00000000000000# # control # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # # This file part of: SWarp # # Copyright: (C) 2006-2021 IAP/CNRS/SorbonneU # # License: GNU General Public License # # SCAMP 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 3 of the License, or # (at your option) any later version. # SCAMP 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 SCAMP. If not, see . # # Last modified: 27/01/2021 # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Source: swarp Section: science Priority: optional Maintainer: Emmanuel Bertin Build-Depends: debhelper (>= 9), libcfitsio-dev Homepage: http://astromatic.net/software/swarp Package: swarp Architecture: any Depends: ${misc:Depends}, ${shlibs:Depends} Description: a utility that resamples and coadd FITS images to an arbitrary astrometric projection of the WCS standard. swarp-2.41.5/debian/rules000077500000000000000000000023111400430667300152410ustar00rootroot00000000000000#! /usr/bin/make -f # These are used for cross-compiling and for saving the configure script # from having to guess our platform (since we know it already) DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH) DEB_BUILD_OPTIONS = noddebs parallel=4 %: dh $@ --parallel --with autoreconf override_dh_auto_configure: ifeq ($(USE_BEST),1) dh_auto_configure -- --host=$(DEB_HOST_GNU_TYPE) \ --build=$(DEB_BUILD_GNU_TYPE) \ --prefix=/usr --mandir=\$${prefix}/share/man \ --enable-icc \ --enable-auto-flags --enable-best-link \ --with-release=$(PACKAGE_RELEASE) else ifeq ($(USE_ICC),1) dh_auto_configure -- --host=$(DEB_HOST_GNU_TYPE) \ --build=$(DEB_BUILD_GNU_TYPE) \ --prefix=/usr --mandir=\$${prefix}/share/man \ --enable-icc \ --with-release=$(PACKAGE_RELEASE) else dh_auto_configure -- --host=$(DEB_HOST_GNU_TYPE) \ --build=$(DEB_BUILD_GNU_TYPE) \ --prefix=/usr --mandir=\$${prefix}/share/man \ --with-release=$(PACKAGE_RELEASE) endif endif override_dh_installchangelogs: dh_installchangelogs ChangeLog override_dh_auto_clean: swarp-2.41.5/doc/000077500000000000000000000000001400430667300135075ustar00rootroot00000000000000swarp-2.41.5/doc/Makefile.am000066400000000000000000000021721400430667300155450ustar00rootroot00000000000000# # Makefile.am # # Makefile for Sphinx documentation. # Process this file with autoconf to generate a Makefile # EXTRA_DIST = requirements.txt TODO src theme # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build SPHINXPROJ = @PACKAGE_NAME@ SOURCEDIR = src BUILDDIR = build .PHONY: all clean-am mostlyclean-am distdir-am help html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf latexpdfja text man texinfo info gettext changes xml pseudoxml linkcheck doctest coverage # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). clean: rm -rf $(BUILDDIR)/* pdf: latexpdf html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf latexpdfja text man texinfo info gettext changes xml pseudoxml linkcheck doctest coverage: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) swarp-2.41.5/doc/TODO000066400000000000000000000002531400430667300141770ustar00rootroot00000000000000The full SWarp manual in Sphinx format will go here. Meanwhile, the previous version is available at: https://www.astromatic.net/pubsvn/software/swarp/trunk/doc/swarp.pdf swarp-2.41.5/doc/requirements.txt000066400000000000000000000000251400430667300167700ustar00rootroot00000000000000sphinxcontrib-bibtex swarp-2.41.5/doc/src/000077500000000000000000000000001400430667300142765ustar00rootroot00000000000000swarp-2.41.5/doc/src/conf.py000066400000000000000000000232671400430667300156070ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # SWarp documentation build configuration file, created by # sphinx-quickstart on Mon Dec 9 14:56:27 2019. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # # import os # import sys # sys.path.insert(0, os.path.abspath('.')) import sphinx_rtd_theme # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.coverage', 'sphinx.ext.mathjax', 'sphinxcontrib.bibtex', 'sphinx.ext.githubpages' ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] source_suffix = '.rst' # The encoding of source files. # # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'SWarp' filename = 'swarp' copyright = u'2019, IAP/CNRS/SorbonneU' author = u'Emmanuel Bertin' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '2.41.5' # The full version, including alpha/beta/rc tags. release = '2.41.5' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = 'Wed Jan 27 2021' # # Else, today_fmt is used as the format for a strftime call. # # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path exclude_patterns = ['global.rst','keys.rst','roles.rst'] # The reST default role (used for this markup: `text`) to use for all # documents. # # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True numfig = True # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # # html_theme_options = {} # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['../theme'] # Trick for having ReadTheDocs read custom theme changes def setup(app): app.add_stylesheet("css/custom.css") # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # # html_extra_path = [] # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. htmlhelp_basename = 'SWarpdoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # 'papersize': 'a4paper', # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # 'preamble': '\usepackage{amssymb}', # Latex figure (float) alignment # # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, filename + '.tex', project + u' Documentation', author, 'manual'), ] # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ (master_doc, filename, project + u' Documentation', author, 1) ] # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ (master_doc, filename, project + u' Documentation', author, project, 'One line description of project.', 'Miscellaneous'), ] # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'inline' # -- Options for Epub output ---------------------------------------------- # Bibliographic Dublin Core info. epub_title = project epub_author = author epub_publisher = author epub_copyright = copyright # The unique identifier of the text. This can be a ISBN number # or the project homepage. # # epub_identifier = '' # A unique identification for the text. # # epub_uid = '' # A list of files that should not be packed into the epub file. epub_exclude_files = ['search.html'] # The depth of the table of contents in toc.ncx. # # epub_tocdepth = 3 # Allow duplicate toc entries. # # epub_tocdup = True # Choose between 'default' and 'includehidden'. # # epub_tocscope = 'default' # Fix unsupported image types using the Pillow. # # epub_fix_images = False # Scale large images. # # epub_max_image_width = 0 # How to display URL addresses: 'footnote', 'no', or 'inline'. # # epub_show_urls = 'inline' # If false, no index is generated. # # epub_use_index = True # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'https://docs.python.org/': None} # -- Options for pybtex ---------------------------------------------- from pybtex.style.formatting.unsrt import Style as UnsrtStyle, date, pages, toplevel from pybtex.style.template import * # ... and anything else needed from pybtex.plugin import register_plugin class ADSArxivStyle(UnsrtStyle): def format_article(self, e): volume_and_pages = first_of [ # volume and pages, with optional issue number optional [ join [ field('volume'), optional['(', field('number'),')'], ':', pages ], ], # pages only words ['pages', pages], ] myurl = first_of [ optional_field('adsurl'), join ['http://arxiv.org/abs/', optional_field('eprint')], optional_field('url'), optional [join ['http://dx.doi.org/', field('doi')]] ] template = toplevel [ self.format_names('author'), href [myurl, self.format_title(e, 'title')] \ if len(myurl.format_data(e)) > 0 \ else tag('strong') [self.format_title(e, 'title')], sentence(capfirst=False) [ tag('emph') [field('journal')], optional[ volume_and_pages ], field('year')], sentence(capfirst=False) [ optional_field('note') ], ] return template.format_data(e) def format_inproceedings(self, e): myurl = first_of [ optional_field('adsurl'), optional [join ['http://arxiv.org/abs/', field('eprint')]], optional_field('url'), optional [join ['http://dx.doi.org/', field('doi')]] ] template = toplevel [ sentence [self.format_names('author')], href [myurl, self.format_title(e, 'title')] \ if len(myurl.format_data(e)) > 0 \ else tag('strong') [self.format_title(e, 'title')], words [ 'In', sentence(capfirst=False) [ optional[ self.format_editor(e, as_sentence=False) ], self.format_btitle(e, 'booktitle', as_sentence=False), self.format_volume_and_series(e, as_sentence=False), optional[ pages ], ], self.format_address_organization_publisher_date(e), ], sentence(capfirst=False) [ optional_field('note') ], ] return template.format_data(e) register_plugin('pybtex.style.formatting', 'adsarxiv', ADSArxivStyle) swarp-2.41.5/doc/src/conf.py.in000066400000000000000000000233321400430667300162050ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # SWarp documentation build configuration file, created by # sphinx-quickstart on Mon Dec 9 14:56:27 2019. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # # import os # import sys # sys.path.insert(0, os.path.abspath('.')) import sphinx_rtd_theme # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.coverage', 'sphinx.ext.mathjax', 'sphinxcontrib.bibtex', 'sphinx.ext.githubpages' ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] source_suffix = '.rst' # The encoding of source files. # # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'@PACKAGE_NAME@' filename = '@PACKAGE_TARNAME@' copyright = u'2019, IAP/CNRS/SorbonneU' author = u'Emmanuel Bertin' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '@PACKAGE_VERSION@' # The full version, including alpha/beta/rc tags. release = '@PACKAGE_VERSION@' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '@DATE2@' # # Else, today_fmt is used as the format for a strftime call. # # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path exclude_patterns = ['global.rst','keys.rst','roles.rst'] # The reST default role (used for this markup: `text`) to use for all # documents. # # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True numfig = True # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # # html_theme_options = {} # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['../theme'] # Trick for having ReadTheDocs read custom theme changes def setup(app): app.add_stylesheet("css/custom.css") # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # # html_extra_path = [] # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. htmlhelp_basename = 'SWarpdoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # 'papersize': 'a4paper', # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # 'preamble': '\usepackage{amssymb}', # Latex figure (float) alignment # # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, filename + '.tex', project + u' Documentation', author, 'manual'), ] # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ (master_doc, filename, project + u' Documentation', author, 1) ] # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ (master_doc, filename, project + u' Documentation', author, project, 'One line description of project.', 'Miscellaneous'), ] # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'inline' # -- Options for Epub output ---------------------------------------------- # Bibliographic Dublin Core info. epub_title = project epub_author = author epub_publisher = author epub_copyright = copyright # The unique identifier of the text. This can be a ISBN number # or the project homepage. # # epub_identifier = '' # A unique identification for the text. # # epub_uid = '' # A list of files that should not be packed into the epub file. epub_exclude_files = ['search.html'] # The depth of the table of contents in toc.ncx. # # epub_tocdepth = 3 # Allow duplicate toc entries. # # epub_tocdup = True # Choose between 'default' and 'includehidden'. # # epub_tocscope = 'default' # Fix unsupported image types using the Pillow. # # epub_fix_images = False # Scale large images. # # epub_max_image_width = 0 # How to display URL addresses: 'footnote', 'no', or 'inline'. # # epub_show_urls = 'inline' # If false, no index is generated. # # epub_use_index = True # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'https://docs.python.org/': None} # -- Options for pybtex ---------------------------------------------- from pybtex.style.formatting.unsrt import Style as UnsrtStyle, date, pages, toplevel from pybtex.style.template import * # ... and anything else needed from pybtex.plugin import register_plugin class ADSArxivStyle(UnsrtStyle): def format_article(self, e): volume_and_pages = first_of [ # volume and pages, with optional issue number optional [ join [ field('volume'), optional['(', field('number'),')'], ':', pages ], ], # pages only words ['pages', pages], ] myurl = first_of [ optional_field('adsurl'), join ['http://arxiv.org/abs/', optional_field('eprint')], optional_field('url'), optional [join ['http://dx.doi.org/', field('doi')]] ] template = toplevel [ self.format_names('author'), href [myurl, self.format_title(e, 'title')] \ if len(myurl.format_data(e)) > 0 \ else tag('strong') [self.format_title(e, 'title')], sentence(capfirst=False) [ tag('emph') [field('journal')], optional[ volume_and_pages ], field('year')], sentence(capfirst=False) [ optional_field('note') ], ] return template.format_data(e) def format_inproceedings(self, e): myurl = first_of [ optional_field('adsurl'), optional [join ['http://arxiv.org/abs/', field('eprint')]], optional_field('url'), optional [join ['http://dx.doi.org/', field('doi')]] ] template = toplevel [ sentence [self.format_names('author')], href [myurl, self.format_title(e, 'title')] \ if len(myurl.format_data(e)) > 0 \ else tag('strong') [self.format_title(e, 'title')], words [ 'In', sentence(capfirst=False) [ optional[ self.format_editor(e, as_sentence=False) ], self.format_btitle(e, 'booktitle', as_sentence=False), self.format_volume_and_series(e, as_sentence=False), optional[ pages ], ], self.format_address_organization_publisher_date(e), ], sentence(capfirst=False) [ optional_field('note') ], ] return template.format_data(e) register_plugin('pybtex.style.formatting', 'adsarxiv', ADSArxivStyle) swarp-2.41.5/doc/src/index.rst000066400000000000000000000006571400430667300161470ustar00rootroot00000000000000.. SWarp documentation master file, created by sphinx-quickstart on Mon Dec 9 14:56:27 2019. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Welcome to SWarp's documentation! ================================= .. toctree:: :maxdepth: 2 :caption: Contents: Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` swarp-2.41.5/doc/theme/000077500000000000000000000000001400430667300146115ustar00rootroot00000000000000swarp-2.41.5/doc/theme/css/000077500000000000000000000000001400430667300154015ustar00rootroot00000000000000swarp-2.41.5/doc/theme/css/custom.css000066400000000000000000000034771400430667300174400ustar00rootroot00000000000000/* Change heading font */ /* h1,h2,h3 { font-weight: 700; font-family: "CherrySoda","ff-tisa-web-pro","Georgia",Arial,sans-serif; } @font-face { font-family: "CherrySoda"; font-style: normal; font-weight: 700; src: url(../fonts/CherrySoda.ttf) format('truetype'); } */ /* Extend page width size limit */ .wy-nav-content { max-width: 1600px; } /* Justified and slightly lower line interval for text */ li, p { text-align: justify; line-height: 20px; } /* Smaller caption text, further away from the figure */ .caption { font-size: smaller; margin-top: 1em; } /* Override responsive image scaling */ img { width: auto; } /* Override Mathjax colors forced to dark grey */ span[id*="MathJax-Span"] { color: inherit; } /* Move equation no to the right */ .math .eqno { position: relative; float: right; margin: 1em 0em; z-index: 10; } /* Hide permalinks on equation numbers */ .section { position: relative z-index: 0; } .math { position: relative; z-index: 1; } .math .MathJax_Display { z-index: 2; } .math .eqno a.headerlink { visibility: hidden; position: absolute; } .math .eqno:hover a.headerlink { visibility: visible; } /* new param class */ @font-face { font-family: MathJax_Typewriter; src: url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/woff/MathJax_Typewriter-Regular.woff?V=2.7.1') format('woff'), url('https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/fonts/HTML-CSS/TeX/otf/MathJax_Typewriter-Regular.otf?V=2.7.1') format('opentype') } .targetparam .target, .param { font-family: "MathJax_Typewriter",monospace; font-size: 116%; } /* Hide permalinks on captions */ caption a.headerlink { visibility: hidden; } caption:hover a.headerlink { visibility: visible; } /* Remove space before muliline cells in tables */ td div.line-block { margin-left: 0px !important; } swarp-2.41.5/m4/000077500000000000000000000000001400430667300132625ustar00rootroot00000000000000swarp-2.41.5/m4/acx_cfitsio.m4000066400000000000000000000072161400430667300160250ustar00rootroot00000000000000dnl dnl acx_cfitsio.m4 dnl dnl Figure out if the CFITSIO library and header files are installed. dnl dnl %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dnl dnl This file part of: AstrOmatic software dnl dnl Copyright: (C) 2013 Emmanuel Bertin -- IAP/CNRS/UPMC dnl dnl License: GNU General Public License dnl dnl AstrOmatic software is free software: you can redistribute it and/or dnl modify it under the terms of the GNU General Public License as dnl published by the Free Software Foundation, either version 3 of the dnl License, or (at your option) any later version. dnl AstrOmatic software is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the dnl GNU General Public License for more details. dnl You should have received a copy of the GNU General Public License dnl along with AstrOmatic software. dnl If not, see . dnl dnl Last modified: 27/02/2013 dnl dnl %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dnl dnl @synopsis ACX_CFITSIO([CFITSIO_DIR, CFITSIO_INCDIR, dnl [ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]]) dnl This macro figures out if the CFITSIO libraries and header dnl files are installed. dnl You may wish to use these variables in your default LIBS and CFLAGS: dnl dnl LIBS="$CFITSIO_LIBS $LIBS" dnl dnl You may wish to use these variables in your default CFLAGS: dnl dnl CFLAGS="$CFLAGS $CFITSIO_CFLAGS" dnl dnl ACTION-IF-FOUND is a list of shell commands to run if CFITSIO dnl is found (HAVE_CFITSIO are defined first), and ACTION-IF-NOT-FOUND dnl is a list of commands to run it if it is not found. AC_DEFUN([ACX_CFITSIO], [ AC_REQUIRE([AC_CANONICAL_HOST]) dnl -------------------- dnl Search include files dnl -------------------- acx_cfitsio_ok=no if test x$2 = x; then AC_CHECK_HEADER(fitsio.h,[acx_cfitsio_ok=yes]) if test x$acx_cfitsio_ok = xyes; then AC_DEFINE(CFITSIO_H, "fitsio.h", [CFITSIO header filename.]) else AC_CHECK_HEADER(cfitsio/fitsio.h,[acx_cfitsio_ok=yes]) if test x$acx_cfitsio_ok = xyes; then AC_DEFINE(CFITSIO_H, "cfitsio/fitsio.h", [CFITSIO header filename.]) else CFITSIO_ERROR="CFITSIO include files not found at default location!" fi fi else AC_CHECK_HEADER($2/fitsio.h,[acx_cfitsio_ok=yes]) if test x$acx_cfitsio_ok = xyes; then AC_DEFINE_UNQUOTED(CFITSIO_H, "$2/fitsio.h", [CFITSIO header filename.]) else CFITSIO_ERROR="CFITSIO include files not found in $2!" fi fi dnl -------------------- dnl Search library files dnl -------------------- CFITSIO_LIBS="" OLIBS="$LIBS" LIBS="" if test x$acx_cfitsio_ok = xyes; then if test x$1 = x; then AC_CHECK_LIB(cfitsio, ffopen, [acx_cfitsio_ok=yes], [acx_cfitsio_ok=no]) if test x$acx_cfitsio_ok = xyes; then AC_DEFINE(HAVE_CFITSIO,1, [Define if you have the CFITSIO libraries and header files.]) CFITSIO_LIBS="-lcfitsio" else CFITSIO_ERROR="CFITSIO library files not found at usual locations!" fi else dnl ------------------------- dnl Specific libdir specified dnl ------------------------- AC_CHECK_LIB(cfitsio, ffopen, [acx_cfitsio_ok=yes], [acx_cfitsio_ok=no], [-L$1]) if test x$acx_cfitsio_ok = xyes; then AC_DEFINE(HAVE_CFITSIO,1, [Define if you have the CFITSIO libraries and header files.]) CFITSIO_LIBS="-L$1 -lcfitsio" else CFITSIO_ERROR="CFITSIO library files not found in $1!" fi fi fi LIBS="$OLIBS" if test x$acx_cfitsio_ok = xyes; then AC_SUBST(CFITSIO_LIBS) $3 else AC_SUBST(CFITSIO_ERROR) $4 fi ])dnl ACX_CFITSIO swarp-2.41.5/m4/acx_prog_cc_optim.m4000066400000000000000000000124511400430667300172060ustar00rootroot00000000000000dnl dnl acx_prog_cc_optim.m4 dnl dnl Enable a reasonable set of optimization flags for the C compiler. dnl dnl %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dnl dnl This file part of: AstrOmatic software dnl dnl Copyright: (C) 2002-2013 Emmanuel Bertin -- IAP/CNRS/UPMC dnl (C) 2002 Ville Lauriki (original version) dnl dnl Licenses: GPL (this version) dnl MIT AllPermissive (original script) dnl dnl AstrOmatic software is free software: you can redistribute it and/or dnl modify it under the terms of the GNU General Public License as dnl published by the Free Software Foundation, either version 3 of the dnl License, or (at your option) any later version. dnl AstrOmatic software is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the dnl GNU General Public License for more details. dnl You should have received a copy of the GNU General Public License dnl along with AstrOmatic software. dnl If not, see . dnl dnl Last modified: 13/03/2013 dnl dnl %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dnl dnl @synopsis ACX_PROG_CC_OPTIM dnl dnl Currently this macro knows about GCC, Solaris C compiler, dnl Digital Unix C compiler, C for AIX Compiler, HP-UX C compiler, dnl IRIX C compiler, NEC SX-5 (Super-UX 10) C compiler, and Cray J90 dnl (Unicos 10.0.0.8) C compiler. dnl dnl This macro is a modification of Ville Laurikari's VL_PROG_CC_WARNINGS dnl AC_DEFUN([ACX_PROG_CC_OPTIM], [ msg="for C compiler optimization flags" AC_CACHE_CHECK($msg, prog_cc_optim_cv_flags, [ if test -n "$CC"; then cat > conftest.c <&1 | grep -i "Intel(R) 64" > /dev/null 2>&1 && $CC -c -O conftest.c > /dev/null 2>&1 && test -f conftest.o; then prog_cc_optim_cv_flags="-O3 -axSSSE3,SSE4.1,SSE4.2,AVX,CORE-AVX2,CORE-AVX-I -no-prec-div -unroll" prog_ld_optim_cv_flags="" dnl INTEL C 32bits compiler elif $CC -V 2>&1 | grep -i "Intel(R)" > /dev/null 2>&1 && $CC -c -O conftest.c > /dev/null 2>&1 && test -f conftest.o; then prog_cc_optim_cv_flags="-O3 -axSSE2,SSE3,SSE4.1,SSE4.2,AVX,CORE-AVX2,CORE-AVX-I -no-prec-div -unroll" prog_ld_optim_cv_flags="" dnl GCC elif test "$GCC" = "yes"; then prog_cc_optim_cv_flags="-O3 -g -funroll-loops -fomit-frame-pointer -Wall" prog_ld_optim_cv_flags="" dnl Solaris C compiler elif $CC -V 2>&1 | grep -i "WorkShop" > /dev/null 2>&1 && $CC -c -O conftest.c > /dev/null 2>&1 && test -f conftest.o; then prog_cc_optim_cv_flags="-O" prog_ld_optim_cv_flags="" dnl Digital Unix/Compaq C compiler elif ($CC -V 2>&1 | grep -i "Digital UNIX Compiler"> /dev/null 2>&1 || $CC -V 2>&1 | grep -i "Compaq C"> /dev/null 2>&1) && $CC -c -fast conftest.c > /dev/null 2>&1 && test -f conftest.o; then prog_cc_optim_cv_flags="-fast -tune host" prog_ld_optim_cv_flags="" dnl C for AIX Compiler elif $CC 2>&1 | grep -i "C for AIX Compiler" > /dev/null 2>&1 && $CC -c -qinfo=all -O2 conftest.c > /dev/null 2>&1 && test -f conftest.o; then prog_cc_optim_cv_flags="-O2" prog_ld_optim_cv_flags="" dnl IRIX C compiler elif $CC -version 2>&1 | grep -i "MIPSpro Compilers" > /dev/null 2>&1 && $CC -c -fullwarn -O3 conftest.c > /dev/null 2>&1 && test -f conftest.o; then prog_cc_optim_cv_flags="-O3" prog_ld_optim_cv_flags="" dnl HP-UX C compiler elif what $CC 2>&1 | grep -i "HP C Compiler" > /dev/null 2>&1 && $CC -c -Aa +O3 conftest.c > /dev/null 2>&1 && test -f conftest.o; then prog_cc_optim_cv_flags="+O3" prog_ld_optim_cv_flags="" dnl The NEC SX-5 (Super-UX 10) C compiler elif $CC -V 2>&1 | grep "/SX" > /dev/null 2>&1 && $CC -c -Xc -O conftest.c > /dev/null 2>&1 && test -f conftest.o; then prog_cc_optim_cv_flags="-O" prog_ld_optim_cv_flags="" dnl The Cray C compiler (Unicos) elif $CC -V 2>&1 | grep -i "Cray" > /dev/null 2>&1 && $CC -c -h conform -O3 conftest.c > /dev/null 2>&1 && test -f conftest.o; then prog_cc_optim_cv_flags="-O3" prog_ld_optim_cv_flags="" fi rm -f conftest.* fi if test -n "$prog_cc_optim_cv_flags"; then AM_CFLAGS="$CFLAGS $prog_cc_optim_cv_flags" AM_LDFLAGS="$LDFLAGS $prog_ld_optim_cv_flags" else prog_cc_optim_cv_flags="" prog_ld_optim_cv_flags="" fi ]) ])dnl swarp-2.41.5/m4/acx_pthread.m4000066400000000000000000000235001400430667300160060ustar00rootroot00000000000000dnl dnl acx_pthread.m4 dnl dnl Figure out how to build C programs using POSIX threads dnl dnl %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dnl dnl This file part of: AstrOmatic software dnl dnl Copyright: (C) 2002-2010 Emmanuel Bertin -- IAP/CNRS/UPMC dnl (C) 2001 Steven G. Johnson (original version) dnl dnl Licenses: GPL (this version) dnl GPLWithACException (original script) dnl dnl AstrOmatic software is free software: you can redistribute it and/or dnl modify it under the terms of the GNU General Public License as dnl published by the Free Software Foundation, either version 3 of the dnl License, or (at your option) any later version. dnl AstrOmatic software is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the dnl GNU General Public License for more details. dnl You should have received a copy of the GNU General Public License dnl along with AstrOmatic software. dnl If not, see . dnl dnl Last modified: 09/10/2010 dnl dnl %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dnl dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) dnl dnl This macro figures out how to build C programs using POSIX dnl threads. It sets the PTHREAD_LIBS output variable to the threads dnl library and linker flags, and the PTHREAD_CFLAGS output variable dnl to any special C compiler flags that are needed. (The user can also dnl force certain compiler flags/libs to be tested by setting these dnl environment variables.) dnl dnl Also sets PTHREAD_CC to any special C compiler that is needed for dnl multi-threaded programs (defaults to the value of CC otherwise). dnl (This is necessary on AIX to use the special cc_r compiler alias.) dnl dnl If you are only building threads programs, you may wish to dnl use these variables in your default LIBS, CFLAGS, and CC: dnl dnl LIBS="$PTHREAD_LIBS $LIBS" dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS" dnl CC="$PTHREAD_CC" dnl dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE dnl to that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). dnl dnl ACTION-IF-FOUND is a list of shell commands to run if a threads dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands dnl to run it if it is not found. If ACTION-IF-FOUND is not specified, dnl the default action will define HAVE_PTHREAD. dnl dnl Please let the authors know if this macro fails on any platform, dnl or if you have any other suggestions or comments. This macro was dnl based on work by SGJ on autoconf scripts for FFTW (www.fftw.org) dnl (with help from M. Frigo), as well as ac_pthread and hb_pthread dnl macros posted by AFC to the autoconf macro repository. We are also dnl grateful for the helpful feedback of numerous users. AC_DEFUN([ACX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) acx_pthread_ok=no # First, check if the POSIX threads header, pthread.h, is available. # If it isn't, don't bother looking for the threads libraries. # AC_CHECK_HEADER(pthread.h, , acx_pthread_ok=noheader) AC_CHECK_HEADER(pthread.h, , acx_pthread_ok=no) # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) AC_MSG_RESULT($acx_pthread_ok) if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all. acx_pthread_flags="pthreads none -Kthread -kthread lthread pthread -pthread -pthreads -mthreads --thread-safe -mt" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # pthread: Linux, etcetera # --thread-safe: KAI C++ case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthread or # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [acx_pthread_ok=yes]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($acx_pthread_ok) if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: threads are created detached by default # and the JOINABLE attribute has a nonstandard name (UNDETACHED). AC_MSG_CHECKING([for joinable pthread attribute]) AC_TRY_LINK([#include ], [int attr=PTHREAD_CREATE_JOINABLE;], ok=PTHREAD_CREATE_JOINABLE, ok=unknown) if test x"$ok" = xunknown; then AC_TRY_LINK([#include ], [int attr=PTHREAD_CREATE_UNDETACHED;], ok=PTHREAD_CREATE_UNDETACHED, ok=unknown) fi if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok, [Define to the necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_RESULT(${ok}) if test x"$ok" = xunknown; then AC_MSG_WARN([we do not know how to create joinable pthreads]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";; *solaris* | alpha*-osf*) flag="-D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with cc_r AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) else PTHREAD_CC="$CC" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_CC) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else acx_pthread_ok=no $2 fi ])dnl ACX_PTHREAD swarp-2.41.5/m4/acx_urbi_resolve_dir.m4000066400000000000000000000044621400430667300177230ustar00rootroot00000000000000dnl dnl acx_urbi_resolve_dir.m4 dnl dnl Enable a reasonable set of optimization flags for the C compiler. dnl dnl %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dnl dnl This file part of: AstrOmatic software dnl dnl Copyrights: (C) 2007-2011 Emmanuel Bertin -- IAP/CNRS/UPMC dnl (C) 2007 Akim Demaille (original version) dnl dnl License: GPL dnl dnl AstrOmatic software is free software: you can redistribute it and/or dnl modify it under the terms of the GNU General Public License as dnl published by the Free Software Foundation, either version 3 of the dnl License, or (at your option) any later version. dnl AstrOmatic software is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the dnl GNU General Public License for more details. dnl You should have received a copy of the GNU General Public License dnl along with AstrOmatic software. dnl If not, see . dnl dnl Last modified: 27/12/2011 dnl dnl %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dnl dnl @synopsis ACX_URBI_RESOLVE_DIR dnl dnl Return a directory with all inner variables expanded. dnl Based on a macro kindly provided by Akim Demaille . # URBI_RESOLVE_DIR_PREPARE # ------------------------ # Define urbi_resolve_dir. m4_defun([URBI_RESOLVE_DIR_PREPARE], [# PATH urbi_resolve_dir(DIR) # -------------------------- # urbi_resolve_dir () { ac_$0_dir=$[]1 ac_$0_res= ac_$0_prefix_NONE= ac_$0_exec_prefix_NONE= test "x$prefix" = xNONE && ac_$0_exec_prefix_NONE=yes && prefix=$ac_default_prefix test "x$exec_prefix" = xNONE && ac_$0_exec_prefix_NONE=yes && exec_prefix=$prefix while true do eval ac_$0_res="$ac_$0_dir" if test x"$ac_$0_dir" = x"$ac_$0_res"; then break fi ac_$0_dir=$ac_$0_res done test "$ac_$0_prefix_NONE" && prefix=NONE test "$ac_$0_exec_prefix_NONE" && exec_prefix=NONE echo "$ac_$0_res" } ]) # PATH URBI_RESOLVE_DIR(DIR) # -------------------------- # Return the DIR with all inner variables expanded. AC_DEFUN([URBI_RESOLVE_DIR], [AC_REQUIRE([URBI_RESOLVE_DIR_PREPARE])dnl urbi_resolve_dir '$1'[]dnl ]) ## Local Variables: ## mode: autoconf ## End: swarp-2.41.5/man/000077500000000000000000000000001400430667300135155ustar00rootroot00000000000000swarp-2.41.5/man/Makefile.am000066400000000000000000000017761400430667300155640ustar00rootroot00000000000000# # Makefile.am # # man Makefile. Process this file with automake to generate a Makefile # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # # This file part of: SWarp # # Copyright: (C) 2002-2010 Emmanuel Bertin -- IAP/CNRS/UPMC # # SWarp 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 3 of the License, or # (at your option) any later version. # SWarp 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 SWarp. If not, see . # # Last modified: 26/10/2010 # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dist_man_MANS = swarp.1 swarp.x swarp-2.41.5/man/swarp.1000066400000000000000000000021511400430667300147320ustar00rootroot00000000000000.TH SWARP "1" "January 2021" "SWarp 2.41.5" "User Commands" .SH NAME swarp \- resample and combine FITS images .SH SYNOPSIS .B swarp \fIinput\_image1\fR [\fIinput\_image2 ...\fR] [\fI-c configuration-file\fR] .RS [\fI-parameter1 value1 -parameter2 value2 ...\fR] .RE .TP .B swarp \fI-d\fR .SH DESCRIPTION Resample and combine FITS images in an arbitrary World Coordinate System. .RE See http://astromatic.net/software/swarp for more details. .SS "Operation modes:" .TP \fB\-h\fR, \fB\-\-help\fR print this help, then exit .TP \fB\-V\fR, \fB\-\-version\fR print version number, then exit .TP \fB\-d\fR, \fB\-\-dump\fR dump a default configuration file .SH AUTHOR Written by Emmanuel Bertin (Institut d'Astrophysique de Paris). .PP Copyright 2000-2010 Emmanuel Bertin .RE This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. .SH "REPORTING BUGS" Report bugs to . .SH "SEE ALSO" .BR sex (1). .PP The full documentation for .B SWarp is maintained as a PDF manual available at .B http://astromatic.net/software/swarp swarp-2.41.5/man/swarp.1.in000066400000000000000000000021571400430667300153450ustar00rootroot00000000000000.TH SWARP "1" "@DATE3@" "SWarp @PACKAGE_VERSION@" "User Commands" .SH NAME swarp \- resample and combine FITS images .SH SYNOPSIS .B swarp \fIinput\_image1\fR [\fIinput\_image2 ...\fR] [\fI-c configuration-file\fR] .RS [\fI-parameter1 value1 -parameter2 value2 ...\fR] .RE .TP .B swarp \fI-d\fR .SH DESCRIPTION Resample and combine FITS images in an arbitrary World Coordinate System. .RE See http://astromatic.net/software/swarp for more details. .SS "Operation modes:" .TP \fB\-h\fR, \fB\-\-help\fR print this help, then exit .TP \fB\-V\fR, \fB\-\-version\fR print version number, then exit .TP \fB\-d\fR, \fB\-\-dump\fR dump a default configuration file .SH AUTHOR Written by Emmanuel Bertin (Institut d'Astrophysique de Paris). .PP Copyright 2000-2010 Emmanuel Bertin .RE This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. .SH "REPORTING BUGS" Report bugs to . .SH "SEE ALSO" .BR sex (1). .PP The full documentation for .B SWarp is maintained as a PDF manual available at .B http://astromatic.net/software/swarp swarp-2.41.5/man/swarp.x000066400000000000000000000000621400430667300150400ustar00rootroot00000000000000[name] swarp \- resample and combine FITS images swarp-2.41.5/src/000077500000000000000000000000001400430667300135315ustar00rootroot00000000000000swarp-2.41.5/src/Makefile.am000066400000000000000000000027431400430667300155730ustar00rootroot00000000000000# # Makefile.am # # src Makefile. Process this file with automake to generate a Makefile # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # # This file part of: SWarp # # Copyright: (C) 2002-2013 Emmanuel Bertin -- IAP/CNRS/UPMC # # SWarp 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 3 of the License, or # (at your option) any later version. # SWarp 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 SWarp. If not, see . # # Last modified: 04/04/2013 # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SUBDIRS = fits wcs bin_PROGRAMS = swarp swarp_SOURCES = back.c coadd.c data.c field.c fitswcs.c header.c \ interpolate.c main.c makeit.c misc.c prefs.c \ projapprox.c resample.c threads.c weight.c xml.c \ back.h coadd.h data.h define.h field.h fitswcs.h \ globals.h header.h interpolate.h key.h misc.h \ preflist.h prefs.h projapprox.h resample.h threads.h \ types.h wcscelsys.h weight.h xml.h swarp_LDADD = $(srcdir)/fits/libfits.a $(srcdir)/wcs/libwcs_c.a DATE=`date +"%Y-%m-%d"` swarp-2.41.5/src/back.c000066400000000000000000000737161400430667300146130ustar00rootroot00000000000000/* * back.c * * Functions dealing with the image background. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2019 IAP/CNRS/SorbonneU * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 03/12/2019 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include #include #include #include "define.h" #include "globals.h" #include "fits/fitscat.h" #include "back.h" #include "coadd.h" #include "field.h" #include "misc.h" #include "prefs.h" #include "weight.h" /******************************** make_back **********************************/ /* Background maps are established from the images themselves; thus we need to make at least one first pass through the data. */ void make_back(fieldstruct *field, fieldstruct *wfield, int wscale_flag) { backstruct *backmesh,*wbackmesh, *bm,*wbm; tabstruct *tab, *wtab; PIXTYPE *buf,*wbuf, *buft,*wbuft; size_t bufsize, bufsize2, bufshift, size,meshsize,jumpsize; off_t fcurpos,wfcurpos, wfcurpos2,fcurpos2; #ifdef HAVE_CFITSIO off_t cfitsio_fcurpos,cfitsio_wfcurpos, cfitsio_wfcurpos2,cfitsio_fcurpos2; #endif // HAVE_CFITSIO int i,j,k,m,n, step, nlines, w,bw, bh, nx,ny,nb, lflag, nr; float *ratio,*ratiop, *weight, *sigma, sratio; /* If the weight-map is not an external one, no stats are needed for it */ if (wfield && (wfield->flags&BACKRMS_FIELD)) wfield= NULL; tab = field->tab; if (wfield) wtab = wfield->tab; else wtab = NULL; /* to avoid gcc -Wall warnings */ w = field->width; bw = field->backw; bh = field->backh; nx = field->nbackx; ny = field->nbacky; nb = field->nback; NFPRINTF(OUTPUT, "Setting up background maps ..."); /* Decide if it is worth displaying progress each 16 lines */ lflag = (field->width*field->backh >= (size_t)65536); /* Save current positions in files */ wfcurpos = wfcurpos2 = 0; /* to avoid gcc -Wall warnings */ QFSEEK(tab->cat->file, tab->bodypos, SEEK_SET, field->filename); QFTELL(fcurpos, tab->cat->file, field->filename); #ifdef HAVE_CFITSIO cfitsio_wfcurpos = cfitsio_wfcurpos2 = 0; /* to avoid gcc -Wall warnings */ tab->currentElement = 1; // CFITSIO cfitsio_fcurpos = (fcurpos - tab->bodypos)/tab->bytepix; #endif // HAVE_CFITSIO if (wfield) { QFSEEK(wtab->cat->file, wtab->bodypos, SEEK_SET, wfield->filename); QFTELL(wfcurpos, wtab->cat->file, wfield->filename); #ifdef HAVE_CFITSIO wtab->currentElement = 1; cfitsio_wfcurpos = (wfcurpos - wtab->bodypos)/wtab->bytepix; #endif // HAVE_CFITSIO } /* Allocate a correct amount of memory to store pixels */ bufsize = (size_t)w*bh; meshsize = bufsize; nlines = 0; if (bufsize > (size_t)BACK_BUFSIZE) { nlines = BACK_BUFSIZE/w; step = (field->backh-1)/nlines+1; bufsize = (size_t)(nlines = field->backh/step)*w; bufshift = (step/2)*(size_t)w; jumpsize = (step-1)*(size_t)w; } else bufshift = jumpsize = 0; /* to avoid gcc -Wall warnings */ /* Allocate some memory */ QMALLOC(backmesh, backstruct, nx); /* background information */ QMALLOC(buf, PIXTYPE, bufsize); /* pixel buffer */ free(field->back); QMALLOC(field->back, float, nb); /* background map */ free(field->backline); QMALLOC(field->backline, PIXTYPE, w); /* current background line */ free(field->sigma); QMALLOC(field->sigma, float, nb); /* sigma map */ if (wfield) { QMALLOC(wbackmesh, backstruct, nx); /* background information */ QMALLOC(wbuf, PIXTYPE, bufsize); /* pixel buffer */ free(wfield->back); QMALLOC(wfield->back, float, nb); /* background map */ free(wfield->sigma); QMALLOC(wfield->sigma, float, nb); /* sigma map */ wfield->sigfac = 1.0; set_weightconv(wfield); /* Prepare conversion */ } else { wbackmesh = NULL; wbuf = NULL; } /* Loop over the data packets */ for (j=0; j Setting up background map at line:%7d / %-7d\n\33[1A", j*bh, field->height); if (!nlines) { /*---- The image is small enough so that we can make exhaustive stats */ if (j == ny-1 && field->npix%bufsize) bufsize = field->npix%bufsize; read_body(tab, buf, bufsize); if (wfield) { read_body(wtab, wbuf, bufsize); weight_to_var(wbuf, bufsize); } /*---- Build the histograms */ backstat(backmesh, wbackmesh, buf, wbuf, bufsize,nx, w, bw, wfield?wfield->var_thresh:0.0); bm = backmesh; for (m=nx; m--; bm++) if (bm->mean <= -BIG) bm->histo=NULL; else QCALLOC(bm->histo, int, bm->nlevels); if (wfield) { wbm = wbackmesh; for (m=nx; m--; wbm++) if (wbm->mean <= -BIG) wbm->histo=NULL; else QCALLOC(wbm->histo, int, wbm->nlevels); } backhisto(backmesh, wbackmesh, buf, wbuf, bufsize,nx, w, bw, wfield?wfield->var_thresh:0.0); } else { /*---- Image size too big, we have to skip a few data !*/ QFTELL(fcurpos2, tab->cat->file, field->filename); #ifdef HAVE_CFITSIO cfitsio_fcurpos2 = (fcurpos2 - tab->bodypos)/tab->bytepix; #endif // HAVE_CFITSIO if (wfield) { QFTELL(wfcurpos2, wtab->cat->file, wfield->filename); #ifdef HAVE_CFITSIO cfitsio_wfcurpos2 = (wfcurpos2 - wtab->bodypos)/wtab->bytepix; #endif // HAVE_CFITSIO } if (j == ny-1 && (n=field->height%field->backh)) { meshsize = n*(size_t)w; nlines = BACK_BUFSIZE/w; step = (n-1)/nlines+1; bufsize = (nlines = n/step)*(size_t)w; bufshift = (step/2)*(size_t)w; jumpsize = (step-1)*(size_t)w; free(buf); QMALLOC(buf, PIXTYPE, bufsize); /* pixel buffer */ if (wfield) { free(wbuf); QMALLOC(wbuf, PIXTYPE, bufsize); /* pixel buffer */ } } /*---- Read and skip, read and skip, etc... */ QFSEEK(tab->cat->file, bufshift*tab->bytepix, SEEK_CUR, field->filename); #ifdef HAVE_CFITSIO tab->currentElement += bufshift; #endif // HAVE_CFITSIO buft = buf; for (i=nlines; i--; buft += w) { read_body(tab, buft, w); if ((i)) { QFSEEK(tab->cat->file, jumpsize*tab->bytepix, SEEK_CUR, field->filename); #ifdef HAVE_CFITSIO tab->currentElement += jumpsize; #endif // HAVE_CFITSIO } } if (wfield) { /*------ Read and skip, read and skip, etc... now on the weight-map */ QFSEEK(wtab->cat->file,bufshift*wtab->bytepix, SEEK_CUR, wfield->filename); #ifdef HAVE_CFITSIO wtab->currentElement += bufshift; #endif // HAVE_CFITSIO wbuft = wbuf; for (i=nlines; i--; wbuft += w) { read_body(wtab, wbuft, w); weight_to_var(wbuft, w); if ((i)) { QFSEEK(wtab->cat->file, jumpsize*wtab->bytepix, SEEK_CUR, wfield->filename); #ifdef HAVE_CFITSIO wtab->currentElement += jumpsize; #endif // HAVE_CFITSIO } } } backstat(backmesh, wbackmesh, buf, wbuf, bufsize, nx, w, bw, wfield?wfield->var_thresh:0.0); QFSEEK(tab->cat->file, fcurpos2, SEEK_SET, field->filename); #ifdef HAVE_CFITSIO tab->currentElement = (cfitsio_fcurpos2 == 0) ? 1 : cfitsio_fcurpos2; #endif // HAVE_CFITSIO bm = backmesh; for (m=nx; m--; bm++) if (bm->mean <= -BIG) bm->histo=NULL; else QCALLOC(bm->histo, int, bm->nlevels); if (wfield) { QFSEEK(wtab->cat->file, wfcurpos2, SEEK_SET, wfield->filename); #ifdef HAVE_CFITSIO wtab->currentElement = (cfitsio_wfcurpos2 == 0) ? 1 : cfitsio_wfcurpos2; #endif // HAVE_CFITSIO wbm = wbackmesh; for (m=nx; m--; wbm++) if (wbm->mean <= -BIG) wbm->histo=NULL; else QCALLOC(wbm->histo, int, wbm->nlevels); } /*---- Build (progressively this time) the histograms */ for(size=meshsize, bufsize2=bufsize; size>0; size -= bufsize2) { if (bufsize2>size) bufsize2 = size; read_body(tab, buf, bufsize2); if (wfield) { read_body(wtab, wbuf, bufsize2); weight_to_var(wbuf, bufsize2); } backhisto(backmesh, wbackmesh, buf, wbuf, bufsize2, nx, w, bw, wfield?wfield->var_thresh:0.0); } } /*-- Compute background statistics from the histograms */ bm = backmesh; for (m=0; mback+k, field->sigma+k); free(bm->histo); } if (wfield) { wbm = wbackmesh; for (m=0; mback+k, wfield->sigma+k); free(wbm->histo); } } } /* Free memory */ free(buf); free(backmesh); if (wfield) { free(wbackmesh); free(wbuf); } /* Go back to the original position */ QFSEEK(field->tab->cat->file, fcurpos, SEEK_SET, field->filename); #ifdef HAVE_CFITSIO field->tab->currentElement = (cfitsio_fcurpos == 0) ? 1 : cfitsio_fcurpos; #endif // HAVE_CFITSIO if (wfield) { QFSEEK(wfield->tab->cat->file, wfcurpos, SEEK_SET, wfield->filename); #ifdef HAVE_CFITSIO wfield->tab->currentElement = (cfitsio_wfcurpos == 0) ? 1 : cfitsio_wfcurpos; #endif // HAVE_CFITSIO } /* Median-filter and check suitability of the background map */ NFPRINTF(OUTPUT, "Filtering background map(s) ..."); filter_back(field); if (wfield) filter_back(wfield); /* Compute normalization for variance- or weight-maps*/ if (wfield && wscale_flag && wfield->flags&(VAR_FIELD|WEIGHT_FIELD)) { nr = 0; QMALLOC(ratio, float, wfield->nback); ratiop = ratio; weight = wfield->back; sigma = field->sigma; for (i=wfield->nback; i--; sigma++) if ((sratio=*(weight++)) > 0.0 && (sratio = *sigma/sqrt(sratio)) > 0.0) { *(ratiop++) = sratio; nr++; } wfield->sigfac = (double)fqmedian(ratio, nr); for (i=0; isigfac = (double)fqmedian(ratio+i, nr-i); else { warning("Null or negative global weighting factor:","defaulted to 1"); wfield->sigfac = 1.0; } /*-- Update variance threshold */ wfield->var_thresh *= (PIXTYPE)(wfield->sigfac*wfield->sigfac); free(ratio); } /* Compute 2nd derivatives along the y-direction */ NFPRINTF(OUTPUT, "Computing backgound d-map ..."); free(field->dback); field->dback = make_backspline(field, field->back); NFPRINTF(OUTPUT, "Computing backgound-noise d-map ..."); free(field->dsigma); field->dsigma = make_backspline(field, field->sigma); /* If asked for, force the backmean parameter to the supplied value */ if (field->back_type == BACK_ABSOLUTE) field->backmean = field->backdefault; field->fbackmean = field->backmean*field->fascale; field->fbacksig = field->backsig*field->fascale; return; } /******************************** backstat **********************************/ /* Compute robust statistical estimators in a row of meshes. */ void backstat(backstruct *backmesh, backstruct *wbackmesh, PIXTYPE *buf, PIXTYPE *wbuf, size_t bufsize, int n, int w, int bw, PIXTYPE wthresh) { backstruct *bm, *wbm; double pix,wpix, sig, mean,wmean, sigma,wsigma, step; PIXTYPE *buft,*wbuft, lcut,wlcut, hcut,whcut; int m,h,x,y, npix,wnpix, offset, lastbite; h = bufsize/w; bm = backmesh; wbm = wbackmesh; offset = w - bw; step = sqrt(2/PI)*QUANTIF_NSIGMA/QUANTIF_AMIN; wmean = wsigma = wlcut = whcut = 0.0; /* to avoid gcc -Wall warnings */ for (m = n; m--; bm++,buf+=bw) { if (!m && (lastbite=w%bw)) { bw = lastbite; offset = w-bw; } mean = sigma = 0.0; buft=buf; /*-- We separate the weighted case at this level to avoid penalty in CPU */ npix = 0; if (wbackmesh) { wmean = wsigma = 0.0; wbuft = wbuf; for (y=h; y--; buft+=offset,wbuft+=offset) for (x=bw; x--;) { pix = *(buft++); if ((wpix = *(wbuft++)) < wthresh && pix > -BIG) { wmean += wpix; wsigma += wpix*wpix; mean += pix; sigma += pix*pix; npix++; } } } else { for (y=h; y--; buft+=offset) for (x=bw; x--;) if ((pix = *(buft++)) > -BIG) { mean += pix; sigma += pix*pix; npix++; } } /*-- If not enough valid pixels, discard this mesh */ if ((float)npix < (float)(bw*h*BACK_MINGOODFRAC)) { bm->mean = bm->sigma = -BIG; if (wbackmesh) { wbm->mean = wbm->sigma = -BIG; wbm++; wbuf += bw; } continue; } if (wbackmesh) { wmean /= (double)npix; wsigma = (sig = wsigma/npix - wmean*wmean)>0.0? sqrt(sig):0.0; wlcut = wbm->lcut = (PIXTYPE)(wmean - 2.0*wsigma); whcut = wbm->hcut = (PIXTYPE)(wmean + 2.0*wsigma); } mean /= (double)npix; sigma = (sig = sigma/npix - mean*mean)>0.0? sqrt(sig):0.0; lcut = bm->lcut = (PIXTYPE)(mean - 2.0*sigma); hcut = bm->hcut = (PIXTYPE)(mean + 2.0*sigma); mean = sigma = 0.0; npix = wnpix = 0; buft = buf; if (wbackmesh) { wmean = wsigma = 0.0; wbuft=wbuf; for (y=h; y--; buft+=offset, wbuft+=offset) for (x=bw; x--;) { pix = *(buft++); if ((wpix = *(wbuft++))=lcut) { mean += pix; sigma += pix*pix; npix++; if (wpix<=whcut && wpix>=wlcut) { wmean += wpix; wsigma += wpix*wpix; wnpix++; } } } } else for (y=h; y--; buft+=offset) for (x=bw; x--;) { pix = *(buft++); if (pix<=hcut && pix>=lcut) { mean += pix; sigma += pix*pix; npix++; } } bm->npix = npix; mean /= (double)npix; sig = sigma/npix - mean*mean; sigma = sig>0.0 ? sqrt(sig):0.0; bm->mean = mean; bm->sigma = sigma; if ((bm->nlevels = (int)(step*npix+1)) > QUANTIF_NMAXLEVELS) bm->nlevels = QUANTIF_NMAXLEVELS; bm->qscale = sigma>0.0? 2*QUANTIF_NSIGMA*sigma/bm->nlevels : 1.0; bm->qzero = mean - QUANTIF_NSIGMA*sigma; if (wbackmesh) { wbm->npix = wnpix; wmean /= (double)wnpix; sig = wsigma/wnpix - wmean*wmean; wsigma = sig>0.0 ? sqrt(sig):0.0; wbm->mean = wmean; wbm->sigma = wsigma; if ((wbm->nlevels = (int)(step*wnpix+1)) > QUANTIF_NMAXLEVELS) wbm->nlevels = QUANTIF_NMAXLEVELS; wbm->qscale = wsigma>0.0? 2*QUANTIF_NSIGMA*wsigma/wbm->nlevels : 1.0; wbm->qzero = wmean - QUANTIF_NSIGMA*wsigma; wbm++; wbuf += bw; } } return; } /******************************** backhisto *********************************/ /* Compute robust statistical estimators in a row of meshes. */ void backhisto(backstruct *backmesh, backstruct *wbackmesh, PIXTYPE *buf, PIXTYPE *wbuf, size_t bufsize, int n, int w, int bw, PIXTYPE wthresh) { backstruct *bm,*wbm; PIXTYPE *buft,*wbuft, pix; float qscale,wqscale, cste,wcste, wpix; int *histo,*whisto; int h,m,x,y, nlevels,wnlevels, lastbite, offset, bin; h = bufsize/w; bm = backmesh; wbm = wbackmesh; offset = w - bw; for (m=0; m++mean <= -BIG) { if (wbackmesh) { wbm++; wbuf += bw; } continue; } nlevels = bm->nlevels; histo = bm->histo; qscale = bm->qscale; cste = 0.499999 - bm->qzero/qscale; buft = buf; if (wbackmesh) { wnlevels = wbm->nlevels; whisto = wbm->histo; wqscale = wbm->qscale; wcste = 0.499999 - wbm->qzero/wqscale; wbuft = wbuf; for (y=h; y--; buft+=offset, wbuft+=offset) for (x=bw; x--;) { bin = (int)((pix=*(buft++))/qscale + cste); if ((wpix = *(wbuft++))-BIG && bin=0) { (*(histo+bin))++; bin = (int)(wpix/wqscale + wcste); if (bin>=0 && bin=0 && bin-BIG) (*(histo+bin))++; } } return; } /******************************* backguess **********************************/ /* Estimate the background from a histogram; */ float backguess(backstruct *bkg, float *mean, float *sigma) #define EPS (1e-4) /* a small number */ { int *histo, *hilow, *hihigh, *histot; unsigned int lowsum, highsum, sum; double ftemp, mea, sig, sig1, med, dpix; int i, n, lcut,hcut, nlevelsm1, pix; /* Leave here if the mesh is already classified as `bad' */ if (bkg->mean<=-BIG) { *mean = *sigma = -BIG; return -BIG; } histo = bkg->histo; hcut = nlevelsm1 = bkg->nlevels-1; lcut = 0; sig = 10.0*nlevelsm1; sig1 = 1.0; mea = med = bkg->mean; for (n=100; n-- && (sig>=0.1) && (fabs(sig/sig1-1.0)>EPS);) { sig1 = sig; sum = mea = sig = 0.0; lowsum = highsum = 0; histot = hilow = histo+lcut; hihigh = histo+hcut; for (i=lcut; i<=hcut; i++) { if (lowsum=histo? ((hihigh-histo)+0.5+((double)highsum-lowsum)/(2.0*(*hilow>*hihigh? *hilow:*hihigh))) : 0.0; if (sum) { mea /= (double)sum; sig = sig/sum - mea*mea; } sig = sig>0.0?sqrt(sig):0.0; lcut = (ftemp=med-3.0*sig)>0.0 ?(int)(ftemp>0.0?ftemp+0.5:ftemp-0.5):0; hcut = (ftemp=med+3.0*sig)0.0?ftemp+0.5:ftemp-0.5) : nlevelsm1; } *mean = fabs(sig)>0.0? (fabs(bkg->sigma/(sig*bkg->qscale)-1) < 0.0 ? bkg->qzero+mea*bkg->qscale :(fabs((mea-med)/sig)< 0.3 ? bkg->qzero+(2.5*med-1.5*mea)*bkg->qscale :bkg->qzero+med*bkg->qscale)) :bkg->qzero+mea*bkg->qscale; *sigma = sig*bkg->qscale; return *mean; } /******************************* filter_back *********************************/ /* Median filtering of the background map to remove the contribution from bright sources. */ void filter_back(fieldstruct *field) { float *back,*sigma, *back2,*sigma2, *bmask,*smask, *sigmat, d2,d2min, fthresh, med, val,sval; int i,j,px,py, np, nx,ny, npx,npx2, npy,npy2, dpx,dpy, x,y, nmin; fthresh = prefs.back_fthresh; nx = field->nbackx; ny = field->nbacky; np = field->nback; npx = field->nbackfx/2; npy = field->nbackfy/2; npy *= nx; QMALLOC(bmask, float, (2*npx+1)*(2*npy+1)); QMALLOC(smask, float, (2*npx+1)*(2*npy+1)); QMALLOC(back2, float, np); QMALLOC(sigma2, float, np); back = field->back; sigma = field->sigma; val = sval = 0.0; /* to avoid gcc -Wall warnings */ /* Look for `bad' meshes and interpolate them if necessary */ for (i=0,py=0; py-BIG) { d2 = (float)(x-px)*(x-px)+(y-py)*(y-py); if (d2npy) npy2 = npy; if (npy2>py) npy2 = py; for (px=0; pxnpx) npx2 = npx; if (npx2>px) npx2 = px; i=0; for (dpy = -npy2; dpy<=npy2; dpy+=nx) { y = py+dpy; for (dpx = -npx2; dpx <= npx2; dpx++) { x = px+dpx; bmask[i] = back[x+y]; smask[i++] = sigma[x+y]; } } if (fabs((med=fqmedian(bmask, i))-back[px+py])>=fthresh) { back2[px+py] = med; sigma2[px+py] = fqmedian(smask, i); } else { back2[px+py] = back[px+py]; sigma2[px+py] = sigma[px+py]; } } } free(bmask); free(smask); memcpy(back, back2, np*sizeof(float)); field->backmean = (double)fqmedian(back2, np); free(back2); memcpy(sigma, sigma2, np*sizeof(float)); field->backsig = (double)fqmedian(sigma2, np); if (field->backsig<=0.0) { sigmat = sigma2+np; for (i=np; i-- && *(--sigmat)>0.0;); if (i>=0 && i<(np-1)) field->backsig = fqmedian(sigmat+1, np-1-i); else { if (field->flags&(DETECT_FIELD|MEASURE_FIELD)) warning("Image contains mainly constant data; ", "I'll try to cope with that..."); field->backsig = 1.0; } } free(sigma2); return; } /******************************* make_backspline *****************************/ /* Pre-compute 2nd derivatives along the y direction at background nodes. */ float *make_backspline(fieldstruct *field, float *map) { int x,y, nbx,nby,nbym1; float *dmap,*dmapt,*mapt, *u, temp; nbx = field->nbackx; nby = field->nbacky; nbym1 = nby - 1; QMALLOC(dmap, float, field->nback); for (x=0; x1) { QMALLOC(u, float, nbym1); /* temporary array */ *dmapt = *u = 0.0; /* "natural" lower boundary condition */ mapt += nbx; for (y=1; ywidth; if (field->back_type==BACK_ABSOLUTE) { /*-- In absolute background mode, just subtract a cste */ bval = (PIXTYPE)field->backmean; for (i=width; i--;) *(line++) = bval; return; } nbx = field->nbackx; nbxm1 = nbx - 1; nby = field->nbacky; if (nby > 1) { dy = (float)y/field->backh - 0.5; dy -= (yl = (int)dy); if (yl<0) { yl = 0; dy -= 1.0; } else if (yl>=nby-1) { yl = nby<2 ? 0 : nby-2; dy += 1.0; } /*-- Interpolation along y for each node */ cdy = 1 - dy; dy3 = (dy*dy*dy-dy); cdy3 = (cdy*cdy*cdy-cdy); ystep = nbx*yl; blo = field->back + ystep; bhi = blo + nbx; dblo = field->dback + ystep; dbhi = dblo + nbx; QMALLOC(node, float, nbx); /* Interpolated background */ nodep = node; for (x=nbx; x--;) *(nodep++) = cdy**(blo++) + dy**(bhi++) + cdy3**(dblo++) + dy3**(dbhi++); /*-- Computation of 2nd derivatives along x */ QMALLOC(dnode, float, nbx); /* 2nd derivative along x */ if (nbx>1) { QMALLOC(u, float, nbxm1); /* temporary array */ *dnode = *u = 0.0; /* "natural" lower boundary condition */ nodep = node+1; for (x=nbxm1; --x; nodep++) { temp = -1/(*(dnode++)+4); *dnode = temp; temp *= *(u++) - 6*(*(nodep+1)+*(nodep-1)-2**nodep); *u = temp; } *(++dnode) = 0.0; /* "natural" upper boundary condition */ for (x=nbx-2; x--;) { temp = *(dnode--); *dnode = (*dnode*temp+*(u--))/6.0; } free(u); dnode--; } } else { /*-- No interpolation and no new 2nd derivatives needed along y */ node = field->back; dnode = field->dback; } /*-- Interpolation along x */ if (nbx>1) { nx = field->backw; xstep = 1.0/nx; changepoint = nx/2; dx = (xstep - 1)/2; /* dx of the first pixel in the row */ dx0 = ((nx+1)%2)*xstep/2; /* dx of the 1st pixel right to a bkgnd node */ blo = node; bhi = node + 1; dblo = dnode; dbhi = dnode + 1; for (x=i=0,j=width; j--; i++, dx += xstep) { if (i==changepoint && x>0 && x1) { free(node); free(dnode); } return; } /******************************* backrmsline ******************************** PROTO void backrmsline(fieldstruct *field, int y, PIXTYPE *line) PURPOSE Bicubic-spline interpolation of the background noise along the current scanline (y). INPUT Measurement or detection field pointer, Current line position. Where to put the data. OUTPUT -. NOTES Most of the code is a copy of subbackline(), for optimization reasons. AUTHOR E. Bertin (IAP & Leiden & ESO) VERSION 02/02/98 ***/ void backrmsline(fieldstruct *field, int y, PIXTYPE *line) { int i,j,x,yl, nbx,nbxm1,nby, nx,width, ystep, changepoint; float dx,dx0,dy,dy3, cdx,cdy,cdy3, temp, xstep, *node,*nodep,*dnode, *blo,*bhi,*dblo,*dbhi, *u; nbx = field->nbackx; nbxm1 = nbx - 1; nby = field->nbacky; if (nby > 1) { dy = (float)y/field->backh - 0.5; dy -= (yl = (int)dy); if (yl<0) { yl = 0; dy -= 1.0; } else if (yl>=nby-1) { yl = nby<2 ? 0 : nby-2; dy += 1.0; } /*-- Interpolation along y for each node */ cdy = 1 - dy; dy3 = (dy*dy*dy-dy); cdy3 = (cdy*cdy*cdy-cdy); ystep = nbx*yl; blo = field->sigma + ystep; bhi = blo + nbx; dblo = field->dsigma + ystep; dbhi = dblo + nbx; QMALLOC(node, float, nbx); /* Interpolated background */ nodep = node; for (x=nbx; x--;) *(nodep++) = cdy**(blo++) + dy**(bhi++) + cdy3**(dblo++) + dy3**(dbhi++); /*-- Computation of 2nd derivatives along x */ QMALLOC(dnode, float, nbx); /* 2nd derivative along x */ if (nbx>1) { QMALLOC(u, float, nbxm1); /* temporary array */ *dnode = *u = 0.0; /* "natural" lower boundary condition */ nodep = node+1; for (x=nbxm1; --x; nodep++) { temp = -1/(*(dnode++)+4); *dnode = temp; temp *= *(u++) - 6*(*(nodep+1)+*(nodep-1)-2**nodep); *u = temp; } *(++dnode) = 0.0; /* "natural" upper boundary condition */ for (x=nbx-2; x--;) { temp = *(dnode--); *dnode = (*dnode*temp+*(u--))/6.0; } free(u); dnode--; } } else { /*-- No interpolation and no new 2nd derivatives needed along y */ node = field->sigma; dnode = field->dsigma; } /*-- Interpolation along x */ width = field->width; if (nbx>1) { nx = field->backw; xstep = 1.0/nx; changepoint = nx/2; dx = (xstep - 1)/2; /* dx of the first pixel in the row */ dx0 = ((nx+1)%2)*xstep/2; /* dx of the 1st pixel right to a bkgnd node */ blo = node; bhi = node + 1; dblo = dnode; dbhi = dnode + 1; for (x=i=0,j=width; j--; i++, dx += xstep) { if (i==changepoint && x>0 && x1) { free(node); free(dnode); } return; } /********************************* end_back **********************************/ /* Terminate background procedures (mainly freeing memory). */ void end_back(fieldstruct *field) { free(field->back); free(field->dback); free(field->sigma); free(field->dsigma); free(field->backline); return; } swarp-2.41.5/src/back.h000066400000000000000000000047421400430667300146110ustar00rootroot00000000000000/* * back.h * * Include file for back.c. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 26/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _FIELD_H_ #include "field.h" #endif /*----------------------------- Internal constants --------------------------*/ #define BACK_BUFSIZE (8*1024*1024) /* bkgnd buffer */ #define BACK_MINGOODFRAC 0.5 /* min frac with good weights*/ #define QUANTIF_NSIGMA 5 /* histogram limits */ #define QUANTIF_NMAXLEVELS 4096 /* max nb of quantif. levels */ #define QUANTIF_AMIN 4 /* min nb of "mode pixels" */ /* NOTES: One must have: BACK_BUFSIZE >= MAXPICSIZE 0 < QUANTIF_NSIGMA <= 10 QUANTIF_AMIN > 0 */ /*------------------------------- structures --------------------------------*/ /* Background info */ typedef struct structback { float mode, mean, sigma; /* Background mode, mean and sigma */ int *histo; /* Pointer to a histogram */ int nlevels; /* Nb of histogram bins */ float qzero, qscale; /* Position of histogram */ float lcut, hcut; /* Histogram cuts */ int npix; /* Number of pixels involved */ } backstruct; /*------------------------------- functions ---------------------------------*/ extern void backhisto(backstruct *, backstruct *, PIXTYPE *, PIXTYPE *, size_t, int, int, int, PIXTYPE), backline(fieldstruct *, int, PIXTYPE *), backstat(backstruct *, backstruct *, PIXTYPE *, PIXTYPE *, size_t, int, int, int, PIXTYPE), backrmsline(fieldstruct *, int, PIXTYPE *), end_back(fieldstruct *), filter_back(fieldstruct *), make_back(fieldstruct *, fieldstruct *, int); extern float backguess(backstruct *, float *, float *), *make_backspline(fieldstruct *, float *); swarp-2.41.5/src/coadd.c000066400000000000000000002143071400430667300147560ustar00rootroot00000000000000/* * coadd.c * * Manage co-addition (image combine). * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2021 IAP/CNRS/SorbonneU * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 27/01/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include #include #include #include #include "define.h" #include "types.h" #include "globals.h" #include "fits/fitscat.h" #include "fitswcs.h" #include "coadd.h" #include "data.h" #include "field.h" #include "header.h" #include "interpolate.h" #include "prefs.h" #ifdef USE_THREADS #include "threads.h" #endif #include "weight.h" #include "wcs/wcs.h" #define ARRAY_BIT(x,y) (array[(y/(8*sizeof(unsigned int)))*nnode+x]&(1 \ <<(y%(8*sizeof(unsigned int))))) #define SET_ARRAY_BIT(x,y) (array[(y/(8*sizeof(unsigned int)))*ninput+x] \ |= (1<<(y%(8*sizeof(unsigned int))))) #ifdef HAVE_LGAMMA #define LOGGAMMA lgamma #else #define LOGGAMMA gammln static double gammln(); #endif coaddenum coadd_type; double *coadd_bias; FLAGTYPE *multiibuf,*multiwibuf, *outibuf,*outwibuf; PIXTYPE *multibuf,*multiwbuf, *outbuf,*outwbuf, coadd_wthresh, *coadd_pixstack, *coadd_pixfstack; unsigned int *multinbuf,*multiobuf; int coadd_nomax, coadd_width, iflag; FILE *cliplog; fieldstruct **infields; #ifdef USE_THREADS pthread_t *thread, movthread; pthread_mutex_t coaddmutex; threads_gate_t *pthread_startgate, *pthread_stopgate, *pthread_startgate2, *pthread_stopgate2; FLAGTYPE *pthread_lineibuf, *pthread_multiibuf; PIXTYPE *pthread_linebuf, *pthread_multibuf; unsigned int *pthread_multinbuf, *pthread_multiobuf, *pthread_baseline_y, *pthread_origin; int pthread_bufline, pthread_nbuflines, pthread_npix, pthread_step, pthread_endflag, pthread_wdataflag; #endif /*------------------------------ function -----------------------------------*/ static int coadd_iline(int l), coadd_line(int l, int b, int *bufmin); static double *chi_bias(int n); static PIXTYPE fast_median(PIXTYPE *arr, int n); static int coadd_iload(fieldstruct *field, fieldstruct *wfield, FLAGTYPE *multibuf, FLAGTYPE *multiwibuf, unsigned int *multinbuf, int *rawpos, int *rawmin, int *rawmax, int nlines, int outwidth, int multinmax), coadd_load(fieldstruct *field, fieldstruct *wfield, PIXTYPE *multibuf, unsigned int *multiobuf, PIXTYPE *multiwbuf, unsigned int *multinbuf, int *rawpos, int *rawmin, int *rawmax, int nlines, int outwidth, int multinmax, int n); static void max_clique_recur(unsigned int *array, int nnode, int *old, int ne, int ce, int **compsub, int *ncompsub, int **best, int *nbest); #ifdef USE_THREADS static void *pthread_coadd_lines(void *arg), *pthread_move_lines(void *arg); #endif #ifdef HAVE_CFITSIO /** * CFITSIO * * Function to create a cfitsio tile-compressed image. * Uses the existing filename with an 'fz' extension. * Currently, cfitsio compression defaults are used: * - each tile is one row of the image * - Rice compression is used */ int setupTileCompressedFile(fieldstruct *outfield, int disallow_negative_pixels) { if (!prefs.tile_compress_flag) { outfield->cat->tab->infptr = NULL; //printf("DEBUG CFITSIO NOT creating tile-compressed output image file\n"); return 0; } // create a file-name: use existing name with '.fz' suffix char compressedFilename[strlen(outfield->cat->filename) + 20]; sprintf(compressedFilename, "!%s.fz[compress]", outfield->cat->filename); // now create file int status = 0; fits_create_file(&outfield->cat->tab->infptr, compressedFilename, &status); if (status != 0) { printf("CFITSIO ERROR creating output image file\n"); fits_report_error(stderr, status); return 0; } // now create image extension long naxis[2] = {outfield->cat->tab->naxisn[0], outfield->cat->tab->naxisn[1]}; if (disallow_negative_pixels) { // set quantisation method. We can use this to prevent <0 pixel values status = 0; #if CFITSIO_MAJOR >= 3 #if CFITSIO_MINOR >= 35 fits_set_quantize_method(outfield->cat->tab->infptr, SUBTRACTIVE_DITHER_2, &status); #else fits_set_quantize_dither(outfield->cat->tab->infptr, SUBTRACTIVE_DITHER_1, &status); #endif #endif if (status != 0) { printf("CFITSIO ERROR error setting CFitsIO quantize method\n"); fits_report_error(stderr, status); return 0; } } // actually create the image status = 0; fits_create_img(outfield->cat->tab->infptr, FLOAT_IMG, 2, naxis, &status); if (status != 0) { printf("CFITSIO ERROR creating output image extension\n"); fits_report_error(stderr, status); return 0; } // point to the first element in the image, ready for writing outfield->tab->currentElement = 1; //printf("DEBUG CFITSIO successfully created tile-compressed output image file, %s\n", compressedFilename); // now, change original filename to temp one (.tmp suffix) sprintf(outfield->cat->filename, "%s.tmp", outfield->cat->filename); return 1; } /** * CFITSIO * * Function to copy all non-structural keywords from one FITS file to tile-compressed one * */ int copyHeaderToTileCompressedFile(fieldstruct *outfield) { if (outfield->tab->infptr == NULL) return 0; // use cfitsio to open input file from which to copy header fitsfile *infptr; int status = 0; fits_open_file(&infptr, outfield->cat->filename, READONLY, &status); if (status != 0) { printf("ERROR cfitsio could not open FITS file for header copying: %s\n", outfield->cat->filename); fits_report_error(stderr, status); return 0; } // copy headers int nkeys; fits_get_hdrspace(infptr, &nkeys, NULL, &status); // loop through and copy non-structural keywords int i; char card[81]; for (i=1; i<=nkeys; i++) { fits_read_record(infptr, i, card, &status); if (fits_get_keyclass(card) > TYP_CMPRS_KEY) { fits_write_record(outfield->tab->infptr, card, &status); //printf("DEBUG WRITING %s\n", card); } //else //printf("DEBUG NOT WRITING %s\n", card); } return 1; } /** * CFITSIO * * Function to close a cfitsio-created tile-compressed image. * Also deletes temp non-tile-compressed file used to copy header keywords. * */ int closeTileCompressedFile(fieldstruct *outfield) { if (outfield->tab->infptr == NULL) return 0; // first copy header from non-tile compressed file copyHeaderToTileCompressedFile(outfield); int status = 0; fits_close_file(outfield->tab->infptr, &status); if (status != 0) { printf("CFITSIO ERROR closing tile-compressed image file\n"); fits_report_error(stderr, status); return 0; } //printf("CFITSIO successfully closed tile-compressed output image file\n"); // now delete temp file if (unlink (outfield->cat->filename) != 0) { printf("CFITSIO ERROR could not delete %s\n", outfield->cat->filename); } return 1; } #endif // HAVE_CFITSIO /******* coadd_fields ********************************************************* PROTO int coadd_fields(fieldstruct **infield, fieldstruct **inwfield, int ninput, fieldstruct *outfield, fieldstruct *outwfield, coaddenum coaddtype, PIXTYPE wthresh) PURPOSE Coadd images. INPUT Input field ptr array, Input weight field ptr array, number of input fields, Output field ptr, Output weight field ptr, Coaddition type. OUTPUT RETURN_OK if no error, or RETURN_ERROR in case of non-fatal error(s). NOTES -. AUTHOR E. Bertin (IAP) VERSION 27/01/2021 ***/ int coadd_fields(fieldstruct **infield, fieldstruct **inwfield, int ninput, fieldstruct *outfield, fieldstruct *outwfield, coaddenum coaddtype, PIXTYPE wthresh) { #ifdef USE_THREADS static pthread_attr_t pthread_attr; int *proc, p; #endif wcsstruct *wcs; FLAGTYPE *emptyibuf,*outiline, *ipix,*wipix; PIXTYPE *emptybuf,*outline, *pix,*wpix; double exptime, w,w1,w2, mw, satlev; size_t multiwidth; unsigned int *cflag,*array, d, n, n1,n2, flag; int bufmin[NAXIS], bufmax[NAXIS], bufpos[NAXIS], rawmax[NAXIS], rawpos[NAXIS], rawpos2[NAXIS], min1[NAXIS],max1[NAXIS], *ybegbufline,*yendbufline, *maxclique, y, y2,dy, ybuf,ybufmax, outwidth, width, height,min,max, naxis, nlines, nlinesmax, nbuflines,nbuflines2,nbuflinesmax, omax,omax2, offbeg, offend, fieldno, nopenfiles, closeflag; #ifdef HAVE_CFITSIO // CFITSIO set up tile compressed output images (if specified by user) setupTileCompressedFile(outfield, 0); setupTileCompressedFile(outwfield, 1); #endif // HAVE_CFITSIO coadd_type = coaddtype; coadd_wthresh = wthresh; naxis = outfield->tab->naxis; iflag = outfield->bitpix>0; /* The output width is the useful length of the NAXIS1 axis */ width = outfield->width; /* The output ``height'' is the product of all other axis lengths */ height = outfield->height; /* Find global extrema of mapped image */ for (d=0; dwcs; /*---- Update input frame limits in output frame */ wcs->outmin[d] = (int)floor(outfield->wcs->crpix[d]-wcs->crpix[d] + 1.0); if (wcs->outmin[d] < min) min = (int)wcs->outmin[d]; wcs->outmax[d] = wcs->outmin[d] + wcs->naxisn[d] - 1; if (wcs->outmax[d] > max) max = (int)wcs->outmax[d]; } rawpos[d] = 1; rawmax[d] = outfield->wcs->naxisn[d]; bufmin[d] = min>0 ? (min0 ? (maxwcs; nbuflines = nbuflines2 = 0; nlines = 1; for (d=1; d1) nlines *= (bufmax[d-1] - bufmin[d-1]) + 1; nbuflines += (wcs->outmin[d]-bufmin[d])*nlines; nbuflines2 += (wcs->outmax[d]-bufmin[d])*nlines; } ybegbufline[n] = nbuflines; yendbufline[n] = nbuflines2; } /* Empty pixels at the beginning of each line */ offbeg = bufmin[0]-1; /* Empty pixels at the end of each line */ offend = outfield->wcs->naxisn[0] - bufmax[0]; coadd_width = outwidth = outfield->wcs->naxisn[0] - offend - offbeg; /* Build a graph of overlaps */ QCALLOC(array, unsigned int, ninput*(1+(ninput-1)/(8*sizeof(unsigned int)))); for (n1=0; n1wcs; for (d=0; doutmin[d]; max1[d] = wcs->outmax[d]; } for (n2=n1+1; n2wcs; flag = 1; for (d=0; doutmin[d] > max1[d] || wcs->outmax[d] < min1[d]) { flag = 0; break; } if (flag) { SET_ARRAY_BIT(n1,n2); SET_ARRAY_BIT(n2,n1); } } } /* Find the densest overlap, that is the maximal clique (NP-complete pb!) */ omax = max_clique(array, ninput, &maxclique); free(array); /* Compute maximum gain and maximum total exposure time */ exptime = w1 = w2 = mw = 0.0; fieldno = -1; omax2 = 0; for (n=0; nfieldno == fieldno) continue; omax2++; fieldno = infield[n1]->fieldno; exptime += infield[n1]->exptime; w = ((coaddtype == COADD_WEIGHTED || coaddtype == COADD_CLIPPED) && infield[n1]->backsig > 0.0)? // entirely true only in the // approximation of no clipping 1.0/(infield[n1]->fbacksig*infield[n1]->fbacksig) : 1.0; w1 += w; if (infield[n1]->fgain > 0.0) { w2 += w*w/infield[n1]->fgain; mw += infield[n1]->fgain; } } free(maxclique); outfield->fieldno = omax2; /* This is not what is meant for but hey */ outfield->exptime = exptime; /* Compute biases for CHI and centered CHI combine types */ if (coaddtype == COADD_CHI_MODE || coaddtype == COADD_CHI_MEAN) coadd_bias = chi_bias(omax2); /* Approximation to the final equivalent gain */ outfield->fgain = 0.0; if (coaddtype == COADD_WEIGHTED || coaddtype == COADD_AVERAGE || coaddtype == COADD_CLIPPED) { if (w2 > 0.0) outfield->fgain = w1*w1/w2; } else if (coaddtype == COADD_MEDIAN) { if (w2 > 0.0) outfield->fgain = w1*w1/w2; if (omax2 > 2) outfield->fgain /= PI; } else if (coaddtype == COADD_SUM) { if (w2 > 0.0) outfield->fgain = w1*w1/w2/omax2; } else outfield->fgain = mw/omax2; outfield->gain = outfield->fgain; /* "true" gain = effective gain */ /* Compute output saturation level (the minimum on all saturation) */ satlev = BIG; for (n=0; nfsaturation = (prefs.subback_flag[n] && infield[n]->fsaturation > infield[n]->fbackmean)? (infield[n]->fsaturation - infield[n]->fbackmean) : infield[n]->fsaturation; if (infield[n]->fsaturation < satlev) satlev = infield[n]->fsaturation; } outfield->saturation = outfield->fsaturation = satlev; /* Add relevant information to output FITS headers */ writefitsinfo_outfield(outfield, *infield); writefitsinfo_outfield(outwfield, inwfield? *inwfield : *infield); *gstr = '\0'; QPRINTF(OUTPUT, "-------------- Co-adding frames \n"); QPRINTF(OUTPUT, "Maximum overlap density: %d frame%s\n", omax2, omax2>1? "s" : ""); coadd_nomax = omax; multiwidth = (size_t)outwidth*omax; nbuflinesmax = (int)(((size_t)prefs.coaddbuf_size*1024*1024) / ((2*multiwidth+3*outwidth+2*coadd_nomax)*sizeof(PIXTYPE))); if (nbuflinesmax < 1) nbuflinesmax = 1; else if (nbuflinesmax>height) nbuflinesmax = height; #ifdef USE_THREADS /* Number of active threads */ nproc = prefs.nthreads; /* Make sure that the number of multibuffer lines is a multiple of the */ /* number of processes */ nbuflinesmax += (nproc - (nbuflinesmax%nproc))%nproc; #endif /* Allocate memory for the "multi-buffers" storing "packed" pixels from all */ /* images for the current line(s), prior to co-addition */ if (iflag) { QMALLOC(multiibuf, FLAGTYPE, nbuflinesmax*multiwidth); QMALLOC(multiwibuf, FLAGTYPE, nbuflinesmax*multiwidth); } else { QMALLOC(multibuf, PIXTYPE, nbuflinesmax*multiwidth); QMALLOC(multiobuf, unsigned int, nbuflinesmax*multiwidth); if (coadd_type==COADD_CLIPPED && prefs.clip_logflag) { /* Open clipping log for mode COADD_CLIPPED */ if(!(cliplog = fopen(prefs.clip_logname,"w"))) error(EXIT_FAILURE, "*Error*: cannot open for writing ", prefs.clip_logname); } QMALLOC(multiwbuf, PIXTYPE, nbuflinesmax*multiwidth); } QMALLOC(multinbuf, unsigned int, nbuflinesmax*(size_t)outwidth); /* Allocate memory for the output buffers that contain "empty data" */ if (iflag) { QCALLOC(emptyibuf, FLAGTYPE, width); QCALLOC(outiline, FLAGTYPE, width); } else { QCALLOC(emptybuf, PIXTYPE, width); QCALLOC(outline, PIXTYPE, width); } /* Allocate memory for the output buffers that contain the final data in */ /* internal format (PIXTYPE or FLAGTYPE) */ if (iflag) { QMALLOC(outibuf, FLAGTYPE, nbuflinesmax*(size_t)outwidth); QMALLOC(outwibuf, FLAGTYPE, nbuflinesmax*(size_t)outwidth); } else { QMALLOC(outbuf, PIXTYPE, nbuflinesmax*(size_t)outwidth); QMALLOC(outwbuf, PIXTYPE, nbuflinesmax*(size_t)outwidth); QMALLOC(coadd_pixstack, PIXTYPE, nbuflinesmax*(size_t)coadd_nomax); QMALLOC(coadd_pixfstack, PIXTYPE, nbuflinesmax*(size_t)coadd_nomax); } QCALLOC(cflag, unsigned int, ninput); /* Open output file and save header */ if (open_cat(outfield->cat, WRITE_ONLY) != RETURN_OK) error(EXIT_FAILURE, "*Error*: cannot open for writing ", outfield->filename); QFWRITE(outfield->tab->headbuf, outfield->tab->headnblock*FBSIZE, outfield->cat->file, outfield->filename); /* Open output weight file and save header */ outwfield->sigfac = (double)1.0; /* A possible scaling among others */ if (open_cat(outwfield->cat, WRITE_ONLY) != RETURN_OK) error(EXIT_FAILURE, "*Error*: cannot open for writing ", outwfield->filename); QFWRITE(outwfield->tab->headbuf, outwfield->tab->headnblock*FBSIZE, outwfield->cat->file, outwfield->filename); /* Only for WRITING the weights */ set_weightconv(outwfield); infields = infield; // global pointer so coadd_line can access it easily /* Start all threads! */ #ifdef USE_THREADS /* Set up multi-threading stuff */ QPTHREAD_MUTEX_INIT(&coaddmutex, NULL); QPTHREAD_ATTR_INIT(&pthread_attr); QPTHREAD_ATTR_SETDETACHSTATE(&pthread_attr, PTHREAD_CREATE_JOINABLE); pthread_startgate = threads_gate_init(nproc+1, NULL); pthread_stopgate = threads_gate_init(nproc+1, NULL); pthread_startgate2 = threads_gate_init(2, NULL); pthread_stopgate2 = threads_gate_init(2, NULL); QMALLOC(proc, int, nproc); QMALLOC(thread, pthread_t, nproc); pthread_bufline = pthread_nbuflines = nbuflinesmax; pthread_endflag = 0; /* Start the co-addition threads */ for (p=0; p Preparing line:%7d / %-7d\n\33[1A", y+1, height); /*-- Skip empty lines */ for (d=naxis; --d;) rawpos2[d] = rawpos[d]; nlinesmax = height-y; for (nbuflines=nlines=0; nbuflinesbufmax[d]) break; if (d<=0 && !(nbuflines++)) /*------ bufpos[] stores the coordinates of the next non-empty line */ for (d=naxis; --d;) bufpos[d] = rawpos2[d]; for (d=1; d Reading line:%7d / %-7d\n\33[1A", y+1,height); for (n=0; n= ybufmax) continue; wcs = infield[n]->wcs; /*---- Discard images entirely below the current lower limit */ if (yendbufline[n] < ybuf) { cflag[n] |= COADDFLAG_FINISHED; continue; } /*---- Open images if needed */ if (!(cflag[n] & COADDFLAG_OPEN)) { cflag[n] |= COADDFLAG_OPEN; dy = ybegbufline[n] - ybuf; if (dy<0) dy = 0; } else dy = 0; /* We just keep reading the file */ nbuflines2 = yendbufline[n] - ybuf + 1; if (nbuflines2 > nbuflines) nbuflines2 = nbuflines; nbuflines2 -= dy; /*---- (re-)Open images if needed */ if ((closeflag = !infield[n]->cat->file)) { if (open_cat(infield[n]->cat, READ_ONLY) != RETURN_OK) error(EXIT_FAILURE,"*Error*: cannot open for reading ", infield[n]->filename); nopenfiles++; } if (inwfield[n] && (closeflag = !inwfield[n]->cat->file)) { if (open_cat(inwfield[n]->cat, READ_ONLY) != RETURN_OK) error(EXIT_FAILURE,"*Error*: cannot open for reading ", inwfield[n]->filename); nopenfiles++; } /*---- Refill the buffers with new data */ if ((iflag && coadd_iload(infield[n], inwfield[n], multiibuf+dy*multiwidth, multiwibuf+dy*multiwidth, multinbuf+dy*(size_t)outwidth, bufpos, bufmin, bufmax, nbuflines2, outwidth, omax) != RETURN_OK) || ((!iflag)&&coadd_load(infield[n], inwfield[n], multibuf+dy*multiwidth, multiobuf+dy*multiwidth, multiwbuf+dy*multiwidth, multinbuf+dy*(size_t)outwidth, bufpos, bufmin, bufmax, nbuflines2, outwidth, omax, n) != RETURN_OK)) /*---- End of the image, we can close the file */ { close_cat(infield[n]->cat); nopenfiles--; if (inwfield[n]) { nopenfiles--; close_cat(inwfield[n]->cat); } cflag[n] ^= COADDFLAG_OPEN; cflag[n] |= COADDFLAG_FINISHED; } if (prefs.nopenfiles_max && nopenfiles >= prefs.nopenfiles_max) { if (close_cat(infield[n]->cat) != RETURN_OK) error(EXIT_FAILURE,"*Error*: cannot close ", infield[n]->filename); nopenfiles--; if (inwfield[n]) { if (close_cat(inwfield[n]->cat) != RETURN_OK) error(EXIT_FAILURE,"*Error*: cannot close ", inwfield[n]->filename); nopenfiles--; } } } NPRINTF(OUTPUT, "\33[1M> Co-adding line:%7d / %-7d\n\33[1A", y+1,height); /*-- Now perform the coaddition itself */ #ifdef USE_THREADS QPTHREAD_MUTEX_LOCK(&coaddmutex); pthread_bufline = 0; pthread_nbuflines = nbuflines; QPTHREAD_MUTEX_UNLOCK(&coaddmutex); pthread_baseline_y = &y; threads_gate_sync(pthread_startgate); /* ( Slave threads process the current buffer data here ) */ threads_gate_sync(pthread_stopgate); #else if (iflag) for (y2=0; y2 Writing line:%7d / %-7d\n\33[1A", y+1,height); /*-- Write the image buffer lines */ if (iflag) ipix = outibuf; else pix = outbuf; for (d=naxis; --d;) rawpos2[d] = rawpos[d]; for (y2=nlines; y2--;) { /*---- Skip empty lines */ for (d=naxis; --d;) if (rawpos2[d]bufmax[d]) break; if (iflag) { if (d>0) write_ibody(outfield->tab, emptyibuf, width); else { memcpy(outiline+offbeg, ipix, outwidth*sizeof(FLAGTYPE)); write_ibody(outfield->tab, outiline, width); ipix += outwidth; } } else { if (d>0) write_body(outfield->tab, emptybuf, width); else { memcpy(outline+offbeg, pix, outwidth*sizeof(PIXTYPE)); write_body(outfield->tab, outline, width); pix += outwidth; } } /*---- Update coordinate vector */ for (d=1; dbufmax[d]) break; if (iflag) { if (d>0) write_ibody(outwfield->tab, emptyibuf, width); else { memcpy(outiline+offbeg, wipix, outwidth*sizeof(PIXTYPE)); write_ibody(outwfield->tab, outiline, width); wipix += outwidth; } } else { if (d>0) write_body(outwfield->tab, emptybuf, width); else { var_to_weight(wpix, outwidth); memcpy(outline+offbeg, wpix, outwidth*sizeof(PIXTYPE)); write_body(outwfield->tab, outline, width); wpix += outwidth; } } /*---- Update coordinate vector */ for (d=1; dcat, outfield->tab->tabsize); pad_tab(outwfield->cat, outwfield->tab->tabsize); /* Close files */ close_cat(outfield->cat); close_cat(outwfield->cat); for (n = 0; ncat); if (inwfield[n]) close_cat(inwfield[n]->cat); } if (coadd_type == COADD_CLIPPED && prefs.clip_logflag) fclose(cliplog); #ifdef USE_THREADS pthread_endflag = 1; /* (Re-)activate existing threads... */ threads_gate_sync(pthread_startgate); threads_gate_sync(pthread_startgate2); /* ... and shutdown all threads */ for (p=0; p=1; nod--) { /*-- Interchange */ p = old[s]; old[s] = old[ne]; sel = old[ne] = p; /*-- Fill new set "not" */ newne = 0; for (i=0; i 1) /*---- Select a candidate disconnected to the fixed point */ for (s=ne; ARRAY_BIT(fixp,old[s]); s++); } free(new); return; } #ifdef USE_THREADS /****** pthread_coadd_lines **************************************************** PROTO void *pthread_coadd_lines(void *arg) PURPOSE thread that takes care of coadding image "lines" INPUT Pointer to the thread number. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 10/03/2014 ***/ void *pthread_coadd_lines(void *arg) { int *bufmin, bufline; bufline = -1; bufmin = (int *)arg; threads_gate_sync(pthread_startgate); while (!pthread_endflag) { QPTHREAD_MUTEX_LOCK(&coaddmutex); if (pthread_bufline-BIG/2) { ninput2++; wval += (wval2=1.0/wval2); val += fval2*wval2; } else *(pixft++) = fval2; } if (ninput2) { *(outwpix++) = (wval= 1.0/wval); *(outpix++) = val*wval; } else { *(outpix++) = (blankflag||!ninput)? 0.0 : fast_median(pixfstack, ninput); *(outwpix++) = BIG; } } break; case COADD_CLIPPED: QMALLOC(pixstack, PIXTYPE, coadd_nomax); QMALLOC(pixwstack, PIXTYPE, coadd_nomax); QMALLOC(pixstackbuf, PIXTYPE, coadd_nomax); QMALLOC(pixostack, unsigned int, coadd_nomax); inorigin = multiobuf + lcoadd_width * coadd_nomax; for (x=coadd_width; x--; inpix+=coadd_nomax, inwpix+=coadd_nomax, inorigin += coadd_nomax) // for each pixel in the line { ninput2 = 0; val2 = 0.0; wval = 0.0; inpixt = inpix; inwpixt = inwpix; pixt = pixstack; pixwt = pixwstack; pixot = pixostack; inorigint = inorigin; for (i=*(inn++); i--;) { val2 = *(inpixt++); wval2 = *(inwpixt++); origin2 = *(inorigint++); if (wval2-BIG/2) { ninput2++; *(pixt++) = val2; *(pixwt++) = wval2; *(pixot++) = origin2; wval += 1.0 / sqrt(wval2); } } switch(ninput2) { case 0: // no good values *(outpix++) = blankflag? 0.0 : val2; *(outwpix++) = BIG; break; case 1: // only one good value: take it *(outpix++) = *(pixstack); *(outwpix++) = *(pixwstack); break; case 2: // only two good values: reject both if not compatible; // else use weighted mean { int o1 = *(pixostack), o2 = *(pixostack+1); float f1f2o2 = fabsf(*(pixstack)+*(pixstack+1)) / 2.0, sumw = *(pixwstack) + *(pixwstack+1), sigmaeff = sqrtf(sumw + f1f2o2*(1.0/infields[o1]->fgain + 1.0/infields[o2]->fgain)), dpix = *(pixstack)-*(pixstack+1); if (fabs(dpix) <= prefs.clip_sigma*sigmaeff + prefs.clip_ampfrac*f1f2o2) { *(outpix++) = (*(pixstack) * *(pixwstack+1) + *(pixstack+1) * *(pixwstack)) / sumw; *(outwpix++) = *(pixwstack) * *(pixwstack+1) / sumw; } else // difference is too high, discard both { *(outpix++) = 0.0; *(outwpix++) = BIG; if (prefs.clip_logflag) { mu = (dpix > 0.0 ? 1.0 : -1.0) * (fabsf(dpix ) - prefs.clip_ampfrac*f1f2o2) / sigmaeff; fprintf(cliplog, "%4d %6d %6d %+10g\n", o1, ((int)(outpix - outbuf))%coadd_width + bufmin[0], b + l + (b==0 ? bufmin[1] : 1), mu); fprintf(cliplog, "%4d %6d %6d %+10g\n", o2, ((int)(outpix - outbuf))%coadd_width + bufmin[0], b + l + (b==0 ? bufmin[1] : 1), -mu); } } } break; default: // 3 or more, take a median and discard incompatible values memcpy(pixstackbuf, pixstack, sizeof(PIXTYPE)*coadd_nomax); mu = fast_median(pixstackbuf,ninput2); float amu = fabsf(mu); wval = val = 0.0; for(i=0; ifgain); if (fabsf(*(pixstack+i) - mu) <= prefs.clip_sigma*sigmaeff + prefs.clip_ampfrac*amu) { wval += (wval2 = 1.0 / *(pixwstack+i)); val += wval2 * *(pixstack+i); } else if (prefs.clip_logflag) fprintf(cliplog, "%4d %6d %6d %+10g\n", o, ((int)(outpix - outbuf))%coadd_width + bufmin[0], b + l + (b==0 ? bufmin[1] : 1), ((*(pixstack+i) - mu > 0.0)?1.0 : -1.0) * (fabsf(fabsf(*(pixstack+i) - mu) - prefs.clip_ampfrac*amu)) / sigmaeff); } if (wval > 0.0 && val>-BIG/2) { *(outwpix++) = (wval = 1.0/wval); *(outpix++) = val*wval; } else { *(outwpix++) = BIG; *(outpix++) = 0.0; } } } free(pixstack); free(pixwstack); free(pixstackbuf); free(pixostack); break; case COADD_MEDIAN: for (x=coadd_width; x--; inpix+=coadd_nomax, inwpix+=coadd_nomax) { ninput = *(inn++); ninput2 = 0; wval = wval3 = val2 = 0.0; inpixt = inpix; inwpixt = inwpix; pixt = pixstack; pixft = pixfstack; for (i=ninput; i--;) { fval2 = *(inpixt++); wval2 = *(inwpixt++); if (wval2 < coadd_wthresh && fval2>-BIG/2) { *(pixt++) = fval2; wval += 1.0/sqrt(wval2); wval3 += wval2; ninput2++; } else *(pixft++) = fval2; } if (ninput2) { *(outpix++) = fast_median(pixstack, ninput2); /*-------- We assume Gaussian input noise */ *(outwpix++) = ninput2>2? (PI*ninput2*ninput2/(2*wval*wval*(ninput2+((ninput2&1)?(PI/2-1) :(PI-2))))) : wval3/(ninput2*ninput2); } else { *(outpix++) = (blankflag||!ninput)? 0.0 : fast_median(pixfstack, ninput); *(outwpix++) = BIG; } } break; case COADD_AVERAGE: for (x=coadd_width; x--; inpix+=coadd_nomax, inwpix+=coadd_nomax) { ninput = *(inn++); ninput2 = 0; wval = val = 0.0; inpixt = inpix; inwpixt = inwpix; pixft = pixfstack; for (i=ninput; i--;) { fval2 = *(inpixt++); wval2 = *(inwpixt++); if (wval2-BIG/2) { ninput2++; val += fval2; wval += wval2; } else *(pixft++) = fval2; } if (ninput2) { *(outpix++) = val/ninput2; *(outwpix++) = wval/(ninput2*ninput2); } else { *(outpix++) = (blankflag||!ninput)? 0.0 : fast_median(pixfstack, ninput); *(outwpix++) = BIG; } } break; case COADD_MIN: for (x=coadd_width; x--; inpix+=coadd_nomax, inwpix+=coadd_nomax) { ninput = *(inn++); ninput2 = 0; val = val0 = BIG; inpixt = inpix; inwpixt = inwpix; for (i=ninput; i--;) { val2 = *(inpixt++); wval2 = *(inwpixt++); if (wval2-BIG/2) { ninput2++; if (val2-BIG/2) { ninput2++; if (val2>val) val = val2; } else if (val2>val0) val0 = val2; } if (ninput2) { *(outpix++) = val; *(outwpix++) = 1.0; } else { *(outpix++) = (blankflag||!ninput)? 0.0 : val0; *(outwpix++) = BIG; } } break; case COADD_CHI_OLD: wval0 = 1.0; for (x=coadd_width; x--; inpix+=coadd_nomax, inwpix+=coadd_nomax) { ninput = *(inn++); ninput2 = 0; wval = val = 0.0; inpixt = inpix; inwpixt = inwpix; pixft = pixfstack; for (i=ninput; i--;) { val2 = *(inpixt++); wval2 = *(inwpixt++); if (wval2-BIG/2) { ninput2++; wval0 = 1.0/wval2; val += val2*val2*wval0; } else *(pixft++) = val2*val2*wval0; } if (ninput2) { *(outpix++) = sqrt(val/ninput2); *(outwpix++) = 1.0; } else { *(outpix++) = (blankflag||!ninput)? 0.0 : sqrt(fast_median(pixfstack, ninput)); *(outwpix++) = BIG; } } break; case COADD_CHI_MODE: wval0 = 1.0; for (x=coadd_width; x--; inpix+=coadd_nomax, inwpix+=coadd_nomax) { ninput = *(inn++); ninput2 = 0; wval = val = 0.0; inpixt = inpix; inwpixt = inwpix; pixft = pixfstack; for (i=ninput; i--;) { val2 = *(inpixt++); wval2 = *(inwpixt++); if (wval2-BIG/2) { ninput2++; val0 = val2; wval0 = 1.0/wval2; val += val0*val0*wval0; } else *(pixft++) = val2*sqrt(wval0); } if (ninput2) { mu = coadd_bias[ninput2-1]; *(outpix++) = ninput2>1? (sqrt(val)-sqrt(ninput2-1.0))/sqrt(ninput2-mu*mu) : val0*sqrt(wval0); *(outwpix++) = 1.0; } else { *(outpix++) = (blankflag||!ninput)? 0.0 : fast_median(pixfstack, ninput); *(outwpix++) = BIG; } } break; case COADD_CHI_MEAN: wval0 = 1.0; for (x=coadd_width; x--; inpix+=coadd_nomax, inwpix+=coadd_nomax) { ninput = *(inn++); ninput2 = 0; wval = val = 0.0; inpixt = inpix; inwpixt = inwpix; pixft = pixfstack; for (i=ninput; i--;) { val2 = *(inpixt++); wval2 = *(inwpixt++); if (wval2-BIG/2) { ninput2++; val0 = val2; wval0 = 1.0/wval2; val += val0*val0*wval0; } else *(pixft++) = val2*sqrt(wval0); } if (ninput2) { mu = coadd_bias[ninput2-1]; *(outpix++) = ninput2>1? (sqrt(val)-mu)/sqrt(ninput2-mu*mu) : val0*sqrt(wval0); *(outwpix++) = 1.0; } else { *(outpix++) = (blankflag||!ninput)? 0.0 : fast_median(pixfstack, ninput); *(outwpix++) = BIG; } } break; case COADD_SUM: for (x=coadd_width; x--; inpix+=coadd_nomax, inwpix+=coadd_nomax) { ninput = *(inn++); ninput2 = 0; wval = val = val0 = 0.0; inpixt = inpix; inwpixt = inwpix; for (i=ninput; i--;) { val2 = *(inpixt++); wval2 = *(inwpixt++); if (wval2-BIG/2) { ninput2++; val += val2; wval += wval2; } else val0 += val; } if (ninput2) { *(outpix++) = val; *(outwpix++) = wval; } else { *(outpix++) = (blankflag||!ninput)? 0.0 : val0; *(outwpix++) = BIG; } } break; case COADD_WEIGHTED_WEIGHT: for (x=coadd_width; x--; inpix+=coadd_nomax, inwpix+=coadd_nomax) { ninput = *(inn++); ninput2 = 0; wval = val = 0.0; inpixt = inpix; inwpixt = inwpix; for (i=ninput; i--;) { fval2 = *(inpixt++); fval2 = fval2>(1.0/BIG)? 1.0/fval2 : BIG; wval2 = *(inwpixt++); if (wval2(1.0/BIG)? 1.0/fval2 : BIG; wval2 = *(inwpixt++); if (wval2 < coadd_wthresh) { val += 1.0/sqrt(fval2); val3 += fval2; wval += 1.0/sqrt(wval2); wval3 += wval2; ninput2++; } } if (ninput2) { val = ninput2>2? (PI*ninput2*ninput2/(2*val*val*(ninput2+((ninput2&1)?(PI/2-1) :(PI-2))))) : val3/(ninput2*ninput2); *(outpix++) = val<(BIG/1000.0)? 1.0/val : 0.0; /*-------- We assume Gaussian input noise */ *(outwpix++) = ninput2>2? (PI*ninput2*ninput2/(2*wval*wval*(ninput2+((ninput2&1)?(PI/2-1) :(PI-2))))) : wval3/(ninput2*ninput2); } else { *(outpix++) = 0.0; *(outwpix++) = BIG; } } break; case COADD_AND: case COADD_NAND: case COADD_OR: case COADD_NOR: default: error(EXIT_FAILURE, "*Internal Error*: Unknown Combine option in ", "coadd_line()"); } return RETURN_OK; } /******* fast_median ********************************************************** PROTO PIXTYPE fast_median(PIXTYPE *arr, int n) PURPOSE Fast median from an input array, based on the quick-select algorithm described by N. Devillard at http://ansi.c.sources.free.fr/median/median/index.html. If n is even, then the result is the average of the 2 "central" values. INPUT Input pixel array ptr, number of input pixels, OUTPUT Value of the median. NOTES n must be >0. Warning: changes the order of data (but does not sort them)! AUTHOR E. Bertin (IAP) VERSION 27/06/2003 ***/ #define MEDIAN_SWAP(a,b) \ {val=a; a=b; b=val;} PIXTYPE fast_median(PIXTYPE *arr, int n) { PIXTYPE *alow, *ahigh, *amedian, *amiddle, *all, *ahh, val, valmax, valmax2; int i, nless; if (n==1) return *arr; else if (n==2) return 0.5*(arr[0]+arr[1]); else if (n==3) { if (arr[0]>arr[1]) MEDIAN_SWAP(*arr, *(arr+1)); if (arr[1]>arr[2]) MEDIAN_SWAP(*(arr+1), *(arr+2)); if (arr[0]>arr[1]) MEDIAN_SWAP(*arr, *(arr+1)); return arr[1]; } alow = arr; ahigh = arr + n - 1; amedian = arr + n/2; while (ahigh > (all=alow + 1)) { /*-- Find median of low, middle and high items; swap into position low */ amiddle = alow + (ahigh-alow)/2; if (*amiddle > *ahigh) MEDIAN_SWAP(*amiddle, *ahigh); if (*alow > *ahigh) MEDIAN_SWAP(*alow, *ahigh); if (*amiddle > *alow) MEDIAN_SWAP(*amiddle, *alow); /*-- Swap low item (now in position middle) into position (low+1) */ MEDIAN_SWAP(*amiddle, *all); /*-- Nibble from each end towards middle, swapping items when stuck */ ahh = ahigh; for (;;) { while (*alow > *(++all)); while (*(--ahh) > *alow); if (ahh < all) break; MEDIAN_SWAP(*all, *ahh); } /*-- Swap middle item (in position low) back into correct position */ MEDIAN_SWAP(*alow, *ahh) ; /*-- Re-set active partition */ if (ahh <= amedian) alow = all; if (ahh >= amedian) ahigh = ahh - 1; } /* One or two elements left */ if (ahigh == all && *alow > *ahigh) MEDIAN_SWAP(*alow, *ahigh); if (n&1) /*-- Odd case */ return *amedian; else { /*-- Even case */ valmax2 = *amedian; valmax = -BIG; alow = arr; nless = 0; for (i=n/2;i--;) if ((val=*(alow++)) valmax) valmax = val; } return nlesswcs; naxis = wcs->naxis; inoffset = 0; inbeg = wcs->outmin[0] - bufmin[0]; if (inbeg<0) { inoffset = -inbeg; inbeg = 0; } muloffset = inbeg*multinmax; width = wcs->outmax[0] - bufmin[0] + 1; if (width > (outwidth - inbeg)) width = outwidth - inbeg; if (width<=0) return RETURN_ERROR; /* the image is not included in the output */ else if (width > field->width) width = field->width; /* First, the data themselves */ #ifdef USE_THREADS pthread_wdataflag = 0; pthread_npix = width; pthread_step = multinmax; threadstep = 0; QMALLOC(lineibuf, FLAGTYPE, 2*field->width); #else QMALLOC(lineibuf, FLAGTYPE, field->width); linei = lineibuf; #endif for (d=naxis; --d;) rawpos2[d] = rawpos[d]; multinbuf2 = multinbuf; nflag = 1; for (y=nbuflines; y;) { /*-- Check that the present line is contained in the field */ for (d=naxis; --d;) if (rawpos2[d]outmin[d] || rawpos2[d]>wcs->outmax[d]) break; if (d>0) nflag = 1; else { if (nflag) /*------ well now we are back within the frame; we might need to fseek() */ { nflag = 0; offset = 0; pixcount = 1; for (d=1; dnaxisn[d-1]; ival = rawpos2[d] - wcs->outmin[d]; if (ival > 0) offset += (OFF_T2)ival*pixcount; } QFSEEK(field->cat->file, field->tab->bodypos+offset*field->tab->bytepix, SEEK_SET, field->filename); #ifdef HAVE_CFITSIO field->tab->currentElement = (offset == 0) ? 1 : offset; #endif // HAVE_CFITSIO } #ifdef USE_THREADS linei = lineibuf + (threadstep&1)*field->width; read_ibody(field->tab, linei, field->width); if (threadstep++) threads_gate_sync(pthread_stopgate2); pthread_lineibuf = linei+inoffset; pthread_multiibuf = multiibuf+muloffset; pthread_multinbuf = multinbuf2+inbeg; threads_gate_sync(pthread_startgate2); #else read_ibody(field->tab, linei, field->width); coadd_moveidata(linei+inoffset, multiibuf+muloffset, multinbuf2+inbeg, width, multinmax); #endif multiibuf += (size_t)outwidth*multinmax; multinbuf2 += outwidth; y--; } /*---- Update coordinate vector */ for (d=1; doutmin[d] || rawpos2[d]>wcs->outmax[d]) break; if (d>0) nflag = 1; else { #ifdef USE_THREADS linei = lineibuf + (threadstep&1)*field->width; #endif if (wfield) { if (nflag) /*-------- well now we are back withing the frame; we might need to fseek() */ { nflag = 0; offset = 0; pixcount = 1; for (d=1; dnaxisn[d-1]; ival = rawpos2[d] - wcs->outmin[d]; if (ival > 0) offset += ival*pixcount; } QFSEEK(wfield->cat->file, wfield->tab->bodypos+offset*wfield->tab->bytepix, SEEK_SET, wfield->filename); #ifdef HAVE_CFITSIO wfield->tab->currentElement = (offset == 0) ? 1 : offset; #endif // HAVE_CFITSIO } read_ibody(wfield->tab, linei, field->width); } #ifdef USE_THREADS if (threadstep++) threads_gate_sync(pthread_stopgate2); pthread_wdataflag = 1; pthread_lineibuf = wfield? (linei+inoffset) : NULL; pthread_multiibuf = multiwibuf+muloffset; pthread_multinbuf = multinbuf2+inbeg; threads_gate_sync(pthread_startgate2); #else coadd_movewidata(wfield? (linei+inoffset) : NULL, multiwibuf+muloffset, multinbuf2+inbeg, width, multinmax); #endif multiwibuf += (size_t)outwidth*multinmax; multinbuf2 += outwidth; y--; } /*-- Update coordinate vector */ for (d=1; dwcs->outmax[d]) return RETURN_ERROR; else if (rawpos2[d]outmax[d]) break; return RETURN_OK; } /******* coadd_load ********************************************************** PROTO int coadd_load(fieldstruct *field, fieldstruct *wfield, PIXTYPE *multibuf, unsigned int *multiobuf, PIXTYPE *multiwbuf, unsigned int *multinbuf, int *rawpos, int *bufmin, int *bufmax, int nlines, int outwidth, int multinmax, int nfield) PURPOSE Load images and weights to coadd in the current buffer. INPUT Input field ptr array, input weight field ptr array, science image buffer, science image origin id buffer, weight image buffer, number-of-pixels buffer, array of current coordinates in output frame, array of minimum coordinates in output frame, array of maximum coordinates in output frame, total number of lines (can be higher than the number of buffers lines), pixel buffer line width, number of overlapping images, input origin ID OUTPUT RETURN_ERROR in case no more data are worth reading, RETURN_OK otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 10/03/2014 ***/ int coadd_load(fieldstruct *field, fieldstruct *wfield, PIXTYPE *multibuf, unsigned int *multiobuf, PIXTYPE *multiwbuf, unsigned int *multinbuf, int *rawpos, int *bufmin, int *bufmax, int nbuflines, int outwidth, int multinmax, int oid) { wcsstruct *wcs; OFF_T2 offset, pixcount; PIXTYPE *linebuf, *line,*linet, thresh; unsigned int *multinbuf2, d, x,y, nflag, naxis; int rawpos2[NAXIS], ival, inoffset, inbeg, muloffset, width; #ifdef USE_THREADS unsigned int threadstep; #endif wcs = field->wcs; naxis = wcs->naxis; inoffset = 0; inbeg = wcs->outmin[0] - bufmin[0]; if (inbeg<0) { inoffset = -inbeg; inbeg = 0; } muloffset = inbeg*multinmax; width = wcs->outmax[0] - bufmin[0] + 1; if (width > (outwidth - inbeg)) width = outwidth - inbeg; if (width<=0) return RETURN_ERROR; /* the image is not included in the output */ else if (width > field->width) width = field->width; /* First, the data themselves */ #ifdef USE_THREADS pthread_wdataflag = 0; pthread_npix = width; pthread_step = multinmax; threadstep = 0; QMALLOC(linebuf, PIXTYPE, 2*field->width); #else QMALLOC(linebuf, PIXTYPE, field->width); line = linebuf; #endif for (d=naxis; --d;) rawpos2[d] = rawpos[d]; multinbuf2 = multinbuf; nflag = 1; for (y=nbuflines; y;) { /*-- Check that the present line is contained in the field */ for (d=naxis; --d;) if (rawpos2[d]outmin[d] || rawpos2[d]>wcs->outmax[d]) break; if (d>0) nflag = 1; else { if (nflag) /*------ well now we are back within the frame; we might need to fseek() */ { nflag = 0; offset = 0; pixcount = 1; for (d=1; dnaxisn[d-1]; ival = rawpos2[d] - wcs->outmin[d]; if (ival > 0) offset += (OFF_T2)ival*pixcount; } QFSEEK(field->cat->file, field->tab->bodypos+offset*field->tab->bytepix, SEEK_SET, field->filename); #ifdef HAVE_CFITSIO field->tab->currentElement = (offset == 0) ? 1 : offset; #endif // HAVE_CFITSIO } #ifdef USE_THREADS line = linebuf+(threadstep&1)*field->width; read_body(field->tab, line, field->width); if (threadstep++) threads_gate_sync(pthread_stopgate2); pthread_linebuf = line+inoffset; pthread_multibuf = multibuf+muloffset; pthread_multiobuf = multiobuf+muloffset; pthread_origin = &oid; pthread_multinbuf = multinbuf2+inbeg; threads_gate_sync(pthread_startgate2); #else read_body(field->tab, line, field->width); coadd_movedata(line+inoffset, multibuf+muloffset, multiobuf+muloffset, multinbuf2+inbeg, width, multinmax, oid); #endif multibuf += (size_t)outwidth*multinmax; multiobuf += outwidth*multinmax; multinbuf2 += outwidth; y--; } /*---- Update coordinate vector */ for (d=1; doutmin[d] || rawpos2[d]>wcs->outmax[d]) break; if (d>0) nflag = 1; else { #ifdef USE_THREADS line = linebuf+(threadstep&1)*field->width; #endif if (wfield) { if (nflag) /*-------- well now we are back withing the frame; we might need to fseek() */ { nflag = 0; offset = 0; pixcount = 1; for (d=1; dnaxisn[d-1]; ival = rawpos2[d] - wcs->outmin[d]; if (ival > 0) offset += ival*pixcount; } QFSEEK(wfield->cat->file, wfield->tab->bodypos+offset*wfield->tab->bytepix, SEEK_SET, wfield->filename); #ifdef HAVE_CFITSIO wfield->tab->currentElement = (offset == 0) ? 1 : offset; #endif // HAVE_CFITSIO } read_body(wfield->tab, line, field->width); if ((thresh=wfield->weight_thresh)>0.0) { linet = line; for (x=field->width; x--; linet++) if (*linet<=thresh) *linet = 0.0; } } #ifdef USE_THREADS if (threadstep++) threads_gate_sync(pthread_stopgate2); pthread_wdataflag = 1; pthread_linebuf = (wfield? (line+inoffset) : NULL); pthread_multibuf = multiwbuf+muloffset; pthread_multinbuf = multinbuf2+inbeg; threads_gate_sync(pthread_startgate2); #else coadd_movewdata(wfield? (line+inoffset) : NULL, multiwbuf+muloffset, multinbuf2+inbeg, width, multinmax); #endif multiwbuf += (size_t)outwidth*multinmax; multinbuf2 += outwidth; y--; } /*-- Update coordinate vector */ for (d=1; dwcs->outmax[d]) return RETURN_ERROR; else if (rawpos2[d]outmax[d]) break; return RETURN_OK; } #ifdef USE_THREADS /****** pthread_move_lines *************************************************** PROTO void *pthread_move_lines(void *arg) PURPOSE thread that takes care of moving image "lines" from the input to the co-addition buffer INPUT Pointer to the thread number (unused). OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 10/03/2014 ***/ void *pthread_move_lines(void *arg) { threads_gate_sync(pthread_startgate2); while (!pthread_endflag) { if (pthread_wdataflag) { if (iflag) coadd_movewidata(pthread_lineibuf, pthread_multiibuf, pthread_multinbuf, pthread_npix, pthread_step); else coadd_movewdata(pthread_linebuf, pthread_multibuf, pthread_multinbuf, pthread_npix, pthread_step); } else { if (iflag) coadd_moveidata(pthread_lineibuf, pthread_multiibuf, pthread_multinbuf, pthread_npix, pthread_step); else coadd_movedata(pthread_linebuf, pthread_multibuf, pthread_multiobuf, pthread_multinbuf, pthread_npix, pthread_step, *pthread_origin); } threads_gate_sync(pthread_stopgate2); /*-- ( Master thread loads new data here ) */ threads_gate_sync(pthread_startgate2); } pthread_exit(NULL); return (void *)NULL; } #endif /******* coadd_movedata ****************************************************** PROTO void coadd_movedata(PIXTYPE *linebuf, PIXTYPE *multibuf, unsigned int *multiobuf, int *multinbuf, int npix, int step, int oid) PURPOSE Move data from the input load buffer to the co-addition buffer. INPUT Input Buffer, co-addition buffer, origin id buffer number-of-inputs buffer, number of pixels to process, step in pixels of the co-addition buffer origin id. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 10/03/2014 ***/ void coadd_movedata(PIXTYPE *linebuf, PIXTYPE *multibuf, unsigned int *multiobuf, unsigned int *multinbuf, int npix, int step, int oid) { PIXTYPE *pix, *multi; unsigned int *multin, *multo, x; pix = linebuf; multi = multibuf; multin = multinbuf; for (x=npix; x--; multi += step) *(multi+*(multin++)) = *(pix++); if(coadd_type==COADD_CLIPPED) { multo = multiobuf; multin = multinbuf; for (x=npix; x--; multo += step) { *(multo+*(multin++)) = oid; } } return; } /******* coadd_moveidata ****************************************************** PROTO void coadd_moveidata(FLAGTYPE *linebuf, FLAGTYPE *multiibuf, int *multinbuf, int npix, int step) PURPOSE Move integer data from the input load buffer to the co-addition buffer. INPUT Input Buffer, co-addition buffer, number-of-inputs buffer, number of pixels to process, step in pixels of the co-addition buffer. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 01/02/2012 ***/ void coadd_moveidata(FLAGTYPE *lineibuf, FLAGTYPE *multiibuf, unsigned int *multinbuf, int npix, int step) { FLAGTYPE *ipix, *multii; unsigned int *multin, x; ipix = lineibuf; multii = multiibuf; multin = multinbuf; for (x=npix; x--; multii += step) *(multii+*(multin++)) = *(ipix++); return; } /******* coadd_movewdata ***************************************************** PROTO void coadd_movewdata(PIXTYPE *linebuf, PIXTYPE *multiwbuf, int *multinbuf, int npix, int step) PURPOSE Move weight data from the input load buffer to the co-addition buffer. INPUT Input Buffer, co-addition weight buffer, number-of-inputs buffer, number of pixels to process, step in pixels of the co-addition buffer. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 01/08/2006 ***/ void coadd_movewdata(PIXTYPE *linebuf, PIXTYPE *multiwbuf, unsigned int *multinbuf, int npix, int step) { PIXTYPE *wpix, *multiw, val; unsigned int *multin, x, n; multiw = multiwbuf; multin = multinbuf; if (linebuf) { /*-- Resampled weight-map present (always the case when RESAMPLE is Y) */ wpix = linebuf; for (x=npix; x--; multiw += step) { n = *multin; if ((val=*(wpix++)) > 0.0) { *(multiw+n) = 1.0/val; (*(multin++))++; } else if (!n) { *(multiw+n) = BIG; (*(multin++))++; } else multin++; } } else /*-- Resampled weight-map not present: weight is 1 within frame limits */ for (x=npix; x--; multiw += step) { *(multiw+*multin) = 1.0; (*(multin++))++; } return; } /******* coadd_movewidata **************************************************** PROTO void coadd_movewidata(FLAGTYPE *lineibuf, FLAGTYPE *multiwibuf, int *multinbuf, int npix, int step) PURPOSE Move integer weight data from the input load buffer to the co-addition buffer. INPUT Input Buffer, co-addition weight buffer, number-of-inputs buffer, number of pixels to process, step in pixels of the co-addition buffer. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 18/07/2012 ***/ void coadd_movewidata(FLAGTYPE *lineibuf, FLAGTYPE *multiwibuf, unsigned int *multinbuf, int npix, int step) { FLAGTYPE *wipix, *multiwi; unsigned int *multin, x; multiwi = multiwibuf; multin = multinbuf; if (lineibuf) { /*-- Resampled weight-map present (always the case when RESAMPLE is Y) */ wipix = lineibuf; for (x=npix; x--; multiwi += step) { *(multiwi+*multin) = *(wipix++); (*(multin++))++; } } else /*-- Resampled weight-map not present: weight is 1 within frame limits */ for (x=npix; x--; multiwi += step) { *(multiwi+*multin) = 1; (*(multin++))++; } return; } swarp-2.41.5/src/coadd.h000066400000000000000000000053601400430667300147600ustar00rootroot00000000000000/* * coadd.h * * Include file for coadd.c. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2014 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 10/03/2014 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _FITSCAT_H_ #include "fits/fitscat.h" #endif #ifndef _FIELD_H_ #include "field.h" #endif #ifndef _COADD_H_ #define _COADD_H_ /*-------------------------------- macros -----------------------------------*/ /*------------------------------- constants ---------------------------------*/ #define COADDFLAG_OPEN 0x01 #define COADDFLAG_FINISHED 0x02 /*--------------------------------- typedefs --------------------------------*/ typedef enum {COADD_MEDIAN, COADD_AVERAGE, COADD_MIN, COADD_MAX, COADD_WEIGHTED, COADD_CLIPPED, COADD_CHI_OLD, COADD_CHI_MODE, COADD_CHI_MEAN, COADD_SUM, COADD_WEIGHTED_WEIGHT, COADD_MEDIAN_WEIGHT, COADD_AND, COADD_NAND, COADD_OR, COADD_NOR} coaddenum; /* Coaddition type */ /*-------------------------- structure definitions --------------------------*/ typedef struct coaddact { int line; int fieldno; enum {COADDACT_OPEN, COADDACT_CLOSE, COADDACT_LOAD} com; } coaddactstruct; /*----------------------- miscellaneous variables ---------------------------*/ /*-------------------------------- protos -----------------------------------*/ extern int coadd_fields(fieldstruct **infield, fieldstruct **inwfield, int ninput, fieldstruct *outfield, fieldstruct *outwfield, coaddenum coaddtype, PIXTYPE wthresh), max_clique(unsigned int *array, int nnode, int **max); extern void coadd_movedata(PIXTYPE *linebuf, PIXTYPE *multibuf, unsigned int *multiobuf, unsigned int *multinbuf, int npix, int step, int oid), coadd_moveidata(FLAGTYPE *lineibuf, FLAGTYPE *multiibuf, unsigned int *multinbuf, int npix, int step), coadd_movewdata(PIXTYPE *linebuf, PIXTYPE *multiwbuf, unsigned int *multinbuf, int npix, int step), coadd_movewidata(FLAGTYPE *lineibuf, FLAGTYPE *multiwibuf, unsigned int *multinbuf, int npix, int step); #endif swarp-2.41.5/src/data.c000066400000000000000000000131031400430667300146040ustar00rootroot00000000000000/* * data.c * * Read and convert data. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2020 IAP/CNRS/SorbonneU * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 04/02/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include #include #include #include "define.h" #include "globals.h" #include "fits/fitscat.h" #include "back.h" #include "data.h" #include "field.h" /* Conversion routine globals */ fieldstruct *convert_field; PIXTYPE *convert_pix, *convert_varpix, *convert_backupbuf, *convert_backup, convert_varthresh; long convert_pixcount; int *convert_ytimeoutbuf, *convert_ytimeout, convert_xtimeout,convert_xtimeout0,convert_ytimeout0, convert_width, convert_y, convert_interpflag, convert_backsubflag; /******* read_data ********************************************************** PROTO void read_data(fieldstruct *field, fieldstruct *wfield, int bitpix) PURPOSE Read data and store them in internal format (interpolated, background-subtracted, and dynamic-compressed). INPUT Input field ptr, Input weight field ptr, Number of bits per pixel. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 04/02/2020 ***/ void read_data(fieldstruct *field, fieldstruct *wfield, int bitpix) { char str[MAXCHAR]; /* Prepare static (global) variables */ convert_width = field->width; convert_pixcount = 0; convert_y = 0; convert_field = field; /* Prepare interpolation */ if (wfield && (field->cflags & CONVERT_INTERP) && bitpix<0) { convert_interpflag = 1; convert_varpix = wfield->pix; convert_varthresh = wfield->var_thresh; QCALLOC(convert_ytimeoutbuf, int, convert_width); QMALLOC(convert_backupbuf, PIXTYPE, convert_width); } else convert_interpflag = 0; /* Prepare background subtraction */ if ((field->cflags & CONVERT_BACKSUB) && bitpix<0) convert_backsubflag = 1; else convert_backsubflag = 0; if (bitpix>0) { if (!(field->ipix = alloc_ibody(field->tab, NULL))) { sprintf(str, "*Error*: Not enough memory " "(either in RAM or mapped to disk) to store %s;", field->rfilename); error(EXIT_FAILURE, str, " try to increase MEM_MAX or VMEM_MAX"); } } else { if (!(field->pix = alloc_body(field->tab, convert_data))) { sprintf(str, "*Error*: Not enough memory " "(either in RAM or mapped to disk) to store %s;", field->rfilename); error(EXIT_FAILURE, str, " try to increase MEM_MAX or VMEM_MAX"); } } /* Free allocated buffers */ if (convert_interpflag) { free(convert_ytimeoutbuf); free(convert_backupbuf); } return; } /******* convert_data ******************************************************** PROTO void convert_data(PIXTYPE *pix, int npix) PURPOSE Read data and store them in internal format (interpolated, background-subtracted, and dynamic-compressed). INPUT Input field ptr, Number of pixels. OUTPUT -. NOTES This routine is intended to be repeatedly called from alloc_body() over the SAME IMAGE (no interleaving). It makes use of many static variables which are kept between calls. AUTHOR E. Bertin (IAP) VERSION 09/11/2003 ***/ void convert_data(PIXTYPE *pix, int npix) { static PIXTYPE *convert_backdata; PIXTYPE *data, *vardata; int i,n; /* Data interpolation using the weight map */ if (convert_interpflag) { data = pix; n = convert_pixcount; vardata = convert_varpix; for (i=npix; i--;) { /*---- New line */ if (!(n++%convert_width)) { convert_xtimeout = 0; /* As if first pixel is already interpolated */ convert_ytimeout = convert_ytimeoutbuf; convert_backup = convert_backupbuf; } /*---- Check if interpolation is needed */ if (*(vardata++)>=convert_varthresh || *data < -BIG) { /*------ Check if the previous pixel was already interpolated */ if (!convert_xtimeout) { if (*convert_ytimeout) { (*convert_ytimeout)--; *data = *convert_backup; } } else { convert_xtimeout--; *data = *(data-1); } } else { convert_xtimeout = convert_xtimeout0; *convert_ytimeout = convert_ytimeout0; } *(convert_backup++) = *(data++); } } /* Background-subtraction */ if (convert_backsubflag) { data = pix; n = convert_pixcount; for (i=npix; i--; data++) { /*---- New line */ if (!(n++%convert_width)) { backline(convert_field, convert_y++, convert_field->backline); convert_backdata = convert_field->backline; } if (*data>-BIG) *data -= *convert_backdata; convert_backdata++; } } convert_pixcount += npix; return; } swarp-2.41.5/src/data.h000066400000000000000000000027041400430667300146160ustar00rootroot00000000000000/* * data.h * * Include file for data.c. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2012 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 30/01/2012 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _FIELD_H_ #include "field.h" #endif /*--------------------------- conversion flags ------------------------------*/ #define CONVERT_INTERP 0x01 /* Interpolation */ #define CONVERT_BACKSUB 0x02 /* Background subtraction */ #define CONVERT_DYNCOMP 0x04 /* Dynamic compression */ /*------------------------------- functions ---------------------------------*/ extern void convert_data(PIXTYPE *pix, int npix), read_data(fieldstruct *field, fieldstruct *wfield, int bitpix); swarp-2.41.5/src/define.h000066400000000000000000000124251400430667300151400ustar00rootroot00000000000000/* * define.h * * Global definitions. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2012 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 25/04/2012 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /* Check if we are using a configure script here */ #ifndef HAVE_CONFIG_H #define VERSION "1.x" #define DATE "2003-x-x" #define THREADS_NMAX 1024 /* max. number of threads */ #endif /*------------------------ what, who, when and where ------------------------*/ #define BANNER "SWarp" #define MYVERSION VERSION #define COPYRIGHT "2010-2012 IAP/CNRS/UPMC" #define DISCLAIMER BANNER " comes with ABSOLUTELY NO WARRANTY\n" \ "You may redistribute copies of " BANNER "\n" \ "under the terms of the GNU General Public License." #define AUTHORS "Emmanuel BERTIN " #define WEBSITE "http://astromatic.net/software/swarp/" #define INSTITUTE "IAP http://www.iap.fr" /*----------------------------- Physical constants --------------------------*/ #ifndef PI #define PI 3.1415926535898 #endif /*----------------------------- Internal constants --------------------------*/ #define BIG 1e+30 /* a huge number */ #define OUTPUT stderr /* where all msgs are sent */ #define MAXCHAR 512 /* max. number of characters */ /*--------------------- in case of missing constants ------------------------*/ #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef EXIT_SUCCESS #define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE #define EXIT_FAILURE -1 #endif /*---------------------------- return messages ------------------------------*/ #define RETURN_OK 0 #define RETURN_ERROR (-1) #define RETURN_FATAL_ERROR (-2) /*------------------------------- Other Macros ------------------------------*/ #ifdef _LARGEFILE_SOURCE #define FSEEKO fseeko #define FTELLO ftello #else #define FSEEKO fseek #define FTELLO ftell #endif #define DEXP(x) exp(2.30258509299*(x)) /* 10^x */ #define QFREAD(ptr, size, afile, fname) \ if (fread(ptr, (size_t)(size), (size_t)1, afile)!=1) \ error(EXIT_FAILURE, "*Error* while reading ", fname) #define QFWRITE(ptr, size, afile, fname) \ if (fwrite(ptr, (size_t)(size), (size_t)1, afile)!=1) \ error(EXIT_FAILURE, "*Error* while writing ", fname) #define QFSEEK(afile, offset, pos, fname) \ if (fseek(afile, (offset), pos)) \ error(EXIT_FAILURE,"*Error*: file positioning failed in ", \ fname) #define QFTELL(pos, afile, fname) \ if ((pos=FTELLO(afile))==-1) \ error(EXIT_FAILURE,"*Error*: file position unknown in ", \ fname) #define QCALLOC(ptr, typ, nel) \ {if (!(ptr = (typ *)calloc((size_t)(nel),sizeof(typ)))) \ { \ sprintf(gstr, #ptr " (" #nel " elements=%ld bytes) " \ "at line %d in module " __FILE__ " !", \ (size_t)(nel)*sizeof(typ), __LINE__); \ error(EXIT_FAILURE, "Could not allocate memory for ", gstr);\ }; \ } #define QMALLOC(ptr, typ, nel) \ {if (!(ptr = (typ *)malloc((size_t)(nel)*sizeof(typ)))) \ { \ sprintf(gstr, #ptr " (" #nel " elements=%ld bytes) " \ "at line %d in module " __FILE__ " !", \ (size_t)(nel)*sizeof(typ), __LINE__); \ error(EXIT_FAILURE, "Could not allocate memory for ", gstr);\ }; \ } #define QREALLOC(ptr, typ, nel) \ {if (!(ptr = (typ *)realloc(ptr, (size_t)(nel)*sizeof(typ))))\ { \ sprintf(gstr, #ptr " (" #nel " elements=%ld bytes) " \ "at line %d in module " __FILE__ " !", \ (size_t)(nel)*sizeof(typ), __LINE__); \ error(EXIT_FAILURE, "Could not allocate memory for ", gstr);\ }; \ } #define QMEMCPY(ptrin, ptrout, typ, nel) \ {if (ptrin) \ {if (!(ptrout = (typ *)malloc((size_t)(nel)*sizeof(typ)))) \ { \ sprintf(gstr, #ptrout " (" #nel " elements=%ld bytes) " \ "at line %d in module " __FILE__ " !", \ (size_t)(nel)*sizeof(typ), __LINE__); \ error(EXIT_FAILURE,"Could not allocate memory for ",gstr);\ }; \ memcpy(ptrout, ptrin, (size_t)(nel)*sizeof(typ)); \ }; \ } #define RINT(x) (int)(floor(x+0.5)) #define NPRINTF if (prefs.verbose_type == NORM) fprintf #define NFPRINTF(w,x) {if (prefs.verbose_type == NORM) \ fprintf(w, "\33[1M> %s\n\33[1A",x); \ else if (prefs.verbose_type == FULL) \ fprintf(w, "%s\n", x);} #define FPRINTF if (prefs.verbose_type == FULL) fprintf #define QPRINTF if (prefs.verbose_type != QUIET) fprintf swarp-2.41.5/src/field.c000066400000000000000000000755721400430667300150000ustar00rootroot00000000000000/* * field.c * * Manage fields (input images). * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2019 IAP/CNRS/SorbonneU * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 20/12/2019 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include #include #include #include "define.h" #include "globals.h" #include "fits/fitscat.h" #include "fitswcs.h" #include "back.h" #include "coadd.h" #include "data.h" #include "field.h" #include "header.h" #include "key.h" #include "misc.h" #include "prefs.h" #include "wcs/wcs.h" /****** load_field ************************************************************ PROTO fieldstruct *load_field(catstruct *cat, int frameno, int fieldno) PURPOSE Initialize a field structure (in read mode) INPUT Cat structure, FITS extension number in file (0=primary) Field number in coaddition (for various config settings) Field flags, FITS header filename (null=none). OUTPUT The new field pointer if OK, NULL otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 26/11/2015 ***/ fieldstruct *load_field(catstruct *cat, int frameno, int fieldno, char *hfilename) { tabstruct *tab, *intab; fieldstruct *field; char *pstr; int i; /* First allocate memory for the new field (and nullify pointers) */ QCALLOC(field,fieldstruct, 1); field->flags = FIELD_READ; /* Set conversion flags */ field->cflags = (prefs.interp_flag[fieldno]?CONVERT_INTERP:0) |(prefs.subback_flag[fieldno]?CONVERT_BACKSUB:0); field->frameno = frameno; field->fieldno = fieldno; field->cat = new_cat(1); strcpy(field->cat->filename, cat->filename); strcpy (field->filename, cat->filename); intab = cat->tab; for (i=frameno; i--;) intab = intab->nexttab; copy_tab_fromptr(intab, field->cat, 0); tab = field->tab = field->cat->tab; tab->cat = field->cat; /* A short, "relative" version of the filename */ if (!(field->rfilename = strrchr(field->filename, '/'))) field->rfilename = field->filename; else field->rfilename++; /* Check if a header filename is provided */ if (hfilename && *hfilename) strcpy(field->hfilename, hfilename); else { /* Create a file name with a "header" extension */ strcpy(field->hfilename, field->filename); if (!(pstr = strrchr(field->hfilename, '.'))) pstr = field->hfilename+strlen(field->hfilename); sprintf(pstr, "%s", prefs.head_suffix); } sprintf(gstr, "Looking for %s ...", field->rfilename); NFPRINTF(OUTPUT, gstr); /* Insert additional header informations from the "header" file */ field->headflag = !read_aschead(field->hfilename, frameno, tab); if (hfilename && *hfilename && !field->headflag) warning(hfilename, " header file not found"); if (tab->naxis<1) error(EXIT_FAILURE, "*Error*: Zero-dimensional table in ",field->filename); /* Force data to be at least 2D */ #ifdef CFITSTIO_SUPPORT // CFITSIO: only valid when NOT tile compressed if(!tab->isTileCompressed) #endif // HAVE_CFITSIO if (tab->naxis<2) { tab->naxis = 2; QREALLOC(tab->naxisn, int, 2); tab->naxisn[1] = 1; } /* Some defaults */ field->fascale = 1.0; field->fscale = prefs.fscale_default[fieldno]; field->gain = prefs.gain_default[fieldno]; field->saturation = prefs.sat_default[fieldno]; /* Force input celestial system to "PIXEL" if requested by user */ if (prefs.celsys_type == CELSYS_PIXEL) for (i=0; inaxis; i++) { sprintf(gstr, "CTYPE%-3d", i+1); fitswrite(tab->headbuf, gstr, "PIXEL", H_STRING, T_STRING); } /* Read WCS information in FITS header */ field->wcs = read_wcs(tab); /* Read additional field-related information in FITS header */ readfitsinfo_field(field, tab); /* Initialize effective (flux-scaled) levels */ field->fgain = field->gain; field->fsaturation = field->saturation; field->fbackmean = field->backmean; field->fbacksig = field->backsig; /* Set field width and field height (the latter can be "virtual") */ field->width = tab->naxisn[0]; field->height = 1; for (i=1; inaxis; i++) field->height *= tab->naxisn[i]; field->npix = field->width*field->height; /*-- Background */ field->backw = prefs.back_size[fieldno]width ? prefs.back_size[fieldno] : field->width; field->backh = prefs.back_size[fieldno]height ? prefs.back_size[fieldno] : field->height; field->nbackp = field->backw * field->backh; if ((field->nbackx = (field->width-1)/field->backw + 1) < 1) field->nbackx = 1; if ((field->nbacky = (field->height-1)/field->backh + 1) < 1) field->nbacky = 1; field->nback = field->nbackx * field->nbacky; field->nbackfx = field->nbackx>1 ? prefs.back_fsize[fieldno] : 1; field->nbackfy = field->nbacky>1 ? prefs.back_fsize[fieldno] : 1; /* Set the back_type flag if absolute background is selected */ field->back_type = prefs.back_type[fieldno]; field->backdefault = prefs.back_default[fieldno]; /* Check flux scale */ if (field->fscale == 0.0) { warning(field->filename, " has flux scale = 0: I will take 1 instead"); field->fscale = 1.0; } return field; } /****** inherit_field ******************************************************** PROTO fieldstruct *inherit_field(char *filename, fieldstruct *reffield, int flags) PURPOSE Make a copy of a field structure. INPUT Reference field pointer. flags. OUTPUT The new field pointer if OK, NULL otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 24/01/2012 ***/ fieldstruct *inherit_field(char *filename, fieldstruct *reffield, int flags) { fieldstruct *field; /* First allocate memory for the new field (and nullify pointers) */ QCALLOC(field, fieldstruct, 1); /* Copy what is important and reset the remaining */ *field = *reffield; field->cat = new_cat(1); inherit_cat(reffield->cat, field->cat); field->tab = field->cat->tab; field->tab->cat = field->cat; field->flags = flags; /* We don't need this */ field->back = NULL; field->dback = NULL; field->sigma = NULL; field->dsigma = NULL; field->ipix = NULL; field->pix = NULL; field->backline = NULL; field->wcs = NULL; field->rawmin = NULL; field->rawmax = NULL; field->reffield =reffield; strcpy(field->filename, filename); strcpy(field->cat->filename, filename); return field; } /****** end_field ************************************************************ PROTO void end_field(fieldstruct *field) PURPOSE Free a field structure. INPUT field structure pointer. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 16/04/2000 ***/ void end_field(fieldstruct *field) { /* Check first that a tab structure is present */ if (field->tab) { /*-- Terminate astrometry */ end_wcs(field->wcs); /*-- End memory mapping (if allocated) */ free_body(field->tab); /*-- Close cat if not already done */ if (field->cat) free_cat(&field->cat, 1); field->tab = NULL; } end_back(field); field->pix = NULL; field->ipix = NULL; free(field); return; } /****** printinfo_field ****************************************************** PROTO void printinfo_field(fieldstruct *field) PURPOSE Print info about a field INPUT Pointer to the field. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 08/03/2007 ***/ void printinfo_field(fieldstruct *field, fieldstruct *wfield) { wcsstruct *wcs; char stra[16], strd[16]; static double pixpos[NAXIS], wcspos[NAXIS]; double pixscale; int i; /* Information about the file */ if (field->frameno) sprintf(gstr, "Extension #%d:", field->frameno); else *gstr ='\0'; QPRINTF(OUTPUT, " %s \"%.20s\" %s %s %dx%d %d bits (%s)\n", gstr, *field->ident? field->ident: "no ident", wfield? "WEIGHTED" : "unweighted", field->headflag? "EXT. HEADER" : "no ext. header", field->width, field->height, field->tab->bytepix*8, field->tab->bitpix>0? (field->tab->compress_type!=COMPRESS_NONE ? "compressed":"integers") : "floats"); /* Astrometry */ wcs = field->wcs; /* Find field center */ for (i=0; inaxis; i++) pixpos[i] = (wcs->naxisn[i]+1.0)/2.0; raw_to_wcs(wcs, pixpos, wcspos); if (wcs->lat != wcs->lng) { pixscale = wcs->wcsscale[wcs->lng]*DEG; QPRINTF(OUTPUT, " Center: %s %s %.3g'x%.3g' Scale: %.4g ''/pixel\n", degtosexal(wcspos[wcs->lng], stra), degtosexde(wcspos[wcs->lat], strd), wcs->naxisn[wcs->lng]*pixscale/ARCMIN, wcs->naxisn[wcs->lat]*pixscale/ARCMIN, pixscale/ARCSEC); } else if (wcs->naxis >= 2) { QPRINTF(OUTPUT, " Center: %.3g,%.3g %.3gx%.3g Scale: %.4gx%.4g /pixel\n", wcspos[0], wcspos[1], wcs->naxisn[0]*wcs->wcsscale[0], wcs->naxisn[1]*wcs->wcsscale[1], wcs->wcsscale[0], wcs->wcsscale[1]); } else QPRINTF(OUTPUT, " Center: %.3g %.3g Scale: %.3g /pixel\n", wcspos[0], wcs->naxisn[0]*wcs->wcsscale[0], wcs->wcsscale[0]); for (i=0; inaxis; i++) if (i==wcs->lat || i==wcs->lng) { pixscale = wcs->wcsscale[i]*DEG; break; } /* Photometry */ QPRINTF(OUTPUT, " Gain: %.3g e-/ADU Flux scaling (astrom/photom): " "%.4g X / %.4g X\n", field->gain, field->fascale, field->fscale); return; } /******* init_field ******************************************************** PROTO fieldstruct *init_field(fieldstruct **infield, int ninput, char *filename, char *hfilename) PURPOSE Automatically set appropriate output field parameters according to the prefs and a set of input fields. INPUT Input field ptr array, number of input fields, Filename, FITS header filename (null=none). OUTPUT Pointer to the new output field. NOTES Global preferences are used. AUTHOR E. Bertin (IAP) VERSION 20/12/2019 ***/ fieldstruct *init_field(fieldstruct **infield, int ninput, char *filename, char *hfilename) { extern char celsysname[][2][8]; fieldstruct *field; tabstruct *tab; wcsstruct *wcs; double pixscale[NAXIS], val, epoch, obsdate, obsend; float *scale; char *ctype[NAXIS], *pstr; int *axis, i,j,n,npstr, lng,lat, naxis, countmin0,countmax0, countmin,countmax; /* First allocate memory for the new field */ QCALLOC(field,fieldstruct, 1); field->flags = FIELD_WRITE; strcpy (field->filename, filename); /* A short, "relative" version of the filename */ if (!(field->rfilename = strrchr(field->filename, '/'))) field->rfilename = field->filename; else field->rfilename++; /* Check if a header filename is provided */ if (hfilename && *hfilename) strcpy(field->hfilename, hfilename); else { /*-- Create a file name with a "header" extension */ strcpy(field->hfilename, filename); if (!(pstr = strrchr(field->hfilename, '.'))) pstr = field->hfilename+strlen(field->hfilename); sprintf(pstr, "%s", prefs.head_suffix); } field->cat = new_cat(1); init_cat(field->cat); strcpy(field->cat->filename, field->filename); field->tab = tab = field->cat->tab; tab->cat = field->cat; /*-------------------------- Set the astrometry -----------------------------*/ /* Check that angular axes are the same and adopt them for output */ lng = lat = -1; naxis = 0; /* to avoid gcc -Wall warnings */ for (i=0; iwcs->lng; if (lat == -1) lat = infield[i]->wcs->lat; if (!i) naxis = infield[i]->wcs->naxis; else if (infield[i]->wcs->naxis != naxis) error(EXIT_FAILURE, "*Error*: Mismatched number of axes in ", infield[i]->filename); } /* Make sure that longitudes are before latitudes */ /* if (lng>lat) { i = lng; lng = lat; lat = i; } */ QMALLOC(axis, int, ninput*naxis); for (i=0; iwcs->lng != -1) axis[i*naxis+lng] = infield[i]->wcs->lng; if (lat != -1 && infield[i]->wcs->lat != -1) axis[i*naxis+lat] = infield[i]->wcs->lat; } QMALLOC(scale, float, ninput); QMALLOC(tab->naxisn, int, naxis); /* Produce a floating point output */ field->bitpix = tab->bitpix = prefs.outfield_bitpix; if (prefs.resample_flag) { double wcsmin[NAXIS],wcsmax[NAXIS], wcsmin1,wcsmax1,wcsmin2,wcsmax2; tab->naxis = naxis; /*-- Create a new WCS structure */ /*-- Copy the types */ for (n=0; nwcs->ctype[axis[0+n]], 8); } /*---- Change the Celestial system if needed */ if (lng!=lat) { if (prefs.celsys_type == CELSYS_PIXEL) { strcpy(ctype[lng], "PIXEL"); strcpy(ctype[lat], "PIXEL"); } else if (prefs.celsys_type != CELSYS_NATIVE) { n = prefs.celsys_type - 2; /* Drop "NATIVE" and "PIXEL" options */ strncpy(ctype[lng], celsysname[n][0], 4); strncpy(ctype[lat], celsysname[n][1], 4); } } field->wcs = wcs = create_wcs(ctype, NULL, NULL, NULL, NULL, naxis); /*-- Copy the units */ for (n=0; ncunit[lng], infield[0]->wcs->cunit[axis[0+lng]], 8); else if (n==lat) strncpy(wcs->cunit[lat], infield[0]->wcs->cunit[axis[0+lat]], 8); free(ctype[n]); } for (n=0; nwcs->wcsmin[axis[j*naxis+n]]; wcsmax1 = infield[j]->wcs->wcsmax[axis[j*naxis+n]]; countmin = countmax = 0; for (i=0; iwcs->wcsmin[axis[i*naxis+n]]; wcsmax2 = infield[i]->wcs->wcsmax[axis[i*naxis+n]]; /*------------ Test for the lower and upper limits */ if (lng==lat || n!=lng) { if (wcsmin1>wcsmin2) countmin++; if (wcsmax2>wcsmin1) countmin++; if (wcsmax2>wcsmax1) countmax++; if (wcsmax1>wcsmin2) countmax++; } else { if (fcmp_0_p360(wcsmin1, wcsmin2)) countmin++; if (fcmp_0_p360(wcsmax2, wcsmin1)) countmin++; if (fcmp_0_p360(wcsmax2, wcsmax1)) countmax++; if (fcmp_0_p360(wcsmax1, wcsmin2)) countmax++; } } /*---------- Update the "most intersecting" limits */ if (countmin>countmin0) { wcsmin[n] = wcsmin1; countmin0 = countmin; } if (countmax>countmax0) { wcsmax[n] = wcsmax1; countmax0 = countmax; } } wcs->crval[n] = (wcsmin[n]+wcsmax[n])/2.0; if (lat!=lng && n==lng) wcs->crval[n] = wcsmax[n]>wcsmin[n]? fmod_0_p360(wcs->crval[n]) : fmod_0_p360(wcs->crval[n] - 180.0); break; case CENTER_ALL: wcsmin[n] = infield[0]->wcs->wcsmin[axis[n]]; wcsmax[n] = infield[0]->wcs->wcsmax[axis[n]]; for (i=1; iwcs->wcsmin[axis[i*naxis+n]]; wcsmax2 = infield[i]->wcs->wcsmax[axis[i*naxis+n]]; /*---------- Test for the lower and upper limits */ if (lng==lat || n!=lng) { if (wcsmin[n]>wcsmin2) wcsmin[n] = wcsmin2; if (wcsmax2>wcsmax[n]) wcsmax[n] = wcsmax2; } else { if (fcmp_0_p360(wcsmin[n],wcsmin2)) wcsmin[n] = wcsmin2; if (fcmp_0_p360(wcsmax2,wcsmax[n])) wcsmax[n] = wcsmax2; } } wcs->crval[n] = (wcsmin[n]+wcsmax[n])/2.0; if (n==lng) wcs->crval[n] = wcsmax[n]>wcsmin[n]? fmod_0_p360(wcs->crval[n]) : fmod_0_p360(wcs->crval[n] - 180.0); break; case CENTER_MANUAL: wcsmin[n] = infield[0]->wcs->wcsmin[axis[n]]; wcsmax[n] = infield[0]->wcs->wcsmax[axis[n]]; for (i=1; iwcs->wcsmin[axis[i*naxis+n]]; wcsmax2 = infield[i]->wcs->wcsmax[axis[i*naxis+n]]; /*---------- Test for the lower and upper limits */ if (lng==lat || n!=lng) { if (wcsmin[n]>wcsmin2) wcsmin[n] = wcsmin2; if (wcsmax2>wcsmax[n]) wcsmax[n] = wcsmax2; } else { if (fcmp_0_p360(wcsmin[n],wcsmin2)) wcsmin[n] = wcsmin2; if (fcmp_0_p360(wcsmax2,wcsmax[n])) wcsmax[n] = wcsmax2; } } /*-------- Handled swapped ra, dec axes (e.g. SDSS) */ npstr = n; if (lng>lat) { if (n==lng) npstr = lat; else if (n==lat) npstr = lng; } pstr = prefs.image_center[npstr]; wcs->crval[n] = strchr(pstr, ':') ? ((lat!=lng && n==lng)?sextodegal(pstr):sextodegde(pstr)) : atof(pstr); break; default: error(EXIT_FAILURE, "*Internal Error*: Unknown area type in ", "init_field()"); break; } pixscale[n] = 0.0; switch (prefs.pixscale_type[n]) { case PIXSCALE_MIN: pixscale[n] = BIG; for (i=0; iwcs->wcsscale[axis[i*naxis+n]] < pixscale[n]) pixscale[n] = infield[i]->wcs->wcsscale[axis[i*naxis+n]]; break; case PIXSCALE_MAX: pixscale[n] = -BIG; for (i=0; iwcs->wcsscale[axis[i*naxis+n]] > pixscale[n]) pixscale[n] = infield[i]->wcs->wcsscale[axis[i*naxis+n]]; break; case PIXSCALE_MEDIAN: for (i=0; iwcs->wcsscale[axis[i*naxis+n]]; pixscale[n] = (double)fqmedian(scale, ninput); break; case PIXSCALE_FIT: if (prefs.center_type[n] == CENTER_MANUAL) error(EXIT_FAILURE, "*Error*: cannot choose an output pixel scale if ", "CENTER_TYPE is in MANUAL mode"); if (!prefs.image_size[n]) error(EXIT_FAILURE, "*Error*: cannot choose an output pixel scale if ", "IMAGE_SIZE is not provided"); pixscale[n] = (wcsmax[n] - wcsmin[n]) / (double)prefs.image_size[n]; break; case PIXSCALE_MANUAL: pixscale[n] = prefs.pixscale[n]; if ((n==lng || n==lat) && lat!=lng) pixscale[n] *= (ARCSEC/DEG); break; default: error(EXIT_FAILURE, "*Internal Error*: Unknown pixel scale type in ","init_field()"); break; } if (!pixscale[n]) error(EXIT_FAILURE, "*Error*: null output pixel size ", ""); /*---- Following the tradition in astronomy, CDELTx decreases with longitude */ wcs->cd[n*(naxis+1)] = wcs->cdelt[n] = (n==lng && lng != lat)? -pixscale[n] :pixscale[n]; } /*-- Poorman's boundary computation */ if (wcs->celsysconvflag) { if ((prefs.center_type[lng] != CENTER_MANUAL || prefs.center_type[lat] != CENTER_MANUAL)) eq_to_celsys(wcs, wcs->crval); eq_to_celsys(wcs, wcsmin); eq_to_celsys(wcs, wcsmax); for (n=0; n 0 */ if (prefs.image_size[n]) { tab->naxisn[n] = wcs->naxisn[n] = prefs.image_size[n]; wcs->crpix[n] = (wcs->naxisn[n]+1.0)/2.0; } else { if (prefs.center_type[n] == CENTER_MANUAL) { /*-------- This is a special case where CRPIX is not NAXISN/2 */ val = wcs->cdelt[n] >=0 ? wcs->crval[n] - wcsmin[n] : wcsmax[n] - wcs->crval[n]; if ((n==lng || n==lat) && lat!=lng) { if (val<-180.0) val += 360.0; wcs->crpix[n] = (int)(fmod(val, 180.0)/pixscale[n]) + 1.0; /*-------- Add a 5% margin in field size */ tab->naxisn[n] = wcs->naxisn[n] = (int)(fmod(wcsmax[n]-wcsmin[n]+360.0, 360.0)*1.05/pixscale[n]) + 1; } else { wcs->crpix[n] = (int)(val/pixscale[n]) + 1.0; tab->naxisn[n] = wcs->naxisn[n] = (int)(fabs(wcsmax[n]-wcsmin[n])*1.05/pixscale[n]) + 1; } } else { /*-------- Add a 5% margin in field size */ if (lat!=lng && (n==lng || n==lat)) tab->naxisn[n] = wcs->naxisn[n] = (int)(fmod_0_p360(wcsmax[n]-wcsmin[n])*1.05/pixscale[n]) + 1; else tab->naxisn[n] = wcs->naxisn[n] = (int)(fabs(wcsmax[n]-wcsmin[n])*1.05/pixscale[n]) + 1; wcs->crpix[n] = (wcs->naxisn[n]+1.0)/2.0; } } } /*-- The special case of longitude */ if (lat!=lng) { if (strcmp(prefs.projection_name, "NONE")) { strcpy(wcs->ctype[lng]+5, prefs.projection_name); strcpy(wcs->ctype[lat]+5, prefs.projection_name); } else { strcpy(wcs->ctype[lng], ""); strcpy(wcs->ctype[lat], ""); } if (!prefs.image_size[lng]) { if (prefs.center_type[lng] == CENTER_MANUAL) { val = cos((wcs->crval[lat] + wcs->cdelt[lat] * ((wcs->naxisn[lat]+1.0)/2.0-wcs->crpix[lat]))*DEG); tab->naxisn[lng] = wcs->naxisn[lng] = (int)((wcs->naxisn[lng]-1)*val)+1; wcs->crpix[lng] *= val; wcs->crpix[lng] = (int)(wcs->crpix[lng]+0.4999); } else { tab->naxisn[lng] = wcs->naxisn[lng] = (int)((wcs->naxisn[lng]-1)*cos(wcs->crval[lat]*DEG))+1; wcs->crpix[lng] = (wcs->naxisn[lng]+1.0)/2.0; } } else if (prefs.pixscale_type[lng] == PIXSCALE_FIT) wcs->cd[lng*(naxis+1)] = (wcs->cdelt[lng]*=cos(wcs->crval[lat]*DEG)); /*---- Make pixel scales equal in alpha and delta */ if (prefs.pixscale[lng] == prefs.pixscale[lat]) { if ((val = fabs(wcs->cdelt[lng]/wcs->cdelt[lat])) < 1.0) wcs->cd[lng*(naxis+1)] = (wcs->cdelt[lng] /= val); else wcs->cd[lat*(naxis+1)] = (wcs->cdelt[lat] *= val); } /*---- No negative longitude!! */ wcs->crval[lng] = fmod(wcs->crval[lng]+360.0, 360.0); } /*-- Default equinox, RA-DEC-sys, longpole and latpole */ wcs->equinox = 2000.0; wcs->radecsys = RDSYS_ICRS; wcs->longpole = 999.0; wcs->latpole = 999.0; } else { /*--- No resampling: everything is in the input headers */ /*-----------------------------------------------*/ /*--- Take the first image header as a reference */ double rawcenter[NAXIS], wcscenter[NAXIS], crpixmin,crpixmax,crpixmin1,crpixmax1,crpixmin2,crpixmax2; int naxisnmax, center_flag; wcs = field->wcs = copy_wcs(infield[0]->wcs); center_flag = 0; for (n=0; nwcs->crpix[n]; crpixmin1 = infield[j]->wcs->crpix[n]-infield[j]->wcs->naxisn[n]+1; countmin = countmax = 0; for (i=0; iwcs->crpix[n]; crpixmin2 = infield[i]->wcs->crpix[n] -infield[i]->wcs->naxisn[n]+1; /*------------ Test for the lower limit */ if (crpixmax2>=crpixmax1) countmax++; if (crpixmin2crpixmin1) countmin++; } /*---------- Update the "most intersecting" limits */ if (countmin>countmin0) { crpixmin = crpixmin1; countmin0 = countmin; } if (countmax>countmax0) { crpixmax = crpixmax1; countmax0 = countmax; } } wcs->crpix[n] = crpixmax; wcs->naxisn[n] = (int)(crpixmax-crpixmin + 1.01); if (wcs->naxisn[n]<1) wcs->naxisn[n] = 1; tab->naxisn[0] = wcs->naxisn[n]; break; case CENTER_ALL: crpixmax = -BIG; crpixmin = BIG; for (i=0; iwcs->crpix[n]; crpixmin2 = crpixmax2 - infield[i]->wcs->naxisn[n]+1; /*---------- Test for the lower limit */ if (crpixmax2>crpixmax) crpixmax = crpixmax2; /*---------- Test for the upper limit */ if (crpixmin2crpix[n] = crpixmax; naxisnmax = (int) (crpixmax - crpixmin + 1.01); tab->naxisn[n] = wcs->naxisn[n] = (naxisnmax>1)? naxisnmax : 1; break; case CENTER_MANUAL: center_flag = 1; break; default: error(EXIT_FAILURE, "*Internal Error*: Unknown area type in ", "init_field()"); break; } /*---- Manual Image size */ if (prefs.image_size[n]) { if (!center_flag) wcs->crpix[n] -= (wcs->naxisn[n] - prefs.image_size[n])/2; tab->naxisn[n] = wcs->naxisn[n] = prefs.image_size[n]; } } if (center_flag) { for (n=0; nlat) { if (n==lng) npstr = lat; else if (n==lat) npstr = lng; } pstr = prefs.image_center[npstr]; wcscenter[n] = strchr(pstr, ':') ? (n==lng?sextodegal(pstr):sextodegde(pstr)) : atof(pstr); } wcs_to_raw(wcs, wcscenter, rawcenter); for (n=0; ncrpix[n] += (int)(wcs->naxisn[n]/2 - rawcenter[n] +0.9999); } } free(axis); /* Compute mean epoch and observation start/end */ epoch = 0.0; obsdate = BIG; obsend = -BIG; for (j=0; jwcs->epoch; if (infield[j]->wcs->obsdate != 0.0 && infield[j]->wcs->obsdate < obsdate) obsdate = infield[j]->wcs->obsdate; if (infield[j]->wcs->obsend > obsend) obsend = infield[j]->wcs->obsend; } field->wcs->epoch = epoch / ninput; field->wcs->obsdate = (obsdate < BIG ? obsdate : 0.0); field->wcs->obsend = obsend; update_head(tab); write_wcs(tab, wcs); /* Insert additional header informations from the "header" file */ if (read_aschead(field->hfilename, 0, tab)) { /*-- No external header: update WCS internal structures only */ if (hfilename && *hfilename) warning(hfilename, " header file not found"); if (!wcs->wcsprm) QCALLOC(wcs->wcsprm, struct wcsprm, 1); /*-- Test if the WCS is recognized and a celestial pair is found */ wcsset(wcs->naxis,(const char(*)[9])wcs->ctype, wcs->wcsprm); /*-- Initialize other WCS structures */ init_wcs(wcs); /*-- Find the range of coordinates */ range_wcs(wcs); } else { warning("FITS header data read in ", field->hfilename); /*-- Drop the current WCS structure and update from what's in the header */ end_wcs(wcs); field->wcs = wcs = read_wcs(tab); field->headflag = 1; } field->width = tab->naxisn[0]; field->height = 1; for (i=1; inaxis; i++) field->height *= tab->naxisn[i]; field->npix = field->width*field->height; /* Default flux scale and gain and saturation */ field->fscale = field->fascale = 1.0; field->gain = 0.0; field->saturation = 0.0; free(scale); return field; } /******* scale_field ********************************************************* PROTO void scale_field(fieldstruct *field, fieldstruct *reffield, int scaleflag) PURPOSE Compute the flux-scaling factor for each input field. INPUT Field ptr, Reference field ptr, Scaling flag. OUTPUT -. NOTES If scaleflag is set, pixel values are scaled in such a way that fluxes are conserved (but not surface brightness), otherwise, the scaling only applies to the output gain. AUTHOR E. Bertin (IAP) VERSION 25/08/2010 ***/ void scale_field(fieldstruct *field, fieldstruct *reffield, int scaleflag) { wcsstruct *wcs; static double raw[NAXIS], wcspos[NAXIS], wcspos2[NAXIS]; double *wcsscale, inscale,outscale; int i, naxis, lng,lat, lngin,latin; wcs = reffield->wcs; naxis = wcs->naxis; lngin = lng = wcs->lng; latin = lat = wcs->lat; if (lng != -1 && field->wcs->lng != -1) lngin = field->wcs->lng; if (lat != -1 && field->wcs->lat != -1) latin = field->wcs->lat; /* ``Go'' to the position where scale has been computed on input image */ for (i=0; iwcs->wcsscalepos[i]; wcspos[lng] = field->wcs->wcsscalepos[lngin]; wcspos[lat] = field->wcs->wcsscalepos[latin]; wcs_to_raw(wcs, wcspos, raw); wcsscale = field->wcs->wcsscale; /* Compute scaling factors for input and output images */ inscale = outscale = 1.0; for (i=0; ifascale = (outscale/inscale); field->fsaturation = field->saturation*field->fascale; } else field->fgain = field->gain*(inscale/outscale); } return; } swarp-2.41.5/src/field.h000066400000000000000000000120561400430667300147710ustar00rootroot00000000000000/* * field.h * * Include file for field.c. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2019 IAP/CNRS/SorbonneU * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 03/02/2019 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _FITSCAT_H_ #include "fits/fitscat.h" #endif #ifndef _FIELD_H_ #define _FIELD_H_ #define MAXINFIELD 500000 /* Maximum number of input files */ /*------------------------------ field flags --------------------------------*/ #define DETECT_FIELD 0x01 /* Detection */ #define MEASURE_FIELD 0x02 /* Measurement */ #define FLAG_FIELD 0x04 /* Flagging */ #define RMS_FIELD 0x08 /* Weighting with std deviations */ #define VAR_FIELD 0x10 /* Weighting with variances */ #define WEIGHT_FIELD 0x20 /* Weighting with weights */ #define BACKRMS_FIELD 0x40 /* Weighting from a backrms matrix */ #define FIELD_READ 0x100 /* Field available for read access */ #define FIELD_WRITE 0x200 /* Field available for read access */ /*--------------------------------- typedefs --------------------------------*/ typedef enum {BACK_RELATIVE, BACK_ABSOLUTE} backenum; typedef struct field { char filename[MAXCHAR]; /* image filename */ char *rfilename; /* pointer to the reduced image name */ char hfilename[MAXCHAR]; /* header filename */ int headflag; /* header found? */ char ident[80]; /* field identifier (read from FITS) */ catstruct *cat; /* cat structure */ tabstruct *tab; /* tab structure */ /* ---- main image parameters */ int fieldno; /* pos of parent ima in command line */ int frameno; /* pos in Multi-extension FITS file */ int version; /* filename version */ int width, height; /* x,y size of the field */ size_t npix; /* total number of pixels */ int bitpix; /* Bits per pixel */ double gain; /* conversion factor e-/ADU */ double fgain; /* flux-scaled gain */ double saturation; /* saturation limit in ADU */ double fsaturation; /* flux scale saturation */ double exptime; /* exposure time (s) */ double fscale; /* relative photometric scale */ double fascale; /* relative phot. scale from astrom. */ double ngamma; /* normalized photo gamma */ /* ---- background parameters */ float *back; /* ptr to the background map in mem */ float *dback; /* ptr to the background deriv. map */ float *sigma; /* ptr to the sigma map */ float *dsigma; /* Ptr to the sigma deriv. map */ int backw, backh; /* x,y size of a bkgnd mesh */ int nbackp; /* total nb of pixels per bkgnd mesh */ int nbackx, nbacky; /* x,y number of bkgnd meshes */ int nback; /* total number of bkgnd meshes */ int nbackfx, nbackfy; /* x,y size of bkgnd filtering mask */ double backdefault; /* default background value */ double backmean; /* median bkgnd value in image */ double fbackmean; /* flux-scaled median bkgnd */ double backsig; /* median bkgnd rms in image */ double fbacksig; /* flux-scaled bkgnd rms */ double sigfac; /* scaling RMS factor (for WEIGHTs) */ PIXTYPE *pix; /* pixel data */ FLAGTYPE *ipix; /* flag data */ PIXTYPE *backline; /* current interpolated bkgnd line */ backenum back_type; /* background type */ /* ---- astrometric parameters */ struct wcs *wcs; /* astrometric data */ int flags; /* flags defining the field type */ int cflags; /* flags defining the conversion */ double *rawmin; /* Starting pixel for coaddition */ double *rawmax; /* Ending pixel for coaddition */ /* ---- image interpolation */ PIXTYPE weight_thresh; /* weight threshold */ PIXTYPE var_thresh; /* variance threshold */ struct field *reffield; /* pointer to a reference field */ /* ---- time */ char sdate_end[12]; /* SWarp end date */ char stime_end[12]; /* SWarp end time */ int time_diff; /* Execution time */ } fieldstruct; /*------------------------------- functions ---------------------------------*/ extern fieldstruct *inherit_field(char *filename, fieldstruct *reffield, int fflags), *init_field(fieldstruct **infield, int ninput, char *filename, char *hfilename), *load_field(catstruct *cat, int frameno, int fieldno, char *hfilename); extern void end_field(fieldstruct *field), printinfo_field(fieldstruct *field, fieldstruct *wfield), scale_field(fieldstruct *field, fieldstruct *reffield, int scaleflag); #endif swarp-2.41.5/src/fits/000077500000000000000000000000001400430667300144765ustar00rootroot00000000000000swarp-2.41.5/src/fits/Makefile.am000066400000000000000000000024371400430667300165400ustar00rootroot00000000000000# # Makefile.am # # Process this file with automake to generate a Makefile # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # # This file part of: AstrOmatic FITS/LDAC library # # Copyright: (C) 2002-2010 Emmanuel Bertin -- IAP/CNRS/UPMC # # Last modified: 09/10/2010 # # License: GNU General Public License # # AstrOmatic software 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 3 of the # License, or (at your option) any later version. # AstrOmatic software 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 AstrOmatic software. # If not, see . # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% noinst_LIBRARIES = libfits.a libfits_a_SOURCES = fitsbody.c fitscat.c fitscheck.c fitscleanup.c \ fitsconv.c fitshead.c fitskey.c fitsmisc.c \ fitsread.c fitstab.c fitsutil.c fitswrite.c \ fitscat_defs.h fitscat.h swarp-2.41.5/src/fits/fitsbody.c000066400000000000000000001154201400430667300164700ustar00rootroot00000000000000/* * fitsbody.c * * Handle memory allocation for FITS bodies. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic FITS/LDAC library * * Copyright: (C) 1995-2020 IAP/CNRS/SorbonneU * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 26/08/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #ifdef HAVE_SYS_MMAN_H #include #endif #include "fitscat_defs.h" #include "fitscat.h" #ifdef HAVE_CFITSIO #include CFITSIO_H #endif size_t body_maxram = BODY_DEFRAM, body_maxvram = BODY_DEFVRAM, body_ramleft, body_vramleft, body_ramflag; int body_vmnumber; char body_swapdirname[MAXCHARS] = BODY_DEFSWAPDIR; /******* alloc_body *********************************************************** PROTO PIXTYPE *alloc_body(tabstruct *tab, void (*func)(PIXTYPE *ptr, int npix)) PURPOSE Allocate memory for and read a FITS data body (read-only). If not enough RAM is available, a swap file is created. INPUT Table (tab) structure. OUTPUT Pointer to the mapped data if OK, or NULL otherwise. NOTES The file pointer must be positioned at the beginning of the data. AUTHOR E. Bertin (IAP) VERSION 02/10/2017 ***/ PIXTYPE *alloc_body(tabstruct *tab, void (*func)(PIXTYPE *ptr, int npix)) { FILE *file; PIXTYPE *buffer; size_t npix, size, sizeleft, spoonful; if (!body_ramflag) { body_ramleft = body_maxram; body_vramleft = body_maxvram; body_ramflag = 1; } /* Return a NULL pointer if size is zero */ if (!tab->tabsize) return (PIXTYPE *)NULL; /* Check that there is a cat parent structure and that the file is open */ if (tab->cat && !tab->cat->file) error(EXIT_FAILURE, "*Internal Error*: Cannot access table: ", tab->extname); /* Decide if the data will go in physical memory or on swap-space */ #ifdef HAVE_CFITSIO npix = tab->naxisn[0] * tab->naxisn[1]; #else npix = tab->tabsize/tab->bytepix; #endif size = npix*sizeof(PIXTYPE); if (size < body_ramleft) { /*-- There should be enough RAM left: try to do a malloc() */ if ((tab->bodybuf = malloc(size))) { QFSEEK(tab->cat->file, tab->bodypos, SEEK_SET, tab->cat->filename); #ifdef HAVE_CFITSIO tab->currentElement = 1; #endif read_body(tab, (PIXTYPE *)tab->bodybuf, npix); /*---- Apply pixel processing */ if (func) (*func)((PIXTYPE *)tab->bodybuf, npix); body_ramleft -= size; return (PIXTYPE *)tab->bodybuf; } else tab->bodybuf = NULL; } if (size < body_vramleft) { /*-- Convert and copy the data to a swap file, and mmap() it */ if (!(buffer = malloc(DATA_BUFSIZE))) return NULL; sprintf(tab->swapname, "%s/vm%05ld_%05x.tmp", body_swapdirname, (long)getpid(), (unsigned int)++body_vmnumber) ; if (!(file=fopen(tab->swapname, "wb+"))) error(EXIT_FAILURE, "*Error*: cannot create swap-file ", tab->swapname); add_cleanupfilename(tab->swapname); spoonful = (size%DATA_BUFSIZE); if (!spoonful) spoonful = DATA_BUFSIZE; QFSEEK(tab->cat->file, tab->bodypos, SEEK_SET, tab->cat->filename); #ifdef HAVE_CFITSIO tab->currentElement = 1; #endif read_body(tab, buffer, spoonful/sizeof(PIXTYPE)); /*-- Apply pixel processing */ if (func) (*func)(buffer, spoonful/sizeof(PIXTYPE)); QFWRITE(buffer, spoonful, file, tab->swapname); for (sizeleft = size; sizeleft -= spoonful;) { read_body(tab, buffer, (spoonful=DATA_BUFSIZE)/sizeof(PIXTYPE)); /*--- Apply pixel processing */ if (func) (*func)(buffer, spoonful/sizeof(PIXTYPE)); QFWRITE(buffer, spoonful, file, tab->swapname); } free(buffer); tab->bodybuf = mmap(NULL,size,PROT_READ,MAP_SHARED,fileno(file),(off_t)0); fclose(file); tab->swapflag = 1; body_vramleft -= size; /*-- Memory mapping problem */ if (tab->bodybuf == (void *)-1) return NULL; return (PIXTYPE *)tab->bodybuf; } /* If no memory left at all: forget it! */ return NULL; } /******* alloc_ibody *********************************************************** PROTO FLAGTYPE *alloc_ibody(tabstruct *tab, void (*func)(FLAGTYPE *ptr, int npix)) PURPOSE Allocate memory for and read a FITS integer data body (read-only). If not enough RAM is available, a swap file is created. INPUT Table (tab) structure. OUTPUT Pointer to the mapped data if OK, or NULL otherwise. NOTES The file pointer must be positioned at the beginning of the data. AUTHOR E. Bertin (IAP) VERSION 02/10/2017 ***/ FLAGTYPE *alloc_ibody(tabstruct *tab, void (*func)(FLAGTYPE *ptr, int npix)) { FILE *file; FLAGTYPE *buffer; size_t npix, size, sizeleft, spoonful; if (!body_ramflag) { body_ramleft = body_maxram; body_vramleft = body_maxvram; body_ramflag = 1; } /* Return a NULL pointer if size is zero */ if (!tab->tabsize) return (FLAGTYPE *)NULL; /* Check that there is a cat parent structure and that the file is open */ if (tab->cat && !tab->cat->file) error(EXIT_FAILURE, "*Internal Error*: Cannot access table: ", tab->extname); /* Decide if the data will go in physical memory or on swap-space */ npix = tab->tabsize/tab->bytepix; size = npix*sizeof(FLAGTYPE); if (size < body_ramleft) { /*-- There should be enough RAM left: try to do a malloc() */ if ((tab->bodybuf = malloc(size))) { QFSEEK(tab->cat->file, tab->bodypos, SEEK_SET, tab->cat->filename); #ifdef HAVE_CFITSIO tab->currentElement = 1; #endif read_ibody(tab, (FLAGTYPE *)tab->bodybuf, npix); /*---- Apply pixel processing */ if (func) (*func)((FLAGTYPE *)tab->bodybuf, npix); body_ramleft -= size; return (FLAGTYPE *)tab->bodybuf; } else tab->bodybuf = NULL; } if (size < body_vramleft) { /*-- Convert and copy the data to a swap file, and mmap() it */ if (!(buffer = malloc(DATA_BUFSIZE))) return NULL; sprintf(tab->swapname, "%s/vm%05ld_%05x.tmp", body_swapdirname, (long)getpid(), (unsigned int)++body_vmnumber) ; if (!(file=fopen(tab->swapname, "wb+"))) error(EXIT_FAILURE, "*Error*: cannot create swap-file ", tab->swapname); add_cleanupfilename(tab->swapname); spoonful = (size%DATA_BUFSIZE); if (!spoonful) spoonful = DATA_BUFSIZE; QFSEEK(tab->cat->file, tab->bodypos, SEEK_SET, tab->cat->filename); #ifdef HAVE_CFITSIO tab->currentElement = 1; #endif read_ibody(tab, buffer, spoonful/sizeof(FLAGTYPE)); /*-- Apply pixel processing */ if (func) (*func)(buffer, spoonful/sizeof(FLAGTYPE)); QFWRITE(buffer, spoonful, file, tab->swapname); for (sizeleft = size; sizeleft -= spoonful;) { read_ibody(tab, buffer, (spoonful=DATA_BUFSIZE)/sizeof(FLAGTYPE)); /*--- Apply pixel processing */ if (func) (*func)(buffer, spoonful/sizeof(FLAGTYPE)); QFWRITE(buffer, spoonful, file, tab->swapname); } free(buffer); tab->bodybuf = mmap(NULL,size,PROT_READ,MAP_SHARED,fileno(file),(off_t)0); fclose(file); tab->swapflag = 1; body_vramleft -= size; /*-- Memory mapping problem */ if (tab->bodybuf == (void *)-1) return NULL; return (FLAGTYPE *)tab->bodybuf; } /* If no memory left at all: forget it! */ return NULL; } /******* free_body ************************************************************ PROTO void free_body(tabstruct *tab) PURPOSE Free FITS body data. INPUT Tab structure. OUTPUT -. NOTES . AUTHOR E. Bertin (IAP) VERSION 04/03/2000 ***/ void free_body(tabstruct *tab) { size_t size; /* Free the body! (if allocated) */ if (tab->bodybuf) { size = (tab->tabsize/tab->bytepix)*sizeof(PIXTYPE); if (tab->swapflag) { if (munmap(tab->bodybuf, size)) warning("Can't unmap ", tab->cat->filename); tab->swapflag = 0; tab->bodybuf = NULL; body_vramleft += size; if (unlink(tab->swapname)) warning("Can't delete ", tab->swapname); remove_cleanupfilename(tab->swapname); *tab->swapname = '\0'; } else { QFREE(tab->bodybuf); body_ramleft += size; } } /* Free the decompression buffer if allocated */ if (tab->compress_buf) QFREE(tab->compress_buf); return; } #ifdef HAVE_CFITSIO /******* readTileCompressed *************************************************** * * Function to read a chunk of a tile-compressed FITS image * ***/ void readTileCompressed(tabstruct *tab, size_t spoonful, void *bufdata0) { int status, hdutype; // first of all, move to correct HDU status = 0; fits_movabs_hdu(tab->infptr, tab->hdunum, &hdutype, &status); if (status != 0) { printf("Error moving to HDU %d\n", tab->hdunum); fits_report_error(stderr, status); } // pixels count from 1 if (!tab->currentElement) tab->currentElement = 1; // now read section of image int datatype; switch(tab->bitpix){ case BYTE_IMG: datatype = TBYTE; break; case SHORT_IMG: datatype = TSHORT; break; case LONG_IMG: datatype = TLONG; break; case FLOAT_IMG: datatype = TFLOAT; break; case DOUBLE_IMG: datatype = TDOUBLE; break; default: datatype = TFLOAT; break; } int anynul; double bscale = 1.0, bzero = 0.0, nulval = 0.; // turn off any scaling so that we copy raw pixel values status = 0; fits_set_bscale(tab->infptr, bscale, bzero, &status); // now read the image status = 0; fits_read_img(tab->infptr, datatype, tab->currentElement, spoonful, &nulval, bufdata0, &anynul, &status); // report reading error if (status) { printf("CFITSIO ERROR reading start=%d end=%d absolute end=%d\n", tab->currentElement, (tab->currentElement + spoonful), (tab->naxisn[0]*tab->naxisn[1])); fits_report_error(stderr, status); } // update file 'pointer' tab->currentElement += spoonful; } #endif // HAVE_CFITSIO /******* read_body ************************************************************ PROTO read_body(tabstruct *tab, PIXTYPE *ptr, long size) PURPOSE Read floating point values from the body of a FITS table. INPUT A pointer to the tab structure, a pointer to the array in memory, the number of elements to be read. OUTPUT -. NOTES . AUTHOR E. Bertin (IAP) VERSION 26/08/2020 ***/ void read_body(tabstruct *tab, PIXTYPE *ptr, size_t size) { catstruct *cat; static double bufdata0[DATA_BUFSIZE/sizeof(double)]; unsigned char cuval, cublank; char *bufdata, cval, cblank; unsigned short suval, sublank, ashort=1; short val16, sval, sblank; #ifdef HAVE_LONG_LONG_INT ULONGLONG lluval, llublank; SLONGLONG llval, llblank; #endif unsigned int iuval, iublank; int curval, dval, blankflag, bswapflag, ival, iblank; size_t i, bowl, spoonful, npix; double bs,bz; /* a NULL cat structure indicates that no data can be read */ if (!(cat = tab->cat)) return; bs = tab->bscale; bz = tab->bzero; blankflag = tab->blankflag; bswapflag = *((char *)&ashort); // Byte-swapping flag switch(tab->compress_type) { /*-- Uncompressed image */ case COMPRESS_NONE: bowl = DATA_BUFSIZE/tab->bytepix; spoonful = size0; size -= spoonful) { if (spoonful>size) spoonful = size; bufdata = (char *)bufdata0; #ifdef HAVE_CFITSIO if (tab->isTileCompressed) readTileCompressed(tab, spoonful, (void *)bufdata0); else QFREAD(bufdata, spoonful*tab->bytepix, cat->file, cat->filename); #else QFREAD(bufdata, spoonful*tab->bytepix, cat->file, cat->filename); #endif // HAVE_CFITSIO switch(tab->bitpix) { case BP_BYTE: if (blankflag) { if (tab->bitsgn) { cblank = (char)tab->blank; #pragma ivdep for (i=spoonful; i--;) *(ptr++) = ((cval = *(bufdata++)) == cblank)? -BIG : cval*bs + bz; } else { cublank = (unsigned char)tab->blank; #pragma ivdep for (i=spoonful; i--;) *(ptr++) = ((cuval=*((unsigned char *)bufdata++))==cublank)? -BIG : cuval*bs + bz; } } else { if (tab->bitsgn) #pragma ivdep for (i=spoonful; i--;) *(ptr++) = *(bufdata++)*bs + bz; else #pragma ivdep for (i=spoonful; i--;) *(ptr++) = *((unsigned char *)bufdata++)*bs + bz; } break; case BP_SHORT: #ifdef HAVE_CFITSIO if (!tab->isTileCompressed && bswapflag) #else if (bswapflag) #endif swapbytes(bufdata, 2, spoonful); if (blankflag) { if (tab->bitsgn) { sblank = (short)tab->blank; #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(short)) *(ptr++) = ((sval = *((short *)bufdata)) == sblank)? -BIG : sval*bs + bz; } else { sublank = (unsigned short)tab->blank; #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(unsigned short)) *(ptr++) = ((suval=*((unsigned short *)bufdata)) == sublank)? -BIG : suval*bs + bz; } } else { if (tab->bitsgn) #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(short)) *(ptr++) = *((short *)bufdata)*bs + bz; else #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(unsigned short)) *(ptr++) = *((unsigned short *)bufdata)*bs + bz; } break; case BP_LONG: #ifdef HAVE_CFITSIO if (!tab->isTileCompressed && bswapflag) #else if (bswapflag) #endif swapbytes(bufdata, 4, spoonful); if (blankflag) { if (tab->bitsgn) { iblank = (int)tab->blank; #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(int)) *(ptr++) = ((ival = *((int *)bufdata)) == iblank)? -BIG : ival*bs + bz; } else { iublank = (unsigned int)tab->blank; #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(unsigned int)) *(ptr++) = ((iuval = *((unsigned int *)bufdata)) == iublank)? -BIG : iuval*bs + bz; } } else { if (tab->bitsgn) #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(int)) *(ptr++) = *((int *)bufdata)*bs + bz; else #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(unsigned int)) *(ptr++) = *((unsigned int *)bufdata)*bs + bz; } break; #ifdef HAVE_LONG_LONG_INT case BP_LONGLONG: #ifdef HAVE_CFITSIO if (!tab->isTileCompressed && bswapflag) #else if (bswapflag) #endif swapbytes(bufdata, 8, spoonful); if (blankflag) { if (tab->bitsgn) { llblank = (SLONGLONG)tab->blank; #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(SLONGLONG)) *(ptr++) = ((llval = *((SLONGLONG *)bufdata)) == llblank)? -BIG : llval*bs + bz; } else { llublank = (ULONGLONG)tab->blank; #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(ULONGLONG)) *(ptr++) = ((lluval = *((ULONGLONG *)bufdata)) == llublank)? -BIG : lluval*bs + bz; } } else { if (tab->bitsgn) #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(SLONGLONG)) *(ptr++) = *((SLONGLONG *)bufdata)*bs + bz; else #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(ULONGLONG)) *(ptr++) = *((ULONGLONG *)bufdata)*bs + bz; } break; #endif case BP_FLOAT: #ifdef HAVE_CFITSIO if (!tab->isTileCompressed && bswapflag) #else if (bswapflag) #endif swapbytes(bufdata, 4, spoonful); #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(float)) *(ptr++) = ((0x7f800000&*(unsigned int *)bufdata) == 0x7f800000)? -BIG : *((float *)bufdata)*bs + bz; break; case BP_DOUBLE: if (bswapflag) { #ifdef HAVE_CFITSIO if (!tab->isTileCompressed) swapbytes(bufdata, 8, spoonful); #else swapbytes(bufdata, 8, spoonful); #endif #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(double)) *(ptr++) = ((0x7ff00000 & *(unsigned int *)(bufdata+4)) == 0x7ff00000)? -BIG : *((double *)bufdata)*bs + bz; } else { #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(double)) *(ptr++) = ((0x7ff00000 & *(unsigned int *)bufdata) == 0x7ff00000)? -BIG : *((double *)bufdata)*bs + bz; } break; default: error(EXIT_FAILURE,"*FATAL ERROR*: unknown BITPIX type in ", "read_body()"); break; } } break; /*-- Compressed image */ case COMPRESS_BASEBYTE: if (!tab->compress_buf) QMALLOC(tab->compress_buf, char, FBSIZE); bufdata = tab->compress_bufptr; curval = tab->compress_curval; npix = tab->compress_npix; while (size--) { if (!(npix--)) { if (curval != tab->compress_checkval) error(EXIT_FAILURE, "*Error*: invalid BASEBYTE checksum in ", cat->filename); bufdata = tab->compress_buf; QFREAD(bufdata, FBSIZE, cat->file, cat->filename); curval = 0; if (bswapflag) swapbytes(bufdata, 4, 1); tab->compress_checkval = *((int *)bufdata); bufdata += 4; if (bswapflag) swapbytes(bufdata, 2, 1); npix = (int)(*((short *)bufdata))-1; bufdata+=2; } if ((dval=(int)*(bufdata++))==-128) { if (bswapflag) swapbytes(bufdata, 2, 1); memcpy(&val16, bufdata, 2); dval = (int)val16; if (dval==-32768) { bufdata += 2; if (bswapflag) swapbytes(bufdata, 4, 1); memcpy(&dval,bufdata,4); bufdata += 4; } else bufdata += 2; } *(ptr++) = dval*bs + bz; curval += dval; } tab->compress_curval = curval; tab->compress_bufptr = bufdata; tab->compress_npix = npix; break; case COMPRESS_PREVPIX: if (!tab->compress_buf) QMALLOC(tab->compress_buf, char, FBSIZE); bufdata = tab->compress_bufptr; curval = tab->compress_curval; npix = tab->compress_npix; while (size--) { if (!(npix--)) { if (curval != tab->compress_checkval) error(EXIT_FAILURE, "*Error*: invalid PREV_PIX checksum in ", tab->cat->filename); bufdata = tab->compress_buf; QFREAD(bufdata, FBSIZE, cat->file, cat->filename); if (bswapflag) swapbytes(bufdata, 2, 3); curval = (int)*(short *)bufdata; npix = (int)*(short *)(bufdata+=2)-1; tab->compress_checkval = (int)(*(short *)(bufdata+=2)); bufdata+=4; } if ((dval=(int)*(bufdata++))==-128) { if (bswapflag) swapbytes(bufdata, 2, 1); memcpy(&val16, bufdata, 2); curval = (int)val16; bufdata += 2; } else curval += dval; *(ptr++) = curval*bs + bz; } tab->compress_curval = curval; tab->compress_bufptr = bufdata; tab->compress_npix = npix; break; default: error(EXIT_FAILURE,"*Internal Error*: unknown compression mode in ", "read_body()"); } return; } /******* read_ibody *********************************************************** PROTO read_ibody(tabstruct *tab, FLAGTYPE *ptr, long size) PURPOSE Read integer values from the body of a FITS table. INPUT A pointer to the tab structure, a pointer to the array in memory, the number of elements to be read. OUTPUT -. NOTES . AUTHOR E. Bertin (IAP) VERSION 26/08/2020 ***/ void read_ibody(tabstruct *tab, FLAGTYPE *ptr, size_t size) { catstruct *cat; static int bufdata0[DATA_BUFSIZE/sizeof(int)]; char *bufdata; short val16; unsigned short ashort = 1; int i, bowl, spoonful, npix, curval, dval, bswapflag; /* a NULL cat structure indicates that no data can be read */ if (!(cat = tab->cat)) return; bswapflag = *((char *)&ashort); // Byte-swapping flag switch(tab->compress_type) { /*-- Uncompressed image */ case COMPRESS_NONE: bowl = DATA_BUFSIZE/tab->bytepix; spoonful = size0; size -= spoonful) { if (spoonful>size) spoonful = size; bufdata = (char *)bufdata0; #ifdef HAVE_CFITSIO if (tab->isTileCompressed) readTileCompressed(tab, spoonful, (void *)bufdata0); else QFREAD(bufdata, spoonful*tab->bytepix, cat->file, cat->filename); #else QFREAD(bufdata, spoonful*tab->bytepix, cat->file, cat->filename); #endif switch(tab->bitpix) { case BP_BYTE: #pragma ivdep for (i=spoonful; i--;) *(ptr++) = (FLAGTYPE)*((unsigned char *)bufdata++); break; case BP_SHORT: #ifdef HAVE_CFITSIO if (!tab->isTileCompressed && bswapflag) #else if (bswapflag) #endif swapbytes(bufdata, 2, spoonful); #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(unsigned short)) *(ptr++) = (FLAGTYPE)*((unsigned short *)bufdata); break; case BP_LONG: #ifdef HAVE_CFITSIO if (!tab->isTileCompressed && bswapflag) #else if (bswapflag) #endif swapbytes(bufdata, 4, spoonful); #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(unsigned int)) *(ptr++) = (FLAGTYPE)*((unsigned int *)bufdata); break; #ifdef HAVE_LONG_LONG_INT case BP_LONGLONG: #ifdef HAVE_CFITSIO if (!tab->isTileCompressed && bswapflag) #else if (bswapflag) #endif swapbytes(bufdata, 8, spoonful); #pragma ivdep for (i=spoonful; i--; bufdata += sizeof(ULONGLONG)) *(ptr++) = (FLAGTYPE)*((ULONGLONG *)bufdata); break; #endif case BP_FLOAT: case BP_DOUBLE: error(EXIT_FAILURE,"*Error*: expected integers, not floats, in ", cat->filename); break; default: error(EXIT_FAILURE,"*FATAL ERROR*: unknown BITPIX type in ", "readdata()"); break; } } break; /*-- Compressed image */ case COMPRESS_BASEBYTE: if (!tab->compress_buf) QMALLOC(tab->compress_buf, char, FBSIZE); bufdata = tab->compress_bufptr; curval = tab->compress_curval; npix = tab->compress_npix; while (size--) { if (!(npix--)) { if (curval != tab->compress_checkval) error(EXIT_FAILURE, "*Error*: invalid BASEBYTE checksum in ", cat->filename); bufdata = tab->compress_buf; QFREAD(bufdata, FBSIZE, cat->file, cat->filename); curval = 0; if (bswapflag) swapbytes(bufdata, 4, 1); tab->compress_checkval = *((int *)bufdata); bufdata += 4; if (bswapflag) swapbytes(bufdata, 2, 1); npix = (int)(*((short *)bufdata))-1; bufdata+=2; } if ((dval=(int)*(bufdata++))==-128) { if (bswapflag) swapbytes(bufdata, 2, 1); memcpy(&val16, bufdata, 2); dval = (int)val16; if (dval==-32768) { bufdata += 2; if (bswapflag) swapbytes(bufdata, 4, 1); memcpy(&dval,bufdata,4); bufdata += 4; } else bufdata += 2; } *(ptr++) = (FLAGTYPE)dval; curval += dval; } tab->compress_curval = curval; tab->compress_bufptr = bufdata; tab->compress_npix = npix; break; case COMPRESS_PREVPIX: if (!tab->compress_buf) QMALLOC(tab->compress_buf, char, FBSIZE); bufdata = tab->compress_bufptr; curval = tab->compress_curval; npix = tab->compress_npix; while (size--) { if (!(npix--)) { if (curval != tab->compress_checkval) error(EXIT_FAILURE, "*Error*: invalid PREV_PIX checksum in ", cat->filename); bufdata = tab->compress_buf; QFREAD(bufdata, FBSIZE, cat->file, cat->filename); if (bswapflag) swapbytes(bufdata, 2, 3); curval = (int)*(short *)bufdata; npix = (int)*(short *)(bufdata+=2)-1; tab->compress_checkval = (int)(*(short *)(bufdata+=2)); bufdata+=4; } if ((dval=(int)*(bufdata++))==-128) { if (bswapflag) swapbytes(bufdata, 2, 1); memcpy(&val16, bufdata, 2); curval = (int)val16; bufdata += 2; } else curval += dval; *(ptr++) = (FLAGTYPE)curval; } tab->compress_curval = curval; tab->compress_bufptr = bufdata; tab->compress_npix = npix; break; default: error(EXIT_FAILURE,"*Internal Error*: unknown compression mode in ", "readdata()"); } return; } /******* write_body *********************************************************** PROTO write_body(tabstruct *tab, PIXTYPE *ptr, long size) PURPOSE Write values to a FITS body. INPUT A pointer to the tab structure, a pointer to the array in memory, the number of elements to be written. OUTPUT -. NOTES . AUTHOR E. Bertin (IAP) VERSION 26/08/2020 ***/ void write_body(tabstruct *tab, PIXTYPE *ptr, size_t size) { static double bufdata0[DATA_BUFSIZE/sizeof(double)]; catstruct *cat; char *cbufdata0; size_t i, bowl, spoonful; PIXTYPE bs,bz; unsigned short ashort = 1; int bswapflag; bswapflag = *((char *)&ashort); // Byte-swapping flag bs = (PIXTYPE)tab->bscale; bz = (PIXTYPE)tab->bzero; cat = tab->cat; if (!cat) error(EXIT_FAILURE, "*Internal Error*: no parent cat structure for table ", tab->extname); cbufdata0 = (char *)bufdata0; /* A trick to remove gcc aliasing warnings */ switch(tab->compress_type) { /*-- Uncompressed image */ case COMPRESS_NONE: bowl = DATA_BUFSIZE/tab->bytepix; spoonful = size0; size -= spoonful) { if (spoonful>size) spoonful = size; switch(tab->bitpix) { case BP_BYTE: if (tab->bitsgn) { char *bufdata = (char *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (char)((*(ptr++)-bz)/bs+0.49999); } else { unsigned char *bufdata = (unsigned char *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (unsigned char)((*(ptr++)-bz)/bs+0.49999);; } break; case BP_SHORT: if (tab->bitsgn) { short *bufdata = (short *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (short)((*(ptr++)-bz)/bs+0.49999); } else { unsigned short *bufdata = (unsigned short *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (unsigned short)((*(ptr++)-bz)/bs+0.49999); } if (bswapflag) swapbytes(cbufdata0, 2, spoonful); break; case BP_LONG: if (tab->bitsgn) { int *bufdata = (int *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (int)((*(ptr++)-bz)/bs+0.49999); } else { unsigned int *bufdata = (unsigned int *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (unsigned int)((*(ptr++)-bz)/bs+0.49999); } if (bswapflag) swapbytes(cbufdata0, 4, spoonful); break; #ifdef HAVE_LONG_LONG_INT case BP_LONGLONG: if (tab->bitsgn) { SLONGLONG *bufdata = (SLONGLONG *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (SLONGLONG)((*(ptr++)-bz)/bs+0.49999); } else { ULONGLONG *bufdata = (ULONGLONG *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (ULONGLONG)((*(ptr++)-bz)/bs+0.49999); } if (bswapflag) swapbytes(cbufdata0, 8, spoonful); break; #endif case BP_FLOAT: { float *bufdata = (float *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (*(ptr++)-bz)/bs; #ifdef HAVE_CFITSIO if (!tab->infptr && bswapflag) #else if (bswapflag) #endif swapbytes(cbufdata0, 4, spoonful); } break; case BP_DOUBLE: { double *bufdata = (double *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (double)(*(ptr++)-bz)/bs; if (bswapflag) swapbytes(cbufdata0, 8, spoonful); } break; default: error(EXIT_FAILURE,"*FATAL ERROR*: unknown BITPIX type in ", "read_body()"); break; } #ifdef HAVE_CFITSIO // if cfitsio output file has been set up, then proceed to write if (tab->infptr) { // now read section of image int datatype; switch(tab->bitpix) { case BYTE_IMG: datatype = TBYTE; break; case SHORT_IMG: datatype = TSHORT; break; case LONG_IMG: datatype = TLONG; break; case FLOAT_IMG: datatype = TFLOAT; break; case DOUBLE_IMG: datatype = TDOUBLE; break; default: datatype = TFLOAT; break; } // turn off any scaling so that we copy the raw pixel values double *array, bscale = 1.0, bzero = 0.0, nulval = 0.0; int status = 0; fits_set_bscale(tab->infptr, bscale, bzero, &status); status = 0; fits_write_img(tab->infptr, datatype, tab->currentElement, spoonful, cbufdata0, &status); if (status) { printf("CFITSIO ERROR writing start=%d end=%d absolute end=%d\n", tab->currentElement, (tab->currentElement + spoonful), (tab->naxisn[0]*tab->naxisn[1])); fits_report_error(stderr, status); } tab->currentElement = tab->currentElement + spoonful; } else // otherwise, continue with usual AstrOmatic fits writing routine QFWRITE(cbufdata0, spoonful*tab->bytepix, cat->file, cat->filename); #else QFWRITE(cbufdata0, spoonful*tab->bytepix, cat->file, cat->filename); #endif // HAVE_CFITSIO } break; /*-- Compressed image */ case COMPRESS_BASEBYTE: break; case COMPRESS_PREVPIX: break; default: error(EXIT_FAILURE,"*Internal Error*: unknown compression mode in ", "read_body()"); } return; } /******* write_ibody *********************************************************** PROTO write_ibody(tabstruct *tab, FLAGTYPE *ptr, long size) PURPOSE Write integer values to a FITS body. INPUT A pointer to the tab structure, a pointer to the array in memory, the number of elements to be written. OUTPUT -. NOTES . AUTHOR E. Bertin (IAP) VERSION 11/02/2020 ***/ void write_ibody(tabstruct *tab, FLAGTYPE *ptr, size_t size) { static FLAGTYPE bufdata0[DATA_BUFSIZE/sizeof(FLAGTYPE)]; catstruct *cat; char *cbufdata0; size_t i, bowl, spoonful; unsigned short ashort = 1; double bs,bz; int bswapflag; bswapflag = *((char *)&ashort); // Byte-swapping flag bs = tab->bscale; bz = tab->bzero; cat = tab->cat; if (!cat) error(EXIT_FAILURE, "*Internal Error*: no parent cat structure for table ", tab->extname); cbufdata0 = (char *)bufdata0; /* A trick to remove gcc aliasing warnings */ switch(tab->compress_type) { /*-- Uncompressed image */ case COMPRESS_NONE: bowl = DATA_BUFSIZE/tab->bytepix; spoonful = size0; size -= spoonful) { if (spoonful>size) spoonful = size; switch(tab->bitpix) { case BP_BYTE: if (tab->bitsgn) { char *bufdata = (char *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (char)*(ptr++); } else { unsigned char *bufdata = (unsigned char *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (unsigned char)*(ptr++); } break; case BP_SHORT: if (tab->bitsgn) { short *bufdata = (short *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (short)*(ptr++); } else { unsigned short *bufdata = (unsigned short *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (unsigned short)*(ptr++); } if (bswapflag) swapbytes(cbufdata0, 2, spoonful); break; case BP_LONG: if (tab->bitsgn) { int *bufdata = (int *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (int)*(ptr++); } else { unsigned int *bufdata = (unsigned int *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (unsigned int)*(ptr++); } if (bswapflag) swapbytes(cbufdata0, 4, spoonful); break; #ifdef HAVE_LONG_LONG_INT case BP_LONGLONG: if (tab->bitsgn) { SLONGLONG *bufdata = (SLONGLONG *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (SLONGLONG)*(ptr++); } else { ULONGLONG *bufdata = (ULONGLONG *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (ULONGLONG)*(ptr++); } if (bswapflag) swapbytes(cbufdata0, 8, spoonful); break; #endif case BP_FLOAT: { float *bufdata = (float *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = (float)((double)*(ptr++)-bz)/bs; if (bswapflag) swapbytes(cbufdata0, 4, spoonful); } break; case BP_DOUBLE: { double *bufdata = (double *)cbufdata0; #pragma ivdep for (i=spoonful; i--;) *(bufdata++) = ((double)*(ptr++)-bz)/bs; if (bswapflag) swapbytes(cbufdata0, 8, spoonful); } break; default: error(EXIT_FAILURE,"*FATAL ERROR*: unknown BITPIX type in ", "read_body()"); break; } QFWRITE(cbufdata0, spoonful*tab->bytepix, cat->file, cat->filename); } break; /*-- Compressed image */ case COMPRESS_BASEBYTE: break; case COMPRESS_PREVPIX: break; default: error(EXIT_FAILURE,"*Internal Error*: unknown compression mode in ", "read_body()"); } return; } /******* set_maxram *********************************************************** PROTO int set_maxram(size_t maxram) PURPOSE Set the maximum amount of silicon memory that can be allocated for storing FITS body data. INPUT The maximum amount of RAM (in bytes). OUTPUT RETURN_OK if within limits, RETURN_ERROR otherwise. NOTES . AUTHOR E. Bertin (IAP) VERSION 19/12/99 ***/ int set_maxram(size_t maxram) { if (maxram<1) return RETURN_ERROR; body_maxram = maxram; return RETURN_OK; } /******* set_maxvram ********************************************************** PROTO int set_maxvram(size_t maxram) PURPOSE Set the maximum amount of total virtual memory that can be used for storing FITS body data. INPUT The maximum amount of VRAM (in bytes). OUTPUT RETURN_OK if within limits, RETURN_ERROR otherwise. NOTES . AUTHOR E. Bertin (IAP) VERSION 08/02/2000 ***/ int set_maxvram(size_t maxvram) { if (maxvram<1) return RETURN_ERROR; body_maxvram = maxvram; return RETURN_OK; } /******* set_swapdir ********************************************************** PROTO int set_swapdir(char *dirname) PURPOSE Set the path name of the directory that will be used for storing memory swap files. INPUT The pointer to the path string. OUTPUT RETURN_OK if path appropriate, RETURN_ERROR otherwise. NOTES . AUTHOR E. Bertin (IAP) VERSION 19/12/99 ***/ int set_swapdir(char *dirname) { if (!dirname) return RETURN_ERROR; strcpy(body_swapdirname, dirname); return RETURN_OK; } swarp-2.41.5/src/fits/fitscat.c000066400000000000000000000311371400430667300163040ustar00rootroot00000000000000/* * fitscat.c * * Low-level functions for handling FITS images and tables. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic FITS/LDAC library * * Copyright: (C) 1995-2020 IAP/CNRS/SorbonneU * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 26/08/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "fitscat_defs.h" #include "fitscat.h" char fits_str[MAXCHAR]; /****** about_cat ************************************************************** PROTO int about_cat(catstruct *cat, FILE *stream) PURPOSE Print some info about a catalog. INPUT Catalog structure, output stream. OUTPUT RETURN_OK if everything went as expected, RETURN_ERROR otherwise. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 19/03/2002 ***/ int about_cat(catstruct *cat, FILE *stream) { tabstruct *tab; int i; fprintf(stream,"\n"); /*General info about the catalog itself*/ fprintf(stream, "------------------Catalog information----------------\n"); fprintf(stream, "Filename:..............%s\n", cat->filename); fprintf(stream, "Number of segments:....%d\n", cat->ntab); fprintf(stream,"\n"); /*Now for each table*/ tab = cat->tab; for (i=0; intab; i++) { fprintf(stream, "****** Table #%d\n", i+1); fprintf(stream, " Extension type:.........%s\n", tab->xtension[0]? tab->xtension: "(Primary HDU)"); fprintf(stream, " Extension name:.........%s\n", tab->extname); if (tab->naxis) { fprintf(stream, " Number of dimensions:...%d\n", tab->naxis); fprintf(stream, " Number of elements:.....%d\n", tab->naxisn[1]); if (tab->tfields) fprintf(stream, " Number of data fields...%d\n", tab->tfields); fprintf(stream, " Body size:..............%ld bytes\n", (unsigned long)tab->tabsize); } fprintf(stream,"\n"); while (!(tab=tab->nexttab)->nseg); } fprintf(stream,"\n"); return RETURN_OK; } /****** addhistoryto_cat ******************************************************* PROTO int addhistoryto_cat(catstruct *cat, char *str) PURPOSE Add a HISTORY line to a FITS catalog. INPUT A pointer to catalog structure, and the character string to insert. OUTPUT RETURN_OK if everything went as expected, RETURN_ERROR otherwise. NOTES The pointer to the primary header might be reallocated if necessary. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 25/09/2004 ***/ int addhistoryto_cat(catstruct *cat, char *str) { time_t thetime; char str2[82]; tabstruct *tab; int n, headpos; tab = cat->tab; n = tab->headnblock; headpos = fitsfind(tab->headbuf, "END "); if (headpos >= n*(FBSIZE/80) - 1) { QREALLOC(tab->headbuf, char, (n+1)*FBSIZE); memset(&tab->headbuf[n*FBSIZE], ' ', FBSIZE); tab->headnblock++; } if (time(&thetime)==-1) warning("No time available for history",""); if (!strftime(str2, 16, "%d/%m/%Y %H:%M", localtime(&thetime))) error(EXIT_FAILURE, "*Internal Error*: Time/date string too long in ", "addhistoryto_cat()"); sprintf(str2, "%s %.65s", str2, str); fitsadd(tab->headbuf, "HISTORY ", str2); return RETURN_OK; } /****** close_cat ************************************************************** PROTO int close_cat(catstruct *cat) PURPOSE Close a FITS catalog. INPUT catalog structure. OUTPUT RETURN_OK if everything went as expected, RETURN_ERROR otherwise. NOTES the file structure member is set to NULL; AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 22/06/2001 ***/ int close_cat(catstruct *cat) { if (cat->file && fclose(cat->file)) { cat->file = NULL; return RETURN_ERROR; } cat->file = NULL; return RETURN_OK; } #ifdef HAVE_CFITSIO /****** close_cfitsio ************************************************************** Closes a file previously opened by cfitsio ***/ int close_cfitsio(fitsfile *infptr) { if (infptr != NULL) { int status = 0; fits_close_file(infptr, &status); if (status != 0) { fits_report_error(stderr, status); printf("ERROR could not close FITS file with cfitsio\n"); } else { //printf("Successfully closed FITS file with cfitsio\n"); infptr == NULL; } } else { //printf("ERROR no cfitsio file to close\n"); } } #endif // HAVE_CFITSIO /****** free_cat *************************************************************** PROTO void free_cat(catstruct **cat, int ncat) PURPOSE Free all structures allocated for one or several FITS catalog. INPUT Pointer to a catalog structure, Number of catalogs. OUTPUT -. NOTES Unallocated pointers should have been put to NULL. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 05/12/2009 ***/ void free_cat(catstruct **cat, int ncat) { catstruct **thecat; int i; /*--free memory allocated within each catalog */ thecat = cat; for (i=ncat; i--;) { if ((*thecat)->file) close_cat(*thecat); remove_tabs(*thecat); free(*(thecat++)); } return; } /****** inherit_cat ************************************************************ PROTO int inherit_cat(catstruct *catin, catstruct *catout) PURPOSE Copy the primary table, and all other informations from one catalog to another, except those related to the associated file itself (filename, etc...), INPUT A pointer to both catalog structures. OUTPUT RETURN_OK if at least one table was copied, RETURN_ERROR otherwise. NOTES The output catalog should be ``cleaned'' before call. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 13/06/2002 ***/ int inherit_cat(catstruct *catin, catstruct *catout) { tabstruct *tabin, *tabout, *prevtabout; int j; catout->ntab = 1; tabin = catin->tab; /*copy only one table: well it could be simpler, but let's stay general!*/ prevtabout = NULL; for (j=tabin->nseg; j--;) { QCALLOC(tabout, tabstruct, 1); *tabout = *tabin; if (tabin->naxis) QMEMCPY(tabin->naxisn, tabout->naxisn, int, (size_t)tabin->naxis); if (tabin->headbuf) QMEMCPY(tabin->headbuf, tabout->headbuf, char, tabin->headnblock*FBSIZE); if (tabin->bodybuf) QMEMCPY(tabin->bodybuf, tabout->bodybuf, char, (size_t)tabin->tabsize); if (prevtabout) { tabout->prevtab = prevtabout; prevtabout->nexttab = tabout; } else { catout->tab = tabout; } prevtabout = tabout; tabin = tabin->nexttab; } if (prevtabout) { prevtabout->nexttab = catout->tab; catout->tab->prevtab = prevtabout; } else return RETURN_ERROR; return RETURN_OK; } /****** init_cat *************************************************************** PROTO int init_cat(catstruct *cat) PURPOSE Initialize a catalog, "cleaning" any content if present and adding the primary header "table". INPUT A pointer to the catalog structure. OUTPUT RETURN_OK if everything went as expected, RETURN_ERROR otherwise. NOTES The output catalog should be ``cleaned'' before call. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 28/05/2001 ***/ int init_cat(catstruct *cat) { static char bintabtemplate[][80] = { "SIMPLE = T / This is a FITS file", "BITPIX = 8 / ", "NAXIS = 0 / ", "EXTEND = T / This file may contain FITS extensions", "END "}; tabstruct *tab; char *buf; int i; /* Initialize the primary header itself */ QCALLOC(tab, tabstruct, 1); tab->naxis = 0; tab->bitpix = 8; tab->bytepix = 1; tab->pcount = 0; tab->gcount = 1; tab->seg = 1; tab->nseg = 1; /* Provide a new header*/ QCALLOC(tab->headbuf, char, FBSIZE); memcpy(tab->headbuf, bintabtemplate, sizeof(bintabtemplate)); for (buf = tab->headbuf, i=0; iheadnblock = 1; /* Clean catalog and add the table to it */ remove_tabs(cat); cat->tab = tab->prevtab = tab->nexttab = tab; cat->ntab = 1; return RETURN_OK; } /****** map_cat **************************************************************** PROTO int map_cat(catstruct *cat) PURPOSE Explores the whole FITS file and gets information for each of the FITS tables it contains. INPUT catalog structure. OUTPUT RETURN_OK if at least one table was found, RETURN_ERROR otherwise. NOTES Memory space for the array of fits structures is reallocated. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 14/12/2002 ***/ int map_cat(catstruct *cat) { int ntab; tabstruct *tab, *prevtab; /*scan through the file until we reach the end*/ prevtab = NULL; QCALLOC(tab, tabstruct, 1); tab->cat = cat; QFTELL(cat->file, tab->headpos, cat->filename); #ifdef HAVE_CFITSIO fitsfile *infptr; int status, hdutype, hdunum; status = 0; fits_open_file(&infptr, cat->filename, READONLY, &status); if (status != 0) { fits_report_error(stderr, status); printf("ERROR could not open FITS file with cfitsio: %s\n", cat->filename); } hdunum = 1; int any_tile_compressed = 0; #endif // HAVE_CFITSIO for (ntab=0; !get_head(tab); ntab++) { readbasic_head(tab); readbintabparam_head(tab); QFTELL(cat->file, tab->bodypos, cat->filename); tab->nseg = tab->seg = 1; #ifdef HAVE_CFITSIO if (tab->isTileCompressed) { any_tile_compressed = 1; tab->hdunum = hdunum; tab->infptr = infptr; status = 0; fits_movabs_hdu(tab->infptr, tab->hdunum, &hdutype, &status); if (status != 0) printf("ERROR could not move to hdu %d in file %s\n", tab->hdunum, cat->filename); if (tab->tabsize) fseek(cat->file, infptr->Fptr->headstart[hdunum], SEEK_SET); } // NOT tile-compressed else { tab->infptr = NULL; if (tab->tabsize) QFSEEK(cat->file, PADTOTAL(tab->tabsize), SEEK_CUR, cat->filename); } hdunum++; #else if (tab->tabsize) QFSEEK(cat->file, PADTOTAL(tab->tabsize), SEEK_CUR, cat->filename); #endif // HAVE_CFITSIO if (prevtab) { tab->prevtab = prevtab; prevtab->nexttab = tab; } else cat->tab = tab; prevtab = tab; QCALLOC(tab, tabstruct, 1); tab->cat = cat; QFTELL(cat->file, tab->headpos, cat->filename); } #ifdef HAVE_CFITSIO // we will not need CFitsIO, so close CFitsIO file pointer now if (!any_tile_compressed) close_cfitsio(infptr); #endif cat->ntab = ntab; free(tab); if (prevtab) { prevtab->nexttab = cat->tab; cat->tab->prevtab = prevtab; } else return RETURN_ERROR; /*rewind to the beginning*/ /* QFSEEK(cat->file, 0, SEEK_SET, cat->filename); */ return RETURN_OK; } /****** new_cat **************************************************************** PROTO catstruct *new_cat(int ncat) PURPOSE Initialize a structure for a FITS catalog. INPUT Number of catalogs. OUTPUT A pointer to the catalog array. NOTES All fields are initialized to 0. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 20/03/96 ***/ catstruct *new_cat(int ncat) { catstruct *cat; QCALLOC(cat, catstruct, ncat); cat->access_type = WRITE_ONLY; return cat; } /****** open_cat *************************************************************** PROTO int open_cat(catstruct *cat, access_type_t at) PURPOSE Open a FITS catalog with name filename. INPUT catalog structure, access type (can be WRITE_ONLY or READ_ONLY). OUTPUT RETURN_OK if the cat is found, RETURN_ERROR otherwise. NOTES If the file was already opened by this catalog, nothing is done. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 29/08/2012 ***/ int open_cat(catstruct *cat, access_type_t at) { if (cat->access_type == READ_ONLY && at == WRITE_ONLY) error(EXIT_FAILURE, "*Internal Error*: Trying to write to the " "READ_ONLY catalog ", cat->filename); if (!cat->file) { if ((cat->file = fopen(cat->filename, at==WRITE_ONLY?"wb":"rb")) == NULL) return RETURN_ERROR; cat->access_type = at; } return RETURN_OK; } swarp-2.41.5/src/fits/fitscat.h000066400000000000000000000304451400430667300163120ustar00rootroot00000000000000/* * fitscat.h * * Main include file for the LDACTools FITS library. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic FITS/LDAC library * * Copyright: (C) 1995-2020 IAP/CNRS/SorbonneU * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 26/08/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _FITSCAT_H_ #define _FITSCAT_H_ #include #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_CFITSIO #include CFITSIO_H #endif #define MAXCHARS 256 /* max. number of characters */ #define WARNING_NMAX 1000 /* max. number of recorded warnings */ /*---------------------------- return messages ------------------------------*/ #ifndef RETURN_OK #define RETURN_OK 0 #endif #ifndef RETURN_ERROR #define RETURN_ERROR (-1) #endif #ifndef RETURN_FATAL_ERROR #define RETURN_FATAL_ERROR (-2) #endif /*--------------------------- FITS BitPix coding ----------------------------*/ #define BP_BYTE 8 #define BP_SHORT 16 #define BP_LONG 32 #define BP_LONGLONG 64 #define BP_FLOAT (-32) #define BP_DOUBLE (-64) /*-------------------------------- macros -----------------------------------*/ /* Standard FITS name suffix*/ #define FITS_SUFFIX ".fits" /* size (in bytes) of one FITS block */ #define FBSIZE 2880L /* FITS size after adding padding */ #define PADTOTAL(x) (((x-1)/FBSIZE+1)*FBSIZE) /* extra size to add for padding */ #define PADEXTRA(x) ((FBSIZE - (x%FBSIZE))% FBSIZE) /*--------------------------------- typedefs --------------------------------*/ typedef enum {H_INT, H_FLOAT, H_EXPO, H_BOOL, H_STRING, H_STRINGS, H_COMMENT, H_HCOMMENT, H_KEY} h_type; /* type of FITS-header data */ typedef enum {T_BYTE, T_SHORT, T_LONG, T_LONGLONG, T_FLOAT, T_DOUBLE, T_STRING} t_type; /* Type of data */ typedef enum {WRITE_ONLY, READ_ONLY} access_type_t; /* Type of access */ typedef enum {SHOW_ASCII, SHOW_SKYCAT} output_type; /* Type of output */ typedef float PIXTYPE; /* Pixel type */ typedef unsigned int FLAGTYPE; /* Flag type */ #ifdef HAVE_UNSIGNED_LONG_LONG_INT typedef unsigned long long KINGSIZE_T; /* for large sizes */ typedef unsigned long long ULONGLONG; #else typedef size_t KINGSIZE_T;/* better than nothing */ typedef union {unsigned int l[2];} ULONGLONG; #endif #ifdef HAVE_LONG_LONG_INT typedef long long SLONGLONG; #else typedef union {int l[2];} SLONGLONG; #endif // CFITSIO changed OFF_T to OFF_T2 due to clash with cfitsio lib #if defined(_FILE_OFFSET_BITS) && !defined(OFF_T2) #define OFF_T2 off_t #else #define OFF_T2 long #endif /*------------------------------- constants ---------------------------------*/ extern const int t_size[]; /* size in bytes per t_type (see fitshead.c) */ /*---------------------------------- key ------------------------------------*/ typedef struct structkey { char name[80]; /* name */ char comment[80]; /* a comment */ void *ptr; /* pointer to the data */ h_type htype; /* standard ``h_type'' (display) */ t_type ttype; /* standard ``t_type'' (storage) */ char printf[80]; /* printing format (C Convention) */ char unit[80]; /* physical unit */ char voucd[80]; /* VO ucd */ char vounit[80]; /* VO unit */ int naxis; /* number of dimensions */ int *naxisn; /* pointer to an array of dim. */ int nobj; /* number of objects */ int nbytes; /* number of bytes per element */ long pos; /* position within file */ struct structkey *prevkey; /* previous key within the chain */ struct structkey *nextkey; /* next key within the chain */ struct structtab *tab; /* (original) parent tab */ int allocflag; /* true if ptr dynamically allocated */ } keystruct; /*------------------------------- catalog ---------------------------------*/ typedef struct structcat { char filename[MAXCHARS]; /* file name */ FILE *file; /* pointer to the file structure */ struct structtab *tab; /* pointer to the first table */ int ntab; /* number of tables included */ access_type_t access_type; /* READ_ONLY or WRITE_ONLY */ } catstruct; /*-------------------------------- table ----------------------------------*/ typedef struct structtab { int bitpix; /* bits per element */ int bytepix; /* bytes per element */ int bitsgn; /* = 0 if unsigned data */ double bscale; /* data scale factor */ double bzero; /* data offset parameter */ int blank; /* integer code for undefined values */ int blankflag; /* set if a blank keyword was found */ enum {COMPRESS_NONE, COMPRESS_BASEBYTE, COMPRESS_PREVPIX} compress_type; /* image compression type */ char *compress_buf; /* de-compression buffer */ char *compress_bufptr; /* present pixel in buffer */ int compress_curval; /* current pixel or checksum value */ int compress_checkval; /* foreseen pixel or checksum value */ size_t compress_npix; /* remaining pixels in buffer */ int naxis; /* number of dimensions */ int *naxisn; /* array of dimensions */ int tfields; /* number of fields */ int pcount, gcount; /* alignment of the data */ KINGSIZE_T tabsize; /* total table size (bytes) */ char xtension[82]; /* FITS extension type */ char extname[82]; /* FITS extension name */ char *headbuf; /* buffer containing the header */ int headnblock; /* number of FITS blocks */ char *bodybuf; /* buffer containing the body */ OFF_T2 bodypos; /* position of the body in the file */ OFF_T2 headpos; /* position of the head in the file */ struct structcat *cat; /* (original) parent catalog */ struct structtab *prevtab, *nexttab; /* previous and next tab in chain */ int seg; /* segment position */ int nseg; /* number of tab segments */ keystruct *key; /* pointer to keys */ int nkey; /* number of keys */ int swapflag; /* mapped to a swap file ? */ char swapname[MAXCHARS]; /* name of the swapfile */ unsigned int bodysum; /* Checksum of the FITS body */ #ifdef HAVE_CFITSIO fitsfile *infptr; /* a cfitsio pointer to the file */ int hdunum; /* FITS HDU number for this 'table' */ int isTileCompressed; /* is this a tile compressed image? */ long currentElement; /* tracks the current image pixel */ #endif } tabstruct; /*------------------------------- functions ---------------------------------*/ extern catstruct *new_cat(int ncat), *read_cat(char *filename), *read_cats(char **filenames, int ncat); extern tabstruct *asc2bin_tab(catstruct *catin, char *tabinname, catstruct *catout, char *taboutname), *init_readobj(tabstruct *tab, char **pbuf), *name_to_tab(catstruct *cat, char *tabname, int seg), *new_tab(char *tabname), *pos_to_tab(catstruct *cat, int pos, int seg); extern keystruct *name_to_key(tabstruct *tab, char *keyname), *new_key(char *keyname), *pos_to_key(tabstruct *tab, int pos), *read_key(tabstruct *tab, char *keyname); extern void add_cleanupfilename(char *filename), cleanup_files(void), copy_tab_fromptr(tabstruct *tabin, catstruct *catout, int pos), encode_checksum(unsigned int sum, char *str), end_readobj(tabstruct *keytab, tabstruct *tab, char *buf), end_writeobj(catstruct *cat, tabstruct *tab, char *buf), error(int, char *, char *), error_installfunc(void (*func)(char *msg1, char *msg2)), fixexponent(char *s), free_body(tabstruct *tab), free_cat(catstruct **cat, int ncat), free_key(keystruct *key), free_tab(tabstruct *tab), init_writeobj(catstruct *cat, tabstruct *tab, char **pbuf), install_cleanup(void (*func)(void)), print_obj(FILE *stream, tabstruct *tab), read_keys(tabstruct *tab, char **keynames, keystruct **keys, int nkeys, unsigned char *mask), read_basic(tabstruct *tab), read_body(tabstruct *tab, PIXTYPE *ptr, size_t size), read_ibody(tabstruct *tab, FLAGTYPE *ptr, size_t size), readbasic_head(tabstruct *tab), remove_cleanupfilename(char *filename), save_cat(catstruct *cat, char *filename), save_tab(catstruct *cat, tabstruct *tab), show_keys(tabstruct *tab, char **keynames, keystruct **keys, int nkeys, unsigned char *mask, FILE *stream, int strflag,int banflag, int leadflag, output_type o_type), swapbytes(void *, int, int), ttypeconv(void *ptrin, void *ptrout, t_type ttypein, t_type ttypeout), voprint_obj(FILE *stream, tabstruct *tab), warning(char *, char *), write_body(tabstruct *tab, PIXTYPE *ptr, size_t size), write_ibody(tabstruct *tab, FLAGTYPE *ptr, size_t size), write_checksum(tabstruct *tab); extern char *tdisptoprintf(char *tdisp, char *str), *printftotdisp(char *cprintf, char *str), *fitsnfind(char *fitsbuf, char *str, int nblock), **tabs_list(catstruct *cat, int *n), **keys_list(tabstruct *tab, int *n), *warning_history(void); extern unsigned int compute_blocksum(char *buf, unsigned int sum), compute_bodysum(tabstruct *tab, unsigned int sum), decode_checksum(char *str); extern int about_cat(catstruct *cat, FILE *stream), about_tab(catstruct *cat, char *tabname, FILE *stream), addhistoryto_cat(catstruct *cat, char *str), add_key(keystruct *key, tabstruct *tab, int pos), addkeyto_head(tabstruct *tab, keystruct *key), addkeywordto_head(tabstruct *tab, char *keyword,char *comment), add_tab(tabstruct *tab, catstruct *cat, int pos), blank_keys(tabstruct *tab), close_cat(catstruct *cat), #ifdef HAVE_CFITSIO close_cfitsio(fitsfile *infptr), #endif copy_key(tabstruct *tabin, char *keyname, tabstruct *tabout, int pos), copy_tab(catstruct *catin, char *tabname, int seg, catstruct *catout, int pos), copy_tabs(catstruct *catin, catstruct *catout), copy_tabs_blind(catstruct *catin, catstruct *catout), ext_head(tabstruct *tab), findkey(char *, char *, int), findnkey(char *, char *, int, int), fitsadd(char *fitsbuf, char *keyword, char *comment), fitsfind(char *fitsbuf, char *keyword), fitspick(char *fitsbuf, char *keyword, void *ptr, h_type *htype, t_type *ttype, char *comment), fitsread(char *fitsbuf, char *keyword, void *ptr, h_type htype, t_type ttype), fitsremove(char *fitsbuf, char *keyword), fitswrite(char *fitsbuf, char *keyword, void *ptr, h_type htype, t_type ttype), get_head(tabstruct *tab), inherit_cat(catstruct *catin, catstruct *catout), init_cat(catstruct *cat), map_cat(catstruct *cat), open_cat(catstruct *cat, access_type_t at), pad_tab(catstruct *cat, KINGSIZE_T size), prim_head(tabstruct *tab), readbintabparam_head(tabstruct *tab), read_field(tabstruct *tab, char **keynames, keystruct **keys, int nkeys, int field, tabstruct *ftab), read_obj(tabstruct *keytab, tabstruct *tab, char *buf), read_obj_at(tabstruct *keytab, tabstruct *tab, char *buf, long pos), remove_key(tabstruct *tab, char *keyname), remove_keys(tabstruct *tab), removekeywordfrom_head(tabstruct *tab, char *keyword), remove_tab(catstruct *cat, char *tabname, int seg), remove_tabs(catstruct *cat), save_head(catstruct *cat, tabstruct *tab), set_maxram(size_t maxram), set_maxvram(size_t maxvram), set_swapdir(char *dirname), tab_row_len(char *, char *), tformof(char *str, t_type ttype, int n), tsizeof(char *str), update_head(tabstruct *tab), update_tab(tabstruct *tab), verify_checksum(tabstruct *tab), write_obj(tabstruct *tab, char *buf), wstrncmp(char *, char *, int); extern PIXTYPE *alloc_body(tabstruct *tab, void (*func)(PIXTYPE *ptr, int npix)); extern FLAGTYPE *alloc_ibody(tabstruct *tab, void (*func)(FLAGTYPE *ptr, int npix)); extern t_type ttypeof(char *str); extern void error(int, char *, char *), swapbytes(void *ptr, int nb, int n), warning(char *msg1, char *msg2); #endif swarp-2.41.5/src/fits/fitscat_defs.h000066400000000000000000000132571400430667300173150ustar00rootroot00000000000000/* * fitscat_defs.h * * Internal definitions for the LDACTools FITS library. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic FITS/LDAC library * * Copyright: (C) 1995-2020 IAP/CNRS/SorbonneU * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 15/07/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /* Check if we are using a configure script here */ #ifndef HAVE_CONFIG_H #define VERSION "2.0" #define DATE "2003-x-x" #define HAVE_SYS_MMAN_H 1 #endif /*------------------------ what, who, when and where ------------------------*/ #define BANNER "LDACTools" #define COPYRIGHT "Emmanuel BERTIN (bertin@iap.fr)" #define INSTITUTE "IAP/Leiden" /*----------------------------- Internal constants --------------------------*/ #define MAXCHAR 512 /* max. number of characters */ #define OUTPUT stdout /* where all msgs are sent */ #define KBYTE 1024 /* 1 kbyte! */ #define MBYTE (1024*KBYTE) /* 1 Mbyte! */ #define GBYTE (1024*MBYTE) /* 1 Gbyte! */ #define DATA_BUFSIZE (4*MBYTE) /* data buffer size for I/O's */ #define BODY_DEFRAM (256*MBYTE) /* a fair number by 1999 standards */ #define BODY_DEFVRAM (1.9*GBYTE) /* a fair number by 1999 standards */ #define BODY_DEFSWAPDIR "/tmp" /* OK at least for Unix systems */ #define BIG 1e+30 /* a huge number */ #define TINY (1.0/BIG) /* a tiny number */ #ifndef PI #define PI 3.14159265359 /* never met before? */ #endif /* NOTES: We must have: MAXCHARS >= 16 DATA_BUFSIZE >= 2 although DATA_BUFSIZE >= 100000 is better!! */ /*--------------------- in case of missing constants ------------------------*/ #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef EXIT_SUCCESS #define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE #define EXIT_FAILURE -1 #endif /*--------------------------------- typedefs --------------------------------*/ typedef unsigned char BYTE; /* a byte */ typedef int LONG; /* for DEC-Alpha... */ /*----------------------------- Internal constants --------------------------*/ extern char fits_str[MAXCHAR]; /*----------------------------- External constants --------------------------*/ /*------------------------------- Other Macros -----------------------------*/ #if _LARGEFILE_SOURCE #define FSEEKO fseeko #define FTELLO ftello #else #define FSEEKO fseek #define FTELLO ftell #endif #define QFREAD(ptr, size, file, fname) \ {if (fread(ptr, (size_t)(size), (size_t)1, file)!=1) \ error(EXIT_FAILURE, "*Error* while reading ", fname);;} #define QFWRITE(ptr, size, file, fname) \ {if (fwrite(ptr, (size_t)(size), (size_t)1, file)!=1) \ error(EXIT_FAILURE, "*Error* while writing ", fname);;} #define QFSEEK(file, offset, pos, fname) \ {if (FSEEKO(file, offset, pos)) \ error(EXIT_FAILURE,"*Error*: File positioning failed in ", \ fname);;} #define QFTELL(file, pos, fname) \ {if ((pos=FTELLO(file))==-1) \ error(EXIT_FAILURE,"*Error*: File position unknown in ", \ fname);;} #define QFREE(x) {free(x); x = NULL;} #define QCALLOC(ptr, typ, nel) \ {if (!(ptr = (typ *)calloc((size_t)(nel),sizeof(typ)))) \ { \ sprintf(fits_str, #ptr " (" #nel "=%zd elements) " \ "at line %d in module " __FILE__ " !", \ (size_t)(nel)*sizeof(typ), __LINE__); \ error(EXIT_FAILURE, "Could not allocate memory for ", fits_str);\ }; \ } #define QMALLOC(ptr, typ, nel) \ {if (!(ptr = (typ *)malloc((size_t)(nel)*sizeof(typ)))) \ { \ sprintf(fits_str, #ptr " (" #nel "=%zd elements) " \ "at line %d in module " __FILE__ " !", \ (size_t)(nel)*sizeof(typ), __LINE__); \ error(EXIT_FAILURE, "Could not allocate memory for ", fits_str);\ }; \ } #define QREALLOC(ptr, typ, nel) \ {if (!(ptr = (typ *)realloc(ptr, (size_t)(nel)*sizeof(typ))))\ { \ sprintf(fits_str, #ptr " (" #nel "=%zd elements) " \ "at line %d in module " __FILE__ " !", \ (size_t)(nel)*sizeof(typ), __LINE__); \ error(EXIT_FAILURE, "Could not allocate memory for ", fits_str);\ }; \ } #define QMEMCPY(ptrin, ptrout, typ, nel) \ {if (ptrin) \ {if (!(ptrout = (typ *)malloc((size_t)(nel)*sizeof(typ)))) \ { \ sprintf(fits_str, #ptrout " (" #nel "=%zd elements) " \ "at line %d in module " __FILE__ " !", \ (size_t)(nel)*sizeof(typ), __LINE__); \ error(EXIT_FAILURE,"Could not allocate memory for ",fits_str);\ }; \ memcpy(ptrout, ptrin, (size_t)(nel)*sizeof(typ)); \ }; \ } #define RINT(x) (int)(floor(x+0.5)) #define QPRINTF if (qflag) fprintf #define QFPRINTF(w,x) {if (qflag) \ fprintf(w, "\33[1M> %s\n\33[1A",x);;} #define QGETKEY(tab, key, keyname, dest) \ {if (!(key = name_to_key(tab, keyname))) \ error(EXIT_FAILURE, "*Error*: No such parameter in catalog: ", \ keyname); \ dest = key->ptr;} #define MIN(a,b) (a. * * Last modified: 11/02/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "fitscat_defs.h" #include "fitscat.h" #define ENCODE_OFFSET 0x30 unsigned int exclude[13] = {0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60}; /****** encode_checksum ***************************************************** PROTO void encode_checksum(unsigned int sum, char *str) PURPOSE Encode a checksum to ASCII INPUT Checksum, Destination string. OUTPUT -. NOTES Straightforward copy of Seaman & Pence 1995 (ftp://iraf.noao.edu/misc/checksum/). AUTHOR E. Bertin (IAP) VERSION 08/05/2001 ***/ void encode_checksum(unsigned int sum, char *str) { int ch[4], i,j,k, byte, check; for (i=0; i<4; i++) { /*-- Each byte becomes four */ byte = (sum << 8*i) >> 24; ch[0] = (ch[1] = ch[2] = ch[3] = byte/4 + ENCODE_OFFSET) + (byte%4); for (check=1; check;) /* avoid ASCII punctuation */ for (check=k=0; k<13; k++) { if (ch[0]==exclude[k] || ch[1]==exclude[k]) { ch[0]++; ch[1]--; check++; } if (ch[2]==exclude[k] || ch[3]==exclude[k]) { ch[2]++; ch[3]--; check++; } } for (j=0; j<4; j++) /* assign the bytes */ str[(4*j+i+1)%16] = ch[j]; /* permute the bytes for FITS */ } str[16] = 0; return; } /****** decode_checksum ***************************************************** PROTO unsigned int decode_checksum(char *str) PURPOSE Decode an ASCII checksum INPUT Checksum string. OUTPUT Checksum. NOTES Straightforward copy of Seaman & Pence 1995 (ftp://iraf.noao.edu/misc/checksum/). AUTHOR E. Bertin (IAP) VERSION 11/02/2020 ***/ unsigned int decode_checksum(char *str) { char cbuf[16]; unsigned short *sbuf, los,his, ashort = 1; unsigned int hi,lo, hicarry,locarry; int i; /* Remove the permuted FITS byte alignment and the ASCII 0 offset */ for (i=0; i<16; i++) cbuf[i] = str[(i+1)%16] - 0x30; sbuf = (unsigned short *)cbuf; hi = lo = 0; if (*((char *)&ashort)) // Byte-swapping required for (i=4; i--;) { his = *(sbuf++); los = *(sbuf++); hi += (*((unsigned char *)&his)<<8) + *((unsigned char *)&his+1); lo += (*((unsigned char *)&los)<<8) + *((unsigned char *)&los+1); } else for (i=4; i--;) { hi += *(sbuf++); lo += *(sbuf++); } hicarry = hi>>16; locarry = lo>>16; while (hicarry || locarry) { hi = (hi & 0xffff) + locarry; lo = (lo & 0xffff) + hicarry; hicarry = hi >> 16; locarry = lo >> 16; } return (hi<<16) + lo; } /****** compute_blocksum ***************************************************** PROTO unsigned int compute_blocksum(char *buf, unsigned int sum) PURPOSE Compute the checksum of a FITS block (2880 bytes) INPUT Pointer to the block, The previous checksum. OUTPUT The new computed checksum. NOTES From Seaman & Pence 1995 (ftp://iraf.noao.edu/misc/checksum/). But contrarily to what is stated by the authors, the original algorithm depends on the endianity of the machine. The routine below adds support for ix386-like processors (non-IEEE). AUTHOR E. Bertin (IAP) VERSION 11/02/2020 ***/ unsigned int compute_blocksum(char *buf, unsigned int sum) { unsigned short *sbuf, his,los, ashort = 1; unsigned int hi,lo, hicarry,locarry; int i; sbuf = (unsigned short *)buf; hi = (sum >> 16); lo = (sum << 16) >> 16; if (*((char *)&ashort)) // Byte-swapping required for (i=FBSIZE/4; i--;) { his = *(sbuf++); los = *(sbuf++); hi += (*((unsigned char *)&his)<<8) + *((unsigned char *)&his+1); lo += (*((unsigned char *)&los)<<8) + *((unsigned char *)&los+1); } else for (i=FBSIZE/4; i--;) { hi += *(sbuf++); lo += *(sbuf++); } hicarry = hi>>16; /* fold carry bits in */ locarry = lo>>16; while (hicarry || locarry) { hi = (hi & 0xFFFF) + locarry; lo = (lo & 0xFFFF) + hicarry; hicarry = hi >> 16; locarry = lo >> 16; } return (hi << 16) + lo; } /****** compute_bodysum ***************************************************** PROTO unsigned int compute_bodysum(tabstruct *tab, unsigned int sum) PURPOSE Compute the checksum of a FITS body INPUT Pointer to the tab, Checksum from a previous iteration. OUTPUT The computed checksum. NOTES -. AUTHOR E. Bertin (IAP) VERSION 15/08/2003 ***/ unsigned int compute_bodysum(tabstruct *tab, unsigned int sum) { catstruct *cat; char *buf; KINGSIZE_T size; int n, nblock; /* FITS data are generally padded */ nblock = (tab->tabsize+FBSIZE-1)/FBSIZE; /* 2 cases: either the data are in memory or still on disk */ if (tab->bodybuf) { /*-- In memory: they are probably not padded */ buf = (char *)tab->bodybuf; for (n=nblock-1; n--; buf+=FBSIZE) sum = compute_blocksum(buf, sum); if ((size=PADEXTRA(tab->tabsize))) { QCALLOC(buf, char, FBSIZE); size = FBSIZE-size; memcpy(buf, (char *)tab->bodybuf+tab->tabsize-size, size); sum = compute_blocksum(buf, sum); free(buf); } } else { /*-- On disk: they are padded */ /*-- We open the file (nothing is done if already open) */ if (!(cat=tab->cat)) { warning("Cannot access file while computing the checksum in HDU ", tab->extname); return 0; } open_cat(cat, READ_ONLY); QFSEEK(cat->file, tab->bodypos, SEEK_SET, cat->filename); QMALLOC(buf, char, FBSIZE); for (n=nblock; n--;) { QFREAD(buf, FBSIZE, cat->file, cat->filename); /*---- No need to swap bytes */ sum = compute_blocksum(buf, sum); } } return sum; } /****** write_checksum ***************************************************** PROTO void write_checksum(tabstruct *tab) PURPOSE Compute and write the checksum to a FITS table INPUT Pointer to the tab. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 04/06/2001 ***/ void write_checksum(tabstruct *tab) { char str[32], *buf; unsigned int sum; int i; /* Keep some margin */ QREALLOC(tab->headbuf, char, 80*(tab->headnblock*36+3)); /* Add or update keywords in the header */ fitsadd(tab->headbuf, "CHECKSUM", "ASCII 1's complement checksum"); fitswrite(tab->headbuf, "CHECKSUM", "0000000000000000", H_STRING, T_STRING); fitsadd(tab->headbuf, "DATASUM ", "Checksum of data records"); fitswrite(tab->headbuf, "DATASUM ", "0", H_STRING, T_STRING); fitsadd(tab->headbuf, "CHECKVER", "Checksum version ID"); fitswrite(tab->headbuf, "CHECKVER", "COMPLEMENT", H_STRING, T_STRING); /* Keep only what's necessary */ tab->headnblock = ((fitsfind(tab->headbuf, "END ")+36)*80)/FBSIZE; QREALLOC(tab->headbuf, char, tab->headnblock*FBSIZE); /* First: the data */ tab->bodysum = sum = compute_bodysum(tab, 0); sprintf(str, "%u", sum); fitswrite(tab->headbuf, "DATASUM ", str, H_STRING, T_STRING); /* Now the header */ buf = tab->headbuf; for (i=tab->headnblock; i--; buf+=FBSIZE) sum = compute_blocksum(buf, sum); /* Complement to 1 */ encode_checksum(~sum, str); fitswrite(tab->headbuf, "CHECKSUM", str, H_STRING, T_STRING); return; } /****** verify_checksum ***************************************************** PROTO int verify_checksum(tabstruct *tab) PURPOSE Compute and check the checksum of a FITS table INPUT Pointer to the tab. OUTPUT RETURN_OK if the checksum is correct, RETURN_ERROR if it is incorrect, or RETURN_FATAL_ERROR if no checksum found. NOTES -. AUTHOR E. Bertin (IAP) VERSION 07/05/2001 ***/ int verify_checksum(tabstruct *tab) { char *buf; unsigned int sum; int i; if (fitsfind(tab->headbuf, "CHECKSUM")==RETURN_ERROR) return RETURN_FATAL_ERROR; /* First: the data */ sum = compute_bodysum(tab, 0); /* Now the header */ buf = tab->headbuf; for (i=tab->headnblock; i--; buf+=FBSIZE) sum = compute_blocksum(buf, sum); /* The result should sum to 0 */ sum = ~sum; return sum? RETURN_ERROR : RETURN_OK; } swarp-2.41.5/src/fits/fitscleanup.c000066400000000000000000000120731400430667300171620ustar00rootroot00000000000000/* * fitscleanup.c * * Signal-catching routines to clean-up temporary files. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic FITS/LDAC library * * Copyright: (C) 1995-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 09/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "fitscat_defs.h" #include "fitscat.h" #define CLEANUP_NFILES 64 void (*exit_func)(void); char **cleanup_filename; int cleanup_nfiles; /****** cleanup_files ******************************************************** PROTO void cleanup_files(void) PURPOSE Remove temporary files on exit. INPUT -. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 25/04/2002 ***/ void cleanup_files(void) { char **filename; int i; filename = cleanup_filename; for (i=cleanup_nfiles; i--;) { remove(*filename); free(*(filename++)); } if (cleanup_nfiles) { free(cleanup_filename); cleanup_nfiles = 0; } return; } /****** add_cleanupfilename ************************************************** PROTO void add_cleanupfilename(char *filename) PURPOSE Add a file name to the list of files to be cleaned up at exit. INPUT pointer to filename char string. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 10/01/2003 ***/ void add_cleanupfilename(char *filename) { if (!cleanup_nfiles) { QMALLOC(cleanup_filename, char *, CLEANUP_NFILES); } else if (!(cleanup_nfiles%CLEANUP_NFILES)) { QREALLOC(cleanup_filename, char *, cleanup_nfiles+CLEANUP_NFILES); } QMALLOC(cleanup_filename[cleanup_nfiles], char, MAXCHARS); strcpy(cleanup_filename[cleanup_nfiles++], filename); return; } /****** remove_cleanupfilename *********************************************** PROTO void remove_cleanupfilename(char *filename) PURPOSE remove a file name from the list of files to be cleaned up at exit. INPUT pointer to filename char string. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 16/07/2007 ***/ void remove_cleanupfilename(char *filename) { char **filename2, **filename3; int i, j; if (!cleanup_nfiles) return; /* Search the cleanup filename list for a match */ filename2 = cleanup_filename; for (i=cleanup_nfiles; i--;) if (!strcmp(filename, *(filename2++))) { /* Match found: update the list and free memory is necessary*/ filename3 = filename2 - 1; free(*filename3); for (j=i; j--;) *(filename3++) = *(filename2++); if (!((--cleanup_nfiles)%CLEANUP_NFILES)) { if (cleanup_nfiles) { QREALLOC(cleanup_filename, char *, cleanup_nfiles); } else free(cleanup_filename); } break; } return; } /****** install_cleanup ****************************************************** PROTO void install_cleanup(void (*func)(void)) PURPOSE Install the signal-catching and exit routines to start cleanup_files(). INPUT A pointer to a function to be executed on exit. OUTPUT -. NOTES Catches everything except STOP and KILL signals. AUTHOR E. Bertin (IAP) VERSION 25/04/2002 ***/ void install_cleanup(void (*func)(void)) { void signal_function(int signum); exit_func = func; atexit(cleanup_files); /* Catch CTRL-Cs */ signal(SIGINT, signal_function); /* Catch bus errors */ signal(SIGBUS, signal_function); /* Catch segmentation faults */ signal(SIGSEGV, signal_function); /* Catch floating exceptions */ signal(SIGFPE, signal_function); return; } /****** signal_function ****************************************************** PROTO void signal_function(void) PURPOSE The routine called when a signal is catched. Clean up temporary files and execute a user-provided function. INPUT signal number. OUTPUT -. NOTES . AUTHOR E. Bertin (IAP) VERSION 25/04/2002 ***/ void signal_function(int signum) { cleanup_files(); if (exit_func) exit_func(); switch(signum) { case SIGINT: fprintf(stderr, "^C\n"); exit(-1); case SIGBUS: fprintf(stderr, "bus error\n"); exit(-1); case SIGSEGV: fprintf(stderr, "segmentation fault\n"); exit(-1); case SIGFPE: fprintf(stderr, "floating exception\n"); exit(-1); default: exit(-1); } return; } swarp-2.41.5/src/fits/fitsconv.c000066400000000000000000000153111400430667300164760ustar00rootroot00000000000000/* * fitsconv.c * * Functions for converting LDAC FITS catalogs. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic FITS/LDAC library * * Copyright: (C) 1995-2012 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 13/06/2012 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "fitscat_defs.h" #include "fitscat.h" /****** asc2bin_tab *********************************************************** PROTO tabstruct *asc2bin_tab(catstruct *catin, char *tabinname, catstruct *catout, char *taboutname) PURPOSE Convert an ASCII table to a BINARY table which is then stored in a destination catalog. INPUT Pointer to the input catalog, Name of the input ASCII table, Pointer to the output catalog, Name of the output binary table. OUTPUT RETURN_OK if the ASCII table was transformed, and RETURN_ERROR otherwise. NOTES This function can be used to stick the binary translation of similar ASCII tables. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 25/09/2004 ***/ tabstruct *asc2bin_tab(catstruct *catin, char *tabinname, catstruct *catout, char *taboutname) { catstruct *tabcat; keystruct *key; tabstruct *tabin,*tabout; char comment[82], keyword[16], ptr[82]; h_type htype; t_type ttype; char *buf, *lptr; int i; /*Convert the table name to a pointer*/ if (!(tabin = name_to_tab(catin, tabinname, 0))) return NULL; /*Get the original catalog*/ tabcat = tabin->cat; /*Create a new binary table*/ tabout = new_tab(taboutname); /*Alloc. mem. for the whole ASCII table at once (should not be very large)*/ QMALLOC(buf, char, tabin->tabsize); /*Now read all the elements from the original table*/ if (open_cat(tabcat, READ_ONLY) != RETURN_OK) error(EXIT_FAILURE, "*Error*: Cannot access ", tabcat->filename); QFSEEK(tabcat->file, tabin->bodypos, SEEK_SET, tabcat->filename); QFREAD(buf, tabin->tabsize, tabcat->file, tabcat->filename); if (close_cat(tabcat) != RETURN_OK) error(EXIT_FAILURE, "*Error*: Problem while closing", tabcat->filename); lptr = buf; for (i=tabin->tabsize/80; i-- && strncmp(lptr, "END ", 8);) { /*Interprete the next FITS line */ if (fitspick(lptr, keyword, ptr, &htype, &ttype, comment) != RETURN_OK) { char line[81]; int qflag=1; strncpy(line, lptr, 80); line[80] = '\0'; QFPRINTF(OUTPUT, line); warning("*Warning*: incorrect FITS field will be ignored in ", tabcat->filename); } if (htype != H_COMMENT) { /*----Create a new key and fill it with the right parameters*/ key = new_key(keyword); strcpy(key->comment, comment+strspn(comment, " ")); key->htype = htype; key->ttype = ttype; key->nbytes = t_size[ttype]; /*----!!Temporary (?) solution for STRINGS*/ if (htype==H_STRING) { key->naxis = 1; QMALLOC(key->naxisn, int, 1); key->naxisn[0] = 32; key->nbytes *= key->naxisn[0]; } key->nobj = 1; /*----Allocate memory and copy data in the same time*/ QMEMCPY(ptr, key->ptr, char, key->nbytes); if (add_key(key, tabout, 0)==RETURN_ERROR) { sprintf(comment, "%s keyword found twice in ", keyword); warning(comment, tabcat->filename); } } lptr += 80; } free(buf); update_tab(tabout); return tabout; } /****** ttypeconv ************************************************************ PROTO void ttypeconv(void *ptrin, void *ptrout, t_type ttypein, t_type ttypeout) PURPOSE Convert data from one type to another. INPUT Pointer to element to convert, destination pointer to the converted element, t_type of the element to convert, t_type of the converted element. OUTPUT -. NOTES ttypeconv does not yet handle arrays. AUTHOR E. Bertin (IAP) VERSION 13/06/2012 ***/ void ttypeconv(void *ptrin, void *ptrout, t_type ttypein, t_type ttypeout) { // union {char tbyte; short tshort; int tlong; LONGLONG tlonglong; // float tfloat; double tdouble; char tstring;} ival; #ifdef HAVE_LONG_LONG_INT #define OUTCONV(x, y) \ switch(y) \ { \ case T_BYTE: \ case T_STRING: \ *((char *)ptrout) = (char)x; \ break; \ case T_SHORT: \ *((short *)ptrout) = (short)x; \ break; \ case T_LONG: \ *((int *)ptrout) = (int)x; \ break; \ case T_LONGLONG: \ *((SLONGLONG *)ptrout) = (SLONGLONG)x; \ break; \ case T_FLOAT: \ *((float *)ptrout) = (float)x; \ break; \ case T_DOUBLE: \ *((double *)ptrout) = (double)x; \ break; \ default: \ break; \ } #else #define OUTCONV(x, y) \ switch(y) \ { \ case T_BYTE: \ case T_STRING: \ *((char *)ptrout) = (char)x; \ break; \ case T_SHORT: \ *((short *)ptrout) = (short)x; \ break; \ case T_LONG: \ *((int *)ptrout) = (int)x; \ break; \ case T_FLOAT: \ *((float *)ptrout) = (float)x; \ break; \ case T_DOUBLE: \ *((double *)ptrout) = (double)x; \ break; \ default: \ break; \ } #endif switch(ttypein) { case T_BYTE: case T_STRING: OUTCONV(*(char *)ptrin, ttypeout); break; case T_SHORT: OUTCONV(*(short *)ptrin, ttypeout); break; case T_LONG: OUTCONV(*(int *)ptrin, ttypeout); break; #ifdef HAVE_LONG_LONG_INT case T_LONGLONG: OUTCONV(*(SLONGLONG *)ptrin, ttypeout); break; #endif case T_FLOAT: OUTCONV(*(float *)ptrin, ttypeout); break; case T_DOUBLE: OUTCONV(*(double *)ptrin, ttypeout); break; default: break; } return; } swarp-2.41.5/src/fits/fitshead.c000066400000000000000000000617671400430667300164520ustar00rootroot00000000000000/* * fitshead.c * * General functions for handling FITS file headers * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic FITS/LDAC library * * Copyright: (C) 1995-2019 IAP/CNRS/SorbonneU * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 04/12/2019 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "fitscat_defs.h" #include "fitscat.h" extern char histokeys[][12]; const int t_size[] = {1, 2, 4, 8, 4, 8, 1};/* size in bytes per t_type */ /******* get_head ************************************************************* PROTO int get_head(tabstruct *tab) PURPOSE Read a FITS header. INPUT Table structure. OUTPUT RETURN_OK if a FITS header has been found and loaded, or RETURN_ERROR otherwise. NOTES The file must be opened, and the file pointer must be located at the beginning of a header. The headbuf pointer in the catstruct is reallocated. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 08/02/96 ***/ int get_head(tabstruct *tab) { catstruct *cat; int i; char *buf; buf = tab->headbuf; if (!(cat = tab->cat)) error(EXIT_FAILURE, "*Internal Error*: Table has no parent catalog","!"); QFREE(buf); QMALLOC(buf, char, FBSIZE); /*Read the first block and check that it is FITS */ if (!fread(buf, FBSIZE, 1, cat->file)) { QFREE(buf); return RETURN_ERROR; } if (strncmp(buf, "SIMPLE ", 8) && strncmp(buf, "XTENSION", 8)) { QFREE(buf); return RETURN_ERROR; } /*Find the number of FITS blocks of the header while reading it */ for (i=1; !fitsnfind(buf,"END ", i); i++) { QREALLOC(buf, char, FBSIZE*(i+1)); QFREAD(&buf[FBSIZE*i], FBSIZE, cat->file, cat->filename); } tab->headnblock = i; tab->headbuf = buf; return RETURN_OK; } /****** readbasic_head ******************************************************** PROTO void readbasic_head(tabstruct *tab) PURPOSE Read the current FITS header basic keywords. INPUT pointer to catstruct. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 04/12/2019 ***/ void readbasic_head(tabstruct *tab) { char str[88]; char key[12], name[16], bitpix_key[16], naxis_key[16], *filename; int i; KINGSIZE_T tabsize; filename = (tab->cat? tab->cat->filename : strcpy(name, "internal header")); strncpy(bitpix_key, "BITPIX ", 9); strncpy(naxis_key, "NAXIS ", 9); #ifdef HAVE_CFITSIO tab->isTileCompressed = (fitsread(tab->headbuf, "ZIMAGE ", str, H_STRING, T_STRING) == RETURN_OK)? 1 : 0; if (tab->isTileCompressed) { strncpy(bitpix_key, "ZBITPIX ", 9); strncpy(naxis_key, "ZNAXIS ", 9); } #endif if (fitsread(tab->headbuf, bitpix_key, &tab->bitpix, H_INT, T_LONG) ==RETURN_ERROR) error(EXIT_FAILURE, "*Error*: Corrupted FITS header in ", filename); if (fitsread(tab->headbuf, naxis_key, &tab->naxis, H_INT, T_LONG) ==RETURN_ERROR) error(EXIT_FAILURE, "*Error*: Corrupted FITS header in ", filename); tab->bytepix = tab->bitpix>0?(tab->bitpix/8):(-tab->bitpix/8); tabsize = 0; if (tab->naxis>0) { QFREE(tab->naxisn); QMALLOC(tab->naxisn, int, tab->naxis); /*--get the size of the array*/ tabsize = 1; for (i=0; inaxis && i<999; i++) { #ifdef HAVE_CFITSIO if (tab->isTileCompressed) sprintf(key,"ZNAXIS%-2d", i+1); else #endif sprintf(key,"NAXIS%-3d", i+1); if (fitsread(tab->headbuf, key, &tab->naxisn[i], H_INT, T_LONG) ==RETURN_ERROR) error(EXIT_FAILURE, "*Error*: incoherent FITS header in ", filename); tabsize *= tab->naxisn[i]; } } /*random groups parameters (optional)*/ tab->pcount = 0; fitsread(tab->headbuf, "PCOUNT ", &tab->pcount, H_INT, T_LONG); #ifdef HAVE_CFITSIO // CFITSIO TODO HACK if (tab->isTileCompressed) tab->pcount = 0; #endif tab->gcount = 1; fitsread(tab->headbuf, "GCOUNT ", &tab->gcount, H_INT, T_LONG); /*number of fields (only for tables)*/ tab->tfields = 0; fitsread(tab->headbuf, "TFIELDS ", &tab->tfields, H_INT, T_LONG); /*in case of a non-primary header*/ tab->xtension[0] = (char)'\0'; fitsread(tab->headbuf, "XTENSION", tab->xtension, H_STRING, T_STRING); tab->extname[0] = (char)'\0'; fitsread(tab->headbuf, "EXTNAME ", tab->extname, H_STRING, T_STRING); tab->tabsize = tab->bytepix*tab->gcount*((size_t)tab->pcount+tabsize); /* Scaling parameters for basic FITS integer arrays */ tab->bscale = 1.0; fitsread(tab->headbuf, "BSCALE ", &tab->bscale, H_FLOAT, T_DOUBLE); tab->bzero = 0.0; fitsread(tab->headbuf, "BZERO ", &tab->bzero, H_FLOAT, T_DOUBLE); tab->blankflag = (fitsread(tab->headbuf,"BLANK ",&tab->blank,H_INT,T_LONG) == RETURN_OK)? 1 : 0; /* Custom basic FITS parameters */ tab->bitsgn = (tab->bitpix==BP_BYTE) ? 0 : 1; fitsread(tab->headbuf, "BITSGN ", &tab->bitsgn, H_INT, T_LONG); if (fitsread(tab->headbuf, "IMAGECOD", str, H_STRING, T_STRING)==RETURN_OK) { if (!strcmp(str, "NONE")) tab->compress_type = COMPRESS_NONE; else if (!strcmp(str, "BASEBYTE")) tab->compress_type = COMPRESS_BASEBYTE; else if (!strcmp(str, "PREV_PIX")) tab->compress_type = COMPRESS_PREVPIX; else warning("Compression skipped: unknown IMAGECOD parameter:", str); } /* Checksum */ if (fitsread(tab->headbuf, "DATASUM ", str, H_STRING, T_STRING)==RETURN_OK) tab->bodysum = (unsigned int)atoi(str); return; } /******* readbintabparam_head ************************************************* PROTO int readbintabparam_head(tabstruct *tab) PURPOSE Read the current FITS header parameters concerning the binary-table. INPUT pointer to tabstruct. OUTPUT RETURN_OK if a binary table was found and mapped, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 20/07/2010 ***/ int readbintabparam_head(tabstruct *tab) { catstruct *cat; keystruct *key, *prevkey; char strf[88], strk[16]; char *str; int naxisn[32]; int i,j, larray, nfields,narray, pos; if (!(cat = tab->cat)) error(EXIT_FAILURE, "*Internal Error*: Table has no parent catalog","!"); /*We are expecting a 2D binary-table, and nothing else*/ if ((tab->naxis != 2) || (tab->bitpix!=8) || (tab->tfields == 0) || strncmp(tab->xtension, "BINTABLE", 8)) return RETURN_ERROR; /*Size and number of lines in the binary table*/ larray = tab->naxisn[0]; nfields= tab->nkey = tab->tfields; narray = tab->naxisn[1]; prevkey = NULL; /*For each of the data fields...*/ pos = 0; for (i=0; inextkey = key; key->prevkey = prevkey; } else tab->key = key; prevkey = key; /*--map binary-table fields*/ sprintf(strk, "TTYPE%-3d", i+1); if (fitsread(tab->headbuf, strk, key->name, H_STRING, T_STRING) != RETURN_OK) { error(EXIT_FAILURE, "*Error*: Incorrect FITS binary-table header in ", cat->filename); } fitsread(tab->headbuf, strk, key->comment, H_HCOMMENT, T_STRING); sprintf(strk, "TUNIT%-3d", i+1); fitsread(tab->headbuf, strk, key->unit, H_STRING, T_STRING); sprintf(strk, "TDISP%-3d", i+1); fitsread(tab->headbuf, strk, key->printf, H_STRING, T_STRING); if (*key->printf) tdisptoprintf(key->printf, key->printf); sprintf(strk, "TFORM%-3d", i+1); if (fitsread(tab->headbuf, strk, strf, H_STRING, T_STRING) != RETURN_OK) { error(EXIT_FAILURE, "*Error*: Incorrect FITS binary-table header in ", cat->filename); } key->pos = pos; pos += (key->nbytes = tsizeof(strf)); key->ttype = ttypeof(strf); switch(key->ttype) { case T_BYTE: case T_SHORT: case T_LONG: case T_LONGLONG: key->htype = H_INT; break; case T_FLOAT: case T_DOUBLE: key->htype = H_EXPO; break; case T_STRING: key->htype = H_STRING; break; default: #ifdef HAVE_CFITSIO // CFITSIO TODO dodgy key->ttype = T_FLOAT; #else error(EXIT_FAILURE, "*Error*: Unknown TFORM in ", cat->filename); #endif } /*--handle the special case of multimensional arrays*/ if ((naxisn[0] = key->nbytes/t_size[key->ttype]) > 1) { sprintf(strk, "TDIM%-3d", i+1); if (fitsread(tab->headbuf, strk, strf, H_STRING, T_STRING) == RETURN_OK) { str = strf; for (j=0; (naxisn[j]=(int)strtol(str+1, &str, 10)); j++); key->naxis = j; } else key->naxis = 1; QMALLOC(key->naxisn, int, key->naxis); for (j=0; jnaxis; j++) key->naxisn[j] = naxisn[j]; } else key->naxis = 0; key->nobj = narray; key->tab = tab; } if (pos != larray) error(EXIT_FAILURE, "*Error*: Malformed FITS binary-table header in ", cat->filename); /*make both ends of the chain meet*/ prevkey->nextkey = tab->key; tab->key->prevkey = prevkey; return RETURN_OK; } /****** update_head *********************************************************** PROTO int update_head(tabstruct *tab) PURPOSE Update a FITS header according to what's in the table. INPUT Table structure. OUTPUT RETURN_OK if tab is a binary table, or RETURN_ERROR otherwise. NOTES The headbuf pointer in the tabstruct might be reallocated. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 11/06/2007 ***/ int update_head(tabstruct *tab) { keystruct *key; tabstruct *ctab; int i,j,n,naxis1; char strk[88], str[88]; char *buf; /*Update EXTNAME, the table name */ if (*tab->extname) { addkeywordto_head(tab, "EXTNAME ", "EXTENSION NAME"); fitswrite(tab->headbuf, "EXTNAME ", tab->extname, H_STRING, T_STRING); } /* If not a binary table, do only a few basic things */ if ((tab->naxis != 2) || (tab->bitpix!=8) || (tab->tfields == 0) || strncmp(tab->xtension, "BINTABLE", 8)) { addkeywordto_head(tab, "BITPIX ", "BITS PER PIXEL"); fitswrite(tab->headbuf, "BITPIX ", &tab->bitpix, H_INT, T_LONG); addkeywordto_head(tab, "NAXIS ", "NUMBER OF AXES"); fitswrite(tab->headbuf, "NAXIS ", &tab->naxis, H_INT, T_LONG); for (i=0; inaxis; i++) { sprintf(strk, "NAXIS%-3d", i+1); addkeywordto_head(tab, strk, "NUMBER OF ELEMENTS ALONG THIS AXIS"); fitswrite(tab->headbuf, strk, &tab->naxisn[i], H_INT, T_LONG); } return RETURN_ERROR; } /*First, remove all existing TTYPE, TFORM, etc...*/ removekeywordfrom_head(tab, "TTYPE???"); removekeywordfrom_head(tab, "TFORM???"); removekeywordfrom_head(tab, "TUNIT???"); removekeywordfrom_head(tab, "TZERO???"); removekeywordfrom_head(tab, "TSCAL???"); removekeywordfrom_head(tab, "TDIM???"); removekeywordfrom_head(tab, "TDISP???"); /*Change NAXIS1 in order to take into account changes in width*/ naxis1 = 0; key = tab->key; if (tab->nkey>1000) { for (i=0; inkey); i++) { naxis1 += key->nbytes; key = key->nextkey; } fitswrite(tab->headbuf, "NAXIS1 ", &naxis1, H_INT, T_LONG); } else { fitswrite(tab->headbuf, "NAXIS1 ", &tab->naxisn[0], H_INT, T_LONG); } /*Change NAXIS1 in the number of fields */ tab->tfields = MIN(999,tab->tfields); fitswrite(tab->headbuf, "TFIELDS ", &tab->tfields, H_INT, T_LONG); /*Changes in the number of elements (look for possible segments)*/ for (ctab = tab, n = ctab->naxisn[1]; (ctab=ctab->nexttab) && !ctab->nseg;) n += ctab->naxisn[1]; fitswrite(tab->headbuf, "NAXIS2 ", &n, H_INT, T_LONG); key = tab->key; if (!key) return RETURN_ERROR; if (tab->nkey>1000) warning("Too many output keys, trashing the ones bejond 999", ""); for (i=0; inkey); i++) { sprintf(strk, "TTYPE%-3d", i+1); addkeywordto_head(tab, strk, key->comment); fitswrite(tab->headbuf, strk, key->name, H_STRING, T_STRING); sprintf(strk, "TFORM%-3d", i+1); addkeywordto_head(tab, strk, ""); tformof(str, key->ttype, key->nbytes/t_size[key->ttype]); fitswrite(tab->headbuf, strk, str, H_STRING, T_STRING); if (key->naxis>1) { char *str2, *str2lim; sprintf(strk, "TDIM%-3d", i+1); addkeywordto_head(tab, strk, ""); sprintf(str, "("); str2 = str+1; str2lim = str+70; /* Prevent an excessively large string */ for (n=0; nnaxis && str2naxisn[n],&j); str2 += j; } sprintf(str2, ")"); fitswrite(tab->headbuf, strk, str, H_STRING, T_STRING); } if (*key->unit) { sprintf(strk, "TUNIT%-3d", i+1); addkeywordto_head(tab, strk, ""); fitswrite(tab->headbuf, strk, key->unit, H_STRING, T_STRING); } if (*key->printf) { sprintf(strk, "TDISP%-3d", i+1); addkeywordto_head(tab, strk, ""); fitswrite(tab->headbuf, strk, printftotdisp(key->printf, str), H_STRING, T_STRING); } key = key->nextkey; } /*Finally re-compute CHECKSUM if present */ if (fitsfind(tab->headbuf, "CHECKSUM")==RETURN_OK) { unsigned int sum; if (tab->bodysum) { sprintf(str, "%u", tab->bodysum); fitswrite(tab->headbuf, "DATASUM ", str, H_STRING, T_STRING); } sum = tab->bodysum; /*-- Now the header */ buf = tab->headbuf; for (i=tab->headnblock; i--; buf+=FBSIZE) sum = compute_blocksum(buf, sum); /*-- Complement to 1 */ encode_checksum(~sum, str); fitswrite(tab->headbuf, "CHECKSUM", str, H_STRING, T_STRING); } /*That may be enough for now; to be continued...*/ return RETURN_OK; } /****** prim_head ************************************************************* PROTO int prim_head(tabstruct *tab) PURPOSE Update a FITS header to make it "primary" (not extension) INPUT Table structure. OUTPUT RETURN_OK if tab header was already primary, or RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) C. Marmo (IAP) VERSION 30/08/2011 ***/ int prim_head(tabstruct *tab) { if (!tab->headbuf) return RETURN_ERROR; if (!strncmp(tab->headbuf, "XTENSION",8)) { strncpy(tab->headbuf, "SIMPLE = T " "/ This is a FITS file ", 80); removekeywordfrom_head(tab, "PCOUNT"); removekeywordfrom_head(tab, "GCOUNT"); removekeywordfrom_head(tab, "TFIELDS"); removekeywordfrom_head(tab, "EXTNAME"); *tab->extname = '\0'; return RETURN_ERROR; } return RETURN_OK; } /****** ext_head ************************************************************* PROTO int ext_head(tabstruct *tab) PURPOSE Update a FITS header to make it "extension" (not primary) INPUT Table structure. OUTPUT RETURN_OK if tab header was already extension, or RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) C. Marmo (IAP) VERSION 20/06/2007 ***/ int ext_head(tabstruct *tab) { if (!tab->headbuf) return RETURN_ERROR; if (!strncmp(tab->headbuf, "SIMPLE ",8)) { strncpy(tab->headbuf, "XTENSION= 'IMAGE ' " "/ Image extension ", 80); /* fitsverify 4.13 (CFITSIO V3.002) return an error if EXTEND are in an extension header (20/06/2007)*/ removekeywordfrom_head(tab, "EXTEND"); /* fitsverify 4.13 (CFITSIO V3.002) return an error if PCOUNT and GCOUNT are not in the extension header (23/05/2007) */ addkeywordto_head(tab, "PCOUNT ", "required keyword; must = 0"); addkeywordto_head(tab, "GCOUNT ", "required keyword; must = 1"); fitswrite(tab->headbuf,"PCOUNT ", &tab->pcount, H_INT, T_LONG); fitswrite(tab->headbuf,"GCOUNT ", &tab->gcount, H_INT, T_LONG); return RETURN_ERROR; } return RETURN_OK; } /****** addkeyto_head ********************************************************* PROTO int addkeyto_head(tabstruct *tab, keystruct *key) PURPOSE Add a keyword and its value to a table header. INPUT Table structure, Key containing the keyword and its value. OUTPUT Line position in the FITS header. NOTES The headbuf pointer in the tabstruct might be reallocated. Pre-existing keywords are overwritten (but not their comments). AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 11/05/2002 ***/ int addkeyto_head(tabstruct *tab, keystruct *key) { int n; n = addkeywordto_head(tab, key->name, key->comment); fitswrite(tab->headbuf, key->name, key->ptr, key->htype, key->ttype); return n; } /****** addkeywordto_head ***************************************************** PROTO int addkeywordto_head(tabstruct *tab, char *keyword, char *comment) PURPOSE Add a keyword and a comment to a table header. INPUT Table structure, String containing the keyword, String containing the comment. OUTPUT Line position in the FITS header. NOTES The headbuf pointer in the tabstruct might be reallocated. Pre-existing keywords are overwritten (but not their comments). AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 21/04/2003 ***/ int addkeywordto_head(tabstruct *tab, char *keyword, char *comment) { int n; if ((fitsfind(tab->headbuf, keyword) == RETURN_ERROR || findkey(keyword, (char *)histokeys, 12)!=RETURN_ERROR) && (fitsfind(tab->headbuf, "END ")+1)*80 >= tab->headnblock*FBSIZE) { tab->headnblock++; QREALLOC(tab->headbuf, char, tab->headnblock*FBSIZE); memset(tab->headbuf + (tab->headnblock-1)*FBSIZE, ' ', FBSIZE); } n = fitsadd(tab->headbuf, keyword, comment); return n; } /****** removekeywordfrom_head ************************************************ PROTO int removekeywordfrom_head(tabstruct *tab, char *keyword) PURPOSE Remove a keyword from a table header. INPUT Table structure, String containing the keyword. OUTPUT RETURN_OK if the keyword was found, RETURN_ERROR otherwise.. NOTES The headbuf pointer in the tabstruct might be reallocated. '?' wildcard allowed; Don't remove the ``END'' keyword with this!!! AUTHOR E. Bertin (IAP) VERSION 11/06/2007 ***/ int removekeywordfrom_head(tabstruct *tab, char *keyword) { int nb; if (fitsremove(tab->headbuf, keyword) == RETURN_OK) { if ((nb=fitsfind(tab->headbuf, "END ")/(FBSIZE/80)+1) < tab->headnblock) { tab->headnblock = nb; QREALLOC(tab->headbuf, char, tab->headnblock*FBSIZE); } return RETURN_OK; } else return RETURN_ERROR; } /****** tformof *************************************************************** PROTO int tformof(char *str, t_type ttype, int n) PURPOSE Return the ``TFORM'' string corresponding to a t_type and the number of elements. INPUT a char pointer (to be filled with the T_FORM string), t_type, Number of elements. OUTPUT RETURN_OK if everything went as expected, or RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 28/10/2009 ***/ int tformof(char *str, t_type ttype, int n) { char t; switch (ttype) { case T_BYTE: t = 'B'; break; case T_SHORT: t = 'I'; break; case T_LONG: t = 'J'; break; case T_LONGLONG: t = 'K'; break; case T_FLOAT: t = 'E'; break; case T_DOUBLE: t = 'D'; break; case T_STRING: t = 'A'; break; default: return RETURN_ERROR; } sprintf(str, "%d%c", n, t); return RETURN_OK; } /****** tsizeof *************************************************************** PROTO int tsizeof(char *str) PURPOSE Return the size of a binary-table field from its ``TFORM''. INPUT TFORM string (see the FITS documentation). OUTPUT size in bytes, or RETURN_ERROR if the TFORM is unknown. NOTES -. AUTHOR E. Bertin (IAP) VERSION 10/11/2010 ***/ int tsizeof(char *str) { int n; char *str2; str2 = str; n = strtol(str, &str2, 10); if (str2==str) n = 1; switch ((int)*str2) { case 'L': case 'B': case 'A': return n; case 'X': return (n-1)/8+1; case 'I': return 2*n; case 'J': case 'E': return 4*n; case 'C': case 'D': case 'K': case 'P': return 8*n; case 'M': return 16*n; default: return RETURN_ERROR; } } /****** ttypeof *************************************************************** PROTO t_type ttypeof(char *str) PURPOSE Give the ``t_type'' of a binary-table field from its ``TFORM''. INPUT TFORM string (see the FITS documentation). OUTPUT size in bytes, or RETURN_ERROR if the TFORM is unknown. NOTES -. AUTHOR E. Bertin (IAP) VERSION 29/08/2012 ***/ t_type ttypeof(char *str) { char *str2; str2 = str; strtol(str, &str2, 10); switch ((int)*str2) { case 'L': case 'B': case 'X': return T_BYTE; case 'I': return T_SHORT; case 'J': return T_LONG; case 'K': return T_LONGLONG; case 'E': return T_FLOAT; case 'D': return T_DOUBLE; case 'A': return T_STRING; default: return (t_type)RETURN_ERROR; } } /****** tdisptoprintf ********************************************************* PROTO char *tdisptoprintf(char *tdisp, char *str) PURPOSE Convert the ``TDISP'' FITS format to the printf() format. INPUT TDISP format string (see the FITS documentation), output string (allocated pointer). OUTPUT printf() format string (see e.g. K&R). NOTES The present conversion does not handle binary or engineer notations. A NULL vector is returned if the conversion was unsuccessful. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 25/09/2004 ***/ char *tdisptoprintf(char *tdisp, char *str) { char control[4]; int w,d, n; w = d = 0; n = 0; n=sscanf(tdisp,"%[ALIBOZFENSGD]%d.%d", control, &w, &d)-1; if (!w) { warning("Strange TDISP format: ", tdisp); return NULL; } switch ((int)*control) { case 'A': sprintf(str, "%%%dc",w); break; case 'L': sprintf(str, "%%%dd",w); break; case 'I': if (n>1) sprintf(str, "%%%d.%dd",w,d); else sprintf(str, "%%%dd",w); break; case 'B': case 'Z': if (n>1) sprintf(str, "%%%d.%dx",w,d); else sprintf(str, "%%%dx",w); break; case 'O': if (n>1) sprintf(str, "%%%d.%do",w,d); else sprintf(str, "%%%do",w); break; case 'F': if (n>1) sprintf(str, "%%%d.%df",w,d); else sprintf(str, "%%%df",w); break; case 'E': case 'D': if (n>1) sprintf(str, "%%%d.%dE",w,d); else sprintf(str, "%%%dE",w); break; case 'G': if (n>1) sprintf(str, "%%%d.%dG",w,d); else sprintf(str, "%%%dG",w); break; default: warning("Unknown TDISP format: ", tdisp); return NULL; } return str; } /****** printftotdisp ********************************************************* PROTO char *printftotdisp(char *tdisp, char *str) PURPOSE Convert the printf() format to the ``TDISP'' FITS format. INPUT printf() format string (see e.g. K&R), output string (allocated pointer). OUTPUT TDISP format string (see the FITS documentation). NOTES The handling of C string formatting does not include the precision. NULL is returned in case of unsucessful conversion. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 25/09/2004 ***/ char *printftotdisp(char *cprintf, char *str) { char *control; int w,d,n; *str = 0; w = d = 0; if (!(control = strpbrk(cprintf, "cdueERfFgGoOxXs"))) { warning("Unknown printf() format: ", cprintf); return NULL; } n = sscanf(cprintf,"%%%d.%d", &w, &d); w = abs(w); if (!n) { warning("Unconvertible printf() format: ", cprintf); return NULL; } switch ((int)*control) { case 'c': sprintf(str, "A%d",w); break; case 's': sprintf(str, "A%d",w); break; case 'd': case 'u': if (n>1) sprintf(str, "I%d.%d",w,d); else sprintf(str, "I%d",w); break; case 'o': case 'O': if (n>1) sprintf(str, "O%d.%d",w,d); else sprintf(str, "O%d",w); break; case 'x': case 'X': if (n>1) sprintf(str, "Z%d.%d",w,d); else sprintf(str, "Z%d",w); break; case 'f': case 'F': if (n>1) sprintf(str, "F%d.%d",w,d); else sprintf(str, "F%d",w); break; case 'e': case 'E': if (n>1) sprintf(str, "E%d.%d",w,d); else sprintf(str, "E%d",w); break; case 'g': case 'G': if (n>1) sprintf(str, "G%d.%d",w,d); else sprintf(str, "G%d",w); break; default: warning("Unknown printf() format: ", cprintf); return NULL; } return str; } swarp-2.41.5/src/fits/fitskey.c000066400000000000000000000661321400430667300163300ustar00rootroot00000000000000/* * fitskey.c * * Functions related to the management of FITS table columns ("keys"). * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic FITS/LDAC library * * Copyright: (C) 1995-2020 IAP/CNRS/SorbonneU * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 11/02/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "fitscat_defs.h" #include "fitscat.h" /****** add_key **************************************************************** PROTO int add_key(keystruct *key, tabstruct *tab, int pos) PURPOSE Copy a key from one table to another. INPUT Pointer to the key, Pointer to the table, Pointer to the destination table, Position (1= first, <=0 = at the end) OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise. NOTES A preexisting key in the destination table yields a RETURN_ERROR. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 26/03/96 ***/ int add_key(keystruct *key, tabstruct *tab, int pos) { /*Check if a similar key doesn't already exist in the dest. cat */ if (name_to_key(tab, key->name)) return RETURN_ERROR; /*Update links (portion of code similar to that of copy_key below) */ if ((key->nextkey = pos_to_key(tab, pos))) { (key->prevkey = key->nextkey->prevkey)->nextkey = key; key->nextkey->prevkey = key; /*--the first place has a special meaning*/ if (pos==1) tab->key = key; } else /*There was no no key before*/ tab->key = key->nextkey = key->prevkey = key; tab->nkey++; return RETURN_OK; } /****** blank_keys ************************************************************* PROTO int blank_keys(tabstruct *tab) PURPOSE Put the array pointers from all keys in a table to NULL. INPUT Pointer to the table. OUTPUT RETURN_OK if keys were found, and RETURN_ERROR otherwise. Notes: -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 25/04/97 ***/ int blank_keys(tabstruct *tab) { keystruct *key; int k; if (!(key = tab->key)) return RETURN_ERROR; for (k=tab->nkey; k--;) { key->ptr = NULL; key = key->nextkey; } return RETURN_OK; } /****** copy_key *************************************************************** PROTO int copy_key(tabstruct *tabin, char *keyname, tabstruct *tabout, int pos) PURPOSE Copy a key from one table to another. INPUT Pointer to the original table, Name of the key, Pointer to the destination table, Position (1= first, <=0 = at the end) OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise. NOTES A preexisting key in the destination table yields a RETURN_ERROR, the ptr member is NOT COPIED. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 19/08/96 ***/ int copy_key(tabstruct *tabin, char *keyname, tabstruct *tabout, int pos) { keystruct *keyin, *keyout; /*Convert the key name to a pointer*/ if (!(keyin = name_to_key(tabin, keyname))) return RETURN_ERROR; /*Check if a similar key doesn't already exist in the dest. cat */ if (name_to_key(tabout, keyname)) return RETURN_ERROR; tabout->nkey++; /*First, allocate memory and copy data */ QCALLOC(keyout, keystruct, 1); *keyout = *keyin; keyout->ptr = NULL; if (keyin->naxis) QMEMCPY(keyin->naxisn, keyout->naxisn, int, keyin->naxis); /*Then, update the links */ if ((keyout->nextkey = pos_to_key(tabout, pos))) { (keyout->prevkey = keyout->nextkey->prevkey)->nextkey = keyout; keyout->nextkey->prevkey = keyout; /*--the first place has a special meaning*/ if (pos==1) tabout->key = keyout; } else /*There was no no key before*/ tabout->key = keyout->nextkey = keyout->prevkey = keyout; return RETURN_OK; } /****** free_key *************************************************************** PROTO void free_key(keystruct *key) PURPOSE Free memory associated to a key ptr. INPUT Pointer to the key. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 19/08/96 ***/ void free_key(keystruct *key) { free(key->naxisn); free(key->ptr); free(key); return; } /****** new_key **************************************************************** PROTO keystruct *new_key(char *keyname) PURPOSE Create a new key. INPUT Name of the key. OUTPUT A pointer to the new keystruct. NOTES This function is only provided as a counterpart to new_tab() and new_cat(): in order to be usable, other key parameters MUST be handled by the user. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 26/03/96 ***/ keystruct *new_key(char *keyname) { keystruct *key; QCALLOC(key, keystruct, 1); strcpy(key->name, keyname); return key; } /****** read_key *************************************************************** PROTO keystruct *read_key(tabstruct *tab, char *keyname) PURPOSE Read one simple column from a FITS binary table. INPUT pointer to the table, name of the key, OUTPUT A pointer to the relevant key, or NULL if the desired key is not found in the table. NOTES If key->ptr is not NULL, the function doesn't do anything. AUTHOR E. Bertin (IAP) E.R. Deul (Sterrewacht Leiden) (Added open_cat error checking) VERSION 11/02/2020 ***/ keystruct *read_key(tabstruct *tab, char *keyname) { catstruct *cat; keystruct *key; char *buf, *ptr, *fptr,*fptr0; unsigned short ashort = 1; int i,j, larray,narray,size, esize, bswapflag; if (!(key = name_to_key(tab, keyname))) return NULL; /*If ptr is not NULL, there is already something loaded there: let's free mem */ QFREE(key->ptr); /*!! It is not necessarily the original table */ tab = key->tab; cat = tab->cat; /*We are expecting a 2D binary-table, and nothing else*/ if ((tab->naxis != 2) || (tab->bitpix!=8) || (tab->tfields == 0) || strncmp(tab->xtension, "BINTABLE", 8)) error(EXIT_FAILURE, "*Error*: No binary table in ", cat->filename); /*Size and number of lines in the binary table*/ larray = tab->naxisn[0]; narray = tab->naxisn[1]; /*Positioning to the first element*/ if (open_cat(cat, READ_ONLY) == RETURN_ERROR) error(EXIT_FAILURE, "*Error*: opening catalog ",cat->filename); QFSEEK(cat->file, tab->bodypos , SEEK_SET, cat->filename); /*allocate memory for the buffer where we put one line of data*/ QMALLOC(buf, char, larray); fptr0 = buf+key->pos; size = key->nbytes; /*allocate memory for the array*/ QMALLOC(ptr, char, size*narray); key->ptr = ptr; bswapflag = *((char *)&ashort); // Byte-swapping flag /*read line by line*/ for (i=narray; i--;) { QFREAD(buf, larray, cat->file, cat->filename); fptr = fptr0; if (bswapflag) { esize = t_size[key->ttype]; swapbytes(fptr0, esize, size/esize); } for (j = size; j--;) *(ptr++) = *(fptr++); } free(buf); return key; } /****** read_keys ************************************************************** PURPOSE Read several columns from a FITS binary table. INPUT pointer to the table, pointer to an array of char *, pointer to an array of keystruct * (memory must have been allocated), number of keys to read, an optional mask pointer. OUTPUT -. NOTES The array of pointers pointed by keys is filled with pointers to the relevant keys (a NULL means NO key with such name was found). A NULL keys pointer can be given (no info returned of course). A NULL keynames pointer means read ALL keys belonging to the table. A NULL mask pointer means NO selection for reading. AUTHOR E. Bertin (IAP) VERSION 11/02/2020 ***/ void read_keys(tabstruct *tab, char **keynames, keystruct **keys, int nkeys, BYTE *mask) { catstruct *cat; keystruct *key, **ckeys; BYTE *mask2; char *buf, *ptr, *fptr; unsigned short ashort = 1; int i,j,k,n, larray,narray, nb, kflag = 0, size, esize, bswapflag; /*!! It is not necessarily the original table */ tab = tab->key->tab; cat = tab->cat; /*We are expecting a 2D binary-table, and nothing else*/ if ((tab->naxis != 2) || (tab->bitpix!=8) || (tab->tfields == 0) || strncmp(tab->xtension, "BINTABLE", 8)) error(EXIT_FAILURE, "*Error*: No binary table in ", cat->filename); /*Size and number of lines in the binary table*/ larray = tab->naxisn[0]; narray = tab->naxisn[1]; nb = 0; if ((mask2 = mask)) { for (i=narray; i--;) if (*(mask2++)) nb++; } if (!keynames) nkeys = tab->nkey; /*Allocate memory to store the list of keys to be read */ if (!keys) { QMALLOC(keys, keystruct *, nkeys); kflag = 1; } /*allocate memory for the arrays*/ ckeys = keys; if (keynames) for (i=nkeys; i--;) { if ((key = name_to_key(tab, *(keynames++)))) { QFREE(key->ptr); if (nb) key->nobj = nb; else nb=key->nobj; QMALLOC(key->ptr, char, key->nbytes*nb); *(ckeys++) = key; } else *(ckeys++) = NULL; } else { key = tab->key; for (i=nkeys; i--;) { QFREE(key->ptr); if (nb) key->nobj = nb; else nb=key->nobj; QMALLOC(key->ptr, char, key->nbytes*nb); *(ckeys++) = key; key = key->nextkey; } } /*allocate memory for the buffer where we put one line of data*/ QMALLOC(buf, char, larray); /*Positioning to the first element*/ open_cat(cat, READ_ONLY); QFSEEK(cat->file, tab->bodypos , SEEK_SET, cat->filename); /*read line by line*/ bswapflag = *((char *)&ashort); // Byte-swapping flag n = 0; mask2 = mask; for (i=narray; i--;) { QFREAD(buf, larray, cat->file, cat->filename); if (!mask || *(mask2++)) { ckeys = keys; for (j=nkeys; j--;) if ((key = *(ckeys++))) { fptr = buf+key->pos; ptr = (char *)key->ptr+n*(size=key->nbytes); if (bswapflag) { esize = t_size[key->ttype]; swapbytes(fptr, esize, size/esize); } for (k = size; k--;) *(ptr++) = *(fptr++); } n++; } } free(buf); if (kflag) free(keys); return; } /****** remove_key ************************************************************* PROTO int remove_key(tabstruct *tab, char *keyname) PURPOSE Remove a key from a table. INPUT Pointer to the table, Name of the key. OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise. NOTES If keyname = "", the last key from the list is removed. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 15/01/97 ***/ int remove_key(tabstruct *tab, char *keyname) { keystruct *key, *prevkey, *nextkey; if (!keyname || !tab->nkey || !tab->key) return RETURN_ERROR; if (keyname[0]) { /*--Convert the key name to a pointer*/ if (!(key = name_to_key(tab, keyname))) return RETURN_ERROR; } else key = tab->key->prevkey; prevkey = key->prevkey; /*Free memory*/ nextkey = key->nextkey; if (tab->key==key) tab->key = nextkey; free_key(key); if (--tab->nkey) { /*--update the links of neighbours*/ nextkey->prevkey = prevkey; prevkey->nextkey = nextkey; } else tab->key = NULL; return RETURN_OK; } /****** remove_keys ************************************************************ PROTO int remove_keys(tabstruct *tab) PURPOSE Remove all keys from a table. INPUT Pointer to the table. OUTPUT RETURN_OK if keys were found, and RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 13/03/99 ***/ int remove_keys(tabstruct *tab) { int k; if (!tab->key) return RETURN_ERROR; for (k=tab->nkey; k--;) remove_key(tab, ""); return RETURN_OK; } /****** name_to_key ************************************************************ PROTO keystruct *name_to_key(tabstruct *tab, char *keyname) PURPOSE Name search of a key in a table. INPUT Pointer to the table, Key name. OUTPUT The key pointer if the name was matched, and NULL otherwise. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 25/04/97 ***/ keystruct *name_to_key(tabstruct *tab, char *keyname) { keystruct *key; int i; if (!(key=tab->key)) return NULL; for (i=tab->nkey; strcmp(keyname, key->name) && i--; key=key->nextkey); return i<0? NULL:key; } /****** keys_list ************************************************************** PROTO char **keys_list(catstruct *tab, int *n) PURPOSE List all keys in a table. INPUT Pointer to the table, Pointer to the number of names in that list. OUTPUT A list of all key names. NOTES -. AUTHOR E.R. Deul (Leiden observatory) VERSION ??/??/96 ***/ char **keys_list(tabstruct *tab, int *n) { keystruct *key; int i; char **names; QCALLOC(names, char *, tab->nkey); key = tab->key; for (i=0; inkey; i++) { QCALLOC(names[i], char, MAXCHARS); strcpy(names[i],key->name); key = key->nextkey; } *n = tab->nkey; return names; } /****** pos_to_key ************************************************************* PROTO keystruct *pos_to_key(tabstruct *tab, int pos) PURPOSE Position search of a key in a table. INPUT Pointer to the table, Position of the key. OUTPUT The key pointer if a key exists at the given position, and the pointer to the first key otherwise. NOTES pos = 0 or 1 means the first key. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 20/03/96 ***/ keystruct *pos_to_key(tabstruct *tab, int pos) { keystruct *key; int i; if (!(key=tab->key)) return NULL; if ((pos--)==1) return tab->key; for (i=0; i!=pos && inkey; i++, key=key->nextkey); return inkey?key:tab->key; } /****** show_keys ************************************************************** PROTO void show_keys(tabstruct *tab, char **keynames, keystruct **keys, int nkeys, BYTE *mask, FILE *stream, int strflag, int banflag, int leadflag, output_type o_type) PURPOSE Convert a binary table to an ASCII file. INPUT pointer to the table, pointer to an array of char *, pointer to an array of keystruct * (memory must have been allocated), number of keys to read, an optional mask pointer, a stream, a flag to indicate if arrays should be displayed (0=NO), a flag to indicate if a banner with keynames should be added (0=NO). a flag to indicate if a leading row number should be added (0=NO). the output type OUTPUT -. NOTES This is approximately the same code as for read_keys. The array of pointers pointed by keys is filled with pointers to the relevant keys (a NULL means NO key with such name was found). A NULL keys pointer can be given (no info returned of course). A NULL keynames pointer means read ALL keys belonging to the table. A NULL mask pointer means NO selection for reading. AUTHOR E. Bertin (IAP) VERSION 11/02/2020 ***/ void show_keys(tabstruct *tab, char **keynames, keystruct **keys, int nkeys, BYTE *mask, FILE *stream, int strflag, int banflag, int leadflag, output_type o_type) { catstruct *cat; keystruct *key, **ckeys; BYTE *mask2; char *buf, *rfield, *ptr; unsigned short ashort = 1; int *key_col, i,j,k,n,c, larray,narray, nb, kflag, maxnbytes, nelem, esize, bswapflag; typedef struct structreq_keyname { char oldname[80]; /* Name of the original pipeline key */ char newname[80]; /* Name of the skycat required key */ } req_keynamestruct; req_keynamestruct objectmap[] = { {"SeqNr", "id"}, {"Ra", "ra"}, {"Dec", "dec"}, {"MAG_ISO", "Mag"}, {"", ""} }; req_keynamestruct *map; char skycathead[] = "QueryResult\n\n" "# Config entry for original catalog server:\n" "serv_type: catalog\n" "long_name: ldactoskycat catalog\n" "short_name: ldactoaskycat\n" "symbol: id circle %4.1f\n" "search_cols: mag {Brightest (min)} {Faintest (max)}\n" "# End config entry\n\n"; char *t, skycattail[] = ""; /* !! It is not necessarily the original table */ if (tab->key) tab = tab->key->tab; cat = tab->cat; /* We are expecting a 2D binary-table, and nothing else */ if ((tab->naxis != 2) || (tab->bitpix!=8) || (tab->tfields == 0) || strncmp(tab->xtension, "BINTABLE", 8)) error(EXIT_FAILURE, "*Error*: Not a binary table in ", cat->filename); /* Size and number of lines in the binary table */ larray = tab->naxisn[0]; narray = tab->naxisn[1]; nb = 0; if ((mask2 = mask)) { for (i=narray; i--;) if (*(mask2++)) nb++; } if (!keynames) nkeys = tab->nkey; QCALLOC(key_col, int, nkeys); if (keynames) { for (i=0;ioldname[0]&&o_type == SHOW_SKYCAT; map++) { if (strcmp(key->name, map->oldname) == 0) { strcpy(key->name, map->newname); } } *(ckeys++) = key; switch (o_type) { case SHOW_ASCII: if (banflag) { if (*key->unit) fprintf(stream, "# %3d %-15.15s %-47.47s [%s]\n", n, key->name,key->comment, key->unit); else fprintf(stream, "# %3d %-15.15s %.47s\n", n, key->name,key->comment); n += key->nbytes/t_size[key->ttype]; } break; case SHOW_SKYCAT: if (key->nbytes/t_size[key->ttype] > 1) for (j=0;jnbytes/t_size[key->ttype];j++) fprintf(stream, "%s(%d)\t", key->name,j+1); else fprintf(stream, "%s\t", key->name); break; } if (key->nbytes>maxnbytes) maxnbytes = key->nbytes; } else *(ckeys++) = NULL; } else { key = tab->key; for (i=nkeys; i--; key = key->nextkey) if (strflag || key->naxis==0) { for (map=objectmap; map->oldname[0]&&o_type == SHOW_SKYCAT; map++) { if (strcmp(key->name, map->oldname) == 0) { strcpy(key->name, map->newname); } } *(ckeys++) = key; switch (o_type) { case SHOW_ASCII: if (banflag) { if (*key->unit) fprintf(stream, "# %3d %-15.15s %-47.47s [%s]\n", n, key->name,key->comment, key->unit); else fprintf(stream, "# %3d %-15.15s %.47s\n", n, key->name,key->comment); n += key->nbytes/t_size[key->ttype]; } break; case SHOW_SKYCAT: if (key->nbytes/t_size[key->ttype] > 1) for (j=0;jnbytes/t_size[key->ttype];j++) fprintf(stream, "%s(%d)\t", key->name,j+1); else fprintf(stream, "%s\t", key->name); break; } if (key->nbytes>maxnbytes) maxnbytes = key->nbytes; } else { switch (o_type) { case SHOW_ASCII: if (*key->unit) fprintf(stream, "# %-15.15s %-47.47s [%s]\n", key->name,key->comment, key->unit); else fprintf(stream, "# %-15.15s %.47s\n", key->name,key->comment); break; case SHOW_SKYCAT: break; } *(ckeys++) = NULL; } } if (o_type == SHOW_SKYCAT) fprintf(stream, "\n------------------\n"); /* Allocate memory for the buffer where we put one line of data */ QMALLOC(buf, char, larray); /* Allocate memory for the buffer where we put one element */ QMALLOC(rfield, char, maxnbytes); /* Positioning to the first element */ open_cat(cat, READ_ONLY); QFSEEK(cat->file, tab->bodypos , SEEK_SET, cat->filename); /*read line by line*/ bswapflag = *((char *)&ashort); // Byte-swapping flag n = 0; mask2 = mask; for (i=narray; i--;) { QFREAD(buf, larray, cat->file, cat->filename); if (!mask || *(mask2++)) { ckeys = keys; if (leadflag) { fprintf(stream, "%d", ++n); if (nkeys) putc(' ', stream); } for (k=0; knaxis==0)) { ptr = memcpy(rfield, buf+key->pos, key->nbytes); esize = t_size[key->ttype]; nelem = key->nbytes/esize; if (bswapflag) swapbytes(ptr, esize, nelem); switch(key->ttype) { case T_SHORT: for (j = 0; jprintf?key->printf:"%d", *(short *)ptr); if (j < nelem-1) { switch (o_type) { case SHOW_ASCII: putc(' ', stream); break; case SHOW_SKYCAT: putc('\t', stream); break; } } } } break; case T_LONG: for (j = 0; jprintf?key->printf:"%d", *(int *)ptr); if (j < nelem-1) { switch (o_type) { case SHOW_ASCII: putc(' ', stream); break; case SHOW_SKYCAT: putc('\t', stream); break; } } } } break; case T_LONGLONG: for (j = 0; jprintf?key->printf:"%lld", *(SLONGLONG *)ptr); #else fprintf(stream, *key->printf?key->printf:"%d", *(int *)ptr); #endif if (j < nelem-1) { switch (o_type) { case SHOW_ASCII: putc(' ', stream); break; case SHOW_SKYCAT: putc('\t', stream); break; } } } } break; case T_FLOAT: for (j = 0; jprintf?key->printf:"%g", *(float *)ptr); if (j < nelem-1) { switch (o_type) { case SHOW_ASCII: putc(' ', stream); break; case SHOW_SKYCAT: putc('\t', stream); break; } } } } break; case T_DOUBLE: for (j = 0; jprintf?key->printf:"%f", *(double *)ptr); if (j < nelem-1) { switch (o_type) { case SHOW_ASCII: putc(' ', stream); break; case SHOW_SKYCAT: putc('\t', stream); break; } } } } break; case T_BYTE: if (key->htype==H_BOOL) for (j = 0; jprintf?key->printf:"%d", (int)*((unsigned char *)ptr)); if (j) { switch (o_type) { case SHOW_ASCII: putc(' ', stream); break; case SHOW_SKYCAT: putc('\t', stream); break; } } } } break; case T_STRING: for (j = nelem; j-- && (c=(int)*ptr); ptr += esize) fprintf(stream, "%c", c); break; default: error(EXIT_FAILURE, "*FATAL ERROR*: Unknown FITS type in ", "show_keys()"); break; } if (k < nkeys - 1) { switch (o_type) { case SHOW_ASCII: putc(' ', stream); break; case SHOW_SKYCAT: putc('\t', stream); break; } } } } putc('\n', stream); } } free(key_col); free(buf); if (kflag) free(keys); if (o_type == SHOW_SKYCAT) fprintf(stream, "%s", skycattail); return; } swarp-2.41.5/src/fits/fitsmisc.c000066400000000000000000000135331400430667300164700ustar00rootroot00000000000000/* * fitsmisc.c * * Miscellaneous functions. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic FITS/LDAC library * * Copyright: (C) 1995-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 09/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "fitscat_defs.h" #include "fitscat.h" static void (*errorfunc)(char *msg1, char *msg2) = NULL; static char warning_historystr[WARNING_NMAX][192]={""}; static int nwarning = 0, nwarning_history = 0, nerror = 0; /********************************* error ************************************/ /* I hope it will never be used! */ void error(int num, char *msg1, char *msg2) { fprintf(stderr, "\n> %s%s\n\n",msg1,msg2); if (num && errorfunc && !nerror) { nerror = 1; errorfunc(msg1, msg2); } exit(num); } /**************************** error_installfunc *****************************/ /* I hope it will never be used! */ void error_installfunc(void (*func)(char *msg1, char *msg2)) { if (func) errorfunc = func; return; } /********************************* warning **********************************/ /* Print a warning message on screen. */ void warning(char *msg1, char *msg2) { time_t warntime; struct tm *tm; warntime = time(NULL); tm = localtime(&warntime); fprintf(stderr, "\n> WARNING: %s%s\n\n",msg1,msg2); sprintf(warning_historystr[(nwarning++)%WARNING_NMAX], "%04d-%02d-%02d %02d:%02d:%02d : %.80s%.80s", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, msg1, msg2); return; } /****************************** warning_history ******************************/ /* Return warning. */ char *warning_history(void) { char *str; if (nwarning_history >= WARNING_NMAX) { nwarning_history = 0; /* So it can be accessed later on */ return ""; } str = warning_historystr[((nwarning>WARNING_NMAX? (nwarning%WARNING_NMAX):0) + nwarning_history++)%WARNING_NMAX]; if (!*str) nwarning_history = 0; /* So it can be accessed later on */ return str; } /******************************* swapbytes **********************************/ /* Swap bytes for doubles, longs and shorts (for DEC machines or PC for inst.). */ void swapbytes(void *ptr, int nb, int n) { char *cp, c; int j; cp = (char *)ptr; if (nb&4) { for (j=n; j--; cp+=4) { c = cp[3]; cp[3] = cp[0]; cp[0] = c; c = cp[2]; cp[2] = cp[1]; cp[1] = c; } return; } if (nb&2) { for (j=n; j--; cp+=2) { c = cp[1]; cp[1] = cp[0]; cp[0] = c; } return; } if (nb&1) return; if (nb&8) { for (j=n; j--; cp+=8) { c = cp[7]; cp[7] = cp[0]; cp[0] = c; c = cp[6]; cp[6] = cp[1]; cp[1] = c; c = cp[5]; cp[5] = cp[2]; cp[2] = c; c = cp[4]; cp[4] = cp[3]; cp[3] = c; } return; } error(EXIT_FAILURE, "*Internal Error*: Unknown size in ", "swapbytes()"); return; } /****** wstrncmp *************************************************************** PROTO int wstrncmp(char *cs, char *ct, int n) PURPOSE simple wildcard strcmp. INPUT character string 1, character string 2, maximum number of characters to be compared. OUTPUT comparison integer (same meaning as strcmp). NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 15/02/96 ***/ int wstrncmp(char *cs, char *ct, int n) { int diff,i; i = n; diff = 0; do { diff = ((*cs=='?'&&*ct)||(*ct=='?'&&*cs))?0:*cs-*ct; } while (!diff && --i && *(cs++) && *(ct++)); return diff; } /****** findkey **************************************************************** PROTO int findkey(char *str, char *key, int size) PURPOSE Find an item within a list of keywords. INPUT character string, an array of character strings containing the list of keywords, offset (in char) between each keyword. OUTPUT position in the list (0 = first) if keyword matched, RETURN_ERROR otherwise. NOTES the matching is case-sensitive. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 15/02/96 ***/ int findkey(char *str, char *key, int size) { int i; for (i=0; key[0]; i++, key += size) if (!strcmp(str, key)) return i; return RETURN_ERROR; } /********************************* findnkey ********************************** PROTO int findnkey(char *str, char *key, int size, int nkey) PURPOSE Find an item within a list of nkey keywords. INPUT character string, an array of character strings containing the list of keywords, offset (in char) between each keyword. number of keywords. OUTPUT position in the list (0 = first) if keyword matched, RETURN_ERROR otherwise. NOTES the matching is case-sensitive. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 15/02/96 ***/ int findnkey(char *str, char *key, int size, int nkey) { int i; for (i=0; i. * * Last modified: 11/02/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "fitscat_defs.h" #include "fitscat.h" char padbuf[FBSIZE]; /****** read_cat *************************************************************** PROTO catstruct read_cat(char *filename) PURPOSE ``Read'' a FITS catalog with name filename. INPUT Filename, OUTPUT catstruct pointer. NOTES Returns NULL if no file with name \ is found. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 07/05/2002 ***/ catstruct *read_cat(char *filename) { catstruct *cat; if (!(cat = new_cat(1))) error (EXIT_FAILURE, "Not enough memory to read ", filename); strcpy(cat->filename, filename); if (open_cat(cat, READ_ONLY) != RETURN_OK) { free_cat(&cat, 1); return NULL; } if (map_cat(cat) != RETURN_OK) { free_cat(&cat, 1); return NULL; } return cat; } /****** read_cats ************************************************************** PROTO read_cats(char **filenames, int ncat) PURPOSE ``Read'' several FITS catalogs. INPUT A pointer to pointers of char, The number of catalogs. OUTPUT catstruct pointer. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 25/04/97 ***/ catstruct *read_cats(char **filenames, int ncat) { catstruct *cat, *ccat; int i; if (!(cat = new_cat(ncat))) error (EXIT_FAILURE, "Not enough memory to read ", "catalogs"); for (i=ncat, ccat = cat; i--; ccat++, filenames++) { strcpy(ccat->filename, *filenames); if (open_cat(ccat, READ_ONLY) != RETURN_OK) error (EXIT_FAILURE, "Cannot open ", *filenames); if (map_cat(ccat) != RETURN_OK) error (EXIT_FAILURE, "Cannot map ", *filenames); close_cat(ccat); } return cat; } /****** init_readobj ********************************************************** PROTO tabstruct *init_readobj(tabstruct *tab, char **pbuf) PURPOSE Prepare the reading of individual sources in a FITS table INPUT Table structure, pointer to an array pointer to be used as a temporary buffer. OUTPUT Pointer to the table structure from which the data will be read. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 26/09/2004 ***/ tabstruct *init_readobj(tabstruct *tab, char **pbuf) { catstruct *tabcat; tabstruct *keytab; keystruct *key; int k; /* Scan keys to find the reference tab and other things*/ keytab = NULL; tabcat = NULL; key = tab->key; for (k=tab->nkey; k--; key = key->nextkey) if (!key->ptr) { keytab = key->tab; tabcat = keytab->cat; QMALLOC(key->ptr, char, key->nbytes); } else key->pos = -1; if (!keytab) error(EXIT_FAILURE,"*Error*: no original table found among keys in table ", tab->extname); if (open_cat(tabcat, READ_ONLY) != RETURN_OK) error(EXIT_FAILURE, "*Error*: Cannot access ", tabcat->filename); QFSEEK(tabcat->file, keytab->bodypos, SEEK_SET, tabcat->filename); /* Allocate memory for the input buffer */ QMALLOC(*pbuf, char, tab->naxisn[0]); return keytab; } /****** read_obj ************************************************************** PROTO int read_obj(tabstruct *keytab, tabstruct *tab, char *buf) PURPOSE Read one individual source at the current position in a FITS table. INPUT Table which will be accessed from disk (provided by init_readobj()), table containing the keys that will be read, pointer to the temporary buffer. OUTPUT The number of table lines that remain to be read. NOTES -. AUTHOR E. Bertin (IAP) VERSION 11/02/2020 ***/ int read_obj(tabstruct *keytab, tabstruct *tab, char *buf) { keystruct *key; char *pin, *pout; unsigned short ashort = 1; int b, k, esize, bswapflag; QFREAD(buf,keytab->naxisn[0],keytab->cat->file,keytab->cat->filename); bswapflag = *((char *)&ashort); // Byte-swapping flag key = tab->key; for (k=tab->nkey; k--; key = key->nextkey) if (key->pos>=0) { pin = buf+key->pos; pout = key->ptr; if (bswapflag) { esize = t_size[key->ttype]; swapbytes(pin, esize, key->nbytes/esize); } for (b=key->nbytes; b--;) *(pout++) = *(pin++); } return --keytab->naxisn[1]; } /****** read_obj_at *********************************************************** PROTO int read_obj_at(tabstruct *keytab, tabstruct *tab, char *buf, long pos) PURPOSE Get one source at a specific position in a FITS table. INPUT Table which will be accessed from disk (provided by init_readobj()), table containing the keys that will be read. pointer to the temporary buffer, position number in table. OUTPUT RETURN_OK if the object has been accessed, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 11/02/2020 ***/ int read_obj_at(tabstruct *keytab, tabstruct *tab, char *buf, long pos) { keystruct *key; char *pin, *pout; size_t n; unsigned short ashort = 1; int b, k, esize, bswapflag; if ((n=keytab->naxisn[0]*pos) >= keytab->tabsize) return RETURN_ERROR; QFSEEK(keytab->cat->file,keytab->bodypos+n, SEEK_SET, keytab->cat->filename); QFREAD(buf,keytab->naxisn[0],keytab->cat->file,keytab->cat->filename); bswapflag = *((char *)&ashort); // Byte-swapping flag key = tab->key; for (k=tab->nkey; k--; key = key->nextkey) if (key->pos>=0) { pin = buf+key->pos; pout = key->ptr; if (bswapflag) { esize = t_size[key->ttype]; swapbytes(pin, esize, key->nbytes/esize); } for (b=key->nbytes; b--;) *(pout++) = *(pin++); } return RETURN_OK; } /****** end_readobj ********************************************************** PROTO void end_readobj(tabstruct *keytab, tabstruct *tab, char *buf) PURPOSE End the writing of individual sources in a FITS table INPUT Table which will be accessed from disk (provided by init_readobj()), table containing the keys that have been read, pointer to the temporary buffer. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 26/09/2004 ***/ void end_readobj(tabstruct *keytab, tabstruct *tab, char *buf) { if (close_cat(keytab->cat) != RETURN_OK) error(EXIT_FAILURE,"*Error*: Problem while closing",keytab->cat->filename); /* Recover the original state of the original table */ update_tab(keytab); free(buf); return; } swarp-2.41.5/src/fits/fitstab.c000066400000000000000000000470511400430667300163050ustar00rootroot00000000000000/* * fitstab.c * * Handle FITS extensions and tables. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic FITS/LDAC library * * Copyright: (C) 1995-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 11/09/2012 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "fitscat_defs.h" #include "fitscat.h" /****** about_tab ************************************************************** PROTO int about_tab(catstruct *cat, char *tabname, FILE *stream) PURPOSE Print information concerning a tab structure. INPUT Pointer to the input catalog, table name, an output stream. OUTPUT RETURN_OK if the table was found, RETURN_ERROR otherwise. NOTES -. AUTHOR E.R. Deul(Leiden observatory), E. Bertin (IAP & Leiden observatory): return value modified. E.R. Deul(Leiden observatory): output units VERSION 28/10/2009 ***/ int about_tab(catstruct *cat, char *tabname, FILE *stream) { tabstruct *tab; keystruct *key; int i, j; if ((tab = name_to_tab(cat, tabname, 0))) { fprintf(stream, "Table %s\n", tabname); for (i=0, key=tab->key; inkey; i++,key=key->nextkey) { fprintf(stream, "****** Key #%d\n", i+1); fprintf(stream, " Key name:...............%s\n", key->name); fprintf(stream, " Key comment:............%s\n", key->comment); fprintf(stream, " Key type:..............."); switch (key->ttype) { case T_BYTE: fprintf(stream,"Byte"); break; case T_SHORT: fprintf(stream,"Short Int"); break; case T_LONG: fprintf(stream,"Long Int"); break; case T_LONGLONG: fprintf(stream,"Long Long Int"); break; case T_FLOAT: fprintf(stream,"Float"); break; case T_DOUBLE: fprintf(stream,"Double"); break; case T_STRING: fprintf(stream,"String"); break; } fprintf(stream,"\n"); fprintf(stream, " Key dimension:..........%d ", key->naxis); if (key->naxis) fprintf(stream, "("); for (j=0;jnaxis;j++) { if (j>0) fprintf(stream, " "); fprintf(stream, "%d", key->naxisn[j]); } if (key->naxis) fprintf(stream, ")"); fprintf(stream, "\n"); if (key->unit[0] != '\0') fprintf(stream, " Key unit:...............%s\n", key->unit); } } else return RETURN_ERROR; return RETURN_OK; } /****** add_tab **************************************************************** PROTO int add_tab(tabstruct *tab, catstruct *cat, int pos) PURPOSE Add a table to a catalog. INPUT Pointer to the table, Pointer to the destination catalog, Position (1= first after the primary HDU, <=0 = at the end). OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise. NOTES Only 1-segment tables are accepted. To copy multi-segment tables, use copy_tab() instead. If a table with the same name and basic attributes already exists in the destination catalog, then the new table is appended to it. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 15/08/2003 ***/ int add_tab(tabstruct *tab, catstruct *cat, int pos) { tabstruct *outtab, *prevtab; int i; /*Check if a similar table doesn't already exist in the dest. cat */ if ((outtab = name_to_tab(cat, tab->extname, 0))) { if ((outtab->naxis != 2) || (outtab->bitpix!=8) || strcmp(outtab->xtension,tab->xtension) || (outtab->tfields != tab->tfields) || (outtab->naxisn[0] != tab->naxisn[0])) return RETURN_ERROR; prevtab = outtab; for (i=outtab->nseg-1; i--;) prevtab = prevtab->nexttab; tab->seg = prevtab->seg+1; tab->nseg = 0; outtab->nseg++; } else { if ((prevtab = pos_to_tab(cat, pos, 0))) prevtab = prevtab->prevtab; else tab->nexttab = tab->prevtab = prevtab = tab; cat->ntab++; } (tab->nexttab = (tab->prevtab = prevtab)->nexttab)->prevtab = tab; prevtab->nexttab = tab; return RETURN_OK; } /****** copy_tab ************************************************************** PROTO int copy_tab(catstruct *catin, char *tabname, int seg, catstruct *catout, int pos) PURPOSE Copy a table from one catalog to another. INPUT Pointer to the original catalog, Name of the table, Table segment (0 = all), Pointer to the destination catalog, Position (1= first after the primary HDU, <=0 = at the end) OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise. NOTES If a table with the same name and basic attributes already exists in the destination catalog, then the original table is appended to it. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 15/08/2003 ***/ int copy_tab(catstruct *catin, char *tabname, int seg, catstruct *catout, int pos) { keystruct *key; tabstruct *outtab, *prevtab, *nexttab, *tabin,*tabout; int i,j, nseg; /*Convert the table name to a pointer*/ if (!(tabin = name_to_tab(catin, tabname, seg))) return RETURN_ERROR; nseg = seg?1:tabin->nseg; /*Check if a similar table doesn't already exist in the dest. cat */ if (*tabname && (outtab = name_to_tab(catout, tabname, 0))) { if ((outtab->naxis != 2) || (outtab->bitpix!=8) || strcmp(outtab->xtension,tabin->xtension) || (outtab->tfields != tabin->tfields) || (outtab->naxisn[0] != tabin->naxisn[0])) return RETURN_ERROR; prevtab = outtab; for (i=0; inseg-1; i++) prevtab = prevtab->nexttab; nexttab = prevtab->nexttab; outtab->nseg += nseg; } else { prevtab = nexttab = outtab = NULL; catout->ntab++; } /*Now copy each segment of the original table*/ tabout = NULL; /* to satisfy gcc -Wall */ for (i=nseg; i--;) { /*---First, allocate memory and copy data */ QCALLOC(tabout, tabstruct, 1); *tabout = *tabin; if (tabin->naxis) QMEMCPY(tabin->naxisn, tabout->naxisn, int, tabin->naxis); if (tabin->headbuf) QMEMCPY(tabin->headbuf, tabout->headbuf, char, tabin->headnblock*FBSIZE); if (tabin->bodybuf) QMEMCPY(tabin->bodybuf, tabout->bodybuf, char, tabin->tabsize); key = tabin->key; tabout->key = NULL; tabout->nkey = 0; for (j=tabin->nkey; j--;) { copy_key(tabin, key->name, tabout, 0); key = key->nextkey; } /*---Then, update the links */ if (prevtab) { prevtab->nexttab = tabout; tabout->prevtab = prevtab; tabout->seg = prevtab->seg+1; tabout->nseg = 0; } else { outtab = tabout; outtab->prevtab = NULL; tabout->seg = 1; } tabin = tabin->nexttab; prevtab = tabout; } /*place the new chain of table-segments within the catalog (tricky, isn't it?)*/ if (!nexttab) /*--if the table is new */ { nexttab = pos_to_tab(catout, pos, 0); if (!nexttab) nexttab = catout->tab = tabout; else { outtab->prevtab = nexttab->prevtab; nexttab->prevtab->nexttab = outtab; } } prevtab->nexttab = nexttab; nexttab->prevtab = prevtab; return RETURN_OK; } /****** copy_tab_fromptr ****************************************************** PROTO void copy_tab_fromptr(tabstruct *tabin, catstruct *catout, int pos) PURPOSE Copy a table from one catalog to another. INPUT Pointer to the original catalog, Pointer to the table, Pointer to the destination catalog, Position (1= first after the primary HDU, <=0 = at the end) OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 22/06/2001 ***/ void copy_tab_fromptr(tabstruct *tabin, catstruct *catout, int pos) { keystruct *key; tabstruct *prevtab, *nexttab,*tabout; int j; catout->ntab++; /* First, allocate memory and copy data */ QCALLOC(tabout, tabstruct, 1); *tabout = *tabin; if (tabin->naxis) QMEMCPY(tabin->naxisn, tabout->naxisn, int, tabin->naxis); if (tabin->headbuf) QMEMCPY(tabin->headbuf, tabout->headbuf, char, tabin->headnblock*FBSIZE); if (tabin->bodybuf) QMEMCPY(tabin->bodybuf, tabout->bodybuf, char, tabin->tabsize); key = tabin->key; tabout->key = NULL; tabout->nkey = 0; for (j=tabin->nkey; j--;) { copy_key(tabin, key->name, tabout, 0); key = key->nextkey; } /* Then, update the links */ tabout->prevtab = NULL; tabout->seg = 1; tabin = tabin->nexttab; prevtab = tabout; if (!(nexttab = pos_to_tab(catout, pos, 0))) nexttab = catout->tab = tabout; else { tabout->prevtab = nexttab->prevtab; nexttab->prevtab->nexttab = tabout; } prevtab->nexttab = nexttab; nexttab->prevtab = prevtab; return; } /****** copy_tabs ************************************************************** PROTO int copy_tabs(catstruct *catin, catstruct *catout) PURPOSE Copy all tables from one catalog to another. INPUT Pointer to the original catalog, Pointer to the destination catalog, OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise (for instance if there were tabs that were not binary-tables, and therefore that were not copied). NOTES If a table with the same name and basic attributes already exists in the destination catalog, then the original table is appended to it. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 12/06/2001 ***/ int copy_tabs(catstruct *catin, catstruct *catout) { tabstruct *tab; int i, flag, ntab; if (!catin->tab) return RETURN_ERROR; tab = catin->tab->nexttab; /* skip the primary header */ flag = RETURN_OK; ntab = catin->ntab-1; if (!ntab) ntab = 1; for (i=ntab; i--;) { flag |= copy_tab(catin, tab->extname, 0, catout, 0); while (!(tab=tab->nexttab)->nseg); } return flag; } /****** copy_tabs_blind ******************************************************* PROTO int copy_tabs(catstruct *catin, catstruct *catout) PURPOSE Copy all tables from one catalog to another, without trying to append. INPUT Pointer to the original catalog, Pointer to the destination catalog, OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 07/05/2002 ***/ int copy_tabs_blind(catstruct *catin, catstruct *catout) { tabstruct *tab; int i, ntab; if (!catin->tab) return RETURN_ERROR; tab = catin->tab; /* don't skip the primary header */ ntab = catin->ntab; for (i=ntab; i--;) { copy_tab_fromptr(tab, catout, 0); tab=tab->nexttab; } return RETURN_OK; } /****** free_tab *************************************************************** PROTO void free_tab(tabstruct *tab) PURPOSE Free memory associated to a table pointer. INPUT Pointer to the table. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 28/02/2000 ***/ void free_tab(tabstruct *tab) { free_body(tab); free(tab->naxisn); free(tab->headbuf); free(tab->compress_buf); remove_keys(tab); free(tab); return; } /****** new_tab **************************************************************** PROTO tabstruct *new_tab(char *tabname) PURPOSE Create a new binary table. INPUT Name. OUTPUT A pointer to the new table. NOTES A defaut header is also created. No links are initialized. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 25/04/97 ***/ tabstruct *new_tab(char *tabname) { static char bintabtemplate[][80] = { "XTENSION= 'BINTABLE' / THIS IS A BINARY TABLE (FROM THE LDACTOOLS)", "BITPIX = 8 / ", "NAXIS = 2 / ", "NAXIS1 = 0 / BYTES PER ROW", "NAXIS2 = 0 / NUMBER OF ROWS", "PCOUNT = 0 / RANDOM PARAMETER COUNT", "GCOUNT = 1 / GROUP COUNT", "TFIELDS = 0 / FIELDS PER ROWS", "EXTNAME = 'WHOCARES' / TABLE NAME", "END "}; tabstruct *tab; char *buf; int i; QCALLOC(tab, tabstruct, 1); strcpy(tab->xtension, "BINTABLE"); strcpy(tab->extname, tabname); tab->naxis = 2; QCALLOC(tab->naxisn, int, tab->naxis); tab->bitpix = 8; tab->bytepix = 1; tab->pcount = 0; tab->gcount = 1; tab->seg = 1; tab->nseg = 1; /*Provide a new header*/ QCALLOC(tab->headbuf, char, FBSIZE); memcpy(tab->headbuf, bintabtemplate, sizeof(bintabtemplate)); for (buf = tab->headbuf, i=FBSIZE; i--; buf++) if (!*buf) *buf = ' '; tab->headnblock = 1; return tab; } /****** remove_tab ************************************************************* PROTO int remove_tab(catstruct *cat, char *tabname, int seg) PURPOSE Remove a table from a catalog. INPUT Pointer to the catalog, Name of the table, Table segment (0 = all). OUTPUT RETURN_OK if everything went as expected, and RETURN_ERROR otherwise. NOTES If tabname = "", the last table from the list is removed. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 15/08/2003 ***/ int remove_tab(catstruct *cat, char *tabname, int seg) { tabstruct *tab, *prevtab, *nexttab; int i,nseg; if (!tabname || !cat->ntab || !cat->tab) return RETURN_ERROR; if (tabname[0]) { /*--Convert the table name to a pointer*/ if (!(tab = name_to_tab(cat, tabname, seg))) return RETURN_ERROR; /*--a small trick to simplify decisions afterwards*/ if (seg && tab->nseg==1) seg = 0; } else { tab = cat->tab->prevtab; if (!seg) for (;!tab->nseg; tab = tab->prevtab); } prevtab = tab->prevtab; nseg = seg?1:tab->nseg; /*Free memory for each table segment*/ nexttab = NULL; /* to satisfy gcc -Wall */ for (i=nseg; i--;) { nexttab = tab->nexttab; if (cat->tab == tab) cat->tab = nexttab; free_tab(tab); tab = nexttab; } if (!seg) if (!--cat->ntab) { cat->tab = NULL; return RETURN_OK; } /*update the links of neighbours*/ nexttab->prevtab = prevtab; prevtab->nexttab = nexttab; if (seg) /*--update status for each table segment*/ { for (tab=prevtab;!tab->nseg; tab = tab->prevtab); for (nexttab=tab->nexttab,i=2;!nexttab->nseg;nexttab=nexttab->nexttab,i++); nexttab->seg = i; tab->nseg = i; tab->seg = 1; } return RETURN_OK; } /****** remove_tabs ************************************************************ PROTO int remove_tabs(catstruct *cat) PURPOSE Remove all tables from a catalog. INPUT Pointer to the catalog. OUTPUT RETURN_OK if tabs were found, and RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 25/05/97 ***/ int remove_tabs(catstruct *cat) { int t; if (!cat->tab) return RETURN_ERROR; for (t=cat->ntab; t--;) remove_tab(cat, "",0); return RETURN_OK; } /****** update_tab ************************************************************ PROTO int update_tab(tabstruct *tab) PURPOSE Update a table according to what's in the keys. INPUT Table structure. OUTPUT RETURN_OK if tab is a binary table, or RETURN_ERROR otherwise. NOTES The headbuf pointer in the catstruct might be reallocated. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 11/09/2012 ***/ int update_tab(tabstruct *tab) { tabstruct *keytab; keystruct *key; int i,j, nobj, nbytes; /*Just pass if not a binary table*/ if ((tab->naxis != 2) || (tab->bitpix!=8) || strncmp(tab->xtension, "BINTABLE", 8)) return RETURN_ERROR; /*Well, not much to do if there are no keys!*/ if (!(key = tab->key)) return RETURN_OK; nobj = -1; keytab = NULL; nbytes = 0; for (i=tab->nkey; i--;) { if (keytab && !key->ptr && key->tab != keytab) error(EXIT_FAILURE, "*Error*: wrong reference table in ", key->name); if (nobj!=-1 && (nobj != key->nobj)) error(EXIT_FAILURE, "*Error*: wrong number of elements in key ", key->name); keytab = key->tab; nobj = key->nobj; /*-- If the number of bytes per element is not set, recover it */ if (!key->nbytes) { key->nbytes = t_size[key->ttype]; for (j=key->naxis; j--;) key->nbytes *= key->naxisn[j]; } nbytes += key->nbytes; key = key->nextkey; } tab->tabsize = (KINGSIZE_T)nobj*nbytes; tab->naxisn[0] = nbytes; tab->naxisn[1] = nobj; tab->tfields = tab->nkey; return RETURN_OK; } /****** name_to_tab *********************************************************** PROTO tabstruct *name_to_tab(catstruct *cat, char *tabname, int seg) PURPOSE Name search of a table in a catalog. INPUT Pointer to the catalog, Table name, Table segment (0 = first). OUTPUT The table pointer if the name was matched, and NULL otherwise. NOTES - VERSION 12/06/2001 ***/ tabstruct *name_to_tab(catstruct *cat, char *tabname, int seg) { tabstruct *tab; int i; if (!(tab = cat->tab)) return NULL; for (i=cat->ntab; strcmp(tabname,tab->extname) && i--;) while (!(tab=tab->nexttab)->nseg); if (i<0) return NULL; if (seg) { for (;tab->seg!=seg && !tab->nexttab->nseg; tab=tab->nexttab); return tab->seg==seg?tab:NULL; } return tab; } /****** pos_to_tab ************************************************************* PROTO tabstruct *pos_to_tab(catstruct *cat, int pos, int seg) PURPOSE Position search of a table in a catalog. INPUT Pointer to the catalog, Position of the table, Table segment (0 = first). OUTPUT The table pointer if the table exists at the given position, and the pointer to the primary ``table'' otherwise. NOTES pos = 1 means the first table after the primary one. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 15/02/96 ***/ tabstruct *pos_to_tab(catstruct *cat, int pos, int seg) { tabstruct *tab; int i; tab = cat->tab; for (i=0; i!=pos && intab; i++) while (!(tab=tab->nexttab)->nseg); if (seg) for (;tab->seg!=seg && !tab->nexttab->nseg; tab=tab->nexttab); return intab?tab:cat->tab; } /****** tabs_list ************************************************************** PROTO char **tabs_list(catstruct *cat, int *n) PURPOSE List all tables in a catalog. INPUT Pointer to the catalog, Pointer to the number of names in that list. OUTPUT A list of all table names. NOTES -. AUTHOR E.R. Deul (Leiden observatory) VERSION ??/??/96 ***/ char **tabs_list(catstruct *cat, int *n) { tabstruct *tab; int i; char **names; tab = cat->tab; QCALLOC(names, char *, cat->ntab); for (i=0; intab; i++) { QCALLOC(names[i], char, MAXCHARS); strcpy(names[i],tab->extname); while (!(tab=tab->nexttab)->nseg); } *n = cat->ntab; return names; } /****** tabs_row_len *********************************************************** PROTO int tab_row_len(char *file, char *tabname) PURPOSE Return the row length in bytes of a given table in a given catalog. INPUT File pointer. OUTPUT Table size (bytes) NOTES -. AUTHOR E.R. Deul (Leiden observatory) VERSION 05/06/200` ***/ int tab_row_len(char *file, char *tabname) { catstruct *tcat; tabstruct *tab; int retcode = -1; if ((tcat = read_cat(file)) != NULL) { if ((tab = name_to_tab(tcat, tabname, 0)) != NULL) { retcode = tab->naxisn[0]; free_tab(tab); } close_cat(tcat); free_cat(&tcat,1); } return retcode; } swarp-2.41.5/src/fits/fitsutil.c000066400000000000000000000406051400430667300165120ustar00rootroot00000000000000/* * fitsutil.c * * Handle FITS header keywords. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic FITS/LDAC library * * Copyright: (C) 1995-2012 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 30/11/2012 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "fitscat_defs.h" #include "fitscat.h" char histokeys[][12] = {"COMMENT ", "HISTORY ", " ", ""}; /****** fitsadd *************************************************************** PROTO int fitsadd(char *fitsbuf, char *keyword, char *comment) PURPOSE Write a FITS keyword in a fits header. INPUT pointer to the FITS buffer, name of the keyword to be created, a comment to put beyond the slash, or next to a COMMENT or HISTORY. OUTPUT line position or RETURN_ERROR if the keyword is invalid. NOTES For all keywords except commentary ones (like COMMENT, HISTORY or blank), it is checked that they do not exist already. Enough memory should be provided for the FITS header to contain one more line of 80 char. AUTHOR E. Bertin (IAP & Leiden observatory) C. Marmo (IAP) VERSION 13/06/2007 ***/ int fitsadd(char *fitsbuf, char *keyword, char *comment) { char *key_ptr; char str[82]; int headpos, headpos2, commentflag, i, n; if (strcspn(keyword, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 -_")) return RETURN_ERROR; commentflag = findkey(keyword, (char *)histokeys, 12)==RETURN_ERROR?0:1; if (commentflag || (headpos = fitsfind(fitsbuf, keyword))==RETURN_ERROR) { headpos2 = headpos = fitsfind(fitsbuf, "END "); /*-- Special case of NAXIS parameters */ if (!strncmp(keyword, "NAXIS", 5) && keyword[5] && keyword[5] != ' ') { sscanf(keyword, "NAXIS%d", &n); /*---- Look for all previous NAXIS parameters */ for (i=n; i--;) { sprintf(str, "NAXIS%-3d", i); headpos=fitsfind(fitsbuf, str); if (headpos>0) break; } if (headpos<0) /*---- Most likely keyword is NAXIS1 */ headpos=fitsfind(fitsbuf, "NAXIS "); if (headpos>0) headpos++; else return RETURN_ERROR; } /*-- Special case of PCOUNT/GCOUNT parameters */ if (!strncmp(keyword, "PCOUNT", 6)) { headpos=fitsfind(fitsbuf, "NAXIS "); sscanf(fitsbuf+80*headpos, "NAXIS = %d", &n); if (headpos>0) headpos+=(n+1); else return RETURN_ERROR; } if (!strncmp(keyword, "GCOUNT", 6)) { headpos=fitsfind(fitsbuf, "NAXIS "); sscanf(fitsbuf+80*headpos, "NAXIS = %d", &n); if (headpos>0) headpos+=(n+2); else return RETURN_ERROR; } key_ptr = fitsbuf+80*headpos; memmove(key_ptr+80, key_ptr, 80*(headpos2-headpos+1)); if (commentflag) sprintf(str, "%-8.8s %-71.71s", keyword, comment?comment:" "); else if (comment && *comment) sprintf(str, "%-8.8s= / %-47.47s", keyword, comment); else sprintf(str, "%-8.8s= %-47.47s", keyword, " "); memcpy(key_ptr, str, 80); } return headpos; } /****** fitsfind ************************************************************** PROTO int fitsfind(char *fitsbuf, char *keyword) PURPOSE Search for a FITS keyword in a FITS header. INPUT pointer to the FITS buffer, name of the keyword to search for. OUTPUT position in lines of 80 char (0=first) of the keyword if it was found, RETURN_ERROR otherwise. NOTES The buffer MUST contain the ``END '' keyword. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 15/02/96 ***/ int fitsfind(char *fitsbuf, char *keyword) { char *ptr; int i, len; len = strlen(keyword); for (i=0; strncmp(ptr=&fitsbuf[80*i], "END ", 8); i++) if (!wstrncmp(ptr, keyword, len)) return i; if (strncmp(keyword, "END ", 8)) return RETURN_ERROR; else return i; } /****** fitsnfind ************************************************************* PROTO char *fitsnfind(char *fitsbuf, char *str, int nblock) PURPOSE Search for a FITS keyword in a fits header of nblock blocks. INPUT pointer to the FITS buffer, name of the keyword to search for, number of FITS blocks (2880 bytes each). OUTPUT pointer at the keyword position if it was found, NULL otherwise. NOTES No need for an ``END '' keyword. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 25/04/97 ***/ char *fitsnfind(char *fitsbuf, char *str, int nblock) { int i; for (i=36*nblock;i--; fitsbuf+=80) if (!strncmp(fitsbuf, str, strlen(str))) return fitsbuf; return (char *)NULL; } /****** fitspick ************************************************************** PROTO int fitspick(char *fitsline, char *keyword, void *ptr, h_type *htype, t_type *ttype, char *comment) PURPOSE Pick up FITS keyword,content,type and comment in a fits header line. INPUT pointer to the current line of FITS buffer, pointer to a char * (where to put the keyword), pointer to ``where to put the data'', pointer to ``where to put the h_type'', pointer to ``where to put the t_type'', pointer to a char * (where to put the comment). OUTPUT RETURN_OK if something was found, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP), E.R. Deul - Handling of NaN VERSION 30/11/2012 ***/ int fitspick(char *fitsline, char *keyword, void *ptr, h_type *htype, t_type *ttype, char *comment) { char *fptr, *cptr, c, *lastspace; int i,j, toggle; *((char *)ptr) = 0; /*First, get the keyword*/ memcpy(keyword, fitsline, 8); keyword[8] = 0; /*Handle comments*/ if ((int)fitsline[8] != '=') { if (strncmp(keyword, "COMMENT ", 8) && strncmp(keyword, "HISTORY ", 8) && strncmp(keyword, "HIERARCH", 8) && strncmp(keyword, " ", 8)) return RETURN_ERROR; fptr = fitsline+9; lastspace = NULL; for(i=71; i-- && (c=*(fptr++));) if ((int)c >= ' ') { *(comment++) = c; if (c > ' ') lastspace = comment; } if (lastspace) *lastspace = '\0'; else *comment = '\0'; *htype = H_COMMENT; *ttype = T_STRING; return RETURN_OK; } for (j=10; j<80 && fitsline[j] == (char)' '; j++); if (j==80 || fitsline[j] == '/') { *htype = H_COMMENT; *ttype = T_STRING; return RETURN_ERROR; } if ((int)fitsline[j] == '\'') { cptr = ptr; for (fptr = fitsline + (i=j+1); i<80; i++) { if (*fptr==(char)'\'') { if (i++>=79 || *(fptr+1)!=(char)'\'') break; else fptr++; } *cptr++ = *fptr++; } *cptr = 0; /*-- Check if there is a trailing space */ *htype = (cptr != ptr && *(cptr-1)==' ') ? H_STRINGS: H_STRING; *ttype = T_STRING; } else if (fitsline[j] == (char)'T' || fitsline[j] == (char)'F') { *((BYTE *)ptr) = fitsline[j]==(char)'T'?1:0; *htype = H_BOOL; *ttype = T_BYTE; } else if (!strncmp(fitsline+j, "NaN", 3)) { *((double *)ptr) = BIG; *htype = H_EXPO; *ttype = T_DOUBLE; } else { for (i=j; i<80 && fitsline[i]!=(char)'/' && fitsline[i]!=(char)'.'; i++); /*-- Handle floats*/ if (i==80 || fitsline[i]!=(char)'.') /*---- Handle ints*/ { *((int *)ptr) = atoi(fitsline+j); *htype = H_INT; *ttype = T_LONG; } else { fixexponent(fitsline); *((double *)ptr) = atof(fitsline+j); *htype = H_EXPO; *ttype = T_DOUBLE; } } /*Store comment if it is found*/ toggle = 0; lastspace = NULL; for (fptr = fitsline + (i=j); i<80; i++) { if (*fptr == (char)'\'') toggle ^= 1; if (*(fptr++) == (char)'/' && !toggle) { while (++i<80 && *fptr<=' ') fptr++; i--; while (++i<80) if ((c=*(fptr++))>= ' ') { *(comment++) = c; if (c>' ') lastspace = comment; } } } if (lastspace) *lastspace = '\0'; else *comment = '\0'; return RETURN_OK; } /****** fitsread ************************************************************** PROTO int fitsread(char *fitsbuf, char *keyword, void *ptr, h_type htype, t_type ttype) PURPOSE Read a FITS keyword in a fits header. INPUT pointer to the FITS buffer, name of the keyword to be read, pointer where to put the read data, h_type of the data to be read (see fitscat.h), t_type of the data to be read (see fitscat.h). OUTPUT RETURN_OK if the keyword was found, RETURN_ERROR otherwise. NOTES The buffer MUST contain the ``END '' keyword. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 13/06/2012 ***/ int fitsread(char *fitsbuf, char *keyword, void *ptr, h_type htype, t_type ttype) { int i,pos; char s[4], str[82]; char *st, *st2; if ((pos = fitsfind(fitsbuf, keyword)) < 0) return RETURN_ERROR; strncpy(str,fitsbuf+80*pos,80); str[80] = '\0'; switch(htype) { case H_INT: if (ttype == T_LONG) sscanf(str+10, " %d", (LONG *)ptr); else if (ttype == T_SHORT) sscanf(str+10, " %hd", (short *)ptr); #ifdef HAVE_LONG_LONG_INT else sscanf(str+10, " %lld", (SLONGLONG *)ptr); #endif break; case H_FLOAT: case H_EXPO: fixexponent(str); if (ttype == T_DOUBLE) sscanf(str+10, " %lf", (double *)ptr); else sscanf(str+10, " %f", (float *)ptr); break; case H_BOOL: sscanf(str+10, "%1s", s); if (ttype == T_BYTE) *(BYTE *)ptr = ((int)s[0] == 'T') ? 1 : 0; else if (ttype == T_SHORT) *(short *)ptr = ((int)s[0] == 'T') ? 1 : 0; else if (ttype == T_LONG) *(LONG *)ptr = ((int)s[0] == 'T') ? 1 : 0; #ifdef HAVE_LONG_LONG_INT else *(SLONGLONG *)ptr = ((int)s[0] == 'T') ? 1 : 0; #endif break; case H_STRING: st = ptr; st2= str+10; for (i=70; i-- && *(st2++)!=(char)'\'';); while (i-->0) { if (*st2 == '\'' && *(++st2) != '\'') break; *(st++) = *(st2++); } do { *(st--) = (char)'\0'; } while (st>(char *)ptr && (*st == (char)' ')); break; case H_STRINGS: st = ptr; st2= str+10; for (i=70; i-- && *(st2++)!=(char)'\'';); while (i-->0) { if (*st2 == '\'' && *(++st2) != '\'') break; *(st++) = *(st2++); } *st = (char)'\0'; break; case H_COMMENT: strcpy(ptr,str+9); break; case H_HCOMMENT: strcpy(ptr,str+33); break; default: error(EXIT_FAILURE, "*Internal Error*: Unknown FITS type in ", "fitsread()"); break; } return RETURN_OK; } /****** fitsremove ************************************************************ PROTO int fitsremove(char *fitsbuf, char *keyword) PURPOSE Remove one (or more) FITS keyword from a fits header. INPUT pointer to the FITS buffer, name of the keyword to be created. OUTPUT RETURN_OK if the keyword was found, RETURN_ERROR otherwise. NOTES '?' wildcard allowed; Don't remove the ``END'' keyword with this!!! AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 08/04/99 ***/ int fitsremove(char *fitsbuf, char *keyword) { char *cp1,*cp2; int endpos,pos, i,n; endpos = fitsfind(fitsbuf, "END "); for (n=0; (pos = fitsfind(fitsbuf, keyword))>=0; n++, endpos--) for (cp1=fitsbuf+80*(pos+1), cp2=fitsbuf+80*pos, i=80*(endpos - pos); i--;) *(cp2++) = *(cp1++); if (!n) return RETURN_ERROR; memset(fitsbuf+80*(endpos+1), ' ', 80*n); return RETURN_OK; } /****** fitswrite ************************************************************* PROTO int fitswrite(char *fitsbuf, char *keyword, void *ptr, h_type htype, t_type ttype) PURPOSE Write a FITS keyword in a fits header. INPUT pointer to the FITS buffer, name of the keyword to be written, pointer where to retrieve the data, h_type of the data to be written (see fitscat.h), t_type of the data to be written (see fitscat.h). OUTPUT RETURN_OK if the keyword was found, RETURN_ERROR otherwise. NOTES The buffer MUST contain the ``END '' keyword. The keyword must already exist in the buffer (use fitsadd()). AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 13/06/2012 ***/ int fitswrite(char *fitsbuf, char *keyword, void *ptr, h_type htype, t_type ttype) { int i, l, pos, posoff, flag; char str[81],str2[81]; char *cstr, *cstr1,*cstr2, c; /* Ignore HISTORY and COMMENTS */ if (findkey(keyword, (char *)histokeys, 12)!=RETURN_ERROR || (pos = fitsfind(fitsbuf, keyword)) < 0) return RETURN_ERROR; posoff = 10; fitsbuf += 80*pos; switch(htype) { case H_INT: if (ttype==T_LONG) sprintf(str, "%20d", *(int *)ptr); else if (ttype==T_SHORT) sprintf(str, "%20d", *(short *)ptr); #ifdef HAVE_LONG_LONG_INT else sprintf(str, "%20lld", *(SLONGLONG *)ptr); #endif break; case H_FLOAT: sprintf(str, " %16.8f", (ttype==T_DOUBLE)? *(double *)ptr: *(float *)ptr); break; case H_EXPO: sprintf(str, " %19.12E", (ttype==T_DOUBLE)? *(double *)ptr: *(float *)ptr); break; case H_BOOL: if ((ttype==T_SHORT)? *(short *)ptr : ((ttype==T_BYTE)? *(BYTE *)ptr : *(LONG *)ptr)) sprintf(str, " T"); else sprintf(str, " F"); break; case H_STRING: /* Handle the famous quote */ cstr1 = (char *)ptr; cstr2 = str2; for (i=0; i<80; i++) if (!(c=*(cstr2++) = *(cstr1++))) break; else if (c == '\'') { *(cstr2++) = '\''; i++; } if (strlen(str2)<=18) { sprintf(str, "'%-18.18s ", str2); cstr = str+18; i = 10; } else { sprintf(str, "'%-68.68s ", str2); cstr = str+68; i = 60; } for (; i-- && *cstr==(char)' '; cstr--); *(++cstr) = (char)'\''; if (i>9) *(++cstr) = 0; break; case H_STRINGS: /* Handle the famous quote */ cstr1 = (char *)ptr; cstr2 = str2; for (i=0; i<80; i++) if (!(c=*(cstr2++) = *(cstr1++))) break; else if (c == '\'') { *(cstr2++) = '\''; i++; } sprintf(str, "'%s'", str2); for (i+=2;i<20; i++) str[i]=' '; str[i] = '\0'; break; case H_COMMENT: sprintf(str, "%-70s", (char *)ptr); posoff = 9; break; /* Special case of ``half-comments'' */ case H_HCOMMENT: sprintf(str, " / %-47s", (char *)ptr); posoff = 30; break; default: error(EXIT_FAILURE, "*FATAL ERROR*: Unknown FITS type in ", "fitswrite()"); break; } /* Now the tricky problem of (former) comments */ flag=1; cstr = fitsbuf+10; for (i=71; --i; cstr++) { if (*cstr=='\'') flag ^= 1; else if (flag && *cstr=='/') break; } if (posoff==10 && i && (l=69-strlen(str))>0) { strncpy(str2, cstr, i); str2[i] = 0; strcat(str, " "); strncat(str, str2, l); } memset(fitsbuf+9, ' ', 71); fitsbuf += posoff; /* Finally copy the result to the right place (except the trailing zero) */ for (cstr = str; *cstr; *(fitsbuf++) = *(cstr++)); return RETURN_OK; } /****** fixexponent *********************************************************** PROTO void fixexponent(char *s) PURPOSE Replaces the FORTRAN 'D' exponent sign to 'E' in a FITS line, and filter out non-numerical characters INPUT FITS line OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 22/05/2009 ***/ void fixexponent(char *s) { int c,i; s += 9; for (i=71; (c=(int)*s) && c != '/' && i--; s++) if (c == 'D' || c == 'd') *s = (char)'E'; else if ((c<'0' || c>'9') && c != '+' && c != '-' && c != 'e' && c != 'E' && c != '.') *s = ' '; return; } swarp-2.41.5/src/fits/fitswrite.c000066400000000000000000000360361400430667300166720ustar00rootroot00000000000000/* * fitswrite.c * * Low-level functions for writing LDAC FITS catalogs. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic FITS/LDAC library * * Copyright: (C) 1995-2020 IAP/CNRS/SorbonneU * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 26/08/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "fitscat_defs.h" #include "fitscat.h" /****** save_cat ************************************************************** PROTO void save_cat(catstruct *cat, char *filename) PURPOSE Save a FITS catalog with name filename. INPUT catalog structure, filename. OUTPUT -. NOTES Any preexisting file with name filename is overwritten. AUTHOR E. Bertin (IAP) VERSION 09/09/2003 ***/ void save_cat(catstruct *cat, char *filename) { tabstruct *tab; int i; strcpy(cat->filename, filename); if (open_cat(cat, WRITE_ONLY) != RETURN_OK) error(EXIT_FAILURE, "*Error*: cannot open for writing ", filename); tab = cat->tab; /*Go through each segment in the right order to save data*/ for (i=0; intab; i++) { /*-- Make sure that the tab header is primary or extension! */ if (i) ext_head(tab); else prim_head(tab); save_tab(cat, tab); while (!((tab=tab->nexttab)->nseg)); } if (close_cat(cat) != RETURN_OK) error(EXIT_FAILURE, "*Error*: Problem while closing", cat->filename); return; } /****** save_tab ************************************************************** PROTO void save_tab(catstruct *cat, tabstruct *tab) PURPOSE Save a FITS table. INPUT pointer to the catalog structure, pointer to the table structure. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 11/02/2020 ***/ void save_tab(catstruct *cat, tabstruct *tab) { catstruct *tabcat; keystruct *key; tabstruct *keytab; KINGSIZE_T tabsize; long size; char *buf, *inbuf, *outbuf, *fptr,*ptr; unsigned short ashort = 1; int b,j,k,o, nbytes,nkey,nobj,spoonful, tabflag, larrayin,larrayout, esize, bswapflag; bswapflag = *((char *)&ashort); // Byte-swapping flag /* The header itself*/ tabflag = save_head(cat, tab)==RETURN_OK?1:0; /* Allocate memory for the output buffer */ tabsize = 0; tabcat = NULL; /* to satisfy gcc -Wall */ inbuf = NULL; /* to satisfy gcc -Wall */ if (tabflag) { /*-- If segment is a binary table, save it row by row */ QMALLOC(outbuf, char, (larrayout = tab->naxisn[0])); nkey = tab->nkey; tabsize = larrayin = 0; for (j=tab->nseg; j--;) { update_tab(tab); /*---- Scan keys to find the reference tab and other things*/ keytab = NULL; key = tab->key; for (k=nkey; k--; key = key->nextkey) if (!key->ptr) { keytab = key->tab; tabcat = keytab->cat; } /*---- If table contains some keys with no ptrs, we have to access a file */ if (keytab) { QMALLOC(inbuf, char, (larrayin = keytab->naxisn[0])); if (open_cat(tabcat, READ_ONLY) != RETURN_OK) error(EXIT_FAILURE, "*Error*: Cannot access ", tabcat->filename); QFSEEK(tabcat->file, keytab->bodypos, SEEK_SET, tabcat->filename); } nobj = tab->naxisn[1]; for (o=0; ofile, tabcat->filename); fptr = outbuf; for (k=nkey; k--; key = key->nextkey) { nbytes = key->nbytes; ptr = key->ptr? (char *)key->ptr+nbytes*o:inbuf+key->pos; for (b=nbytes; b--;) *(fptr++) = *(ptr++); if (bswapflag) if (key->ptr) { esize = t_size[key->ttype]; swapbytes(fptr-nbytes, esize, nbytes/esize); } } QFWRITE(outbuf, larrayout, cat->file, cat->filename); } if (keytab) { free(inbuf); if (close_cat(tabcat) != RETURN_OK) error(EXIT_FAILURE, "*Error*: Problem while closing", tabcat->filename); } tabsize += tab->tabsize; tab = tab->nexttab; } free(outbuf); } else { /*-- If segment is not a binary table, save it ``as it is'' */ /*-- We use a limited-size buffer ``in case of'' */ size = tabsize = tab->tabsize; if (tabsize) { if (tab->bodybuf) { /*------ A body is present in memory and needs to be written */ if (bswapflag) swapbytes(tab->bodybuf, tab->bytepix, tabsize/tab->bytepix); QFWRITE(tab->bodybuf, (size_t)tabsize, cat->file, cat->filename); if (bswapflag) swapbytes(tab->bodybuf, tab->bytepix, tabsize/tab->bytepix); } else /*------ The body should be copied from the source tab */ { tabcat = tab->cat; spoonful = sizefilename); QFSEEK(tabcat->file, tab->bodypos, SEEK_SET, tabcat->filename); for (;size>0; size -= spoonful) { if (spoonful>size) spoonful = size; QFREAD(buf, spoonful, tabcat->file, tabcat->filename); QFWRITE(buf, spoonful, cat->file, cat->filename); } free(buf); if (close_cat(tabcat) != RETURN_OK) error(EXIT_FAILURE, "*Error*: Problem while closing", tabcat->filename); } } } /* FITS padding*/ pad_tab(cat, tabsize); return; } /****** save_head ************************************************************* PROTO int save_head(catstruct *cat, tabstruct *tab) PURPOSE Save a FITS table header. INPUT catalog structure, table structure. OUTPUT RETURN_OK if tab is a binary table, or RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 16/12/2004 ***/ int save_head(catstruct *cat, tabstruct *tab) { int tabflag; /* Make the table parameters reflect its content*/ update_tab(tab); /* The header itself*/ tabflag = update_head(tab); QFTELL(cat->file, tab->headpos, cat->filename); QFWRITE(tab->headbuf, tab->headnblock*FBSIZE, cat->file, cat->filename); return tabflag; } /******* pad_tab ************************************************************* PROTO int pad_tab(catstruct *cat, KINGSIZE_T size) PURPOSE Pad the FITS body of a tab with 0's to FBSIZE. INPUT A pointer to the cat structure, the number of elements that have been written. OUTPUT RETURN_OK if padding necessary, RETURN_ERROR otherwise. NOTES . AUTHOR E. Bertin (IAP) VERSION 23/01/2003 ***/ int pad_tab(catstruct *cat, KINGSIZE_T size) { static char padbuf[FBSIZE]; int padsize; padsize = PADEXTRA(size); if (padsize) { QFWRITE(padbuf, padsize, cat->file, cat->filename); return RETURN_OK; } else return RETURN_ERROR; } /****** init_writeobj ********************************************************* PROTO void init_writeobj(catstruct *cat, tabstruct *tab, char **pbuf) PURPOSE Prepare the writing of individual sources in a FITS table INPUT catalog structure, table structure, pointer to an array pointer to be used as a temporary buffer. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 02/11/2009 ***/ void init_writeobj(catstruct *cat, tabstruct *tab, char **pbuf) { keystruct *key; int k; /* The header itself */ if (save_head(cat, tab) != RETURN_OK) error(EXIT_FAILURE, "*Error*: Not a binary table: ", tab->extname); /* Store the current position */ QFTELL(cat->file, tab->bodypos, cat->filename); /* Allocate memory for the output buffer */ QMALLOC(*pbuf, char, tab->naxisn[0]); /* Scan keys to check that memory has been allocated */ key = tab->key; for (k=tab->nkey; k--; key = key->nextkey) if (!key->ptr) error(EXIT_FAILURE, "*Error*: no memory allocated for ", key->name); /* No object written yet: initialize counter */ tab->naxisn[1] = 0; return; } /****** write_obj ************************************************************* PROTO int write_obj(tabstruct *tab, char *buf) PURPOSE Write one individual source in a FITS table INPUT Table structure, pointer to the temporary buffer. OUTPUT -. NOTES key content is destroyed (actually, byte-swapped) on output. AUTHOR E. Bertin (IAP) VERSION 11/02/2020 ***/ int write_obj(tabstruct *tab, char *buf) { catstruct *cat; keystruct *key; char *pin, *pout, *pout2; unsigned short ashort = 1; int b, k, esize, bswapflag; bswapflag = *((char *)&ashort); // Byte-swapping flag key = tab->key; cat = tab->cat; pout = buf; for (k=tab->nkey; k--; key = key->nextkey) { pin = key->ptr; pout2 = pout; for (b=key->nbytes; b--;) *(pout++) = *(pin++); if (bswapflag) { esize = t_size[key->ttype]; swapbytes(pout2, esize, key->nbytes/esize); } } QFWRITE(buf, *tab->naxisn, cat->file, cat->filename); return ++tab->naxisn[1]; } /****** end_writeobj ********************************************************** PROTO void end_writeobj(catstruct *cat, tabstruct *tab, char *buf) PURPOSE End the writing of individual sources in a FITS table INPUT catalog structure, table structure, pointer to the temporary buffer. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 03/12/2019 ***/ void end_writeobj(catstruct *cat, tabstruct *tab, char *buf) { keystruct *key; OFF_T2 pos; int k; /* Make the table parameters reflect its content*/ key = tab->key; for (k=tab->nkey; k--; key = key->nextkey) key->nobj = tab->naxisn[1]; update_tab(tab); /* The header itself */ if (update_head(tab) != RETURN_OK) error(EXIT_FAILURE, "*Error*: Not a binary table: ", tab->extname); /*--FITS padding*/ pad_tab(cat, tab->tabsize); pos = ftell(cat->file); QFTELL(cat->file, pos, cat->filename); QFSEEK(cat->file, tab->headpos, SEEK_SET, cat->filename); QFWRITE(tab->headbuf, FBSIZE*tab->headnblock, cat->file, cat->filename); QFSEEK(cat->file, pos, SEEK_SET, cat->filename); free(buf); return; } /****** print_obj ************************************************************* PROTO void print_obj(FILE *stream, tabstruct *tab) PURPOSE Print one individual source to the output stream. INPUT Output stream Table structure. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP & Leiden observatory) VERSION 13/06/2012 ***/ void print_obj(FILE *stream, tabstruct *tab) { keystruct *key; char *ptr; int i,k, esize; if (!(key = tab->key)) error(EXIT_FAILURE, "*Error*: no key to print in table ", tab->extname); for (k=tab->nkey; k--; key = key->nextkey) { esize = t_size[key->ttype]; ptr = key->ptr; for (i = key->nbytes/esize; i--; ptr += esize) switch(key->ttype) { case T_FLOAT: fprintf(stream, *key->printf?key->printf:"%g", *(float *)ptr); if (i) putc(' ', stream); break; case T_DOUBLE: fprintf(stream, *key->printf?key->printf:"%f", *(double *)ptr); if (i) putc(' ', stream); break; case T_SHORT: fprintf(stream, *key->printf?key->printf:"%d", *(short *)ptr); if (i) putc(' ', stream); break; case T_LONG: fprintf(stream, *key->printf?key->printf:"%d", *(int *)ptr); if (i) putc(' ', stream); break; case T_LONGLONG: fprintf(stream, *key->printf?key->printf:"%lld", *(SLONGLONG *)ptr); if (i) putc(' ', stream); break; case T_BYTE: if (key->htype==H_BOOL) { if (*ptr) fprintf(stream, "T"); else fprintf(stream, "F"); } else fprintf(stream, key->printf?key->printf:"%d", (int)*ptr); if (i) putc(' ', stream); break; case T_STRING: fprintf(stream, "%c", (int)*ptr); break; default: error(EXIT_FAILURE, "*FATAL ERROR*: Unknown FITS type in ", "print_obj()"); } if (k) putc(' ', stream); } putc('\n', stream); return; } /****** voprint_obj *********************************************************** PROTO void voprint_obj(FILE *stream, tabstruct *tab) PURPOSE Print one individual source to the output stream in VOTable format INPUT Output stream Table structure. OUTPUT -. NOTES -. AUTHOR G. Tissier & E.Bertin (IAP) VERSION 13/06/2012 ***/ void voprint_obj(FILE *stream, tabstruct *tab) { keystruct *key; char *ptr; int i,k, esize; if (!(key = tab->key)) error(EXIT_FAILURE, "*Error*: no key to print in table ", tab->extname); fprintf(stream, " "); for (k=tab->nkey; k--; key = key->nextkey) { fprintf(stream, ""); esize = t_size[key->ttype]; ptr = key->ptr; for (i = key->nbytes/esize; i--; ptr += esize) switch(key->ttype) { case T_FLOAT: fprintf(stream, *key->printf?key->printf:"%g", *(float *)ptr); if (i) putc(' ', stream); break; case T_DOUBLE: fprintf(stream, *key->printf?key->printf:"%f", *(double *)ptr); if (i) putc(' ', stream); break; case T_SHORT: fprintf(stream, *key->printf?key->printf:"%d", *(short *)ptr); if (i) putc(' ', stream); break; case T_LONG: fprintf(stream, *key->printf?key->printf:"%d", *(int *)ptr); if (i) putc(' ', stream); break; case T_LONGLONG: fprintf(stream, *key->printf?key->printf:"%lld", *(SLONGLONG *)ptr); if (i) putc(' ', stream); break; case T_BYTE: if (key->htype==H_BOOL) { if (*ptr) fprintf(stream, "T"); else fprintf(stream, "F"); } else fprintf(stream, key->printf?key->printf:"%d", (int)*ptr); if (i) putc(' ', stream); break; case T_STRING: fprintf(stream, "%c", (int)*ptr); break; default: error(EXIT_FAILURE, "*FATAL ERROR*: Unknown FITS type in ", "voprint_obj()"); } fprintf(stream, ""); } fprintf(stream, "\n"); return; } swarp-2.41.5/src/fitswcs.c000066400000000000000000001721221400430667300153640ustar00rootroot00000000000000/* * fitswcs.c * * Manage World Coordinate System data. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic software * * Copyright: (C) 1993-2019 IAP/CNRS/SorbonneU * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 20/12/2019 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include #include #include #include "fits/fitscat_defs.h" #include "fits/fitscat.h" #include "fitswcs.h" #include "wcscelsys.h" #include "wcs/wcs.h" #include "wcs/lin.h" #include "wcs/tnx.h" #include "wcs/poly.h" /******* copy_wcs ************************************************************ PROTO wcsstruct *copy_wcs(wcsstruct *wcsin) PURPOSE Copy a WCS (World Coordinate System) structure. INPUT WCS structure to be copied. OUTPUT pointer to a copy of the input structure. NOTES Actually, only FITS parameters are copied. Lower-level structures such as those created by the WCS or TNX libraries are generated. AUTHOR E. Bertin (IAP) VERSION 06/12/2019 ***/ wcsstruct *copy_wcs(wcsstruct *wcsin) { wcsstruct *wcs; /* Copy the basic stuff */ QMEMCPY(wcsin, wcs, wcsstruct, 1); /* The PROJP WCS parameters */ QMEMCPY(wcsin->projp, wcs->projp, double, wcs->naxis*100); /* Set other structure pointers to NULL (they'll have to be reallocated) */ wcs->wcsprm = NULL; wcs->lin = NULL; wcs->cel = NULL; wcs->prj = NULL; wcs->tnx_lngcor = copy_tnxaxis(wcsin->tnx_lngcor); wcs->tnx_latcor = copy_tnxaxis(wcsin->tnx_latcor); wcs->inv_x = wcs->inv_y = NULL; QCALLOC(wcs->wcsprm, struct wcsprm, 1); /* Test if the WCS is recognized and a celestial pair is found */ wcsset(wcs->naxis,(const char(*)[9])wcs->ctype, wcs->wcsprm); /* Initialize other WCS structures */ init_wcs(wcs); /* Copy possible invert projection corrections */ if (wcsin->inv_x) wcs->inv_x = wcs->prj->inv_x = poly_copy(wcsin->inv_x); if (wcsin->inv_y) wcs->inv_y = wcs->prj->inv_y = poly_copy(wcsin->inv_y); /* Find the range of coordinates */ range_wcs(wcs); return wcs; } /******* create_wcs *********************************************************** PROTO wcsstruct *create_wcs(char **ctype, double *crval, double *crpix, double *cdelt, int *naxisn, int naxis) PURPOSE Generate a simple WCS (World Coordinate System) structure. INPUT Pointer to an array of char strings with WCS projection on each axis, pointer to an array of center coordinates (double), pointer to an array of device coordinates (double), pointer to an array of pixel scales (double), pointer to an array of image dimensions (int), number of dimensions. OUTPUT pointer to a WCS structure. NOTES If a pointer is set to null, the corresponding variables are set to default values. AUTHOR E. Bertin (IAP) VERSION 09/08/2006 ***/ wcsstruct *create_wcs(char **ctype, double *crval, double *crpix, double *cdelt, int *naxisn, int naxis) { wcsstruct *wcs; int l; QCALLOC(wcs, wcsstruct, 1); wcs->naxis = naxis; QCALLOC(wcs->projp, double, naxis*100); wcs->nprojp = 0; wcs->longpole = wcs->latpole = 999.0; for (l=0; lnaxisn[l] = naxisn? naxisn[l] : 360.0; /*-- The default WCS projection system is an all-sky Aitoff projection */ if (ctype) strncpy(wcs->ctype[l], ctype[l], 8); else if (l==0) strncpy(wcs->ctype[l], "RA---AIT", 8); else if (l==1) strncpy(wcs->ctype[l], "DEC--AIT", 8); wcs->crval[l] = crval? crval[l]: 0.0; wcs->crpix[l] = crpix? crpix[l]: 0.0; wcs->cdelt[l] = 1.0; wcs->cd[l*(naxis+1)] = cdelt? cdelt[l] : 1.0; } wcs->epoch = wcs->equinox = 2000.0; QCALLOC(wcs->wcsprm, struct wcsprm, 1); /* Test if the WCS is recognized and a celestial pair is found */ wcsset(wcs->naxis,(const char(*)[9])wcs->ctype, wcs->wcsprm); /* Initialize other WCS structures */ init_wcs(wcs); /* Invert projection corrections */ invert_wcs(wcs); /* Find the range of coordinates */ range_wcs(wcs); return wcs; } /******* init_wcs ************************************************************ PROTO void init_wcs(wcsstruct *wcs) PURPOSE Initialize astrometry and WCS (World Coordinate System) structures. INPUT WCS structure. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 17/05/2007 ***/ void init_wcs(wcsstruct *wcs) { int l,n,lng,lat,naxis; naxis = wcs->naxis; if (wcs->lin) { free(wcs->lin->cdelt); free(wcs->lin->crpix); free(wcs->lin->pc); free(wcs->lin->piximg); free(wcs->lin->imgpix); free(wcs->lin); } QCALLOC(wcs->lin, struct linprm, 1); QCALLOC(wcs->lin->cdelt, double, naxis); QCALLOC(wcs->lin->crpix, double, naxis); QCALLOC(wcs->lin->pc, double, naxis*naxis); if (wcs->cel) free(wcs->cel); QCALLOC(wcs->cel, struct celprm, 1); if (wcs->prj) free(wcs->prj); QCALLOC(wcs->prj, struct prjprm, 1); 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; } /* Set WCS flags to 0: structures will be reinitialized by the WCS library */ wcs->lin->flag = wcs->cel->flag = wcs->prj->flag = 0; wcs->lin->naxis = naxis; /* wcsprm structure */ lng = wcs->lng = wcs->wcsprm->lng; lat = wcs->lat = wcs->wcsprm->lat; /* linprm structure */ for (l=0; llin->crpix[l] = wcs->crpix[l]; wcs->lin->cdelt[l] = 1.0; } for (l=0; llin->pc[l] = wcs->cd[l]; /* celprm structure */ if (lng>=0) { wcs->cel->ref[0] = wcs->crval[lng]; wcs->cel->ref[1] = wcs->crval[lat]; } else { wcs->cel->ref[0] = wcs->crval[0]; wcs->cel->ref[1] = wcs->crval[1]; } wcs->cel->ref[2] = wcs->longpole; wcs->cel->ref[3] = wcs->latpole; /* prjprm structure */ wcs->prj->r0 = wcs->r0; wcs->prj->tnx_lngcor = wcs->tnx_lngcor; wcs->prj->tnx_latcor = wcs->tnx_latcor; if (lng>=0) { n = 0; for (l=100; l--;) { wcs->prj->p[l] = wcs->projp[l+lat*100]; /* lat comes first for ... */ wcs->prj->p[l+100] = wcs->projp[l+lng*100];/* ... compatibility reasons */ if (!n && (wcs->prj->p[l] || wcs->prj->p[l+100])) n = l+1; } wcs->nprojp = n; } /* Check-out chirality */ wcs->chirality = wcs_chirality(wcs); /* Initialize Equatorial <=> Celestial coordinate system transforms */ init_wcscelsys(wcs); return; } /******* init_wcscelsys ******************************************************* PROTO void init_wcscelsys(wcsstruct *wcs) PURPOSE Initialize Equatorial <=> Celestial coordinate system transforms. INPUT WCS structure. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 18/07/2006 ***/ void init_wcscelsys(wcsstruct *wcs) { double *mat, a0,d0,ap,dp,ap2,y; int s,lng,lat; lng = wcs->wcsprm->lng; lat = wcs->wcsprm->lat; /* Is it a celestial system? If not, exit! */ if (lng==lat) { wcs->celsysconvflag = 0; return; } /* Find the celestial system */ for (s=0; *celsysname[s][0] && strncmp(wcs->ctype[lng], celsysname[s][0], 4); s++); /* Is it a known, non-equatorial system? If not, exit! */ if (!s || !*celsysname[s][0]) { wcs->celsysconvflag = 0; return; } wcs->celsys = (celsysenum)s; /* Some shortcuts */ a0 = celsysorig[s][0]*DEG; d0 = celsysorig[s][1]*DEG; ap = celsyspole[s][0]*DEG; dp = celsyspole[s][1]*DEG; /* First compute in the output referential the longitude of the south pole */ y = sin(ap - a0); /* x = cos(d0)*(cos(d0)*sin(dp)*cos(ap-a0)-sin(d0)*cos(dp)); ap2 = atan2(y,x); */ ap2 = asin(cos(d0)*y) ; /* Equatorial <=> Celestial System transformation parameters */ mat = wcs->celsysmat; mat[0] = ap; mat[1] = ap2; mat[2] = cos(dp); mat[3] = sin(dp); wcs->celsysconvflag = 1; return; } /******* read_wcs ************************************************************* PROTO wcsstruct *read_wcs(tabstruct *tab) PURPOSE Read WCS (World Coordinate System) info in the FITS header. INPUT tab structure. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 04/05/2018 ***/ wcsstruct *read_wcs(tabstruct *tab) { #define FITSREADF(buf, k, val, def) \ {if (fitsread(buf,k, &val, H_FLOAT,T_DOUBLE) != RETURN_OK) \ val = def; \ } #define FITSREADI(buf, k, val, def) \ {if (fitsread(buf,k, &val, H_INT,T_LONG) != RETURN_OK) \ val = def; \ } #define FITSREADS(buf, k, str, def) \ {if (fitsread(buf,k,str, H_STRING,T_STRING) != RETURN_OK) \ strcpy(str, (def)); \ } char str[MAXCHARS]; char wstr1[TNX_MAXCHARS], wstr2[TNX_MAXCHARS]; wcsstruct *wcs; double drota; int j, l, naxis; char name[16], *buf, *filename; buf = tab->headbuf; filename = (tab->cat? tab->cat->filename : strcpy(name, "internal header")); FITSREADS(buf, "OBJECT ", str, "Unnamed"); QCALLOC(wcs, wcsstruct, 1); if (tab->naxis > NAXIS) { warning("Maximum number of dimensions supported by this version of the ", "software exceeded\n"); tab->naxis = 2; } wcs->naxis = naxis = tab->naxis; QCALLOC(wcs->projp, double, naxis*100); for (l=0; lnaxisn[l] = tab->naxisn[l]; sprintf(str, "CTYPE%-3d", l+1); FITSREADS(buf, str, str, ""); strncpy(wcs->ctype[l], str, 8); sprintf(str, "CUNIT%-3d", l+1); FITSREADS(buf, str, str, "deg"); strncpy(wcs->cunit[l], str, 32); sprintf(str, "CRVAL%-3d", l+1); FITSREADF(buf, str, wcs->crval[l], 0.0); sprintf(str, "CRPIX%-3d", l+1); FITSREADF(buf, str, wcs->crpix[l], 1.0); sprintf(str, "CDELT%-3d", l+1); FITSREADF(buf, str, wcs->cdelt[l], 1.0); sprintf(str, "CRDER%-3d", l+1); FITSREADF(buf, str, wcs->crder[l], 0.0); sprintf(str, "CSYER%-3d", l+1); FITSREADF(buf, str, wcs->csyer[l], 0.0); if (fabs(wcs->cdelt[l]) < 1e-30) error(EXIT_FAILURE, "*Error*: CDELT parameters out of range in ", filename); } if (fitsfind(buf, "CD?_????")!=RETURN_ERROR) { /*-- If CD keywords exist, use them for the linear mapping terms... */ for (l=0; lcd[l*naxis+j], l==j?1.0:0.0) } } else if (fitsfind(buf, "PC?_????")!=RETURN_ERROR) /*-- ...If PC keywords exist, use them for the linear mapping terms... */ for (l=0; lcd[l*naxis+j], l==j?1.0:0.0) wcs->cd[l*naxis+j] *= wcs->cdelt[l]; } else if (fitsfind(buf, "PC0??0??")!=RETURN_ERROR) /*-- ...If PC keywords exist, use them for the linear mapping terms... */ for (l=0; lcd[l*naxis+j], l==j?1.0:0.0) wcs->cd[l*naxis+j] *= wcs->cdelt[l]; } else { /*-- ...otherwise take the obsolete CROTA2 parameter */ FITSREADF(buf, "CROTA2 ", drota, 0.0) wcs->cd[3] = wcs->cd[0] = cos(drota*DEG); wcs->cd[1] = -(wcs->cd[2] = sin(drota*DEG)); wcs->cd[0] *= wcs->cdelt[0]; wcs->cd[2] *= wcs->cdelt[0]; wcs->cd[1] *= wcs->cdelt[1]; wcs->cd[3] *= wcs->cdelt[1]; } QCALLOC(wcs->wcsprm, struct wcsprm, 1); /* Test if the WCS is recognized and a celestial pair is found */ if (!wcsset(wcs->naxis,(const char(*)[9])wcs->ctype, wcs->wcsprm) && wcs->wcsprm->flag<999) { char *pstr; double date; /*-- Coordinate reference frame */ /*-- Search for an observation start date expressed in Julian days */ FITSREADF(buf, "MJD-OBS ", date, -1.0); if (date<0.0) FITSREADF(buf, "MJDSTART", date, -1.0); /*-- in Julian years from 2000.0 */ if (date>0.0) wcs->obsdate = 2000.0 - (MJD2000 - date)/365.25; else { /*---- Search for an observation start date expressed in "civilian" format */ FITSREADS(buf, "DATE-OBS", str, ""); wcs->obsdate = 0.0; if (*str && str_to_date_wcs(str, &wcs->obsdate) != RETURN_OK) warning("Invalid DATE-OBS value in header: ", str); } /*-- Search for an observation end date expressed in Julian days */ FITSREADF(buf, "MJD-END ", date, -1.0); if (date<0.0) FITSREADF(buf, "MJDSTOP ", date, -1.0); /*-- in Julian years from 2000.0 */ if (date>0.0) wcs->obsend = 2000.0 - (MJD2000 - date)/365.25; else { wcs->obsend = 0.0; /*---- Search for an observation start date expressed in "civilian" format */ FITSREADS(buf, "DATE-END", str, ""); if (*str && str_to_date_wcs(str, &wcs->obsend) != RETURN_OK) warning("Invalid DATE-END value in header: ", str); } FITSREADF(buf, "EPOCH", wcs->epoch, 2000.0); FITSREADF(buf, "EQUINOX", wcs->equinox, wcs->epoch); if (fitsread(buf, "RADESYS", str, H_STRING,T_STRING) != RETURN_OK) FITSREADS(buf, "RADECSYS", str, wcs->equinox >= 2000.0? "ICRS" : (wcs->equinox<1984.0? "FK4" : "FK5")); if (!strcmp(str, "ICRS")) wcs->radecsys = RDSYS_ICRS; else if (!strcmp(str, "FK5")) wcs->radecsys = RDSYS_FK5; else if (!strcmp(str, "FK4")) { if (wcs->equinox == 2000.0) { FITSREADF(buf, "EPOCH ", wcs->equinox, 1950.0); FITSREADF(buf, "EQUINOX", wcs->equinox, wcs->equinox); } wcs->radecsys = RDSYS_FK4; warning("FK4 precession formulae not yet implemented:\n", " Astrometry may be slightly inaccurate"); } else if (!strcmp(str, "FK4-NO-E")) { if (wcs->equinox == 2000.0) { FITSREADF(buf, "EPOCH", wcs->equinox, 1950.0); FITSREADF(buf, "EQUINOX", wcs->equinox, wcs->equinox); } wcs->radecsys = RDSYS_FK4_NO_E; warning("FK4 precession formulae not yet implemented:\n", " Astrometry may be slightly inaccurate"); } else if (!strcmp(str, "GAPPT")) { wcs->radecsys = RDSYS_GAPPT; warning("GAPPT reference frame not yet implemented:\n", " Astrometry may be slightly inaccurate"); } else { warning("Using ICRS instead of unknown astrometric reference frame: ", str); wcs->radecsys = RDSYS_ICRS; } /*-- Projection parameters */ if (!strcmp(wcs->wcsprm->pcode, "TNX")) { /*---- IRAF's TNX projection: decode these #$!?@#!! WAT parameters */ if (fitsfind(buf, "WAT?????") != RETURN_ERROR) { /*------ First we need to concatenate strings */ pstr = wstr1; sprintf(str, "WAT1_001"); for (j=2; fitsread(buf,str,pstr,H_STRINGS,T_STRING)==RETURN_OK; j++) { sprintf(str, "WAT1_%03d", j); pstr += strlen(pstr); } pstr = wstr2; sprintf(str, "WAT2_001"); for (j=2; fitsread(buf,str,pstr,H_STRINGS,T_STRING)==RETURN_OK; j++) { sprintf(str, "WAT2_%03d", j); pstr += strlen(pstr); } /*------ LONGPOLE defaulted to 180 deg if not found */ if ((pstr = strstr(wstr1, "longpole")) || (pstr = strstr(wstr2, "longpole"))) pstr = strpbrk(pstr, "1234567890-+."); wcs->longpole = pstr? atof(pstr) : 999.0; wcs->latpole = 999.0; /*------ RO defaulted to 180/PI if not found */ if ((pstr = strstr(wstr1, "ro")) || (pstr = strstr(wstr2, "ro"))) pstr = strpbrk(pstr, "1234567890-+."); wcs->r0 = pstr? atof(pstr) : 0.0; /*------ Read the remaining TNX parameters */ if ((pstr = strstr(wstr1, "lngcor")) || (pstr = strstr(wstr2, "lngcor"))) wcs->tnx_lngcor = read_tnxaxis(pstr); if (!wcs->tnx_lngcor) error(EXIT_FAILURE, "*Error*: incorrect TNX parameters in ", filename); if ((pstr = strstr(wstr1, "latcor")) || (pstr = strstr(wstr2, "latcor"))) wcs->tnx_latcor = read_tnxaxis(pstr); if (!wcs->tnx_latcor) error(EXIT_FAILURE, "*Error*: incorrect TNX parameters in ", filename); } } else { if (fitsread(buf, "LONPOLE",&wcs->longpole,H_FLOAT,T_DOUBLE) != RETURN_OK) FITSREADF(buf, "LONGPOLE", wcs->longpole, 999.0); FITSREADF(buf, "LATPOLE ", wcs->latpole, 999.0); /*---- Old convention */ if (fitsfind(buf, "PROJP???") != RETURN_ERROR) for (j=0; j<10; j++) { sprintf(str, "PROJP%-3d", j); FITSREADF(buf, str, wcs->projp[j], 0.0); } /*---- New convention */ if (fitsfind(buf, "PV?_????") != RETURN_ERROR) for (l=0; lprojp[j+l*100], 0.0); } } } /* Initialize other WCS structures */ init_wcs(wcs); /* Find the range of coordinates */ range_wcs(wcs); /* Invert projection corrections */ invert_wcs(wcs); #undef FITSREADF #undef FITSREADI #undef FITSREADS return wcs; } /******* write_wcs *********************************************************** PROTO void write_wcs(tabstruct *tab, wcsstruct *wcs) PURPOSE Write WCS (World Coordinate System) info in the FITS header. INPUT tab structure, WCS structure. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 20/12/2019 ***/ void write_wcs(tabstruct *tab, wcsstruct *wcs) { double mjd; char str[MAXCHARS]; int j, l, naxis; naxis = wcs->naxis; addkeywordto_head(tab, "BITPIX ", "Bits per pixel"); fitswrite(tab->headbuf, "BITPIX ", &tab->bitpix, H_INT, T_LONG); addkeywordto_head(tab, "NAXIS ", "Number of axes"); fitswrite(tab->headbuf, "NAXIS ", &wcs->naxis, H_INT, T_LONG); for (l=0; lheadbuf, str, &wcs->naxisn[l], H_INT, T_LONG); } addkeywordto_head(tab, "EQUINOX ", "Mean equinox"); fitswrite(tab->headbuf, "EQUINOX ", &wcs->equinox, H_FLOAT, T_DOUBLE); if (wcs->obsdate!=0.0) { mjd = (wcs->obsdate-2000.0)*365.25 + MJD2000; addkeywordto_head(tab, "MJD-OBS ", "Modified Julian date at start"); fitswrite(tab->headbuf, "MJD-OBS ", &mjd, H_FLOAT,T_DOUBLE); } if (wcs->obsend!=0.0) { mjd = (wcs->obsend-2000.0)*365.25 + MJD2000; addkeywordto_head(tab, "MJD-END ", "Modified Julian date at end"); fitswrite(tab->headbuf, "MJD-END ", &mjd, H_FLOAT,T_DOUBLE); } addkeywordto_head(tab, "RADESYS ", "Astrometric system"); switch(wcs->radecsys) { case RDSYS_ICRS: fitswrite(tab->headbuf, "RADESYS ", "ICRS", H_STRING, T_STRING); break; case RDSYS_FK5: fitswrite(tab->headbuf, "RADESYS ", "FK5", H_STRING, T_STRING); break; case RDSYS_FK4: fitswrite(tab->headbuf, "RADESYS ", "FK4", H_STRING, T_STRING); break; case RDSYS_FK4_NO_E: fitswrite(tab->headbuf, "RADESYS ", "FK4-NO-E", H_STRING, T_STRING); break; case RDSYS_GAPPT: fitswrite(tab->headbuf, "RADESYS ", "GAPPT", H_STRING, T_STRING); break; default: error(EXIT_FAILURE, "*Error*: unknown RADESYS type in write_wcs()", ""); } for (l=0; lheadbuf, str, wcs->ctype[l], H_STRING, T_STRING); sprintf(str, "CUNIT%-3d", l+1); addkeywordto_head(tab, str, "Axis unit"); fitswrite(tab->headbuf, str, wcs->cunit[l], H_STRING, T_STRING); sprintf(str, "CRVAL%-3d", l+1); addkeywordto_head(tab, str, "World coordinate on this axis"); fitswrite(tab->headbuf, str, &wcs->crval[l], H_EXPO, T_DOUBLE); sprintf(str, "CRPIX%-3d", l+1); addkeywordto_head(tab, str, "Reference pixel on this axis"); fitswrite(tab->headbuf, str, &wcs->crpix[l], H_EXPO, T_DOUBLE); for (j=0; jheadbuf, str, &wcs->cd[l*naxis+j], H_EXPO, T_DOUBLE); } for (j=0; j<100; j++) if (fabs(wcs->projp[j+100*l]) > TINY) { sprintf(str, "PV%d_%d", l+1, j); addkeywordto_head(tab, str, "Projection distortion parameter"); fitswrite(tab->headbuf, str, &wcs->projp[j+100*l], H_EXPO, T_DOUBLE); } } /* Update the tab data */ readbasic_head(tab); return; } /******* wipe_wcs *********************************************************** PROTO void wipe_wcs(tabstruct *tab) PURPOSE Remove all WCS (World Coordinate System) info in a FITS header. INPUT tab structure. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 27/11/2013 ***/ void wipe_wcs(tabstruct *tab) { removekeywordfrom_head(tab, "CRVAL???"); removekeywordfrom_head(tab, "CTYPE???"); removekeywordfrom_head(tab, "CUNIT???"); removekeywordfrom_head(tab, "CRPIX???"); removekeywordfrom_head(tab, "CRDER???"); removekeywordfrom_head(tab, "CSYER???"); removekeywordfrom_head(tab, "CDELT???"); removekeywordfrom_head(tab, "CROTA???"); removekeywordfrom_head(tab, "CD?_????"); removekeywordfrom_head(tab, "PROJP_??"); removekeywordfrom_head(tab, "PV?_????"); removekeywordfrom_head(tab, "PC?_????"); removekeywordfrom_head(tab, "PC0??0??"); removekeywordfrom_head(tab, "EQUINOX?"); removekeywordfrom_head(tab, "RADESYS?"); removekeywordfrom_head(tab, "RADECSYS"); removekeywordfrom_head(tab, "LONPOLE?"); removekeywordfrom_head(tab, "LONGPOLE"); removekeywordfrom_head(tab, "LATPOLE?"); removekeywordfrom_head(tab, "WAT?????"); return; } /******* end_wcs ************************************************************** PROTO void end_wcs(wcsstruct *wcs) PURPOSE Free WCS (World Coordinate System) infos. INPUT WCS structure. OUTPUT -. NOTES . AUTHOR E. Bertin (IAP) VERSION 24/05/2000 ***/ void end_wcs(wcsstruct *wcs) { if (wcs) { if (wcs->lin) { free(wcs->lin->cdelt); free(wcs->lin->crpix); free(wcs->lin->pc); free(wcs->lin->piximg); free(wcs->lin->imgpix); free(wcs->lin); } free(wcs->cel); free(wcs->prj); free(wcs->wcsprm); free_tnxaxis(wcs->tnx_lngcor); free_tnxaxis(wcs->tnx_latcor); poly_end(wcs->inv_x); poly_end(wcs->inv_y); free(wcs->projp); free(wcs); } return; } /******* wcs_supproj ********************************************************* PROTO int wcs_supproj(char *name) PURPOSE Tell if a projection system is supported or not. INPUT Proposed projection code name. OUTPUT RETURN_OK if projection is supported, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 14/06/2012 ***/ int wcs_supproj(char *name) { char projcode[28][5] = {"TAN", "TPV", "AZP", "SIN", "STG", "ARC", "ZPN", "ZEA", "AIR", "CYP", "CAR", "MER", "CEA", "COP", "COD", "COE", "COO", "BON", "PCO", "GLS", "PAR", "AIT", "MOL", "CSC", "QSC", "TSC", "TNX", "NONE"}; int i; for (i=0; i<28; i++) if (!strcmp(name, projcode[i])) return RETURN_OK; return RETURN_ERROR; } /******* 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/12/2019 ***/ void invert_wcs(wcsstruct *wcs) { polystruct *poly; double pixin[NAXIS],pixout[NAXIS], raw[NAXIS],rawmin[NAXIS]; double *outpos,*outpost, *lngpos,*lngpost, *latpos,*latpost, lngstep,latstep, rawsize, epsilon, errlng, errlat, maxerrlng, maxerrlat; int group[] = {1,1}; /* Don't ask, this is needed by poly_init()! */ int i,j,lng,lat,deg, tnxflag, maxflag, maxflagflag; /* Check first that inversion is not straightforward */ lng = wcs->wcsprm->lng; lat = wcs->wcsprm->lat; if (!strcmp(wcs->wcsprm->pcode, "TNX")) tnxflag = 1; else if ((!strcmp(wcs->wcsprm->pcode, "TAN") || !strcmp(wcs->wcsprm->pcode, "TPV")) && (wcs->projp[1+lng*100] || wcs->projp[1+lat*100])) tnxflag = 0; else return; /* Compute the error margin of the inversion in degrees */ for (i=0; inaxis; i++) raw[i] = (wcs->naxisn[i] + 1.0) / 2.0; epsilon = WCS_INVACCURACY * wcs_scale(wcs, raw); if (epsilon < TINY) error(EXIT_FAILURE, "*Error*: incorrect pixel scale for ", wcs->wcsprm->pcode); /* 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 */ lngstep = wcs->naxisn[lng]/(WCS_NGRIDPOINTS-1.0); latstep = wcs->naxisn[lat]/(WCS_NGRIDPOINTS-1.0); QMALLOC(outpos, double, 2*WCS_NGRIDPOINTS2); QMALLOC(lngpos, double, WCS_NGRIDPOINTS2); QMALLOC(latpos, double, WCS_NGRIDPOINTS2); for (i=0; inaxis; i++) raw[i] = rawmin[i] = 0.5; outpost = outpos; lngpost = lngpos; latpost = latpos; maxflag = 0; maxerrlng = maxerrlat = 0.0; 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)) error(EXIT_FAILURE, "*Error*: incorrect linear conversion in ", wcs->wcsprm->pcode); *(lngpost++) = pixin[lng]; *(latpost++) = pixin[lat]; if (tnxflag) { *(outpost++) = pixin[lng] +raw_to_tnxaxis(wcs->tnx_lngcor,pixin[lng],pixin[lat]); *(outpost++) = pixin[lat] +raw_to_tnxaxis(wcs->tnx_latcor,pixin[lng],pixin[lat]); } else { raw_to_pv(wcs->prj, pixin[lng],pixin[lat], outpost,outpost+1); pv_to_raw(wcs->prj, *outpost,*(outpost+1), &pixout[lng],&pixout[lat]); if ((errlng = fabs(pixout[lng] - pixin[lng])) > maxerrlng) maxerrlng = errlng; if ((errlat = fabs(pixout[lat] - pixin[lat])) > maxerrlat) maxerrlat = errlat; outpost += 2; } } } maxflag |= (maxerrlng > WCS_INVACCURACY || maxerrlat > WCS_INVACCURACY); /// Test if polynomial inversion is required if (maxflag) { /*-- Invert "longitude" */ /*-- 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, 1.0e-9/WCS_NGRIDPOINTS2); maxflag = 0; outpost = outpos; lngpost = lngpos; for (i=WCS_NGRIDPOINTS2; i--; outpost+=2) if (fabs(poly_func(poly, outpost)-*(lngpost++))>epsilon) { maxflag = 1; break; } } /*-- Now link the created structure */ wcs->prj->inv_x = wcs->inv_x = poly; maxflagflag = maxflag; /*-- Invert "latitude" */ /*-- 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, 1.0e-9/WCS_NGRIDPOINTS2); maxflag = 0; outpost = outpos; latpost = latpos; for (i=WCS_NGRIDPOINTS2; i--; outpost+=2) if (fabs(poly_func(poly, outpost)-*(latpost++))>epsilon) { maxflag = 1; break; } } /*-- Now link the created structure */ wcs->prj->inv_y = wcs->inv_y = poly; maxflagflag |= maxflag; if (maxflagflag) warning("Significant inaccuracy likely to occur in projection",""); } /* Free memory */ free(outpos); free(lngpos); free(latpos); return; } /******* range_wcs *********************************************************** PROTO void range_wcs(wcsstruct *wcs) PURPOSE Find roughly the range of WCS coordinates on all axes, and typical pixel scales. INPUT WCS structure. OUTPUT -. NOTES . AUTHOR E. Bertin (IAP) VERSION 24/08/2010 ***/ void range_wcs(wcsstruct *wcs) { double step[NAXIS], raw[NAXIS], rawmin[NAXIS], world[NAXIS], world2[NAXIS]; double *worldmin, *worldmax, *scale, *worldc, rad, radmax, lc; int linecount[NAXIS]; int i,j, naxis, npoints, lng,lat; naxis = wcs->naxis; /* World range */ npoints = 1; worldmin = wcs->wcsmin; worldmax = wcs->wcsmax; /* First, find the center and use it as a reference point for lng */ lng = wcs->lng; lat = wcs->lat; for (i=0; inaxisn[i]+1.0)/2.0; if (raw_to_wcs(wcs, raw, world)) { /*-- Oops no mapping there! So explore the image in an increasingly large */ /*-- domain to find a better "center" (now we know there must be angular */ /*-- coordinates) */ for (j=0; j<100; j++) { for (i=0; inaxisn[i]/100.0*(0.5-(double)rand()/RAND_MAX); if (!raw_to_wcs(wcs, raw, world)) break; } } if (lng!=lat) lc = world[lng]; else { lc = 0.0; /* to avoid gcc -Wall warnings */ lng = -1; } /* Pixel scales at image center */ scale = wcs->wcsscale; for (i=0; ipixscale = scale[i] = sqrt(wcs_scale(wcs, raw)); else { raw[i] += 1.0; raw_to_wcs(wcs, raw, world2); scale[i] = fabs(world2[i] - world[i]); raw[i] -= 1.0; if (lng==lat) wcs->pixscale = scale[i]; } wcs->wcsscalepos[i] = world[i]; } /* Find "World limits" */ for (i=0; inaxisn[i]/(WCS_NRANGEPOINTS-1.0); npoints *= WCS_NRANGEPOINTS; worldmax[i] = -(worldmin[i] = 1e31); linecount[i] = 0; } radmax = 0.0; worldc = wcs->wcsscalepos; for (j=npoints; j--;) { raw_to_wcs(wcs, raw, world); /*-- Compute maximum distance to center */ if ((rad=wcs_dist(wcs, world, worldc)) > radmax) radmax = rad; for (i=0; i180.0) world[i] -= 360.0; else if (world[i] <= -180.0) world[i] += 360.0; } if (world[i]worldmax[i]) worldmax[i] = world[i]; } for (i=0; iwcsmaxradius = radmax; if (lng!=lat) { worldmin[lng] = fmod_0_p360(worldmin[lng]+lc); worldmax[lng] = fmod_0_p360(worldmax[lng]+lc); if (worldmax[lat]<-90.0) worldmax[lat] = -90.0; if (worldmax[lat]>90.0) worldmax[lat] = 90.0; } return; } /******* frame_wcs *********************************************************** PROTO int frame_wcs(wcsstruct *wcsin, wcsstruct *wcsout) PURPOSE Find the x and y limits of an input frame in an output image. INPUT WCS structure of the input frame, WCS structure of the output frame. OUTPUT 1 if frames overlap, 0 otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 26/03/2012 ***/ int frame_wcs(wcsstruct *wcsin, wcsstruct *wcsout) { double rawin[NAXIS], rawout[NAXIS], world[NAXIS]; int linecount[NAXIS]; double worldc; int *min, *max, i,j, naxis, npoints, out, swapflag, overlapflag; naxis = wcsin->naxis; /* World range */ npoints = 1; min = wcsin->outmin; max = wcsin->outmax; for (i=0; ilng != wcsout->lng) || (wcsin->lat != wcsout->lat)) && (wcsin->lng != wcsin->lat) && (wcsout->lng != wcsout->lat)); for (j=npoints; j--;) { if (!raw_to_wcs(wcsin, rawin, world)) { if (swapflag) { worldc = world[wcsout->lat]; world[wcsout->lat] = world[wcsin->lat]; world[wcsin->lat] = worldc; } if (!wcs_to_raw(wcsout, world, rawout)) for (i=0; imax[i]) max[i] = out; } } for (i=0; inaxisn[i] *(1-cos(PI*(linecount[i]+1.0)/(WCS_NRANGEPOINTS-1))); if (++linecount[i]-2147483647) min[i] -= 2; if (max[i]>2147483647) max[i] += 2; } /* Check overlap */ overlapflag = 1; for (i=0; iwcsout->naxisn[i] || max[i]<0) { overlapflag = 0; break; } return overlapflag; } /******* reaxe_wcs *********************************************************** PROTO int reaxe_wcs(wcsstruct *wcs, int lng, int lat) PURPOSE Reformulate a wcs structure to match lng and lat axis indices INPUT WCS structure, longitude index, latitude index. OUTPUT RETURN_OK if successful, RETURN_ERROR otherwise. NOTES . AUTHOR E. Bertin (IAP) VERSION 20/11/2003 ***/ int reaxe_wcs(wcsstruct *wcs, int lng, int lat) { char strlng[80], strlat[80]; double dlng,dlat,dlng2,dlat2; int l, ilng,ilat,olng,olat, naxis; olng = wcs->lng; olat = wcs->lat; if (lng<0 || lat<0 || olng<0 || olat<0) return RETURN_ERROR; ilng = wcs->naxisn[olng]; ilat = wcs->naxisn[olat]; wcs->naxisn[lng] = ilng; wcs->naxisn[lat] = ilat; strcpy(strlng, wcs->ctype[olng]); strcpy(strlat, wcs->ctype[olat]); strcpy(wcs->ctype[lng], strlng); strcpy(wcs->ctype[lat], strlat); dlng = wcs->crval[olng]; dlat = wcs->crval[olat]; wcs->crval[lng] = dlng; wcs->crval[lat] = dlat; naxis = wcs->naxis; dlng = wcs->cd[olng+olng*naxis]; dlng2 = wcs->cd[olng+olat*naxis]; dlat = wcs->cd[olat+olat*naxis]; dlat2 = wcs->cd[olat+olng*naxis]; wcs->cd[lng+lng*naxis] = dlng2; wcs->cd[lng+lat*naxis] = dlng; wcs->cd[lat+lat*naxis] = dlat2; wcs->cd[lat+lng*naxis] = dlat; for (l=0; l<100; l++) { dlng = wcs->projp[l+olng*100]; dlat = wcs->projp[l+olat*100]; wcs->projp[l+lng*100] = dlng; wcs->projp[l+lat*100] = dlat; } /*-- Reinitialize wcs */ wcsset(wcs->naxis,(const char(*)[9])wcs->ctype, wcs->wcsprm); /*-- Initialize other WCS structures */ init_wcs(wcs); /*-- Find the range of coordinates */ range_wcs(wcs); return RETURN_OK; } /******* celsys_to_eq ********************************************************* PROTO int celsys_to_eq(wcsstruct *wcs, double *wcspos) PURPOSE Convert arbitrary celestial coordinates to equatorial. INPUT WCS structure, Coordinate vector. OUTPUT RETURN_OK if mapping successful, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 08/02/2007 ***/ int celsys_to_eq(wcsstruct *wcs, double *wcspos) { double *mat, a2,d2,sd2,cd2cp,sd,x,y; int lng, lat; mat = wcs->celsysmat; a2 = wcspos[lng = wcs->wcsprm->lng]*DEG - mat[1]; d2 = wcspos[lat = wcs->wcsprm->lat]*DEG; /* A bit of spherical trigonometry... */ /* Compute the latitude... */ sd2 = sin(d2); cd2cp = cos(d2)*mat[2]; sd = sd2*mat[3]-cd2cp*cos(a2); /* ...and the longitude */ y = cd2cp*sin(a2); x = sd2 - sd*mat[3]; wcspos[lng] = fmod((atan2(y,x) + mat[0])/DEG+360.0, 360.0); wcspos[lat] = asin(sd)/DEG; return RETURN_OK; } /******* eq_to_celsys ********************************************************* PROTO int eq_to_celsys(wcsstruct *wcs, double *wcspos) PURPOSE Convert equatorial to arbitrary celestial coordinates. INPUT WCS structure, Coordinate vector. OUTPUT RETURN_OK if mapping successful, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 08/02/2007 ***/ int eq_to_celsys(wcsstruct *wcs, double *wcspos) { double *mat, a,d,sd2,cdcp,sd,x,y; int lng, lat; mat = wcs->celsysmat; a = wcspos[lng = wcs->wcsprm->lng]*DEG - mat[0]; d = wcspos[lat = wcs->wcsprm->lat]*DEG; /* A bit of spherical trigonometry... */ /* Compute the latitude... */ sd = sin(d); cdcp = cos(d)*mat[2]; sd2 = sd*mat[3]+cdcp*cos(a); /* ...and the longitude */ y = cdcp*sin(a); x = sd2*mat[3]-sd; wcspos[lng] = fmod((atan2(y,x) + mat[1])/DEG+360.0, 360.0); wcspos[lat] = asin(sd2)/DEG; return RETURN_OK; } /******* raw_to_wcs *********************************************************** PROTO int raw_to_wcs(wcsstruct *, double *, double *) PURPOSE Convert raw (pixel) coordinates to WCS (World Coordinate System). INPUT WCS structure, Pointer to the array of input coordinates, Pointer to the array of output coordinates. OUTPUT RETURN_OK if mapping successful, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 08/02/2007 ***/ int raw_to_wcs(wcsstruct *wcs, double *pixpos, double *wcspos) { double imgcrd[NAXIS], phi,theta; int i; if (wcsrev((const char(*)[9])wcs->ctype, wcs->wcsprm, pixpos, wcs->lin,imgcrd, wcs->prj, &phi, &theta, wcs->crval, wcs->cel, wcspos)) { for (i=0; inaxis; i++) wcspos[i] = WCS_NOCOORD; return RETURN_ERROR; } /* If needed, convert from a different coordinate system to equatorial */ if (wcs->celsysconvflag) celsys_to_eq(wcs, wcspos); return RETURN_OK; } /******* wcs_to_raw *********************************************************** PROTO int wcs_to_raw(wcsstruct *, double *, double *) PURPOSE Convert WCS (World Coordinate System) coords to raw (pixel) coords. INPUT WCS structure, Pointer to the array of input coordinates, Pointer to the array of output coordinates. OUTPUT RETURN_OK if mapping successful, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 08/02/2007 ***/ int wcs_to_raw(wcsstruct *wcs, double *wcspos, double *pixpos) { double imgcrd[NAXIS], phi,theta; int i; /* If needed, convert to a coordinate system different from equatorial */ if (wcs->celsysconvflag) eq_to_celsys(wcs, wcspos); if (wcsfwd((const char(*)[9])wcs->ctype,wcs->wcsprm,wcspos, wcs->crval, wcs->cel,&phi,&theta,wcs->prj, imgcrd,wcs->lin,pixpos)) { for (i=0; inaxis; i++) pixpos[i] = WCS_NOCOORD; return RETURN_ERROR; } return RETURN_OK; } /******* red_to_raw ********************************************************** PROTO int red_to_raw(wcsstruct *, double *, double *) PURPOSE Convert reduced (World Coordinate System) coords to raw (pixel) coords. INPUT WCS structure, Pointer to the array of input (reduced) coordinates, Pointer to the array of output (pixel) coordinates. OUTPUT RETURN_OK if mapping successful, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 23/10/2003 ***/ int red_to_raw(wcsstruct *wcs, double *redpos, double *pixpos) { struct wcsprm *wcsprm; double offset; wcsprm = wcs->wcsprm; /* Initialize if required */ if (wcsprm && wcsprm->flag != WCSSET) { if (wcsset(wcs->naxis, (const char(*)[9])wcs->ctype, wcsprm)) return RETURN_ERROR; } if (wcsprm && wcsprm->flag != 999 && wcsprm->cubeface != -1) { /*-- Separation between faces */ offset = (wcs->prj->r0 == 0.0 ? 90.0 : wcs->prj->r0*PI/2.0); /*-- Stack faces in a cube */ if (redpos[wcs->lat] < -0.5*offset) { redpos[wcs->lat] += offset; redpos[wcsprm->cubeface] = 5.0; } else if (redpos[wcs->lat] > 0.5*offset) { redpos[wcs->lat] -= offset; redpos[wcsprm->cubeface] = 0.0; } else if (redpos[wcs->lng] > 2.5*offset) { redpos[wcs->lng] -= 3.0*offset; redpos[wcsprm->cubeface] = 4.0; } else if (redpos[wcs->lng] > 1.5*offset) { redpos[wcs->lng] -= 2.0*offset; redpos[wcsprm->cubeface] = 3.0; } else if (redpos[wcs->lng] > 0.5*offset) { redpos[wcs->lng] -= offset; redpos[wcsprm->cubeface] = 2.0; } else redpos[wcsprm->cubeface] = 1.0; } /* Apply forward linear transformation */ if (linfwd(redpos, wcs->lin, pixpos)) return RETURN_ERROR; return RETURN_OK; } /******* raw_to_red ********************************************************** PROTO int raw_to_red(wcsstruct *, double *, double *) PURPOSE Convert raw (pixel) coordinates to reduced WCS coordinates. INPUT WCS structure, Pointer to the array of input (pixel) coordinates, Pointer to the array of output (reduced) coordinates. OUTPUT RETURN_OK if mapping successful, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 23/10/2003 ***/ int raw_to_red(wcsstruct *wcs, double *pixpos, double *redpos) { struct wcsprm *wcsprm; double offset; int face; wcsprm = wcs->wcsprm; /* Initialize if required */ if (wcsprm && wcsprm->flag != WCSSET) { if (wcsset(wcs->naxis, (const char(*)[9])wcs->ctype, wcsprm)) return RETURN_ERROR; } /* Apply reverse linear transformation */ if (linrev(pixpos, wcs->lin, redpos)) return RETURN_ERROR; if (wcsprm && wcsprm->flag != 999 && wcsprm->cubeface != -1) { /*-- Do we have a CUBEFACE axis? */ face = (int)(redpos[wcsprm->cubeface] + 0.5); if (fabs(redpos[wcsprm->cubeface]-face) > 1e-10) return RETURN_ERROR; /*-- Separation between faces. */ offset = (wcs->prj->r0 == 0.0 ? 90.0 : wcs->prj->r0*PI/2.0); /*-- Lay out faces in a plane. */ switch (face) { case 0: redpos[wcs->lat] += offset; break; case 1: break; case 2: redpos[wcs->lng] += offset; break; case 3: redpos[wcs->lng] += offset*2; break; case 4: redpos[wcs->lng] += offset*3; break; case 5: redpos[wcs->lat] -= offset; break; default: return RETURN_ERROR; } } return RETURN_OK; } /******* wcs_dist *********************************************************** PROTO double wcs_dist(wcsstruct *wcs, double *wcspos1, double *wcspos2) PURPOSE Compute the angular distance between 2 points on the sky. INPUT WCS structure, Pointer to the first array of world coordinates, Pointer to the second array of world coordinates. OUTPUT Angular distance (in degrees) between points. NOTES -. AUTHOR E. Bertin (IAP) VERSION 24/07/2002 ***/ double wcs_dist(wcsstruct *wcs, double *wcspos1, double *wcspos2) { double d, dp; int i, lng, lat; lng = wcs->lng; lat = wcs->lat; if (lat!=lng) { /*-- We are operating in angular coordinates */ d = sin(wcspos1[lat]*DEG)*sin(wcspos2[lat]*DEG) + cos(wcspos1[lat]*DEG)*cos(wcspos2[lat]*DEG) *cos((wcspos1[lng]-wcspos2[lng])*DEG); return d>-1.0? (d<1.0 ? acos(d)/DEG : 0.0) : 180.0; } else { d = 0.0; for (i=0; inaxis; i++) { dp = wcspos1[i] - wcspos2[i]; d += dp*dp; } return sqrt(d); } } /******* wcs_scale *********************************************************** PROTO double wcs_scale(wcsstruct *wcs, double *pixpos) PURPOSE Compute the sky area equivalent to a local pixel. INPUT WCS structure, Pointer to the array of local raw coordinates, OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 03/01/2008 ***/ double wcs_scale(wcsstruct *wcs, double *pixpos) { double wcspos[NAXIS], wcspos1[NAXIS], wcspos2[NAXIS], pixpos2[NAXIS]; double dpos1,dpos2; int lng, lat; if (raw_to_wcs(wcs, pixpos, wcspos)) return 0.0; lng = wcs->lng; lat = wcs->lat; if (lng == lat) { lng = 0; lat = 1; } /* Compute pixel scale */ pixpos2[lng] = pixpos[lng] + 1.0; pixpos2[lat] = pixpos[lat]; if (raw_to_wcs(wcs, pixpos2, wcspos1)) return 0.0; pixpos2[lng] -= 1.0; pixpos2[lat] += 1.0; if (raw_to_wcs(wcs, pixpos2, wcspos2)) return 0.0; dpos1 = wcspos1[lng]-wcspos[lng]; dpos2 = wcspos2[lng]-wcspos[lng]; if (wcs->lng!=wcs->lat) { if (dpos1>180.0) dpos1 -= 360.0; else if (dpos1<-180.0) dpos1 += 360.0; if (dpos2>180.0) dpos2 -= 360.0; else if (dpos2<-180.0) dpos2 += 360.0; return fabs((dpos1*(wcspos2[lat]-wcspos[lat]) -(wcspos1[lat]-wcspos[lat])*dpos2)*cos(wcspos[lat]*DEG)); } else return fabs((dpos1*(wcspos2[lat]-wcspos[lat]) -(wcspos1[lat]-wcspos[lat])*dpos2)); } /****** wcs jacobian ********************************************************* PROTO double wcs_jacobian(wcsstruct *wcs, double *pixpos, double *jacob) PURPOSE Compute the local Jacobian matrix of the astrometric deprojection. INPUT WCS structure, Pointer to the array of local raw coordinates, Pointer to the jacobian array (output). OUTPUT Determinant over spatial coordinates (=pixel area), or -1.0 if mapping was unsuccesful. NOTES Memory must have been allocated (naxis*naxis*sizeof(double)) for the Jacobian array. AUTHOR E. Bertin (IAP) VERSION 11/10/2007 ***/ double wcs_jacobian(wcsstruct *wcs, double *pixpos, double *jacob) { double pixpos0[NAXIS], wcspos0[NAXIS], wcspos[NAXIS], dpos; int i,j, lng,lat,naxis; lng = wcs->lng; lat = wcs->lat; naxis = wcs->naxis; for (i=0; i180.0) dpos -= 360.0; else if (dpos<-180.0) dpos += 360.0; dpos *= cos(wcspos0[lat]*DEG); } jacob[j*naxis+i] = dpos; } } if (lng==lat) { lng = 0; lat = 1; } return fabs(jacob[lng+naxis*lng]*jacob[lat+naxis*lat] - jacob[lat+naxis*lng]*jacob[lng+naxis*lat]); } /****** wcs rawtoraw ********************************************************* PROTO double wcs_rawtoraw(wcsstruct *wcsin, wcsstruct *wcsout, double *pixpos, double *jacob) PURPOSE Convert raw coordinates from input wcs structure to raw coordinates from output wcs structure, and the local Jacobian matrix of the reprojection. INPUT WCS input structure, WCS output structure, pointer to the array of local input raw coordinates, pointer to the array of local output raw coordinates (output), pointer to the jacobian array (output). OUTPUT Determinant over spatial coordinates (ratio of pixel areas), 0.0 if jacob is NULL (Jacobian not computed in that case), or -1.0 if mapping was unsuccesful. NOTES Memory must have been allocated (naxis*naxis*sizeof(double)) for the Jacobian array. AUTHOR E. Bertin (IAP) VERSION 12/06/2012 ***/ double wcs_rawtoraw(wcsstruct *wcsin, wcsstruct *wcsout, double *pixposin, double *pixposout, double *jacob) { double pixpos0[NAXIS], pixpos2[NAXIS], wcspos[NAXIS]; int i,j, lng,lat,naxis; naxis = wcsin->naxis; for (i=0; ilng; lat = wcsin->lat; for (i=0; ilng; lat = wcs->lat; naxis = wcs->naxis; if (lng==lat && naxis>=2) { lng = 0; lat = 1; } a = wcs->cd[lng*naxis+lng]*wcs->cd[lat*naxis+lat] - wcs->cd[lng*naxis+lat]*wcs->cd[lat*naxis+lng]; return a>TINY? 1 : (a<-TINY? -1 : 0); } /****** precess_wcs ********************************************************** PROTO void precess_wcs(wcsstruct *wcs, double yearin, double yearout) PURPOSE Precess the content of a WCS structure according to the equinox. INPUT WCS structure, Input year, Output year. OUTPUT -. NOTES Epoch for coordinates should be J2000 (FK5 system). AUTHOR E. Bertin (IAP) VERSION 04/01/2008 ***/ void precess_wcs(wcsstruct *wcs, double yearin, double yearout) { double crval[NAXIS],a[NAXIS*NAXIS],b[NAXIS*NAXIS], *c,*at, val, cas, sas, angle, dalpha; int i,j,k, lng,lat, naxis; lng = wcs->lng; lat = wcs->lat; if (lat==lng || yearin==yearout) return; naxis = wcs->naxis; /* Precess to year out */ precess(yearin, wcs->crval[lng], wcs->crval[lat], yearout, &crval[lng], &crval[lat]); dalpha = (crval[lng] - wcs->crval[lng])*DEG; /* Compute difference angle with the north axis between start and end */ angle = (dalpha!=0.0 && (crval[lat] - wcs->crval[lat])*DEG != 0.0) ? 180.0 - (atan2(sin(dalpha), cos(crval[lat]*DEG)*tan(wcs->crval[lat]*DEG) - sin(crval[lat]*DEG)*cos(dalpha)) + atan2(sin(dalpha), cos(wcs->crval[lat]*DEG)*tan(crval[lat]*DEG) - sin(wcs->crval[lat]*DEG)*cos(dalpha)))/DEG : 0.0; /* A = C*B */ c = wcs->cd; /* The B matrix is made of 2 numbers */ cas = cos(angle*DEG); sas = sin(-angle*DEG); for (i=0; icrval[lng] = crval[lng]; wcs->crval[lat] = crval[lat]; wcs->equinox = yearout; /* Initialize other WCS structures */ init_wcs(wcs); /* Find the range of coordinates */ range_wcs(wcs); /* Invert projection corrections */ invert_wcs(wcs); return; } /********************************* precess ***********************************/ /* precess equatorial coordinates according to the equinox (from Ephemerides du Bureau des Longitudes 1992). Epoch for coordinates should be J2000 (FK5 system). */ void precess(double yearin, double alphain, double deltain, double yearout, double *alphaout, double *deltaout) { double dzeta,theta,z, t1,t1t1, t2,t2t2,t2t2t2, cddsadz, cddcadz, cdd, sdd, adz, cdin,sdin,ct,st,caindz; alphain *= DEG; deltain *= DEG; t1 = (yearin - 2000.0)/1000.0; t2 = (yearout - yearin)/1000.0; t1t1 = t1*t1; t2t2t2 = (t2t2 = t2*t2)*t2; theta = (97171.735e-06 - 413.691e-06*t1 - 1.052e-06 * t1t1) * t2 + (-206.846e-06 - 1.052e-06*t1) * t2t2 - 202.812e-06 * t2t2t2; dzeta = (111808.609e-06 + 677.071e-06*t1 - 0.674e-06 * t1t1) * t2 + (146.356e-06 - 1.673e-06*t1) * t2t2 + 87.257e-06 * t2t2t2; z = (111808.609e-06 +677.071e-06*t1 - 0.674e-06 * t1t1) * t2 + (530.716e-06 + 0.320e-06*t1) * t2t2 + 88.251e-06 * t2t2t2; cddsadz = (cdin=cos(deltain)) * sin(alphain+dzeta); cddcadz = -(sdin=sin(deltain))*(st=sin(theta)) +cdin*(ct=cos(theta))*(caindz=cos(alphain+dzeta)); sdd = sdin*ct + cdin*st*caindz; cdd = cos(*deltaout = asin(sdd)); adz = asin(cddsadz/cdd); if (cddcadz<0.0) adz = PI - adz; if (adz<0.0) adz += 2.0*PI; adz += z; *alphaout = adz/DEG; *deltaout /= DEG; return; } /********************************* b2j ***********************************/ /* conver equatorial coordinates from equinox and epoch B1950 to equinox and epoch J2000 for extragalactic sources (from Aoki et al. 1983). */ void b2j(double yearobs, double alphain, double deltain, double *alphaout, double *deltaout) { int i,j; double a[3] = {-1.62557e-6, -0.31919e-6, -0.13843e-6}, ap[3] = {1.245e-3, -1.580e-3, -0.659e-3}, m[6][6] = { { 0.9999256782, -0.0111820611, -0.0048579477, 0.00000242395018, -0.00000002710663, -0.00000001177656}, { 0.0111820610, 0.9999374784, -0.0000271765, 0.00000002710663, 0.00000242397878, -0.00000000006587}, { 0.0048579479, -0.0000271474, 0.9999881997, 0.00000001177656, -0.00000000006582, 0.00000242410173}, {-0.000551, -0.238565, 0.435739, 0.99994704, -0.01118251, -0.00485767}, { 0.238514, -0.002662, -0.008541, 0.01118251, 0.99995883, -0.00002718}, {-0.435623, 0.012254, 0.002117, 0.00485767, -0.00002714, 1.00000956}}, a1[3], r[3], ro[3], r1[3], r2[3], v1[3], v[3]; double cai, sai, cdi, sdi, dotp, rmod, alpha, delta, t1 = (yearobs - 1950.0)/100.0; alphain *= PI/180.0; deltain *= PI/180.0; cai = cos(alphain); sai = sin(alphain); cdi = cos(deltain); sdi = sin(deltain); ro[0] = cdi*cai; ro[1] = cdi*sai; ro[2] = sdi; dotp = 0.0; for (i=0; i<3; i++) { a1[i] = a[i]+ap[i]*ARCSEC*t1; dotp += a1[i]*ro[i]; } for (i=0; i<3; i++) { r1[i] = ro[i] - a1[i] + dotp*ro[i]; r[i] = v[i] = v1[i] = 0.0; } for (j=0; j<6; j++) for (i=0; i<6; i++) { if (j<3) r[j] += m[j][i]*(i<3?r1[i]:v1[i-3]); else v[j-3] += m[j][i]*(i<3?r1[i]:v1[i-3]); } rmod = 0.0; for (i=0; i<3; i++) { r2[i] = r[i]+v[i]*ARCSEC*(t1-0.5); rmod += r2[i]*r2[i]; } rmod = sqrt(rmod); delta = asin(r2[2]/rmod); alpha = acos(r2[0]/cos(delta)/rmod); if (r2[1]<0) alpha = 2*PI - alpha; *alphaout = alpha*180.0/PI; *deltaout = delta*180.0/PI; return; } /*********************************** j2b *************************************/ /* conver equatorial coordinates from equinox and epoch J2000 to equinox and epoch B1950 for extragalactic sources (from Aoki et al. 1983, after inversion of their matrix and some custom arrangements). */ void j2b(double yearobs, double alphain, double deltain, double *alphaout, double *deltaout) { int i,j; double a[3] = {-1.62557e-6, -0.31919e-6, -0.13843e-6}, ap[3] = {1.245e-3, -1.580e-3, -0.659e-3}, m[6][6] = { { 0.9999256794678425, 0.01118148281196562, 0.004859003848996022, -2.423898417033081e-06,-2.710547600126671e-08,-1.177738063266745e-08}, {-0.01118148272969232, 0.9999374849247641, -2.717708936468247e-05, 2.710547578707874e-08,-2.423927042585208e-06, 6.588254898401055e-11}, {-0.00485900399622881, -2.715579322970546e-05, 0.999988194643078, 1.177738102358923e-08, 6.582788892816657e-11,-2.424049920613325e-06}, {-0.0005508458576414713, 0.2384844384742432, -0.4356144527773499, 0.9999043171308133, 0.01118145410120206, 0.004858518651645554}, {-0.2385354433560954, -0.002664266996872802, 0.01225282765749546, -0.01118145417187502, 0.9999161290795875, -2.717034576263522e-05}, { 0.4357269351676567, -0.008536768476441086, 0.002113420799663768, -0.004858518477064975, -2.715994547222661e-05, 0.9999668385070383}}, a1[3], r[3], ro[3], r1[3], r2[3], v1[3], v[3]; double cai, sai, cdi, sdi, dotp, rmod, alpha, delta, t1; /* Convert Julian years from J2000.0 to tropic centuries from B1950.0 */ t1 = ((yearobs - 2000.0) + (MJD2000 - MJD1950)/365.25)*JU2TROP/100.0; alphain *= DEG; deltain *= DEG; cai = cos(alphain); sai = sin(alphain); cdi = cos(deltain); sdi = sin(deltain); r[0] = cdi*cai; r[1] = cdi*sai; r[2] = sdi; for (i=0; i<3; i++) v[i] = r2[i] = v1[i] = 0.0; for (j=0; j<6; j++) for (i=0; i<6; i++) if (j<3) r2[j] += m[j][i]*(i<3?r[i]:v[i-3]); else v1[j-3] += m[j][i]*(i<3?r[i]:v[i-3]); for (i=0; i<3; i++) r1[i] = r2[i]+v1[i]*ARCSEC*t1; dotp = 0.0; for (i=0; i<3; i++) { a1[i] = a[i]+ap[i]*ARCSEC*t1; dotp += a1[i]*(r1[i]+a1[i]); } dotp = 2.0/(sqrt(1+4.0*dotp)+1.0); rmod = 0.0; for (i=0; i<3; i++) { ro[i] = dotp*(r1[i]+a1[i]); rmod += ro[i]*ro[i]; } rmod = sqrt(rmod); delta = asin(ro[2]/rmod); alpha = acos(ro[0]/cos(delta)/rmod); if (ro[1]<0) alpha = 2.0*PI - alpha; *alphaout = alpha/DEG; *deltaout = delta/DEG; return; } /******************************** degtosexal *********************************/ /* Convert degrees to hh mm ss.xx alpha coordinates. */ char *degtosexal(double alpha, char *str) { int hh, mm; double ss; if (alpha>=0.0 && alpha <360.0) { hh = (int)(alpha/15.0); mm = (int)(60.0*(alpha/15.0 - hh)); ss = 60.0*(60.0*(alpha/15.0 - hh) - mm); } else hh = mm = ss = 0.0; sprintf(str,"%02d:%02d:%05.2f", hh, mm, ss); return str; } /******************************** degtosexde *********************************/ /* Convert degrees to dd dm ds.x delta coordinates. */ char *degtosexde(double delta, char *str) { char sign; double ds; int dd, dm; sign = delta<0.0?'-':'+'; delta = fabs(delta); if (delta>=-90.0 && delta <=90.0) { dd = (int)delta; dm = (int)(60.0*(delta - dd)); ds = 60.0*fabs(60.0*(delta - dd) - dm); } else dd = dm = ds = 0.0; sprintf(str,"%c%02d:%02d:%04.1f", sign, dd, dm, ds); return str; } /******************************** sextodegal *********************************/ /* Convert hh mm ss.xxx alpha coordinates to degrees. */ double sextodegal(char *hms) { double val; char *ptr; val = atof(strtok_r(hms, ": \t", &ptr))*15.0; /* Hours */ val += atof(strtok_r(NULL, ": \t", &ptr))/4.0; /* Minutes */ val += atof(strtok_r(NULL, ": \t", &ptr))/240.0; /* Seconds */ return val; } /******************************** sextodegde *********************************/ /* Convert dd dm ds.xxx delta coordinates to degrees. */ double sextodegde(char *dms) { double val, sgn; char *str, *ptr; str = strtok_r(dms, ": \t", &ptr); sgn = (strchr(str, '-') ? -1.0:1.0); val = atof(dms); /* Degrees */ val += atof(strtok_r(NULL, ": \t", &ptr))*sgn/60.0; /* Minutes */ val += atof(strtok_r(NULL, ": \t", &ptr))*sgn/3600.0; /* Seconds */ return val; } /******************************** fmod_0_p360 *******************************/ /* Fold input angle in the [0,+360[ domain. */ double fmod_0_p360(double angle) { return angle>0.0? fmod(angle,360.0) : fmod(angle,360.0)+360.0; } /******************************** fmod_m90_p90 *******************************/ /* Fold input angle in the [-90,+90[ domain. */ double fmod_m90_p90(double angle) { return angle>0.0? fmod(angle+90.0,180.0)-90.0 : fmod(angle-90.0,180.0)+90.0; } /********************************* fmod_0_pmod *******************************/ /* Fold input angle in the [0,+mod[ domain. */ double fmod_0_pmod(double angle, double mod) { return angle>0.0? fmod(angle,mod) : fmod(angle,mod)+mod; } /******************************* fmod_mmod_pmod ******************************/ /* Fold input angle in the [-mod,+mod[ domain. */ double fmod_mmod_pmod(double angle, double mod) { return angle>0.0? fmod(angle+mod,2.0*mod)-mod : fmod(angle-mod,2.0*mod)+mod; } /********************************* fcmp_0_p360 *******************************/ /* Compare angles in the [0,+360[ domain: return 1 if anglep>anglem, 0 otherwise. */ int fcmp_0_p360(double anglep, double anglem) { double dval = anglep - anglem; return (int)((dval>0.0 && dval<180.0) || dval<-180.0); } /****** str_to_date_wcs *****************************************************/ /* PROTO int str_to_date_wcs(char *str, double *year) PURPOSE Convert WCS DATE-OBS string to Julian Date (in years). INPUT Input DATE-OBS string, Output Julian date in years. OUTPUT RETURN_OK if the date was read correctly, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 20/12/2019 ***/ int str_to_date_wcs(char *str, double *year) { double dpar[6] = {0.0}, date, jdsec, tmp, biss; char str2[80], *pstr, *ptr; int l, sflag; strncpy(str2, str, 72); /* Decode DATE-OBS format: DD/MM/YYThh:mm:ss[.sss] or YYYY-MM-DDThh:mm:ss[.sss] */ sflag = strchr(str2, '/') != NULL; for (l=0; l<5 && (pstr = strtok_r(l ? NULL : str2, "/-T: ", &ptr)); l++) dpar[l] = atof(pstr); if (l<3 || dpar[0] == 0.0 || dpar[1] == 0.0 || dpar[2] == 0.0) { /*-- If DATE-OBS value corrupted or incomplete, assume 2000-1-1 */ *year = 2000.0; return RETURN_ERROR; } else if (sflag && dpar[0] < 32.0 && dpar[2] < 100.0) { tmp = dpar[0]; dpar[0] = dpar[2] + 1900.0; dpar[2] = tmp; } biss = (((int)dpar[0]) % 4) ? 0.0 : 1.0; /* Convert date to MJD */ jdsec = (dpar[5] + dpar[4] * 60.0 + dpar[3] * 3600.0) / 86400.0; date = ((365.0 * dpar[0] + dpar[0] / 4.0) - 678956.0 - biss + ((dpar[1] > 2.0? (floor((dpar[1] + 1.0) * 30.6) - 63.0 + biss) : ((dpar[1] - 1.0) * (63.0 + biss)) / 2.0) + dpar[2])) + jdsec; *year = 2000.0 - (MJD2000 - date) / 365.25; return RETURN_OK; } swarp-2.41.5/src/fitswcs.h000066400000000000000000000163261400430667300153740ustar00rootroot00000000000000/* * fitswcs.h * * Include file for fitswcs.c * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic software * * Copyright: (C) 1993-2019 IAP/CNRS/SorbonneU * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 20/12/2019 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _FITSWCS_H_ #define _FITSWCS_H_ #include "fits/fitscat.h" /*-------------------------------- macros -----------------------------------*/ /*----------------------------- Internal constants --------------------------*/ #define NAXIS 2 /* Max number of FITS axes */ #define DEG (PI/180.0) /* 1 deg in radians */ #define ARCMIN (DEG/60.0) /* 1 arcsec in radians */ #define ARCSEC (DEG/3600.0) /* 1 arcsec in radians */ #define MAS (ARCSEC/1000.0) /* 1 mas in radians */ #define YEAR (365.25*DAY) /* 1 year in seconds */ #define DAY (24.0*HOUR) /* 1 day in seconds */ #define HOUR (60.0*MINUTE) /* 1 hour in seconds */ #define MINUTE 60.0 /* 1 minute in seconds */ #define MJD2000 51544.50000 /* Modified Julian date for J2000.0 */ #define JD2000 (2400000.5+MJD2000) /* Julian date for J2000.0 */ #define MJD1950 33281.92346 /* Modified Julian date for B1950.0 */ #define JD1950 (2400000.5+MJD1950) /* Julian date for B1950.0 */ #define JU2TROP 1.0000214 /* 1 Julian century in tropical units*/ #define WCS_NOCOORD 1e31 /* Code for non-existing coordinates */ #define WCS_NGRIDPOINTS 12 /* Number of WCS grid points / axis */ #define WCS_NGRIDPOINTS2 (WCS_NGRIDPOINTS*WCS_NGRIDPOINTS) #define WCS_INVMAXDEG 7 /* Maximum inversion polynom degree */ #define WCS_INVACCURACY 0.001 /* Maximum inversion error (pixels) */ #define WCS_NRANGEPOINTS 32 /* Number of WCS range points / axis */ /*-------------------------------- typedefs ---------------------------------*/ typedef enum {CELSYS_NATIVE, CELSYS_PIXEL, CELSYS_EQUATORIAL, CELSYS_GALACTIC, CELSYS_ECLIPTIC, CELSYS_SUPERGALACTIC} celsysenum; /*------------------------------- structures --------------------------------*/ typedef struct wcs { int naxis; /* Number of image axes */ int naxisn[NAXIS]; /* FITS NAXISx parameters */ char ctype[NAXIS][9]; /* FITS CTYPE strings */ char cunit[NAXIS][32]; /* FITS CUNIT strings */ double crval[NAXIS]; /* FITS CRVAL parameters */ double cdelt[NAXIS]; /* FITS CDELT parameters */ double crpix[NAXIS]; /* FITS CRPIX parameters */ double crder[NAXIS]; /* FITS CRDER parameters */ double csyer[NAXIS]; /* FITS CSYER parameters */ double cd[NAXIS*NAXIS]; /* FITS CD matrix */ double *projp; /* FITS PV/PROJP mapping parameters */ int nprojp; /* number of useful projp parameters */ double longpole,latpole; /* FITS LONGPOLE and LATPOLE */ double wcsmin[NAXIS]; /* minimum values of WCS coords */ double wcsmax[NAXIS]; /* maximum values of WCS coords */ double wcsscale[NAXIS]; /* typical pixel scale at center */ double wcsscalepos[NAXIS]; /* WCS coordinates of scaling point */ double wcsmaxradius; /* Maximum distance to wcsscalepos */ int outmin[NAXIS]; /* minimum output pixel coordinate */ int outmax[NAXIS]; /* maximum output pixel coordinate */ int lat,lng; /* longitude and latitude axes # */ double r0; /* projection "radius" */ double lindet; /* Determinant of the local matrix */ int chirality; /* Chirality of the CD matrix */ double pixscale; /* (Local) pixel scale */ double ap2000,dp2000; /* J2000 coordinates of pole */ double ap1950,dp1950; /* B1950 coordinates of pole */ double obsdate; /* Starting date of observations */ double obsend; /* End date of observations */ double equinox; /* Equinox of observations */ double epoch; /* Epoch of observations (deprec.) */ enum {RDSYS_ICRS, RDSYS_FK5, RDSYS_FK4, RDSYS_FK4_NO_E, RDSYS_GAPPT} radecsys; /* FITS RADECSYS reference frame */ celsysenum celsys; /* Celestial coordinate system */ double celsysmat[4]; /* Equ. <=> Cel. system parameters */ int celsysconvflag; /* Equ. <=> Cel. conversion needed? */ struct wcsprm *wcsprm; /* WCSLIB's wcsprm structure */ struct linprm *lin; /* WCSLIB's linprm structure */ struct celprm *cel; /* WCSLIB's celprm structure */ struct prjprm *prj; /* WCSLIB's prjprm structure */ struct tnxaxis *tnx_latcor; /* IRAF's TNX latitude corrections */ struct tnxaxis *tnx_lngcor; /* IRAF's TNX longitude corrections */ struct poly *inv_x; /* Proj. correction polynom in x */ struct poly *inv_y; /* Proj. correction polynom in y */ } wcsstruct; /*------------------------------- functions ---------------------------------*/ extern wcsstruct *create_wcs(char **ctype, double *crval, double *crpix, double *cdelt, int *naxisn, int naxis), *copy_wcs(wcsstruct *wcsin), *read_wcs(tabstruct *tab); extern double fmod_0_p360(double angle), fmod_0_pmod(double angle, double mod), fmod_m90_p90(double angle), fmod_mmod_pmod(double angle, double mod), sextodegal(char *hms), sextodegde(char *dms), wcs_dist(wcsstruct *wcs, double *wcspos1, double *wcspos2), wcs_jacobian(wcsstruct *wcs, double *pixpos, double *jacob), wcs_rawtoraw(wcsstruct *wcsin, wcsstruct *wcsout, double *pixposin, double *pixposout, double *jacob), wcs_scale(wcsstruct *wcs, double *pixpos); extern int celsys_to_eq(wcsstruct *wcs, double *wcspos), eq_to_celsys(wcsstruct *wcs, double *wcspos), fcmp_0_p360(double anglep, double anglem), frame_wcs(wcsstruct *wcsin, wcsstruct *wcsout), raw_to_red(wcsstruct *wcs, double *pixpos, double *redpos), raw_to_wcs(wcsstruct *wcs, double *pixpos, double *wcspos), reaxe_wcs(wcsstruct *wcs, int lng, int lat), red_to_raw(wcsstruct *wcs, double *redpos, double *pixpos), str_to_date_wcs(char *str, double *year), wcs_chirality(wcsstruct *wcs), wcs_supproj(char *name), wcs_to_raw(wcsstruct *wcs, double *wcspos, double *pixpos); extern char *degtosexal(double alpha, char *str), *degtosexde(double delta, char *str); extern void b2j(double yearobs, double alphain, double deltain, double *alphaout, double *deltaout), end_wcs(wcsstruct *wcs), init_wcs(wcsstruct *wcs), init_wcscelsys(wcsstruct *wcs), invert_wcs(wcsstruct *wcs), j2b(double yearobs, double alphain, double deltain, double *alphaout, double *deltaout), precess(double yearin, double alphain, double deltain, double yearout, double *alphaout, double *deltaout), precess_wcs(wcsstruct *wcs, double yearin, double yearout), range_wcs(wcsstruct *wcs), wipe_wcs(tabstruct *tab), write_wcs(tabstruct *tab, wcsstruct *wcs); #endif // _FITSWCS_H_ swarp-2.41.5/src/globals.h000066400000000000000000000023271400430667300153310ustar00rootroot00000000000000/* * globals.h * * Global declarations. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2002-2020 IAP/CNRS/SorbonneU * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 26/08/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include "types.h" /*----------------------- miscellaneous variables ---------------------------*/ extern char gstr[MAXCHAR]; /*------------------------------- functions ---------------------------------*/ extern void makeit(void), write_error(char *msg1, char *msg2); swarp-2.41.5/src/header.c000066400000000000000000000462631400430667300151400ustar00rootroot00000000000000/* * header.c * * Manage FITS headers. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2019 IAP/CNRS/SorbonneU * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 03/12/2019 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include "define.h" #include "globals.h" #include "data.h" #include "fits/fitscat.h" #include "fitswcs.h" #include "field.h" #include "header.h" #include "key.h" #include "prefs.h" #include "wcs/wcs.h" /****** read_aschead ******************************************************** PROTO int read_aschead(char *filename, int frameno, tabstruct *tab) PURPOSE Read an ASCII header file and update the current field's tab INPUT Name of the ASCII file, Frame number (if extensions), Tab structure. OUTPUT RETURN_OK if the file was found, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 15/11/2019 ***/ int read_aschead(char *filename, int frameno, tabstruct *tab) { char keyword[88],data[88],comment[88], str[MAXCHAR]; FILE *file; h_type htype; t_type ttype; int i, cdfirstflag,pvfirstflag; if ((file=fopen(filename, "r"))) { /*- Skip previous ENDs in multi-FITS extension headers */ for (i=(frameno?(frameno-1):0); i--;) while (fgets(str, MAXCHAR, file) && strncmp(str,"END ",4) && strncmp(str,"END\n",4)); memset(str, ' ', 80); cdfirstflag = pvfirstflag = 1; while (fgets(str, 81, file) && strncmp(str,"END ",4) && strncmp(str,"END\n",4)) { fitspick(str, keyword, data, &htype, &ttype, comment); /*---- Block critical keywords */ if (!wstrncmp(keyword, "SIMPLE ", 8) ||!wstrncmp(keyword, "BITPIX ", 8) ||!wstrncmp(keyword, "NAXIS ", 8) ||!wstrncmp(keyword, "BSCALE ", 8) ||!wstrncmp(keyword, "BZERO ", 8)) continue; /*---- Wipe out conflicting keywords */ if (pvfirstflag && !wstrncmp(keyword, "PV?_????", 8)) { removekeywordfrom_head(tab, "PV?_????"); pvfirstflag = 0; } if (cdfirstflag) { if (!wstrncmp(keyword, "PC0??0??", 8) || !wstrncmp(keyword, "PC?_????", 8)) { removekeywordfrom_head(tab, "CD?_????"); cdfirstflag = 0; } else if (!wstrncmp(keyword, "CD?_????", 8)) { removekeywordfrom_head(tab, "CDELT???"); removekeywordfrom_head(tab, "PC0??0??"); removekeywordfrom_head(tab, "PC?_????"); cdfirstflag = 0; } } addkeywordto_head(tab, keyword, comment); fitswrite(tab->headbuf, keyword, data, htype, ttype); memset(str, ' ', 80); } fclose(file); /*-- Update the tab data */ readbasic_head(tab); return RETURN_OK; } else return RETURN_ERROR; } /****** readfitsinfo_field **************************************************** PROTO void readfitsinfo_field(fieldstruct *field, tabstruct *tab) PURPOSE Read additional information from a FITS header and update the current field's tab INPUT Pointer to the field structure, Tab structure. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 25/06/2007 ***/ void readfitsinfo_field(fieldstruct *field, tabstruct *tab) { #define FITSREADF(buf, k, val, def) \ {if (fitsread(buf,k, &val, H_FLOAT,T_DOUBLE) != RETURN_OK) \ val = def; \ } #define FITSREADI(buf, k, val, def) \ {if (fitsread(buf,k, &val, H_INT,T_LONG) != RETURN_OK) \ val = def; \ } #define FITSREADS(buf, k, str, def) \ {if (fitsread(buf,k,str, H_STRING,T_STRING) != RETURN_OK) \ strcpy(str, (def)); \ } char *buf; wcsstruct *wcs; int l; buf = tab->headbuf; wcs = field->wcs; if (!buf || !wcs) return; for (l=0; lnaxis; l++) { sprintf(gstr, "COMIN%-3d", l+1); FITSREADI(buf, gstr, wcs->outmin[l], 1); wcs->outmax[l] = wcs->outmin[l] + wcs->naxisn[l] - 1; } FITSREADF(buf, "BACKMEAN", field->backmean, 0.0); FITSREADF(buf, "BACKSIG ", field->backsig, 0.0); /* Set the flux scale */ FITSREADF(buf,prefs.fscale_keyword, field->fscale, field->fscale); /* Set the conversion factor */ FITSREADF(buf, prefs.gain_keyword, field->gain, field->gain); FITSREADF(buf, prefs.sat_keyword, field->saturation, field->saturation); FITSREADF(buf, "EXPTIME ", field->exptime, 0.0); FITSREADS(buf, "OBJECT ", field->ident, ""); return; #undef FITSREADF #undef FITSREADI #undef FITSREADS } /****** writefitsinfo_outfield ************************************************ PROTO void writefitsinfo_outfield(fieldstruct *field, fieldstruct *infield) PURPOSE Add relevant information to the output field FITS header. INPUT Pointer to the field. OUTPUT -. NOTES Global preferences are used. AUTHOR E. Bertin (IAP) VERSION 25/08/2010 ***/ void writefitsinfo_outfield(fieldstruct *field, fieldstruct *infield) { struct tm *tm; time_t thetime; tabstruct *tab, *intab; extern pkeystruct key[]; h_type htype; t_type ttype; extern char keylist[][32]; char comment[88], *pstr; int d, n, k, l; tab = field->tab; addkeywordto_head(tab, "EXPTIME ", "Maximum equivalent exposure time (s)"); fitswrite(tab->headbuf, "EXPTIME ", &field->exptime, H_EXPO,T_DOUBLE); addkeywordto_head(tab, "GAIN ", "Maximum equivalent gain (e-/ADU)"); fitswrite(tab->headbuf, "GAIN ", &field->fgain, H_EXPO,T_DOUBLE); addkeywordto_head(tab, "SATURATE", "Saturation Level (ADU)"); fitswrite(tab->headbuf, "SATURATE", &field->fsaturation, H_EXPO,T_DOUBLE); fitswrite(tab->headbuf, "EXPTIME ", &field->exptime, H_EXPO,T_DOUBLE); addkeywordto_head(tab, "COMMENT ", ""); addkeywordto_head(tab, "SOFTNAME", "The software that processed those data"); fitswrite(tab->headbuf, "SOFTNAME", BANNER, H_STRING, T_STRING); addkeywordto_head(tab, "SOFTVERS", "Version of the software"); fitswrite(tab->headbuf, "SOFTVERS", VERSION, H_STRING, T_STRING); addkeywordto_head(tab, "SOFTDATE", "Release date of the software"); fitswrite(tab->headbuf, "SOFTDATE", DATE, H_STRING, T_STRING); addkeywordto_head(tab, "SOFTAUTH", "Maintainer of the software"); fitswrite(tab->headbuf, "SOFTAUTH", COPYRIGHT, H_STRING, T_STRING); addkeywordto_head(tab, "SOFTINST", "Institute"); fitswrite(tab->headbuf, "SOFTINST", INSTITUTE, H_STRING, T_STRING); addkeywordto_head(tab, "COMMENT ", ""); /* User name, we don't use getpwuid() to allow for static linking with glibc 2.3*/ addkeywordto_head(tab, "AUTHOR", "Who ran the software"); #ifdef HAVE_GETENV if (!(pstr=getenv("USERNAME"))) /* Cygwin,... */ if ((pstr=getenv("LOGNAME"))) /* Linux,... */ fitswrite(tab->headbuf, "AUTHOR", pstr, H_STRING, T_STRING); if (!pstr) #endif fitswrite(tab->headbuf, "AUTHOR", "unknown", H_STRING, T_STRING); /* Host name */ if (!gethostname(gstr, 80)) { addkeywordto_head(tab, "ORIGIN", "Where it was done"); fitswrite(tab->headbuf, "ORIGIN", gstr, H_STRING, T_STRING); } /* Obs dates */ thetime = time(NULL); tm = gmtime(&thetime); sprintf(gstr,"%04d-%02d-%02dT%02d:%02d:%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); addkeywordto_head(tab, "DATE ", "When it was started (GMT)"); fitswrite(tab->headbuf, "DATE ", gstr, H_STRING, T_STRING); /* Config parameters */ /* COMBINE_TYPE */ addkeywordto_head(tab, "COMBINET","COMBINE_TYPE config parameter for " \ BANNER); fitswrite(tab->headbuf, "COMBINET", key[findkeys("COMBINE_TYPE", keylist, FIND_STRICT)].keylist[prefs.coadd_type], H_STRING, T_STRING); if (infield && (intab=infield->tab) && prefs.ncopy_keywords) { addkeywordto_head(tab, "COMMENT ", ""); addkeywordto_head(tab, "COMMENT ", "Propagated FITS keywords"); for (k=0; kheadbuf, prefs.copy_keywords[k])) != RETURN_ERROR) { fitspick(intab->headbuf+l*80, prefs.copy_keywords[k], gstr, &htype, &ttype, comment); addkeywordto_head(tab, prefs.copy_keywords[k], comment); fitswrite(tab->headbuf, prefs.copy_keywords[k], gstr, htype, ttype); } } } /* Axis-dependent config parameters */ addkeywordto_head(tab, "COMMENT ", ""); addkeywordto_head(tab, "COMMENT ", "Axis-dependent config parameters"); for (d=0; dnaxis; d++) { /*-- RESAMPLING_TYPE */ sprintf(gstr, "RESAMPT%1d", d+1); addkeywordto_head(tab, gstr, "RESAMPLING_TYPE config parameter"); fitswrite(tab->headbuf, gstr, key[findkeys("RESAMPLING_TYPE", keylist, FIND_STRICT)].keylist[prefs.resamp_type[d]], H_STRING, T_STRING); /*-- CENTER_TYPE */ sprintf(gstr, "CENTERT%1d", d+1); addkeywordto_head(tab, gstr, "CENTER_TYPE config parameter"); fitswrite(tab->headbuf, gstr, key[findkeys("CENTER_TYPE", keylist, FIND_STRICT)].keylist[prefs.center_type[d]], H_STRING, T_STRING); /*-- PIXELSCALE_TYPE */ sprintf(gstr, "PSCALET%1d", d+1); addkeywordto_head(tab, gstr, "PIXELSCALE_TYPE config parameter"); fitswrite(tab->headbuf, gstr, key[findkeys("PIXELSCALE_TYPE", keylist, FIND_STRICT)].keylist[prefs.pixscale_type[d]], H_STRING, T_STRING); } /* Image-dependent config parameters */ if (prefs.writefileinfo_flag) { addkeywordto_head(tab, "COMMENT ", ""); addkeywordto_head(tab, "COMMENT ", "File-dependent config parameters"); for (n=0; nheadbuf, gstr, pstr, H_STRING, T_STRING); /*---- Input weights */ if (nheadbuf, gstr, pstr, H_STRING, T_STRING); /*------ WEIGHT_TYPE */ sprintf(gstr, "WGTT%04d", n+1); addkeywordto_head(tab, gstr, "WEIGHT_TYPE config parameter"); fitswrite(tab->headbuf, gstr, key[findkeys("WEIGHT_TYPE", keylist, FIND_STRICT)].keylist[prefs.weight_type[n]], H_STRING, T_STRING); } /*---- Interpolation flag */ sprintf(gstr, "INTF%04d", n+1); addkeywordto_head(tab, gstr, "INTERPOLATE config flag"); fitswrite(tab->headbuf, gstr, &prefs.interp_flag[n], H_BOOL, T_LONG); /*---- Background-subtraction flag */ sprintf(gstr, "SUBF%04d", n+1); addkeywordto_head(tab, gstr, "SUBTRACT_BACK config flag"); fitswrite(tab->headbuf, gstr, &prefs.subback_flag[n], H_BOOL, T_LONG); /*---- BACK_TYPE */ sprintf(gstr, "BCKT%04d", n+1); addkeywordto_head(tab, gstr, "BACK_TYPE config parameter"); fitswrite(tab->headbuf, gstr, key[findkeys("BACK_TYPE", keylist, FIND_STRICT)].keylist[prefs.back_type[n]], H_STRING, T_STRING); /*---- BACK_DEFAULT */ if (prefs.back_type[n]==BACK_ABSOLUTE) { sprintf(gstr, "BCKD%04d", n+1); addkeywordto_head(tab, gstr,"BACK_DEFAULT config parameter"); fitswrite(tab->headbuf, gstr, &prefs.back_default[n], H_EXPO,T_DOUBLE); } /*---- BACK_SIZE */ sprintf(gstr, "BCKS%04d", n+1); addkeywordto_head(tab, gstr,"BACK_SIZE config parameter"); fitswrite(tab->headbuf, gstr, &prefs.back_size[n], H_INT, T_LONG); /*---- BACK_FILTERSIZE */ sprintf(gstr, "BKFS%04d", n+1); addkeywordto_head(tab, gstr, "BACK_FILTERSIZE config parameter"); fitswrite(tab->headbuf, gstr, &prefs.back_fsize[n], H_INT, T_LONG); } } return; } /****** writefitsinfo_field ************************************************** PROTO void writefitsinfo_field(fieldstruct *field, fieldstruct *infield) PURPOSE Add and copy relevant information to a field FITS header. INPUT Pointer to the field. OUTPUT -. NOTES Global preferences are used. AUTHOR E. Bertin (IAP) VERSION 25/08/2010 ***/ void writefitsinfo_field(fieldstruct *field, fieldstruct *infield) { struct tm *tm; time_t thetime; tabstruct *tab, *intab; wcsstruct *wcs; extern pkeystruct key[]; h_type htype; t_type ttype; extern char keylist[][32]; char comment[88], *pstr; int d, k, l, nf; nf = field->fieldno; tab = field->tab; /* Keep some margin */ addkeywordto_head(tab, "COMMENT ", ""); addkeywordto_head(tab, "SOFTNAME", "The software that processed those data"); fitswrite(tab->headbuf, "SOFTNAME", BANNER, H_STRING, T_STRING); addkeywordto_head(tab, "SOFTVERS", "Version of the software"); fitswrite(tab->headbuf, "SOFTVERS", VERSION, H_STRING, T_STRING); addkeywordto_head(tab, "SOFTDATE", "Release date of the software"); fitswrite(tab->headbuf, "SOFTDATE", DATE, H_STRING, T_STRING); addkeywordto_head(tab, "SOFTAUTH", "Maintainer of the software"); fitswrite(tab->headbuf, "SOFTAUTH", COPYRIGHT, H_STRING, T_STRING); addkeywordto_head(tab, "SOFTINST", "Institute"); fitswrite(tab->headbuf, "SOFTINST", INSTITUTE, H_STRING, T_STRING); addkeywordto_head(tab, "COMMENT ", ""); /* User name, we don't use getpwuid() to allow for static linking with glibc 2.3*/ addkeywordto_head(tab, "AUTHOR", "Who ran the software"); #ifdef HAVE_GETENV if (!(pstr=getenv("USERNAME"))) /* Cygwin,... */ if ((pstr=getenv("LOGNAME"))) /* Linux,... */ fitswrite(tab->headbuf, "AUTHOR", pstr, H_STRING, T_STRING); if (!pstr) #endif fitswrite(tab->headbuf, "AUTHOR", "unknown", H_STRING, T_STRING); /* Host name */ if (!gethostname(gstr, 80)) { addkeywordto_head(tab, "ORIGIN", "Where it was done"); fitswrite(tab->headbuf, "ORIGIN", gstr, H_STRING, T_STRING); } /* Obs dates */ thetime = time(NULL); tm = gmtime(&thetime); sprintf(gstr,"%04d-%02d-%02dT%02d:%02d:%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); addkeywordto_head(tab, "DATE ", "When it was started (GMT)"); fitswrite(tab->headbuf, "DATE ", gstr, H_STRING, T_STRING); /* User-selected keywords */ if (infield && (intab=infield->tab)) for (k=0; kheadbuf, prefs.copy_keywords[k])) != RETURN_ERROR) { fitspick(intab->headbuf+l*80, prefs.copy_keywords[k], gstr, &htype, &ttype, comment); addkeywordto_head(tab, prefs.copy_keywords[k], comment); fitswrite(tab->headbuf, prefs.copy_keywords[k], gstr, htype, ttype); } } /* Config parameters */ /* COMBINE_TYPE */ addkeywordto_head(tab, "COMBINET","COMBINE_TYPE config parameter for " \ BANNER); fitswrite(tab->headbuf, "COMBINET", key[findkeys("COMBINE_TYPE", keylist, FIND_STRICT)].keylist[prefs.coadd_type], H_STRING, T_STRING); /* Axis-dependent config parameters */ addkeywordto_head(tab, "COMMENT ", ""); addkeywordto_head(tab, "COMMENT ", "Axis-dependent SWarp parameters"); for (d=0; dnaxis; d++) { if ((wcs=field->wcs) && wcs->outmax[d]) { sprintf(gstr, "COMIN%-3d", d+1); addkeywordto_head(tab, gstr, "Output minimum position of image"); fitswrite(tab->headbuf, gstr, &wcs->outmin[d], H_INT, T_LONG); } /*-- RESAMPLING_TYPE */ sprintf(gstr, "RESAMPT%1d", d+1); addkeywordto_head(tab, gstr, "RESAMPLING_TYPE config parameter"); fitswrite(tab->headbuf, gstr, key[findkeys("RESAMPLING_TYPE", keylist, FIND_STRICT)].keylist[prefs.resamp_type[d]], H_STRING, T_STRING); /*-- CENTER_TYPE */ sprintf(gstr, "CENTERT%1d", d+1); addkeywordto_head(tab, gstr, "CENTER_TYPE config parameter"); fitswrite(tab->headbuf, gstr, key[findkeys("CENTER_TYPE", keylist, FIND_STRICT)].keylist[prefs.center_type[d]], H_STRING, T_STRING); /*-- PIXELSCALE_TYPE */ sprintf(gstr, "PSCALET%1d", d+1); addkeywordto_head(tab, gstr, "PIXELSCALE_TYPE config parameter"); fitswrite(tab->headbuf, gstr, key[findkeys("PIXELSCALE_TYPE", keylist, FIND_STRICT)].keylist[prefs.pixscale_type[d]], H_STRING, T_STRING); } /* Image-dependent config parameters */ addkeywordto_head(tab, "COMMENT ", ""); addkeywordto_head(tab, "COMMENT ", "Image-dependent SWarp parameters"); /* Flux scales */ addkeywordto_head(tab, prefs.fscale_keyword, "Relative flux scaling from photometry"); fitswrite(tab->headbuf,prefs.fscale_keyword, &field->fscale,H_EXPO,T_DOUBLE); addkeywordto_head(tab, "FLASCALE", "Relative flux scaling from astrometry"); fitswrite(tab->headbuf, "FLASCALE", &field->fascale, H_EXPO,T_DOUBLE); /* Gain (conversion factor) */ addkeywordto_head(tab, prefs.gain_keyword, "Effective conversion factor in e-/ADU"); fitswrite(tab->headbuf,prefs.gain_keyword, &field->fgain, H_EXPO,T_DOUBLE); /* Saturation level */ addkeywordto_head(tab, prefs.sat_keyword, "Saturation level"); fitswrite(tab->headbuf,prefs.sat_keyword,&field->fsaturation,H_EXPO,T_DOUBLE); /* Background */ addkeywordto_head(tab, "BACKMEAN", "Effective background level"); fitswrite(tab->headbuf, "BACKMEAN", &field->fbackmean, H_EXPO,T_DOUBLE); addkeywordto_head(tab, "BACKSIG ", "Effective background RMS"); fitswrite(tab->headbuf, "BACKSIG ", &field->fbacksig, H_EXPO,T_DOUBLE); /* Input image */ addkeywordto_head(tab, "ORIGFILE", "Input filename"); fitswrite(tab->headbuf, "ORIGFILE", field->rfilename, H_STRING, T_STRING); /* Interpolation flag */ addkeywordto_head(tab, "INTERPF ", "INTERPOLATE config flag"); fitswrite(tab->headbuf, "INTERPF ", &prefs.interp_flag[nf], H_BOOL, T_LONG); /* Background-subtraction flag */ addkeywordto_head(tab, "BACKSUBF", "SUBTRACT_BACK config flag"); fitswrite(tab->headbuf, "BACKSUBF", &prefs.subback_flag[nf], H_BOOL, T_LONG); /* BACK_TYPE */ addkeywordto_head(tab, "BACKTYPE", "BACK_TYPE config parameter"); fitswrite(tab->headbuf, "BACKTYPE", key[findkeys("BACK_TYPE", keylist, FIND_STRICT)].keylist[prefs.back_type[nf]], H_STRING, T_STRING); /* BACK_DEFAULT */ if (field->back_type==BACK_ABSOLUTE) { addkeywordto_head(tab, "BACKDEF ", "BACK_DEFAULT config parameter"); fitswrite(tab->headbuf, "BACKDEF ", &prefs.back_default[nf], H_EXPO,T_FLOAT); } /* BACK_SIZE */ addkeywordto_head(tab, "BACKSIZE", "BACK_SIZE config parameter"); fitswrite(tab->headbuf, "BACKSIZE", &prefs.back_size[nf], H_INT, T_LONG); /* BACK_FILTERSIZE */ addkeywordto_head(tab, "BACKFSIZ", "BACK_FSIZE config parameter"); fitswrite(tab->headbuf, "BACKFSIZ", &prefs.back_fsize[nf], H_INT, T_LONG); return; } swarp-2.41.5/src/header.h000066400000000000000000000026571400430667300151440ustar00rootroot00000000000000/* * header.h * * Include file for header.c. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 26/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _FITSCAT_H_ #include "fits/fitscat.h" #endif #ifndef _FIELD_H_ #include "field.h" #endif /*------------------------------- functions ---------------------------------*/ extern int read_aschead(char *filename, int frameno, tabstruct *tab); extern void readfitsinfo_field(fieldstruct *field, tabstruct *tab), writefitsinfo_field(fieldstruct *field, fieldstruct *infield), writefitsinfo_outfield(fieldstruct *field, fieldstruct *infield); swarp-2.41.5/src/interpolate.c000066400000000000000000000273331400430667300162330ustar00rootroot00000000000000/* * interpolate.c * * Manage low-level image resampling. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2012 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 03/02/2012 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #define _GNU_SOURCE #include #endif #include #include #include "define.h" #include "types.h" #include "globals.h" #include "fits/fitscat.h" #include "interpolate.h" static void make_kernel(double pos, double *kernel, interpenum interptype); int interp_kernwidth[6]={1,1,2,4,6,8}; /****** interpolate_pix ******************************************************* PROTO int interpolate_pix(fieldstruct *field, fieldstruct *wfield, ikernelstruct ikernel, double *pos, PIXTYPE *pixout, PIXTYPE *wpixout) PURPOSE Interpolate pixel data through sinc interpolation. INPUT Field structure pointer, Weight field structure pointer, Interpolation kernel structure pointer, Position vector, Pointer to the output pixel, Pointer to the output weight. OUTPUT RETURN_OK if pixel falls within the input frame, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 30/01/2012 ***/ int interpolate_pix(fieldstruct *field, fieldstruct *wfield, ikernelstruct *ikernel, double *pos, PIXTYPE *outpix, PIXTYPE *woutpix) { PIXTYPE *pixin,*pixout, pixval; double dpos[INTERP_MAXDIM], kernel_vector[INTERP_MAXKERNELWIDTH]; double *kvector, max, val; long step[INTERP_MAXDIM]; long start, fac; int linecount[INTERP_MAXDIM]; int *naxisn, i,j,n, ival, naxis, nlines, kwidth,width, badpixflag; naxis = field->tab->naxis; naxisn = field->tab->naxisn; width = field->width; start = 0; fac = 1; for (n=0; ninterptype[n]==INTERP_NEARESTNEIGHBOUR)? (int)(val-0.50001):(int)val; /*-- Store the fractional part of the current coordinate */ dpos[n] = val - ival; /*-- Check if interpolation start/end exceed image boundary... */ kwidth = ikernel->width[n]; ival-=kwidth/2; if (ival<0 || ival+kwidth<=0 || ival+kwidth>width) { *outpix = 0.0; if (woutpix) *woutpix = BIG; return RETURN_ERROR; } /*-- Update starting pointer */ start += ival*fac; /*-- Update step between interpolated regions */ step[n] = fac*(width-kwidth); linecount[n] = 0; fac *= width; } /* Update Interpolation kernel vectors */ make_kernel(*dpos, kernel_vector, ikernel->interptype[0]); kwidth = ikernel->width[0]; nlines = ikernel->nlines; /* First step: interpolate along NAXIS1 from the data themselves */ badpixflag = 0; pixin = field->pix+start; pixout = ikernel->buffer; for (j=nlines; j--;) { val = 0.0; kvector = kernel_vector; for (i=kwidth; i--;) if ((pixval = *(pixin++))>-BIG) val += *(kvector++)*pixval; else { badpixflag = 1; kvector++; } *(pixout++) = val; for (n=1; nwidth[n]) break; else linecount[n] = 0; /* No need to initialize it to 0! */ } } /* Now the weight (variance, in fact) map */ if (wfield) { pixin = wfield->pix+start; pixout = ikernel->wbuffer; for (j=nlines; j--;) { max = 0.0; for (i=kwidth; i--;) if ((val = *(pixin++))>max) max = val; *(pixout++) = max; for (n=1; nwidth[n]) break; else linecount[n] = 0; } } } /* Second step: interpolate along other axes from the interpolation buffer */ for (n=1; ninterptype[n]); kwidth = ikernel->width[n]; pixout = pixin = ikernel->buffer; for (j = (nlines/=kwidth); j--;) { val = 0.0; kvector = kernel_vector; for (i=kwidth; i--;) val += *(kvector++)**(pixin++); *(pixout++) = val; } /*-- Now the weight (variance, in fact) map */ if (wfield) { pixout = pixin = ikernel->wbuffer; for (j = nlines; j--;) { max = 0.0; for (i=kwidth; i--;) if ((val = *(pixin++))>max) max = val; *(pixout++) = max; } } } /* Finally, fill the output pointer(s) */ *outpix = ikernel->buffer[0]; if (woutpix) *woutpix = wfield? ikernel->wbuffer[0] : (badpixflag? BIG : (PIXTYPE)(field->backsig*field->backsig)); return RETURN_OK; } /****** interpolate_ipix ****************************************************** PROTO int interpolate_ipix(fieldstruct *field, fieldstruct *wfield, double *pos, FLAGTYPE *outipix, PIXTYPE *woutpix) PURPOSE "Interpolate" flag data. INPUT Field structure pointer, Weight field structure pointer, Position vector, Pointer to the output pixel, Pointer to the output weight. OUTPUT RETURN_OK if pixel falls within the input frame, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 03/02/2012 ***/ int interpolate_ipix(fieldstruct *field, fieldstruct *wfield, double *pos, FLAGTYPE *outipix, FLAGTYPE *woutpix) { long start, fac; int *naxisn, n, ival, naxis, width; naxis = field->tab->naxis; naxisn = field->tab->naxisn; width = field->width; start = 0; fac = 1; for (n=0; n=width) { *outipix = 0; if (woutpix) *woutpix = 0; return RETURN_ERROR; } /*-- Update starting pointer */ start += ival*fac; /*-- Update step between interpolated regions */ fac *= width; } /* Finally, fill the output pointer(s) */ *outipix = *(field->ipix+start); if (woutpix) *woutpix = 1; return RETURN_OK; } /****** make_kernel ********************************************************** PROTO void make_kernel(double pos, double *kernel, interpenum interptype) PURPOSE Conpute interpolation-kernel data INPUT Position, Pointer to the output kernel data, Interpolation method. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 28/04/2000 ***/ void make_kernel(double pos, double *kernel, interpenum interptype) { double x, val, sinx1,sinx2,sinx3,cosx1; if (interptype == INTERP_NEARESTNEIGHBOUR) *kernel = 1; else if (interptype == INTERP_BILINEAR) { *(kernel++) = 1.0-pos; *kernel = pos; } else if (interptype == INTERP_LANCZOS2) { if (pos<1e-5 && pos>-1e-5) { *(kernel++) = 0.0; *(kernel++) = 1.0; *(kernel++) = 0.0; *kernel = 0.0; } else { x = -PI/2.0*(pos+1.0); #ifdef HAVE_SINCOS sincos(x, &sinx1, &cosx1); #else sinx1 = sin(x); cosx1 = cos(x); #endif val = (*(kernel++) = sinx1/(x*x)); x += PI/2.0; val += (*(kernel++) = -cosx1/(x*x)); x += PI/2.0; val += (*(kernel++) = -sinx1/(x*x)); x += PI/2.0; val += (*kernel = cosx1/(x*x)); val = 1.0/val; *(kernel--) *= val; *(kernel--) *= val; *(kernel--) *= val; *kernel *= val; } } else if (interptype == INTERP_LANCZOS3) { if (pos<1e-5 && pos>-1e-5) { *(kernel++) = 0.0; *(kernel++) = 0.0; *(kernel++) = 1.0; *(kernel++) = 0.0; *(kernel++) = 0.0; *kernel = 0.0; } else { x = -PI/3.0*(pos+2.0); #ifdef HAVE_SINCOS sincos(x, &sinx1, &cosx1); #else sinx1 = sin(x); cosx1 = cos(x); #endif val = (*(kernel++) = sinx1/(x*x)); x += PI/3.0; val += (*(kernel++) = (sinx2=-0.5*sinx1-0.866025403785*cosx1) / (x*x)); x += PI/3.0; val += (*(kernel++) = (sinx3=-0.5*sinx1+0.866025403785*cosx1) /(x*x)); x += PI/3.0; val += (*(kernel++) = sinx1/(x*x)); x += PI/3.0; val += (*(kernel++) = sinx2/(x*x)); x += PI/3.0; val += (*kernel = sinx3/(x*x)); val = 1.0/val; *(kernel--) *= val; *(kernel--) *= val; *(kernel--) *= val; *(kernel--) *= val; *(kernel--) *= val; *kernel *= val; } } else if (interptype == INTERP_LANCZOS4) { if (pos<1e-5 && pos>-1e-5) { *(kernel++) = 0.0; *(kernel++) = 0.0; *(kernel++) = 0.0; *(kernel++) = 1.0; *(kernel++) = 0.0; *(kernel++) = 0.0; *(kernel++) = 0.0; *kernel = 0.0; } else { x = -PI/4.0*(pos+3.0); #ifdef HAVE_SINCOS sincos(x, &sinx1, &cosx1); #else sinx1 = sin(x); cosx1 = cos(x); #endif val = (*(kernel++) = sinx1/(x*x)); x += PI/4.0; val +=(*(kernel++) = -(sinx2=0.707106781186*(sinx1+cosx1)) /(x*x)); x += PI/4.0; val += (*(kernel++) = cosx1/(x*x)); x += PI/4.0; val += (*(kernel++) = -(sinx3=0.707106781186*(cosx1-sinx1))/(x*x)); x += PI/4.0; val += (*(kernel++) = -sinx1/(x*x)); x += PI/4.0; val += (*(kernel++) = sinx2/(x*x)); x += PI/4.0; val += (*(kernel++) = -cosx1/(x*x)); x += PI/4.0; val += (*kernel = sinx3/(x*x)); val = 1.0/val; *(kernel--) *= val; *(kernel--) *= val; *(kernel--) *= val; *(kernel--) *= val; *(kernel--) *= val; *(kernel--) *= val; *(kernel--) *= val; *kernel *= val; } } else error(EXIT_FAILURE, "*Internal Error*: Unknown interpolation type in ", "make_kernel()"); return; } /****** init_ikernel ********************************************************** PROTO ikernelstruct *init_ikernel(interpenum *interptype, int naxis) PURPOSE Prepare interpolation operations. INPUT Interpolation type for each axis, Number of axes. OUTPUT Pointer to the newly created ikernel structure. NOTES -. AUTHOR E. Bertin (IAP) VERSION 16/02/2002 ***/ ikernelstruct *init_ikernel(interpenum *interptype, int naxis) { ikernelstruct *ikernel; int n; QMALLOC(ikernel, ikernelstruct, 1); ikernel->nlines = 1; for (n=0; nnlines*=(ikernel->width[n]=interp_kernwidth[(int)interptype[n]]); ikernel->interptype[n] = interptype[n]; } ikernel->nlines /= ikernel->width[0]; QMALLOC(ikernel->buffer, PIXTYPE, ikernel->nlines); QMALLOC(ikernel->wbuffer,PIXTYPE, ikernel->nlines); return ikernel; } /****** free_ikernel ********************************************************** PROTO void free_kernel(ikernelstruct *ikernel) PURPOSE Free buffers allocated for interpolation operations. INPUT Interpolation kernel. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 16/03/2002 ***/ void free_ikernel(ikernelstruct *ikernel) { free(ikernel->buffer); free(ikernel->wbuffer); free(ikernel); return; } swarp-2.41.5/src/interpolate.h000066400000000000000000000050211400430667300162260ustar00rootroot00000000000000/* * interpolate.h * * Include file for interpolate.c. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2012 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 03/02/2012 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _FIELD_H_ #include "field.h" #endif #ifndef _INTERPOLATE_H_ #define _INTERPOLATE_H_ /*-------------------------------- macros -----------------------------------*/ /*------------------------------- constants ---------------------------------*/ #define INTERP_MAXDIM 10 /* Max. number of image dimensions */ #define INTERP_MAXKERNELWIDTH 8 /* Max. range of kernel (pixels) */ /*--------------------------------- typedefs --------------------------------*/ typedef enum {INTERP_FLAGS, INTERP_NEARESTNEIGHBOUR, INTERP_BILINEAR, INTERP_LANCZOS2, INTERP_LANCZOS3, INTERP_LANCZOS4} interpenum; /*-------------------------- structure definitions --------------------------*/ typedef struct ikernel { interpenum interptype[INTERP_MAXDIM]; /* Interpolation type along axis */ int width[INTERP_MAXDIM]; /* Interpol. kernel size along axis */ int nlines; /* Number of kernel lines */ PIXTYPE *buffer; /* Data processing buffer */ PIXTYPE *wbuffer; /* Weight processing buffer */ } ikernelstruct; /*----------------------- miscellaneous variables ---------------------------*/ /*-------------------------------- protos -----------------------------------*/ extern int interpolate_ipix(fieldstruct *field, fieldstruct *wfield, double *pos, FLAGTYPE *outipix, FLAGTYPE *woutpix), interpolate_pix(fieldstruct *field, fieldstruct *wfield, ikernelstruct *ikernel, double *pos, PIXTYPE *outipix, PIXTYPE *woutpix); extern ikernelstruct *init_ikernel(interpenum *interptype, int naxis); extern void free_ikernel(ikernelstruct *ikernel); #endif swarp-2.41.5/src/key.h000066400000000000000000000037051400430667300144770ustar00rootroot00000000000000/* * key.h * * Keyword structure definition. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic software * * Copyright: (C) 1993-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 10/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*--------------------------------- constants -------------------------------*/ #define FIND_STRICT 0 #define FIND_NOSTRICT 1 /*--------------------------- structure definitions -------------------------*/ /* Preference keyword */ typedef struct { char name[32]; enum {P_FLOAT, P_INT, P_STRING, P_BOOL, P_KEY, P_INTLIST, P_FLOATLIST, P_BOOLLIST, P_KEYLIST, P_STRINGLIST} type; void *ptr; /* Pointer to the keyword value */ int imin, imax; /* Range for int's */ double dmin, dmax; /* Range for floats */ char keylist[32][32]; /* List of keywords */ int nlistmin; /* Minimum number of list members */ int nlistmax; /* Maximum number of list members */ int *nlistptr; /* Ptr to store the nb of read params*/ int flag; } pkeystruct; /*---------------------------------- protos --------------------------------*/ int findkeys(char *str, char key[][32], int mode); swarp-2.41.5/src/main.c000066400000000000000000000077051400430667300146320ustar00rootroot00000000000000/* * main.c * * Command-line parsing. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2014 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 10/03/2014 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "define.h" #include "globals.h" #include "fits/fitscat.h" #include "prefs.h" #define SYNTAX \ "swarp image1 [image2 ...][@image_list1 [@image_list2 ...]]\n" \ "\t\t[-c ][- ]\n" \ "> to dump a default configuration file: " BANNER " -d \n" \ "> to dump a default extended configuration file: " BANNER " -dd \n" extern const char notokstr[]; /********************************** main ************************************/ int main(int argc, char *argv[]) { char **argkey, **argval, *str, *listbuf; int a, narg, nim, ntok, opt, opt2; if (argc<2) { fprintf(OUTPUT, "\n %s version %s (%s)\n", BANNER,MYVERSION,DATE); fprintf(OUTPUT, "\nWritten by %s\n", AUTHORS); fprintf(OUTPUT, "Copyright %s\n", COPYRIGHT); fprintf(OUTPUT, "\nvisit %s\n", WEBSITE); fprintf(OUTPUT, "\n%s\n", DISCLAIMER); error(EXIT_SUCCESS, "SYNTAX: ", SYNTAX); } QMALLOC(argkey, char *, argc); QMALLOC(argval, char *, argc); /*default parameters */ prefs.command_line = argv; prefs.ncommand_line = argc; prefs.ninfield = 1; prefs.infield_name[0] = "image"; strcpy(prefs.prefs_name, "default.swarp"); narg = nim = 0; listbuf = (char *)NULL; for (a=1; a All done (in %.1f s)\n", prefs.time_diff); exit(EXIT_SUCCESS); } swarp-2.41.5/src/makeit.c000066400000000000000000000311511400430667300151500ustar00rootroot00000000000000/* * makeit.c * * Main program. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2020 IAP/CNRS/SorbonneU * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 26/08/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include #include #include #include #include "define.h" #include "globals.h" #include "fits/fitscat.h" #include "fitswcs.h" #include "back.h" #include "data.h" #include "field.h" #include "header.h" #include "misc.h" #include "prefs.h" #include "resample.h" #include "xml.h" #define NFIELD 128 /* Increment in the number of fields */ static int selectext(char *filename); time_t thetime, thetime2; char gstr[MAXCHAR]; /********************************** makeit ***********************************/ void makeit(void) { fieldstruct **infield,**inwfield, *outfield,*outwfield; catstruct *cat, *wcat; tabstruct *tab; struct tm *tm; double dtime, dtimef; char *rfilename; int *next; int i,j,k,l, ninfield, ntinfield,ntinfield2, nfield, jima,jweight, version; /* Install error logging */ error_installfunc(write_error); /* Processing start date and time */ thetime = time(NULL); tm = localtime(&thetime); dtime = counter_seconds(); sprintf(prefs.sdate_start,"%04d-%02d-%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday); sprintf(prefs.stime_start,"%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); NFPRINTF(OUTPUT, ""); QPRINTF(OUTPUT, "----- %s %s started on %s at %s with %d thread%s\n\n", BANNER, MYVERSION, prefs.sdate_start, prefs.stime_start, prefs.nthreads, prefs.nthreads>1? "s":""); /* Install the signal-catching routines for temporary file cleanup */ #ifdef USE_THREADS install_cleanup(cancel_resample_threads); #else install_cleanup(NULL); #endif /* Load input images */ ninfield = prefs.ninfield; /* First check input files and count FITS extensions when available */ ntinfield = k = 0; nfield = NFIELD; QCALLOC(next, int, ninfield); QMALLOC(infield, fieldstruct *, nfield); QMALLOC(inwfield, fieldstruct *, nfield); NFPRINTF(OUTPUT, "Examining input data ...") for (i=0; i= cat->ntab) error(EXIT_FAILURE, "Not enough valid FITS image extensions in ", prefs.infield_name[i]); /*-- Examine all extensions */ wcat = NULL; jweight= RETURN_ERROR; /* to avoid gcc -Wall warnings */ if (prefs.weight_type[i] && prefs.weight_type[i] != WEIGHT_FROMBACK) { jweight = selectext(prefs.inwfield_name[i]); if (!(wcat=read_cat(prefs.inwfield_name[i]))) { sprintf(gstr, "*Error*: %s not found", prefs.inwfield_name[i]); error(EXIT_FAILURE, gstr,""); } if (jweight >= wcat->ntab) error(EXIT_FAILURE, "Not enough valid FITS image extensions in ", prefs.inwfield_name[i]); } tab=cat->tab; for (j=0; jntab; j++,tab=tab->nexttab) { if ((jima>=0 && j!=jima) || (jima<0 && (!tab->naxis || (tab->tfields && tab->bitpix==8)))) continue; if (k >= nfield) { nfield += NFIELD; QREALLOC(infield, fieldstruct *, nfield); QREALLOC(inwfield,fieldstruct *, nfield); } infield[k] = load_field(cat, j, i, prefs.inhead_name[i]); inwfield[k] = load_weight(wcat, infield[k], jweight<0? j:jweight, i, prefs.weight_type[i]); next[i]++; k++; } /*-- Put version to reduced filenames (to avoid duplicated resamps later) */ if (k) { version = 1; rfilename = infield[k-1]->rfilename; for (l=0; lframeno==0 || infield[l]->frameno==1) && !strcmp(infield[l]->rfilename, rfilename)) version++; } if (version>1) { ntinfield2 = ntinfield + next[i]; for (l=ntinfield; lversion = version; } } ntinfield += next[i]; if (!next[i]) warning("No suitable data found in ", cat->filename); free_cat(&cat, 1); if (wcat) free_cat(&wcat, 1); } /* Initialize the XML stack */ if (prefs.xml_flag) init_xml(ntinfield+1); /* Create output image (but nothing written to disk yet) */ outwfield = NULL; NFPRINTF(OUTPUT, "Creating NEW output image ...") outfield = init_field(infield, ntinfield, prefs.outfield_name, prefs.outhead_name[0]); NFPRINTF(OUTPUT, "Creating NEW weight-map ...") outwfield = init_weight(prefs.outwfield_name, outfield); NFPRINTF(OUTPUT, "") QPRINTF(OUTPUT, "------- Output File %s:\n", outfield->rfilename); printinfo_field(outfield, outwfield); QPRINTF(OUTPUT, "\n"); /* The first field in the XML stack is the output field */ if (prefs.xml_flag) update_xml(outfield, outwfield); /* HEADER_ONLY option: write the output FITS header and exit */ if (prefs.headeronly_flag) { /*-- Open output file and save header */ if (open_cat(outfield->cat, WRITE_ONLY) != RETURN_OK) error(EXIT_FAILURE, "*Error*: cannot open for writing ", outfield->filename); /*-- Add relevant information to FITS header */ if (prefs.node_index==0) { writefitsinfo_outfield(outfield, *infield); QFWRITE(outfield->tab->headbuf, outfield->tab->headnblock*FBSIZE, outfield->cat->file, outfield->filename); } goto the_end; } /* Read and transform the data */ NFPRINTF(OUTPUT, "Loading input data ...") k = 0; for (i=0; irfilename); } /*---- Compute projected limits and scaling in output frame */ if (prefs.resample_flag) { frame_wcs(infield[k]->wcs, outfield->wcs); scale_field(infield[k],outfield,prefs.fscalastro_type!=FSCALASTRO_NONE); } printinfo_field(infield[k], inwfield[k]); if (prefs.resample_flag) { /*------ Open input files */ if (open_cat(infield[k]->cat, READ_ONLY) != RETURN_OK) error(EXIT_FAILURE, "*Error*: Cannot re-open ", infield[k]->filename); if (inwfield[k]) { if (open_cat(inwfield[k]->cat, READ_ONLY) != RETURN_OK) error(EXIT_FAILURE, "*Error*: Cannot re-open ", inwfield[k]->filename); } /*------ Pre-compute the background map */ if (prefs.outfield_bitpix<0) { FPRINTF(OUTPUT, "\n"); make_back(infield[k], inwfield[k], prefs.wscale_flag[i]); FPRINTF(OUTPUT, "\n"); } } if (inwfield[k]) sprintf(gstr, " Weight scale: %.7g", inwfield[k]->sigfac); else *gstr = '\0'; QPRINTF(OUTPUT, " Background: %.7g RMS: %.7g%s\n\n", infield[k]->backmean, infield[k]->backsig, gstr); if (prefs.resample_flag) { /*------ Read (and convert) the weight data */ if (inwfield[k]) { sprintf(gstr, "Reading %s ...", inwfield[k]->filename); NFPRINTF(OUTPUT, gstr) read_weight(inwfield[k]); } /*------ Read (and convert) the data */ sprintf(gstr, "Reading %s", infield[k]->filename); NFPRINTF(OUTPUT, gstr) read_data(infield[k], inwfield[k], prefs.outfield_bitpix); /*------ Resample the data (no need to close catalogs) */ sprintf(gstr, "Resampling %s ...", infield[k]->filename); NFPRINTF(OUTPUT, gstr) resample_field(&infield[k], &inwfield[k], outfield, outwfield, prefs.resamp_type); } thetime2 = time(NULL); tm = localtime(&thetime2); sprintf(infield[k]->sdate_end,"%04d-%02d-%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday); sprintf(infield[k]->stime_end,"%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); infield[k]->time_diff = counter_seconds() - dtimef; if (prefs.xml_flag) update_xml(infield[k], inwfield[k]); } } if (!prefs.combine_flag) goto the_end; /* Apply flux scaling to input images */ for (k=0; kcat->tab->bscale /= (infield[k]->fscale*infield[k]->fscale); infield[k]->fbackmean /= (infield[k]->fscale*infield[k]->fscale); infield[k]->fbacksig /= (infield[k]->fscale*infield[k]->fscale); infield[k]->fgain *= (infield[k]->fscale*infield[k]->fscale); infield[k]->fsaturation /= (infield[k]->fscale*infield[k]->fscale); } else { infield[k]->cat->tab->bscale *= infield[k]->fscale; infield[k]->fbackmean *= infield[k]->fscale; infield[k]->fbacksig *= infield[k]->fscale; infield[k]->fgain /= infield[k]->fscale; infield[k]->fsaturation *= infield[k]->fscale; } if (inwfield[k]) inwfield[k]->cat->tab->bscale /= (infield[k]->fscale*infield[k]->fscale); } /* Go! */ coadd_fields(infield, inwfield, ntinfield, outfield, outwfield, prefs.coadd_type, BIG); the_end: /* Update the output field meta-data */ if (prefs.xml_flag) update_xml(outfield, outwfield); /* Close files and free memory */ NFPRINTF(OUTPUT, "Closing files ...") for (k=0; ktm_year+1900, tm->tm_mon+1, tm->tm_mday); sprintf(prefs.stime_end,"%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); prefs.time_diff = counter_seconds() - dtime; /* Write XML */ if (prefs.xml_flag) { write_xml(prefs.xml_name); end_xml(); } return; } /****** selectext ************************************************************ PROTO int selectext(char *filename) PURPOSE Return the user-selected extension number [%d] from the file name. INPUT Filename character string. OUTPUT Extension number, or RETURN_ERROR if nos extension specified. NOTES The bracket and its extension number are removed from the filename if found. AUTHOR E. Bertin (IAP) VERSION 09/10/2007 ***/ static int selectext(char *filename) { char *bracl,*bracr; int next; if (filename && (bracl=strrchr(filename, '['))) { *bracl = '\0'; if ((bracr=strrchr(bracl+1, ']'))) *bracr = '\0'; next = strtol(bracl+1, NULL, 0); #ifdef HAVE_CFITSIO // CFITSIO : VERY BAD HACK to check if this is tile-compressed, // if so, add +1 to extension number requested if (strstr(filename, ".fits.fz") != NULL) next = next + 1; #endif return next; } return RETURN_ERROR; } /****** write_error ******************************************************** PROTO void write_error(char *msg1, char *msg2) PURPOSE Manage files in case of a catched error INPUT a character string, another character string OUTPUT RETURN_OK if everything went fine, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 26/07/2006 ***/ void write_error(char *msg1, char *msg2) { char error[MAXCHAR]; sprintf(error, "%s%s", msg1,msg2); if (prefs.xml_flag) write_xmlerror(prefs.xml_name, error); end_xml(); return; } swarp-2.41.5/src/misc.c000066400000000000000000000053441400430667300146360ustar00rootroot00000000000000/* * misc.c * * Miscellaneous functions. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 26/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "define.h" #include "types.h" #include "globals.h" #include "misc.h" /*i**** fqcmp ************************************************************** PROTO int fqcmp(const void *p1, const void *p2) PURPOSE Sorting function for floats in qsort(). INPUT Pointer to first element, pointer to second element. OUTPUT 1 if *p1>*p2, 0 if *p1=*p2, and -1 otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 05/10/2010 ***/ static int fqcmp(const void *p1, const void *p2) { double f1=*((float *)p1), f2=*((float *)p2); return f1>f2? 1 : (f1. * * Last modified: 26/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*------------------------------- functions ---------------------------------*/ extern double counter_seconds(void); extern float fqmedian(float *arr, int n); swarp-2.41.5/src/preflist.h000066400000000000000000000337731400430667300155470ustar00rootroot00000000000000/* * preflist.h * * Configuration keyword definitions. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2019 IAP/CNRS/SorbonneU * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 03/12/2019 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include "key.h" #ifndef _FIELD_H_ #include "field.h" #endif #ifndef _INTERPOLATE_H_ #include "interpolate.h" #endif #ifndef _PREFS_H_ #include "prefs.h" #endif #ifndef _XML_H_ #include "xml.h" #endif #ifdef USE_THREADS #define THREADS_PREFMAX THREADS_NMAX #else #define THREADS_PREFMAX 65535 #endif int idummy; pkeystruct key[] = { {"BACK_DEFAULT", P_FLOATLIST, prefs.back_default, 1,7, -BIG, BIG, {""}, 1, MAXINFIELD, &prefs.nback_default}, {"BACK_FILTTHRESH", P_FLOAT, &prefs.back_fthresh, 0,0, -BIG, BIG}, {"BACK_SIZE", P_INTLIST, prefs.back_size, 1,2000000000, 0.0,0.0, {""}, 1, MAXINFIELD, &prefs.nback_size}, {"BACK_FILTERSIZE", P_INTLIST, prefs.back_fsize, 1,7, 0.0,0.0, {""}, 1, MAXINFIELD, &prefs.nback_fsize}, {"BACK_TYPE", P_KEYLIST, prefs.back_type, 0,0, 0.0,0.0, {"AUTO", "MANUAL", ""}, 1, MAXINFIELD, &prefs.nback_type}, {"BLANK_BADPIXELS", P_BOOL, &prefs.blank_flag}, {"CELESTIAL_TYPE", P_KEY, &prefs.celsys_type, 0,0, 0.0,0.0, {"NATIVE", "PIXEL", "EQUATORIAL", "GALACTIC", "ECLIPTIC", "SUPERGALACTIC", ""}}, {"CENTER", P_STRINGLIST, prefs.image_center, 0,0, 0.0, 0.0, {""}, 0, INTERP_MAXDIM, &prefs.nimage_center}, {"CENTER_TYPE", P_KEYLIST, prefs.center_type, 0,0, 0.0,0.0, {"MANUAL", "ALL", "MOST",""}, 1, INTERP_MAXDIM, &prefs.ncenter_type}, {"CLIP_AMPFRAC", P_FLOAT, &prefs.clip_ampfrac, 0, 0, 0.0, BIG}, {"CLIP_LOGNAME", P_STRING, prefs.clip_logname}, {"CLIP_SIGMA", P_FLOAT, &prefs.clip_sigma, 0, 0, 0.0, BIG}, {"CLIP_WRITELOG", P_BOOL, &prefs.clip_logflag}, {"COMBINE", P_BOOL, &prefs.combine_flag}, {"COMBINE_BUFSIZE", P_INT, &prefs.coaddbuf_size, 1, 16384*1024}, {"COMBINE_TYPE", P_KEY, &prefs.coadd_type, 0,0, 0.0,0.0, {"MEDIAN", "AVERAGE", "MIN", "MAX", "WEIGHTED", "CLIPPED", "CHI_OLD", "CHI-MODE", "CHI-MEAN", "SUM", "WEIGHTED_WEIGHT", "MEDIAN_WEIGHT", "AND", "NAND", "OR", "NOR", ""}}, {"COPY_KEYWORDS", P_STRINGLIST, prefs.copy_keywords, 0,0, 0.0, 0.0, {""}, 0, 1024, &prefs.ncopy_keywords}, {"DELETE_TMPFILES", P_BOOL, &prefs.removetmp_flag}, {"FSCALASTRO_TYPE", P_KEY, &prefs.fscalastro_type, 0,0, 0.0,0.0, {"NONE", "FIXED", "VARIABLE", ""}}, {"FSCALE_DEFAULT", P_FLOATLIST, prefs.fscale_default, 0,0, -BIG, BIG, {""}, 1, MAXINFIELD, &prefs.nfscale_default}, {"FSCALE_KEYWORD", P_STRING, prefs.fscale_keyword}, {"GAIN_DEFAULT", P_FLOATLIST, prefs.gain_default, 0,0, 0.0, BIG, {""}, 1, MAXINFIELD, &prefs.ngain_default}, {"GAIN_KEYWORD", P_STRING, prefs.gain_keyword}, {"SATLEV_KEYWORD", P_STRING, prefs.sat_keyword}, {"HEADEROUT_NAME", P_STRINGLIST, prefs.outhead_name, 0,0, 0.0,0.0, {""}, 0, 1, &prefs.nouthead_name}, {"HEADER_NAME", P_STRINGLIST, prefs.inhead_name, 0,0, 0.0,0.0, {""}, 0, MAXINFIELD, &prefs.ninhead_name}, {"HEADER_ONLY", P_BOOL, &prefs.headeronly_flag}, {"HEADER_SUFFIX", P_STRING, prefs.head_suffix}, {"IMAGEOUT_NAME", P_STRING, prefs.outfield_name}, {"IMAGE_SIZE", P_INTLIST, prefs.image_size, 0, 2000000000, 0.0, 0.0, {""}, 1, INTERP_MAXDIM, &prefs.nimage_size}, {"INTERPOLATE", P_BOOLLIST, prefs.interp_flag, 0,0, 0.0,0.0, {""}, 1, MAXINFIELD, &prefs.ninterp_flag}, {"MEM_MAX", P_INT, &prefs.mem_max, 1, 1000000000}, {"NNODES", P_INT, &prefs.nnodes, 1, 65535}, {"NOPENFILES_MAX", P_INT, &prefs.nopenfiles_max, 0, 1000000000}, {"NTHREADS", P_INT, &prefs.nthreads, 0, THREADS_PREFMAX}, {"NODE_INDEX", P_INT, &prefs.node_index, -1, 65534}, {"OVERSAMPLING", P_INTLIST, prefs.oversamp, 0, 2000000000, 0.0,0.0, {""}, 1, INTERP_MAXDIM, &prefs.noversamp}, {"PIXELSCALE_TYPE", P_KEYLIST, prefs.pixscale_type, 0,0, 0.0,0.0, {"MANUAL", "MIN", "MAX", "MEDIAN", "FIT", ""}, 1, INTERP_MAXDIM, &prefs.npixscale_type}, {"PIXEL_SCALE", P_FLOATLIST, prefs.pixscale, 0,0, 0.0, BIG, {""}, 1, INTERP_MAXDIM, &prefs.npixscale}, {"PROJECTION_ERR", P_FLOATLIST, prefs.proj_err, 0,0, 0.0, 1.0, {""}, 1, MAXINFIELD, &prefs.nproj_err}, {"PROJECTION_TYPE", P_STRING, prefs.projection_name}, {"RESAMPLE", P_BOOL, &prefs.resample_flag}, {"RESAMPLE_DIR", P_STRING, prefs.resampdir_name}, {"RESAMPLE_SUFFIX", P_STRING, prefs.resamp_suffix}, {"RESAMPLING_TYPE", P_KEYLIST, prefs.resamp_type, 0,0, 0.0,0.0, {"FLAGS", "NEAREST", "BILINEAR", "LANCZOS2", "LANCZOS3", "LANCZOS4", ""}, 1, INTERP_MAXDIM, &prefs.nresamp_type}, {"RESCALE_WEIGHTS", P_BOOLLIST, prefs.wscale_flag, 0,0, 0.0,0.0, {""}, 1, MAXINFIELD, &prefs.nwscale_flag}, {"SATLEV_DEFAULT", P_FLOATLIST, prefs.sat_default, 0,0, -BIG, BIG, {""}, 1, MAXINFIELD, &prefs.nsat_default}, {"SUBTRACT_BACK", P_BOOLLIST, prefs.subback_flag, 0,0, 0.0,0.0, {""}, 1, MAXINFIELD, &prefs.nsubback_flag}, #ifdef HAVE_CFITSIO {"TILE_COMPRESS", P_BOOL, &prefs.tile_compress_flag}, #endif {"VERBOSE_TYPE", P_KEY, &prefs.verbose_type, 0,0, 0.0,0.0, {"QUIET", "LOG", "NORMAL", "FULL", ""}}, {"VMEM_DIR", P_STRING, prefs.swapdir_name}, {"VMEM_MAX", P_INT, &prefs.vmem_max, 1, 1000000000}, {"WEIGHT_IMAGE", P_STRINGLIST, prefs.inwfield_name, 0,0, 0.0,0.0, {""}, 0, MAXINFIELD, &prefs.ninwfield}, {"WEIGHTOUT_NAME", P_STRING, prefs.outwfield_name}, {"WEIGHT_SUFFIX", P_STRING, prefs.weight_suffix}, {"WEIGHT_THRESH", P_FLOATLIST, prefs.weight_thresh, 0,0, 0.0, BIG, {""}, 0, MAXINFIELD, &prefs.nweight_thresh}, {"WEIGHT_TYPE", P_KEYLIST, prefs.weight_type, 0,0, 0.0,0.0, {"NONE", "BACKGROUND", "MAP_RMS", "MAP_VARIANCE", "MAP_WEIGHT",""}, 1, MAXINFIELD, &prefs.nweight_type}, {"WRITE_FILEINFO", P_BOOL, &prefs.writefileinfo_flag}, {"WRITE_XML", P_BOOL, &prefs.xml_flag}, {"XML_NAME", P_STRING, prefs.xml_name}, {"XSL_URL", P_STRING, prefs.xsl_name}, {""} }; char keylist[sizeof(key)/sizeof(pkeystruct)][32]; const char notokstr[] = {" \t=,;\n\r\""}; char *default_prefs[] = { "# Default configuration file for " BANNER " " MYVERSION, "# EB " DATE, "#", "#----------------------------------- Output -----------------------------------", "IMAGEOUT_NAME coadd.fits # Output filename", "WEIGHTOUT_NAME coadd.weight.fits # Output weight-map filename", "*HEADEROUT_NAME # Out. header filename (overrides suffix)", " ", "*HEADER_NAME # Header filename if suffix not used", "HEADER_ONLY N # Only a header as an output file (Y/N)?", "HEADER_SUFFIX .head # Filename extension for additional headers", #ifdef HAVE_CFITSIO "*TILE_COMPRESS N # Write tile compressed output image (Y/N)?", #endif " ", "#------------------------------- Input Weights --------------------------------", " ", "WEIGHT_TYPE NONE # BACKGROUND,MAP_RMS,MAP_VARIANCE", " # or MAP_WEIGHT", "*RESCALE_WEIGHTS Y # Rescale input weights/variances (Y/N)?", "WEIGHT_SUFFIX .weight.fits # Suffix to use for weight-maps", "WEIGHT_IMAGE # Weightmap filename if suffix not used", " # (all or for each weight-map)", "*WEIGHT_THRESH # Bad pixel weight-threshold", " ", "#------------------------------- Co-addition ----------------------------------", " ", "COMBINE Y # Combine resampled images (Y/N)?", "COMBINE_TYPE MEDIAN # MEDIAN,AVERAGE,MIN,MAX,WEIGHTED,CLIPPED", " # CHI-OLD,CHI-MODE,CHI-MEAN,SUM,", " # WEIGHTED_WEIGHT,MEDIAN_WEIGHT,", " # AND,NAND,OR or NOR", "*CLIP_AMPFRAC 0.3 # Fraction of flux variation allowed", "* # with clipping", "*CLIP_SIGMA 4.0 # RMS error multiple variation allowed", "* # with clipping", "*CLIP_WRITELOG N # Write output file with coordinates of", "* # clipped pixels (Y/N) ", "*CLIP_LOGNAME clipped.log # Name of output file with coordinates", "* # of clipped pixels", "*BLANK_BADPIXELS N # Set to 0 pixels having a weight of 0", " ", "#-------------------------------- Astrometry ----------------------------------", " ", "CELESTIAL_TYPE NATIVE # NATIVE, PIXEL, EQUATORIAL,", " # GALACTIC,ECLIPTIC, or SUPERGALACTIC", "PROJECTION_TYPE TAN # Any WCS projection code or NONE", "PROJECTION_ERR 0.001 # Maximum projection error (in output", " # pixels), or 0 for no approximation", "CENTER_TYPE ALL # MANUAL, ALL or MOST", "CENTER 00:00:00.0, +00:00:00.0 # Coordinates of the image center", "PIXELSCALE_TYPE MEDIAN # MANUAL,FIT,MIN,MAX or MEDIAN", "PIXEL_SCALE 0.0 # Pixel scale", "IMAGE_SIZE 0 # Image size (0 = AUTOMATIC)", " ", "#-------------------------------- Resampling ----------------------------------", " ", "RESAMPLE Y # Resample input images (Y/N)?", "RESAMPLE_DIR . # Directory path for resampled images", "RESAMPLE_SUFFIX .resamp.fits # filename extension for resampled images", " ", "RESAMPLING_TYPE LANCZOS3 # NEAREST,BILINEAR,LANCZOS2,LANCZOS3", " # LANCZOS4 (1 per axis) or FLAGS", "OVERSAMPLING 0 # Oversampling in each dimension", " # (0 = automatic)", "INTERPOLATE N # Interpolate bad input pixels (Y/N)?", " # (all or for each image)", " ", "FSCALASTRO_TYPE FIXED # NONE,FIXED, or VARIABLE", "FSCALE_KEYWORD FLXSCALE # FITS keyword for the multiplicative", " # factor applied to each input image", "FSCALE_DEFAULT 1.0 # Default FSCALE value if not in header", " ", "GAIN_KEYWORD GAIN # FITS keyword for effect. gain (e-/ADU)", "GAIN_DEFAULT 0.0 # Default gain if no FITS keyword found", "* # 0 = infinity (all or for each image)", "*SATLEV_KEYWORD SATURATE # FITS keyword for saturation level (ADU)", "*SATLEV_DEFAULT 50000.0 # Default saturation if no FITS keyword", " ", "#--------------------------- Background subtraction ---------------------------", " ", "SUBTRACT_BACK Y # Subtraction sky background (Y/N)?", " # (all or for each image)", " ", "BACK_TYPE AUTO # AUTO or MANUAL", " # (all or for each image)", "BACK_DEFAULT 0.0 # Default background value in MANUAL", " # (all or for each image)", "BACK_SIZE 128 # Background mesh size (pixels)", " # (all or for each image)", "BACK_FILTERSIZE 3 # Background map filter range (meshes)", " # (all or for each image)", "*BACK_FILTTHRESH 0.0 # Threshold above which the background-", "* # map filter operates", " ", "#------------------------------ Memory management -----------------------------", " ", "VMEM_DIR . # Directory path for swap files", "VMEM_MAX 2047 # Maximum amount of virtual memory (MB)", "MEM_MAX 256 # Maximum amount of usable RAM (MB)", "COMBINE_BUFSIZE 256 # RAM dedicated to co-addition(MB)", " ", "#------------------------------ Miscellaneous ---------------------------------", " ", "DELETE_TMPFILES Y # Delete temporary resampled FITS files", " # (Y/N)?", "COPY_KEYWORDS OBJECT # List of FITS keywords to propagate", " # from the input to the output headers", "WRITE_FILEINFO N # Write information about each input", " # file in the output image header?", "WRITE_XML Y # Write XML file (Y/N)?", "XML_NAME swarp.xml # Filename for XML output", "*XSL_URL " XSL_URL, "* # Filename for XSL style-sheet", "VERBOSE_TYPE NORMAL # QUIET,LOG,NORMAL, or FULL", "*NNODES 1 # Number of nodes (for clusters)", "*NODE_INDEX 0 # Node index (for clusters)", " ", #ifdef USE_THREADS "NTHREADS 0 # Number of simultaneous threads for", " # the SMP version of " BANNER, " # 0 = automatic", #else "NTHREADS 1 # 1 single thread", #endif "*NOPENFILES_MAX 512 # Maximum number of files opened by " BANNER, "" }; swarp-2.41.5/src/prefs.c000066400000000000000000000565321400430667300150270ustar00rootroot00000000000000/* * prefs.c * * Run-time configuration. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2020 IAP/CNRS/SorbonneU * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 26/08/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #ifdef HAVE_MATHIMF_H #include #else #include #endif #ifdef HAVE_GETRLIMIT #include #include #endif #include #include #include #include #if defined(USE_THREADS) \ && (defined(__APPLE__) || defined(FREEBSD) || defined(NETBSD)) /* BSD, Apple */ #include #include #elif defined(USE_THREADS) && defined(HAVE_MPCTL) /* HP/UX */ #include #endif #include "define.h" #include "globals.h" #include "fits/fitscat.h" #include "fitswcs.h" #include "prefs.h" #include "preflist.h" prefstruct prefs; /********************************* dumpprefs ********************************/ /* Print the default preference parameters. */ void dumpprefs(int state) { char **dp; dp = default_prefs; while (**dp) if (**dp != '*') printf("%s\n",*(dp++)); else if (state) printf("%s\n",*(dp++)+1); else dp++; return; } /********************************* readprefs ********************************/ /* Read a configuration file in ``standard'' format (see the SExtractor documentation) */ void readprefs(char *filename, char **argkey, char **argval, int narg) { FILE *infile; char *cp, str[MAXCHARL], *keyword, *value, **dp; int i, ival, nkey, warn, argi, flagc, flagd, flage, flagz; double dval; #ifdef HAVE_GETENV static char value2[MAXCHARL],envname[MAXCHAR]; char *dolpos, *listbuf; #endif if ((infile = fopen(filename,"r")) == NULL) { flage = 1; warning(filename, " not found, using internal defaults"); } else flage = 0; /*Build the keyword-list from pkeystruct-array */ for (i=0; key[i].name[0]; i++) strcpy(keylist[i], key[i].name); keylist[i][0] = '\0'; /*Scan the configuration file*/ listbuf = NULL; argi=0; flagc = 0; flagd = 1; dp = default_prefs; for (warn=0;;) { if (flagd) { if (**dp) { if (**dp=='*') strcpy(str, *(dp++)+1); else strcpy(str, *(dp++)); } else flagd = 0; } if (!flagc && !flagd) if (flage || !fgets(str, MAXCHARL, infile)) flagc=1; if (flagc) { if (argi=10) error(EXIT_FAILURE, "*Error*: No valid keyword found in ", filename); nkey = findkeys(keyword, keylist, FIND_STRICT); if (nkey!=RETURN_ERROR) { value = strtok((char *)NULL, notokstr); #ifdef HAVE_GETENV /*------ Expansion of environment variables (preceded by '$') */ if (value && (dolpos=strchr(value, '$'))) { int nc; char *valuet,*value2t, *envval; value2t = value2; valuet = value; while (dolpos) { while (valuet=key[nkey].dmin && dval<=key[nkey].dmax) *(double *)(key[nkey].ptr) = dval; else error(EXIT_FAILURE, keyword," keyword out of range"); break; case P_INT: if (!value || value[0]==(char)'#') error(EXIT_FAILURE, keyword," keyword has no value!"); if (*value=='@') value = listbuf = list_to_str(value+1); ival = strtol(value, NULL, 0); if (ival>=key[nkey].imin && ival<=key[nkey].imax) *(int *)(key[nkey].ptr) = ival; else error(EXIT_FAILURE, keyword, " keyword out of range"); break; case P_STRING: if (!value || value[0]==(char)'#') error(EXIT_FAILURE, keyword," string is empty!"); if (*value=='@') value = listbuf = list_to_str(value+1); strcpy((char *)key[nkey].ptr, value); break; case P_BOOL: if (!value || value[0]==(char)'#') error(EXIT_FAILURE, keyword," keyword has no value!"); if (*value=='@') value = listbuf = list_to_str(value+1); if ((cp = strchr("yYnN", (int)value[0]))) *(int *)(key[nkey].ptr) = (tolower((int)*cp)=='y')?1:0; else error(EXIT_FAILURE, keyword, " value must be Y or N"); break; case P_KEY: if (!value || value[0]==(char)'#') error(EXIT_FAILURE, keyword," keyword has no value!"); if (*value=='@') value = listbuf = list_to_str(value+1); if ((ival = findkeys(value, key[nkey].keylist,FIND_STRICT)) != RETURN_ERROR) *(int *)(key[nkey].ptr) = ival; else error(EXIT_FAILURE, keyword, " set to an unknown keyword"); break; case P_BOOLLIST: if (value && *value=='@') value = strtok(listbuf = list_to_str(value+1), notokstr); for (i=0; i=key[nkey].nlistmax) error(EXIT_FAILURE, keyword, " has too many members"); if ((cp = strchr("yYnN", (int)value[0]))) ((int *)(key[nkey].ptr))[i] = (tolower((int)*cp)=='y')?1:0; else error(EXIT_FAILURE, keyword, " value must be Y or N"); value = strtok((char *)NULL, notokstr); } if (i=key[nkey].nlistmax) error(EXIT_FAILURE, keyword, " has too many members"); ival = strtol(value, NULL, 0); if (ival>=key[nkey].imin && ival<=key[nkey].imax) ((int *)key[nkey].ptr)[i] = ival; else error(EXIT_FAILURE, keyword, " keyword out of range"); value = strtok((char *)NULL, notokstr); } if (i=key[nkey].nlistmax) error(EXIT_FAILURE, keyword, " has too many members"); dval = atof(value); if (dval>=key[nkey].dmin && dval<=key[nkey].dmax) ((double *)key[nkey].ptr)[i] = dval; else error(EXIT_FAILURE, keyword, " keyword out of range"); value = strtok((char *)NULL, notokstr); } if (i=key[nkey].nlistmax) error(EXIT_FAILURE, keyword, " has too many members"); if ((ival = findkeys(value, key[nkey].keylist, FIND_STRICT)) != RETURN_ERROR) ((int *)(key[nkey].ptr))[i] = ival; else error(EXIT_FAILURE, keyword, " set to an unknown keyword"); value = strtok((char *)NULL, notokstr); } if (i=key[nkey].nlistmax) error(EXIT_FAILURE, keyword, " has too many members"); free(((char **)key[nkey].ptr)[i]); QMALLOC(((char **)key[nkey].ptr)[i], char, MAXCHAR); strcpy(((char **)key[nkey].ptr)[i], value); value = strtok((char *)NULL, notokstr); if (flagz) break; } if (iMAXLISTSIZE) error(EXIT_FAILURE, "*Error*: Too many parameters in ", listname); l = strlen(str)+1; if (bufpos+l > bufsize) { bufsize += 8*MAXCHAR; QREALLOC(listbuf, char, bufsize); } if (bufpos) listbuf[bufpos-1] = ' '; strcpy(listbuf+bufpos, str); bufpos += l; } fclose(fp); return listbuf; } /********************************* useprefs *********************************/ /* Update various structures according to the prefs. */ void useprefs(void) { unsigned short ashort=1; char *pstr; int i,j, weight_flag; #ifdef USE_THREADS int nproc; #endif /* Multithreading */ #ifdef USE_THREADS if (!prefs.nthreads) { /*-- Get the number of processors for parallel builds */ /*-- See, e.g. http://ndevilla.free.fr/threads */ nproc = -1; #if defined(_SC_NPROCESSORS_ONLN) /* AIX, Solaris, Linux */ nproc = (int)sysconf(_SC_NPROCESSORS_ONLN); #elif defined(_SC_NPROCESSORS_CONF) nproc = (int)sysconf(_SC_NPROCESSORS_CONF); #elif defined(__APPLE__) || defined(FREEBSD) || defined(NETBSD) /* BSD, Apple */ { int mib[2]; size_t len; mib[0] = CTL_HW; mib[1] = HW_NCPU; len = sizeof(nproc); sysctl(mib, 2, &nproc, &len, NULL, 0); } #elif defined (_SC_NPROC_ONLN) /* SGI IRIX */ nproc = sysconf(_SC_NPROC_ONLN); #elif defined(HAVE_MPCTL) /* HP/UX */ nproc = mpctl(MPC_GETNUMSPUS_SYS, 0, 0); #endif if (nproc>0) prefs.nthreads = nproc; else { prefs.nthreads = 2; warning("Cannot find the number of CPUs on this system:", "NTHREADS defaulted to 2"); } } #else if (prefs.nthreads != 1) { prefs.nthreads = 1; warning("NTHREADS != 1 ignored: ", "this build of " BANNER " is single-threaded"); } #endif #ifdef HAVE_GETRLIMIT /* Check that the maximum number of open files is < what the system allows */ if (prefs.combine_flag) { struct rlimit rlim; if (prefs.nopenfiles_max && getrlimit(RLIMIT_NOFILE, &rlim) != -1 && rlim.rlim_cur< RLIM_INFINITY && prefs.nopenfiles_max > (unsigned int)rlim.rlim_cur) { sprintf(gstr, "%d", (unsigned int)rlim.rlim_cur); warning("NOPENFILES_MAX larger than the system limit currently set at ", gstr); } } #endif /* Trigger integer mode if RESAMPLE is Y and RESAMPLING_TYPE is set to FLAGS */ prefs.outfield_bitpix = BP_FLOAT; for (i=0; i prefs.ninwfield) { for (i=0; ii; j--) prefs.inwfield_name[j] = prefs.inwfield_name[j-1]; /*-------- ... and replace the current one with a dummy one */ QMALLOC(prefs.inwfield_name[i], char, MAXCHAR); sprintf(prefs.inwfield_name[i], "INTERNAL"); prefs.ninwfield++; } } /*---- Now check that we haven't gone too far!! */ if (prefs.ninwfield > prefs.nweight_type) error(EXIT_FAILURE, "*Error*: the number of WEIGHT_TYPEs and ", "weight-maps do not match"); } if (prefs.ninwfield != prefs.ninfield) { /*---- Weight-maps given through the WEIGHT_IMAGE keyword */ if (prefs.ninwfield == 1) { warning("Several input images and a single weight-map found: ", "applying the same weight-map to all images"); prefs.ninwfield = prefs.ninfield; for (i=1; i. * * Last modified: 26/08/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _FIELD_H_ #include "field.h" #endif #ifndef _FITSWCS_H_ #include "fitswcs.h" #endif #ifndef _COADD_H_ #include "coadd.h" #endif #ifndef _INTERPOLATE_H_ #include "interpolate.h" #endif #ifndef _WEIGHT_H_ #include "weight.h" #endif #ifndef _PREFS_H_ #define _PREFS_H_ /*----------------------------- Internal constants --------------------------*/ #define MAXCHARL 16384 /* max. nb of chars in a string list */ #define MAXLIST (MAXINFIELD) /* max. nb of list members */ #define MAXLISTSIZE (100*MAXLIST) /* max size of list */ /*--------------------------------- typedefs --------------------------------*/ /*------------------------------- preferences -------------------------------*/ typedef struct { char **command_line; /* Command line */ int ncommand_line; /* nb of params */ char prefs_name[MAXCHAR]; /* prefs filename*/ char *(infield_name[MAXINFIELD]);/* Filename(s) of input images */ int ninfield; /* Number of input images */ char *(inwfield_name[MAXINFIELD]);/* Filename(s) of input weights */ int ninwfield; /* Number of input weight-maps */ char *(inhead_name[MAXINFIELD]);/* Filename(s) of input headers */ int ninhead_name; /* Number of input headers */ char head_suffix[MAXCHAR]; /* Generic suffix for FITS headers */ char resamp_suffix[MAXCHAR]; /* Generic suffix for resampled FITS */ char weight_suffix[MAXCHAR]; /* Generic suffix for input weights */ char outfield_name[MAXCHAR]; /* Output image filename */ char outwfield_name[MAXCHAR];/* Output weight-map filename */ char *(outhead_name[MAXINFIELD]);/* Output header filename */ int nouthead_name; /* 0 or 1 */ int outfield_bitpix; /* Output image pixel type */ weightenum weight_type[MAXINFIELD];/* Weight type */ int nweight_type; /* nb of params */ double weight_thresh[MAXINFIELD];/* Weight threshold */ int nweight_thresh; /* nb of params */ int wscale_flag[MAXINFIELD];/* Weight rescaling flag */ int nwscale_flag; /* nb of params */ int interp_flag[MAXINFIELD];/* Interpolation flag */ int ninterp_flag; /* nb of params */ int subback_flag[MAXINFIELD];/* Background-subtraction flag */ int nsubback_flag; /* nb of params */ int oversamp[INTERP_MAXDIM];/* Oversampling (per pixel/ per dim) */ int noversamp; /* nb of params */ backenum back_type[MAXINFIELD]; /* Background subtraction type */ int nback_type; /* nb of params */ int back_size[MAXINFIELD]; /* Background mesh size */ int nback_size; /* nb of params */ int back_fsize[MAXINFIELD]; /* Background filter size */ int nback_fsize; /* nb of params */ double back_default[MAXINFIELD];/* Default background in MANUAL */ int nback_default; /* nb of params */ double back_fthresh; /* Background filter threshold */ char gain_keyword[MAXCHAR]; /* FITS keyword for gain */ double gain_default[MAXINFIELD];/* Default gain (e-/ADU) */ int ngain_default; /* nb of params */ char sat_keyword[MAXCHAR]; /* FITS keyword for saturation */ double sat_default[MAXINFIELD];/* Default saturation (ADU) */ int nsat_default; /* nb of params */ char fscale_keyword[MAXCHAR];/* FITS keyword for flux scale */ double fscale_default[MAXINFIELD];/* Default flux scale */ int nfscale_default; /* nb of params */ enum {FSCALASTRO_NONE, FSCALASTRO_FIXED, FSCALASTRO_VARIABLE} fscalastro_type; /* Astrometric flux-scaling type */ interpenum resamp_type[INTERP_MAXDIM];/* Image resampling method */ int nresamp_type; /* nb of params */ coaddenum coadd_type; /* Coaddition type */ double clip_ampfrac; /* Fraction of ampl. variation allowed*/ /* before clipping */ double clip_sigma; /* RMS multiple variation allowed */ /* before clipping */ int clip_logflag; /* Save clipping logfile? */ char clip_logname[MAXCHAR]; /* filename for clipping log */ int blank_flag; /* Blank pixels with a weight of 0? */ /* Output image coordinates */ char projection_name[MAXCHAR];/* Projection WCS code */ celsysenum celsys_type; /* Celestial system type */ enum {CENTER_MANUAL, CENTER_ALL, CENTER_MOST} center_type[INTERP_MAXDIM];/* Centering type */ int ncenter_type; /* nb of params */ char *(image_center[INTERP_MAXDIM]);/* Center coordinates */ int nimage_center; /* nb of params */ enum {PIXSCALE_MANUAL,PIXSCALE_MIN,PIXSCALE_MAX,PIXSCALE_MEDIAN,PIXSCALE_FIT} pixscale_type[INTERP_MAXDIM];/* Pixel scale type */ int npixscale_type; /* nb of params */ double pixscale[INTERP_MAXDIM];/* Pixel scales */ int npixscale; /* nb of params */ int image_size[INTERP_MAXDIM];/* Pixel scales */ int nimage_size; /* nb of params */ double proj_err[MAXINFIELD]; /* max astrom approximation error */ int nproj_err; /* nb of params */ /* Temporary files */ int removetmp_flag; /* Remove temporary FITS files ? */ /* Virtual memory handling */ int mem_max; /* Max amount of allocatable RAM */ int vmem_max; /* Max amount of allocatable VMEM */ char swapdir_name[MAXCHAR]; /* Name of virtual mem directory */ char resampdir_name[MAXCHAR];/* Name of resampling directory */ int coaddbuf_size; /* Amount of RAM for coadd buffer */ /* Multithreading */ int nthreads; /* Number of active threads */ /* Misc */ int combine_flag; /* Write coadded image? */ int headeronly_flag; /* Restrict output to a header? */ int resample_flag; /* Resample input images? */ int writefileinfo_flag; /* Write info for each input file ? */ char *(copy_keywords[1024]); /* FITS keywords to be propagated */ int ncopy_keywords; /* nb of params */ int nnodes; /* Number of nodes (for clusters) */ int node_index; /* Node index (for multiprocessing) */ int nopenfiles_max; /* Max. number of files opened */ enum {QUIET, LOG, NORM, FULL} verbose_type; /* display type */ int xml_flag; /* Write XML file? */ char xml_name[MAXCHAR]; /* XML file name */ char xsl_name[MAXCHAR]; /* XSL file name (or URL) */ char sdate_start[12]; /* SWarp start date */ char stime_start[12]; /* SWarp start time */ char sdate_end[12]; /* SWarp end date */ char stime_end[12]; /* SWarp end time */ double time_diff; /* Execution time */ #ifdef HAVE_CFITSIO int tile_compress_flag; /* Write tile-compressed output file? */ #endif } prefstruct; extern prefstruct prefs; /*-------------------------------- protos -----------------------------------*/ extern char *list_to_str(char *listname); extern int cistrcmp(char *cs, char *ct, int mode); extern void dumpprefs(int state), readprefs(char *filename,char **argkey,char **argval,int narg), useprefs(void); #endif swarp-2.41.5/src/projapprox.c000066400000000000000000000432461400430667300161120ustar00rootroot00000000000000/* * projapprox.c * * Approximate astrometric re-projections (to speed up warping). * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2003-2013 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 19/07/2013 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include #include #include #include "define.h" #include "types.h" #include "globals.h" #include "fits/fitscat.h" #include "fitswcs.h" #include "projapprox.h" /****** projapp_init ********************************************************* PROTO projappstruct *projapp_init(wcsstruct *wcsin, wcsstruct *wcsout, double projmaxerr, int areaflag) PURPOSE Prepare all the necessary data for approximating a reprojection. INPUT Input pointer to wcs structure pointer, Output wcs structure pointer, Maximum reprojection error (pixels) allowed, Pixel area flag (triggers mapping of relative pixel areas if !=0). OUTPUT Pointer to an allocated projappstruct structure, or NULL if approximation failed NOTES Currently limited to 2D (returns NULL otherwise). AUTHOR E. Bertin (IAP) VERSION 19/07/2013 ***/ projappstruct *projapp_init(wcsstruct *wcsin, wcsstruct *wcsout, double projmaxerr, int areaflag) { projappstruct *projapp; double *projpos[NAXIS], rawposout[NAXIS],rawpos[NAXIS],rawposmin[NAXIS], wcspos[NAXIS], stepc[NAXIS], *step, *projline,*projlinet,*projappline,*projapplinet, *projarea, maxerror, cerror, defstep, stepcx, worldc; int linecount[NAXIS], stepcount[NAXIS], npointsc[NAXIS], *npoints, d,i,j, naxis,naxisnmax, ngridpoints,npointstot, npointsmax, npointscx, stepcountx, nlinesc, swapflag; /* The present version only works in 2D */ if (wcsin->naxis != 2 || wcsout->naxis != 2) return (projappstruct *)NULL; QCALLOC(projapp, projappstruct, 1); naxis = projapp->naxis = wcsout->naxis; /* Handle both angular and non-angular coordinates */ projapp->lng = wcsin->lng; projapp->lat = wcsin->lat; /* Find the largest dimension in pixels */ naxisnmax = 0; for (d=0; dnaxisn[d] > naxisnmax) naxisnmax = wcsout->naxisn[d]; /* Check if lng and lat are swapped between in and out wcs (vicious idea!) */ swapflag = (((wcsin->lng != wcsout->lng) || (wcsin->lat != wcsout->lat)) && (wcsin->lng != wcsin->lat) && (wcsout->lng != wcsout->lat)); /* Loop until the error is small enough */ ngridpoints = PROJAPP_NGRIDPOINTS; npoints = projapp->npoints; step = projapp->step; for (maxerror = BIG; maxerror > projmaxerr; ngridpoints *= 2) { /*-- Start all over again */ for (d=0; dprojpos[d]) { free(projapp->projpos[d]); projapp->projpos[d] = NULL; } defstep = naxisnmax /(ngridpoints-1.0); /*-- Adapt the suggested step to each dimension */ npointstot = npointsmax = 1; for (d=0; dnaxisn[d] / defstep + 1.0); if (npoints[d]<2) npoints[d] = 2; step[d] = wcsout->naxisn[d]/(npoints[d]-1.0); npointstot *= npoints[d]; npointsmax *= wcsout->naxisn[d] / PROJAPP_MINSTEP; } /*-- if too many grid points necessary, forget it! */ if (npointstot > npointsmax) { if (ngridpoints > PROJAPP_NGRIDPOINTS) warning("Astrometric approximation too inaccurate for ", "this re-projection"); projapp_end(projapp); return (projappstruct *)NULL; } projapp->npointstot = npointstot; /*-- Allocate memory and set the starting grid coordinate */ for (d=0; dprojpos[d], double, npointstot); projpos[d] = projapp->projpos[d]; rawposout[d] = rawposmin[d] = 0.5; linecount[d] = stepcount[d] = 0; } if (areaflag) { QMALLOC(projapp->projarea, double, npointstot); projarea = projapp->projarea; } else projarea = NULL; /* to avoid gcc -Wall warnings */ /*-- Fill the arrays */ for (i=npointstot; i--;) { if (raw_to_wcs(wcsout, rawposout, wcspos) != RETURN_OK) /*---- There is a coordinate "outside the sky" */ { warning("Astrometric approximation impossible for ", "this re-projection"); projapp_end(projapp); return (projappstruct *)NULL; } if (swapflag) { worldc = wcspos[wcsout->lat]; wcspos[wcsout->lat] = wcspos[wcsin->lat]; wcspos[wcsin->lat] = worldc; } if (wcs_to_raw(wcsin, wcspos, rawpos) != RETURN_OK) /*---- There is a coordinate "outside the sky" */ { warning("Astrometric approximation impossible for ", "this re-projection"); projapp_end(projapp); return (projappstruct *)NULL; } for (d=0; dnaxisn[d] / stepc[d] + 1.0); if (d) nlinesc *= npointsc[d]; linecount[d] = stepcount[d] = 0; } npointscx = npointsc[0]; stepcx = stepc[0]; QMALLOC(projline, double, naxis*npointscx); QMALLOC(projappline, double, naxis*npointscx); maxerror = 0.0; for (i=nlinesc; i--;) { rawposout[0] = rawposmin[0]; /*---- The approximation */ projapp_line(projapp, rawposout, stepcx, npointscx, projappline, NULL); /*---- The exact computation */ projlinet = projline; stepcountx = 0; for (j=npointscx; j--; projlinet += naxis) { raw_to_wcs(wcsout, rawposout, wcspos); if (swapflag) { worldc = wcspos[wcsout->lat]; wcspos[wcsout->lat] = wcspos[wcsin->lat]; wcspos[wcsin->lat] = worldc; } wcs_to_raw(wcsin, wcspos, projlinet); rawposout[0] = rawposmin[0] + (++stepcountx)*stepcx; } /*---- The comparison */ projlinet = projline; projapplinet = projappline; for (j=npointscx; j--;) for (d=0; d maxerror) maxerror = cerror; for (d=1; dnaxis; d++) { if (projapp->projpos[d]) { free(projapp->projpos[d]); projapp->projpos[d] = NULL; } if (projapp->dprojpos2x[d]) { free(projapp->dprojpos2x[d]); projapp->dprojpos2x[d] = NULL; } if (projapp->dprojpos2y[d]) { free(projapp->dprojpos2y[d]); projapp->dprojpos2y[d] = NULL; } } free(projapp->projarea); free(projapp->dprojarea2x); free(projapp->dprojarea2y); free(projapp); return; } /****** projapp_dmap ********************************************************* PROTO void projapp_dmap(projappstruct *projapp) PURPOSE Prepare bicubic-splines by computing arrays of 2nd derivatives. INPUT Input projappstruct pointer. OUTPUT -. NOTES Currently limited to 2D vectors. AUTHOR E. Bertin (IAP) VERSION 03/01/2008 ***/ void projapp_dmap(projappstruct *projapp) { double *u, *map,*dmap, *mapt,*dmapt, temp; int x,y,d, naxis, nbx,nbxm1,nby,nbym1; naxis = projapp->naxis; nbx = projapp->npoints[0]; nbxm1 = nbx - 1; nby = projapp->npoints[1]; nbym1 = nby - 1; /*-- Computation of 2nd derivatives along x */ QMALLOC(u, double, nbxm1); /* temporary array */ for (d=0; ddprojpos2x[d], double, projapp->npointstot); map = projapp->projpos[d]; dmap = projapp->dprojpos2x[d]; for (y=nby; y--;) { mapt = map+1; dmapt = dmap; map += nbx; dmap += nbx; if (nbx>1) { *dmapt = *u = 0.0; /* "natural" lower boundary condition */ for (x=nbxm1; --x; mapt++) { temp = -1.0/(*dmapt+4.0); *(++dmapt) = temp; temp *= *(u++) - 6.0*(*(mapt+1)+*(mapt-1)-2.0**mapt); *u = temp; } *(++dmapt) = 0.0; /* "natural" upper boundary condition */ for (x=nbx-2; x--;) { temp = *(dmapt--); *dmapt = (*dmapt*temp+*(u--))/6.0; } } else *dmapt = 0.0; } } if (projapp->projarea) { /*-- The same for relative pixel areas */ QMALLOC(projapp->dprojarea2x, double, projapp->npointstot); map = projapp->projarea; dmap = projapp->dprojarea2x; for (y=nby; y--;) { mapt = map+1; dmapt = dmap; map += nbx; dmap += nbx; if (nbx>1) { *dmapt = *u = 0.0; /* "natural" lower boundary condition */ for (x=nbxm1; --x; mapt++) { temp = -1.0/(*dmapt+4.0); *(++dmapt) = temp; temp *= *(u++) - 6.0*(*(mapt+1)+*(mapt-1)-2.0**mapt); *u = temp; } *(++dmapt) = 0.0; /* "natural" upper boundary condition */ for (x=nbx-2; x--;) { temp = *(dmapt--); *dmapt = (*dmapt*temp+*(u--))/6.0; } } else *dmapt = 0.0; } } free(u); /* Derivatives along "y" */ QMALLOC(u, double, nbym1); /* temporary array */ for (d=0; ddprojpos2y[d], double, projapp->npointstot); map = projapp->projpos[d]; dmap = projapp->dprojpos2y[d]; for (x=0; x1) { *dmapt = *u = 0.0; /* "natural" lower boundary condition */ mapt += nbx; for (y=nbym1; --y; mapt+=nbx) { temp = -1.0/(*dmapt+4.0); *(dmapt += nbx) = temp; temp *= *(u++) - 6.0*(*(mapt+nbx)+*(mapt-nbx)-2.0**mapt); *u = temp; } *(dmapt+=nbx) = 0.0; /* "natural" upper boundary condition */ for (y=nby-2; y--;) { temp = *dmapt; dmapt -= nbx; *dmapt = (*dmapt*temp+*(u--))/6.0; } } else *dmapt = 0.0; } } if (projapp->projarea) { /*-- The same for relative pixel areas */ QMALLOC(projapp->dprojarea2y, double, projapp->npointstot); map = projapp->projarea; dmap = projapp->dprojarea2y; for (x=0; x1) { *dmapt = *u = 0.0; /* "natural" lower boundary condition */ mapt += nbx; for (y=nbym1; --y; mapt+=nbx) { temp = -1.0/(*dmapt+4.0); *(dmapt += nbx) = temp; temp *= *(u++) - 6.0*(*(mapt+nbx)+*(mapt-nbx)-2.0**mapt); *u = temp; } *(dmapt+=nbx) = 0.0; /* "natural" upper boundary condition */ for (y=nby-2; y--;) { temp = *dmapt; dmapt -= nbx; *dmapt = (*dmapt*temp+*(u--))/6.0; } } else *dmapt = 0.0; } } free(u); return; } /****** projapp_line ********************************************************* PROTO void projapp_line(projappstruct *projapp, double *startposin, double step, int npos, double *posout, double *areaout) PURPOSE Approximate several reprojections on the same line INPUT Input projappstruct pointer, ptr to input coordinate vector array (of size naxis*nvectors), step along "x" (NAXIS1) dimension, number of input vectors. ptr to output coordinate vector array (where the results are written). ptr to output pixel area vector array (where the results are written). OUTPUT -. NOTES Pixel area are computed only if areaout != NULL. Currently limited to 2D vectors. AUTHOR E. Bertin (IAP) VERSION 03/01/2008 ***/ void projapp_line(projappstruct *projapp, double *startposin, double step, int npos, double *posout, double *areaout) { double *node,*nodep, *anode, *blo,*bhi,*dblo,*dbhi, *posoutt,*areaoutt, xstep, dx,ddx,cdx, dy,dy3,cdy,cdy3; int d,i,j, xl,yl, x, ax,ax0,dax, nbx,nbxm1,nby, ylstep, nxnodes, naxis; naxis = projapp->naxis; nbx = projapp->npoints[0]; nbxm1 = nbx - 1; nby = projapp->npoints[1]; node = anode = NULL; /* To avoid gcc -Wall warnings */ /*-- Prepare interpolation along x */ if (nbx>1) { xstep = 1.0/projapp->step[0]; /*-- Reduced start x coordinate */ dx = (startposin[0]-0.5)*xstep; dx -= (xl = (int)dx); xstep *= step; /* input step in reduced units */ if (xl<0) { xl = 0; dx -= 1.0; } else if (xl>=nbx-1) { xl = nbx<2 ? 0 : nbx-2; dx += 1.0; } } else { xl = 0; dx = 0.0; xstep = 1.0; } /* Prepare interpolation along y */ if (nby > 1) { /*-- Reduced start y coordinate */ dy = (startposin[1]-0.5)/projapp->step[1]; dy -= (yl = (int)dy); if (yl<0) { yl = 0; dy -= 1.0; } else if (yl>=nby-1) { yl = nby<2 ? 0 : nby-2; dy += 1.0; } cdy = 1.0 - dy; dy3 = (dy*dy*dy-dy); cdy3 = (cdy*cdy*cdy-cdy); ylstep = nbx*yl; nxnodes = (int)(dx+npos*xstep) + 1; if (nxnodes > (nbx-xl)) nxnodes = nbx - xl; QMALLOC(node, double, nxnodes); /* Interpolated map */ if (areaout) QMALLOC(anode, double, nxnodes); /* Interpolated map */ } else { ylstep = 0.0; /* To avoid gcc -Wall warnings */ dy = dy3 = cdy = cdy3 = nxnodes = 0.0; /* To avoid gcc -Wall warnings */ } for (d=0; d 1) { /*---- Interpolation along y for each node */ blo = projapp->projpos[d] + ylstep + xl; bhi = blo + nbx; dblo = projapp->dprojpos2y[d] + ylstep + xl; dbhi = dblo + nbx; nodep = node; for (x=nxnodes; x--;) *(nodep++) = cdy**(blo++) + dy**(bhi++) + cdy3**(dblo++)+dy3**(dbhi++); } else node = projapp->projpos[d] + xl; if (nbx > 1) { /*---- Interpolation along x */ blo = node; bhi = blo + 1; dblo = projapp->dprojpos2x[d] + xl; dbhi = dblo + 1; ax0 = xl; posoutt = posout+d; for (i=0,j=npos; j--; i++) { ax = (int)(ddx = xl + dx + i*xstep); if ((int)(dax = ax-ax0) && ax 1) { /*---- Interpolation along y for each node */ blo = projapp->projarea + ylstep + xl; bhi = blo + nbx; dblo = projapp->dprojarea2y + ylstep + xl; dbhi = dblo + nbx; nodep = anode; for (x=nxnodes; x--;) *(nodep++) = cdy**(blo++) + dy**(bhi++) + cdy3**(dblo++)+dy3**(dbhi++); } else node = projapp->projarea + xl; if (nbx > 1) { /*---- Interpolation along x */ blo = anode; bhi = blo + 1; dblo = projapp->dprojarea2x + xl; dbhi = dblo + 1; ax0 = xl; areaoutt = areaout; for (i=0,j=npos; j--; i++) { ax = (int)(ddx = xl + dx + i*xstep); if ((int)(dax = ax-ax0) && ax1) { if (areaout) free(anode); free(node); } return; } swarp-2.41.5/src/projapprox.h000066400000000000000000000053721400430667300161150ustar00rootroot00000000000000/* * projapprox.h * * Include file for projapprox.c. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2003-2019 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 20/12/2019 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _FITSWCS_H_ #include "fitswcs.h" #endif #ifndef _PROJAPPROX_H_ #define _PROJAPPROX_H_ /*-------------------------------- macros -----------------------------------*/ /*------------------------------- constants ---------------------------------*/ #define PROJAPP_NGRIDPOINTS 32 /* Min number of control nodes/dim */ #define PROJAPP_MINSTEP 16 /* Min dist between nodes (pixels) */ #define PROJAPP_CHECKOVERSAMP 4 /* node oversampling for checking */ /*--------------------------------- typedefs --------------------------------*/ /*-------------------------- structure definitions --------------------------*/ typedef struct projapp { int naxis; /* Number of dimensions */ int lng,lat; /* Indices for longitude and latitude */ int npoints[NAXIS]; /* Number of nodes per dimension */ int npointstot; /* Total number of nodes */ double step[NAXIS]; /* Step (in pixels) between each node */ double *projpos[NAXIS];/* coordinate value at each node */ double *dprojpos2x[NAXIS];/* second derivative along x at each node */ double *dprojpos2y[NAXIS];/* second derivative along y at each node */ double *projarea; /* coordinate value at each node */ double *dprojarea2x; /* second derivative along x at each node */ double *dprojarea2y; /* second derivative along y at each node */ } projappstruct; /*----------------------- miscellaneous variables ---------------------------*/ projappstruct *projapp_init(wcsstruct *wcsin, wcsstruct *wcsout, double projmaxerr, int areaflag); void projapp_dmap(projappstruct *projapp), projapp_end(projappstruct *projapp), projapp_line(projappstruct *projapp, double *startposin, double step, int npos, double *posout, double *areaout); /*-------------------------------- protos -----------------------------------*/ #endif swarp-2.41.5/src/resample.c000066400000000000000000000571631400430667300155210ustar00rootroot00000000000000/* * resample.c * * Manage high-level resampling. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2021 IAP/CNRS/SorbonneU * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 27/01/2021 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include #include #include #include "define.h" #include "types.h" #include "globals.h" #include "fits/fitscat.h" #include "fitswcs.h" #include "data.h" #include "field.h" #include "header.h" #include "interpolate.h" #include "prefs.h" #include "projapprox.h" #include "resample.h" #ifdef USE_THREADS #include "threads.h" #endif #include "weight.h" #include "wcs/wcs.h" #ifdef USE_THREADS pthread_t *rthread; pthread_mutex_t linemutex; pthread_cond_t *linecond; tabstruct *ftab, *wtab; int *queue,*proc,*writeflag, absline,procline,writeline; #else extern int nproc; #endif fieldstruct *infield,*inwfield, *field, *wfield; ikernelstruct **ikernel; wcsstruct **wcsinp, **wcsoutp; projappstruct *projapp; double rawmin[NAXIS], rawmax[NAXIS],rawpos0[NAXIS], stepover[NAXIS], **rawposp, **rawbuf, **oversampbuf,**oversampwbuf, **rawbufarea, ascale; PIXTYPE **routbuf,**routwbuf; FLAGTYPE **routibuf,**routwibuf, **oversampibuf,**oversampwibuf; int **oversampnbuf, *oversamp, noversamp, oversampflag, width, height, naxis, nlines, approxflag, dispstep, riflag; /*------------------------------ function -----------------------------------*/ #ifdef USE_THREADS static int pthread_nextline(int l); static void *pthread_warp_lines(void *arg); #endif static void warp_line(int p); /****** resample_field ******************************************************* PROTO void resample_field(fieldstruct **pinfield, fieldstruct **pinwfield, fieldstruct *outfield, fieldstruct *outwfield, interpenum *interptype) PURPOSE Resample an image. INPUT Input pointer to field structure pointer, Input pointer weight-map field structure pointer, Output total field structure pointer, Output total weight-map field structure pointer, Interpolation type. Output OUTPUT -. NOTES The structure pointers pointed by pinfield and and pinwfield are updated and point to the resampled fields on output. AUTHOR E. Bertin (IAP) VERSION 26/08/2020 ***/ void resample_field(fieldstruct **pinfield, fieldstruct **pinwfield, fieldstruct *outfield, fieldstruct *outwfield, interpenum *interptype) { #ifdef USE_THREADS static pthread_attr_t pthread_attr; int p; #else int y; #endif wcsstruct wcsloc, *wcs; static char filename[MAXCHAR],filename2[MAXCHAR], resampext1[MAXCHAR], resampext2[MAXCHAR]; char *pstr; double ascale1, projerr; int d, l; infield = *pinfield; inwfield = *pinwfield; /* Create new file name */ strcpy(filename2, infield->rfilename); #ifdef HAVE_CFITSIO // TODO HACK deal with special case of .fits.fz files if ((pstr=strstr(filename2, ".fits.fz"))) *pstr = '\0'; else #endif if ((pstr=strrchr(filename2, '.'))) *pstr = '\0'; if (infield->version>1) sprintf(pstr, "_v%d", infield->version); if (infield->frameno) sprintf(filename, "%s/%s.%04d%s", prefs.resampdir_name, filename2, infield->frameno, prefs.resamp_suffix); else sprintf(filename, "%s/%s%s", prefs.resampdir_name, filename2, prefs.resamp_suffix); /* We make a copy of the output field */ field = inherit_field(filename, outfield, FIELD_WRITE); field->backmean = infield->backmean; field->fbackmean = infield->fbackmean; field->backsig = infield->backsig; field->fbacksig = infield->fbacksig; field->gain = infield->gain; field->fgain = infield->fgain; field->saturation = infield->saturation; field->fsaturation = infield->fsaturation; field->exptime = infield->exptime; field->fieldno = infield->fieldno; field->fascale = infield->fascale; field->fscale = infield->fscale; field->headflag = infield->headflag; strcpy(field->ident, infield->ident); riflag = (outfield->bitpix>0); /* Now modify some characteristics of the output file */ /* We use a small "dirty" trick to frame the output */ wcsloc = *(outfield->wcs); /* Copy the CONTENT only */ wcs = infield->wcs; wcsloc.obsdate = wcs->obsdate; wcsloc.epoch = wcs->epoch; naxis = wcsloc.naxis; for (d=0; doutmin[d] < 1? 1:wcs->outmin[d]; wcsloc.outmax[d] = wcs->outmax[d] > wcsloc.naxisn[d]? (double)wcsloc.naxisn[d] : wcs->outmax[d]; wcsloc.crpix[d] -= (wcsloc.outmin[d]-1); wcsloc.naxisn[d] = (wcsloc.outmax[d]-wcsloc.outmin[d]+1); if (wcsloc.naxisn[d]<=0) /*-- Image out of output bounds: create a dummy one with only 1 pixel */ { wcsloc.naxisn[d]=1; wcsloc.outmax[d] = wcsloc.outmin[d]; } } wcs = field->wcs = copy_wcs(&wcsloc); write_wcs(field->tab, wcs); /* Update field characteristics */ width = field->width = field->tab->naxisn[0]; field->height = 1; for (d=1; dheight *= field->tab->naxisn[d]; height = field->height; field->npix = field->width*field->height; /* Add relevant information to FITS headers */ writefitsinfo_field(field, infield); /* Write image header */ if (open_cat(field->cat, WRITE_ONLY) != RETURN_OK) error(EXIT_FAILURE, "*Error*: cannot open for writing ", filename); if (prefs.removetmp_flag && prefs.combine_flag) add_cleanupfilename(filename); QFTELL(field->tab->headpos, field->cat->file, filename); QFWRITE(field->tab->headbuf, field->tab->headnblock*FBSIZE, field->cat->file, filename); QFTELL(field->tab->bodypos, field->cat->file, filename); /* Get resampled suffix extension if available */ strcpy(resampext1, prefs.resamp_suffix); *resampext2 = '\0'; if ((pstr=strrchr(resampext1, '.'))) { strcpy(resampext2, pstr); *pstr = '\0'; } /* Now go on with output weight-map */ if (infield->frameno) sprintf(filename, "%s/%s.%04d%s.weight%s", prefs.resampdir_name, filename2, infield->frameno,resampext1, resampext2); else sprintf(filename, "%s/%s%s.weight%s", prefs.resampdir_name, filename2, resampext1, resampext2); wfield = init_weight(filename, field); if (inwfield) set_weightconv(inwfield); /* Add relevant information to FITS headers */ writefitsinfo_field(wfield, inwfield? inwfield : infield); wfield->cflags = 0; if (inwfield) { wfield->sigfac = inwfield->sigfac; wfield->weight_thresh = inwfield->weight_thresh; } /* Write image header */ if (open_cat(wfield->cat, WRITE_ONLY) != RETURN_OK) error(EXIT_FAILURE, "*Error*: cannot open for writing ", filename); if (prefs.removetmp_flag && prefs.combine_flag) add_cleanupfilename(filename); QFTELL(wfield->tab->headpos, wfield->cat->file, filename); QFWRITE(wfield->tab->headbuf, wfield->tab->headnblock*FBSIZE, wfield->cat->file, filename); QFTELL(wfield->tab->bodypos, wfield->cat->file, filename); /* Prepare oversampling stuff */ ascale = 1.0; noversamp = 1; oversamp = prefs.oversamp; for (d=0; dwcsscale[d]/infield->wcs->wcsscale[d]; ascale *= ascale1; if (!oversamp[d]) /*-- Automatic oversampling mode */ oversamp[d] = ascale1>1.0 ? (int)(ascale1+0.5) : 1; noversamp *= oversamp[d]; } oversampflag = (noversamp>1); if (ascale < 1.0) ascale = 1.0; /* Turn approximation on or off */ approxflag = (((projerr = prefs.proj_err[infield->fieldno]) > 0.0) && (projapp = projapp_init(infield->wcs, field->wcs, projerr, prefs.fscalastro_type==FSCALASTRO_VARIABLE))); #ifdef USE_THREADS /* Set up multi-threading stuff */ /* Number of active threads */ nproc = prefs.nthreads; /* Twice more lines than threads to deal with desynchronization issues */ nlines = 2*nproc; QMALLOC(linecond, pthread_cond_t, nlines); for (l=0; lnaxisn[d]; } /*-- Allocate memory for buffer pointers */ QMALLOC(rawposp, double *, nlines); if (riflag) { QMALLOC(routibuf, FLAGTYPE *, nlines); QMALLOC(routwibuf, FLAGTYPE *, nlines); } else { QMALLOC(routbuf, PIXTYPE *, nlines) QMALLOC(routwbuf, PIXTYPE *, nlines); } QMALLOC(rawbuf, double *, nlines); QCALLOC(rawbufarea, double *, nlines); QMALLOC(ikernel, ikernelstruct *, nlines); QMALLOC(wcsinp, wcsstruct *, nlines); QMALLOC(wcsoutp, wcsstruct *, nlines); if (oversampflag) { if (riflag) { QMALLOC(oversampibuf, FLAGTYPE *, nlines) QMALLOC(oversampwibuf, FLAGTYPE *, nlines); } else { QMALLOC(oversampbuf, double *, nlines) QMALLOC(oversampwbuf, double *, nlines); } QMALLOC(oversampnbuf, int *, nlines); } for (l=0; lwcs); wcsoutp[l] = copy_wcs(field->wcs); } /* Compute reasonable line display-step */ dispstep = (int)(nproc*50000.0/noversamp/width); if (!dispstep) dispstep = 1; /* Start threads! */ #ifdef USE_THREADS QCALLOC(writeflag, int, nlines); QCALLOC(queue, int, nlines); QMALLOC(proc, int, nproc); QMALLOC(rthread, pthread_t, nproc); ftab = field->tab; wtab = wfield->tab; writeline = absline = procline = 0; for (p=0; p Resampling line:%7d / %-7d\n\33[1A", y, height); warp_line(0); if (riflag) { write_ibody(field->tab, routibuf[0], width); write_ibody(wfield->tab, routwibuf[0], width); } else { write_body(field->tab, routbuf[0], width); write_body(wfield->tab, routwbuf[0], width); } } #endif #ifdef USE_THREADS for (p=0; pcat, field->tab->tabsize); pad_tab(wfield->cat, wfield->tab->tabsize); /* Close files */ close_cat(field->cat); close_cat(wfield->cat); /* Return back new field pointers */ *pinfield = field; *pinwfield = wfield; /* Free memory */ for (l=0; l=0) writeflag[l] = 2; /* If we just finished the "right" line, write it to disk! */ if (l == writeline) { while (writeflag[writeline]==2) { if (riflag) { write_ibody(ftab, routibuf[writeline], width); write_ibody(wtab, routwibuf[writeline], width); } else { write_body(ftab, routbuf[writeline], width); write_body(wtab, routwbuf[writeline], width); } writeflag[writeline] = 0; QPTHREAD_COND_BROADCAST(&linecond[writeline]); writeline = (writeline+1)%nlines; } } /* If no more line to process, return a "-1" (meaning exit thread) */ if ((y=absline++) >= height) l=-1; else { l = procline; procline = (procline+1)%nlines; /*------ Update coordinate vector */ for (d=1; d Resampling line:%7d / %-7d\n\33[1A", y, height); return l; } /****** cancel_resample_threads *********************************************** PROTO void clean_resample_threads(void) PURPOSE Cancel remaining active threads INPUT -. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 25/04/2002 ***/ void cancel_resample_threads(void) { int p; for (p=0; pfascale; /* Check if lng and lat are swapped between in and out wcs (vicious idea!) */ swapflag = (((wcsin->lng != wcsout->lng) || (wcsin->lat != wcsout->lat)) && (wcsin->lng != wcsin->lat) && (wcsout->lng != wcsout->lat)); /* Compute all alpha's and delta's for the current line */ rawpos[0] = rawmin[0]; if (oversampflag) { /*-- Oversampling is on */ for (d=0; dlat]; wcspos[wcsout->lat] = wcspos[wcsin->lat]; wcspos[wcsin->lat] = worldc; } wcs_to_raw(wcsin, wcspos, rawbufc); if (rawbufareac) *rawbufareac = wcs_scale(wcsout, rawposover) / wcs_scale(wcsin, rawbufc); } if (rawbufareac) rawbufareac++; } } /*---- Resample the current line */ if (riflag) { oversampit = oversampibuf[p]; oversampwit = oversampwibuf[p]; oversampnt = oversampnbuf[p]; rawbufc = rawbuf[p]; rawbufareac = rawbufarea[p]; for (x=width; x--; rawbufc+=naxis) { if (rawbufareac) area = *(rawbufareac++); if (*rawbufc != WCS_NOCOORD && interpolate_ipix(infield, inwfield, rawbufc,&ipix,&ipixw) == RETURN_OK) { *(oversampit++) |= ipix; *(oversampwit++) |= 1; (*(oversampnt++))++; } else { oversampit++; oversampwit++; oversampnt++; } } } else { oversampt = oversampbuf[p]; oversampwt = oversampwbuf[p]; oversampnt = oversampnbuf[p]; rawbufc = rawbuf[p]; rawbufareac = rawbufarea[p]; for (x=width; x--; rawbufc+=naxis) { if (rawbufareac) area = *(rawbufareac++); if (*rawbufc != WCS_NOCOORD && (interpolate_pix(infield, inwfield, ikernel[p],rawbufc, &pix,&pixw),pixwlat]; wcspos[wcsout->lat] = wcspos[wcsin->lat]; wcspos[wcsin->lat] = worldc; } wcs_to_raw(wcsin, wcspos, rawbufc); if (rawbufareac) *rawbufareac = wcs_scale(wcsout, rawpos) / wcs_scale(wcsin, rawbufc); } if (rawbufareac) rawbufareac++; } /*-- Resample the line */ rawbufc = rawbuf[p]; rawbufareac = rawbufarea[p]; if (riflag) for (x=width; x--; rawbufc+=naxis) { if (rawbufareac) area = *(rawbufareac++); if (*rawbufc != WCS_NOCOORD) interpolate_ipix(infield, inwfield, rawbufc,outi++,outwi++); else *(outwi++) = *(outi++) = 0; } else for (x=width; x--; rawbufc+=naxis) { if (rawbufareac) area = *(rawbufareac++); if (*rawbufc != WCS_NOCOORD) { interpolate_pix(infield, inwfield, ikernel[p], rawbufc,out,outw); *(out++) *= area; /*------- Convert variance to weight */ *outw = (*outw < BIG) ? 1.0/(*outw*area*area) : 0.0; outw++; } else *(out++) = *(outw++) = 0.0; } } return; } swarp-2.41.5/src/resample.h000066400000000000000000000037651400430667300155250ustar00rootroot00000000000000/* * resample.h * * Include file for resample.c. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 26/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _FITSCAT_H_ #include "fits/fitscat.h" #endif #ifndef _FIELD_H_ #include "field.h" #endif #ifndef _INTERPOLATE_H_ #include "interpolate.h" #endif #ifndef _RESAMPLE_H_ #define _RESAMPLE_H_ /*-------------------------------- macros -----------------------------------*/ /*------------------------------- constants ---------------------------------*/ #define INTERP_MAXDIM 10 /* Max. number of image dimensions */ #define INTERP_MAXKERNELWIDTH 8 /* Max. range of kernel (pixels) */ /*--------------------------------- typedefs --------------------------------*/ /*-------------------------- structure definitions --------------------------*/ /*----------------------- miscellaneous variables ---------------------------*/ /*-------------------------------- protos -----------------------------------*/ #ifdef USE_THREADS extern void cancel_resample_threads(void); #endif extern void resample_field(fieldstruct **pinfield, fieldstruct **pinwfield, fieldstruct *outfield, fieldstruct *outwfield, interpenum *interptype); #endif swarp-2.41.5/src/threads.c000066400000000000000000000104411400430667300153270ustar00rootroot00000000000000/* * threads.c * * Manage POSIX threads. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic software * * Copyright: (C) 2002-2020 IAP/CNRS/SorbonneU * (C) Mark Hays (original tutorial) * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 26/08/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #ifdef USE_THREADS #include "threads.h" #endif #include "define.h" #include "types.h" #include "globals.h" #include "fits/fitscat.h" /*------------------- global variables for multithreading -------------------*/ int nproc; /* Number of child threads */ #ifdef USE_THREADS /******* threads_gate_init *************************************************** PROTO threads_gate_t *threads_gate_init(int nthreads, void (*func)(void)) PURPOSE Create a new gate. INPUT Thread gate structure pointer, Void pointer to a function to exec prior to gate opening (can be NULL). OUTPUT -. NOTES From Mark Hays' POSIX tutorial. See e.g. http://www.cs.ualberta.ca/~paullu/C681/mark.hays.threads.html. AUTHOR E. Bertin (IAP) VERSION 03/07/2003 ***/ threads_gate_t *threads_gate_init(int nthreads, void (*func)(void)) { threads_gate_t *gate; QMALLOC(gate, threads_gate_t, 1); gate->ngate = 0; gate->nthreads = nthreads; gate->func = func; QPTHREAD_MUTEX_INIT(&gate->mutex, NULL); QPTHREAD_MUTEX_INIT(&gate->block, NULL); QPTHREAD_COND_INIT(&gate->condvar, NULL); QPTHREAD_COND_INIT(&gate->last, NULL); return gate; } /******* threads_gate_end **************************************************** PROTO void threads_gate_end(threads_gate_t *gate) PURPOSE Destroy an existing gate. INPUT Thread gate structure pointer. OUTPUT -. NOTES From Mark Hays' POSIX tutorial. See e.g. http://www.cs.ualberta.ca/~paullu/C681/mark.hays.threads.html. AUTHOR E. Bertin (IAP) VERSION 04/01/2010 ***/ void threads_gate_end(threads_gate_t *gate) { gate->ngate=gate->nthreads=0; QPTHREAD_MUTEX_DESTROY(&gate->mutex); QPTHREAD_MUTEX_DESTROY(&gate->block); QPTHREAD_COND_DESTROY(&gate->condvar); QPTHREAD_COND_DESTROY(&gate->last); free(gate); return; } /******* threads_gate_sync **************************************************** PROTO void threads_gate_sync(threads_gate_t *gate, void *func(void)) PURPOSE Synchronize a number of POSIX threads. INPUT Thread gate structure pointer. OUTPUT -. NOTES From Mark Hays' POSIX tutorial. See e.g. http://www.cs.ualberta.ca/~paullu/C681/mark.hays.threads.html. AUTHOR E. Bertin (IAP) VERSION 03/07/2003 ***/ void threads_gate_sync(threads_gate_t *gate) { if (gate->nthreads<2) return; /* trivial case */ QPTHREAD_MUTEX_LOCK(&gate->block); /* lock the block -- new */ /* threads sleep here */ QPTHREAD_MUTEX_LOCK(&gate->mutex); /* lock the mutex */ if (++(gate->ngate) < gate->nthreads) /* are we the last one in? */ { QPTHREAD_MUTEX_UNLOCK(&gate->block); /* no, unlock block and */ QPTHREAD_COND_WAIT(&gate->condvar, &gate->mutex); /* go to sleep */ } else /* yes, we're last */ { if (gate->func) (*gate->func)(); /* execute function */ QPTHREAD_COND_BROADCAST(&gate->condvar); /* wake everyone up and */ QPTHREAD_COND_WAIT(&gate->last, &gate->mutex);/* sleep til all awake */ QPTHREAD_MUTEX_UNLOCK(&gate->block); /* release the block */ } if (--(gate->ngate)==1) /* next to last one out? */ QPTHREAD_COND_BROADCAST(&gate->last); /* yes, wake up last one */ QPTHREAD_MUTEX_UNLOCK(&gate->mutex); /* release the mutex */ return; } #endif swarp-2.41.5/src/threads.h000066400000000000000000000114701400430667300153370ustar00rootroot00000000000000/* * threads.h * * Definitions and shortcuts for POSIX threads. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic software * * Copyright: (C) 2002-2020 IAP/CNRS/SorbonneU * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 26/08/2020 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _THREADS_H_ #define _THREADS_H_ #include #include /*---- Set defines according to machine's specificities and customizing -----*/ /*--------------------------- Technical constants ---------------------------*/ /*---------------------------- Synchro messages -----------------------------*/ #define STATE_FREE 0 #define STATE_READY 1 #define STATE_BUSY 2 /*------------------------------- Other Macros ------------------------------*/ #define QPTHREAD_ATTR_INIT(pthread_attr) \ {if (pthread_attr_init(pthread_attr)) \ error(EXIT_FAILURE, \ "*Error*: pthread_attr_init() failed for ", #pthread_attr );;} #define QPTHREAD_ATTR_SETDETACHSTATE(pthread_attr, attr) \ {if (pthread_attr_setdetachstate(pthread_attr, attr)) \ error(EXIT_FAILURE, \ "*Error*: pthread_attr_setdetachstate() failed for ", \ #pthread_attr );;} #define QPTHREAD_ATTR_DESTROY(pthread_attr) \ {if (pthread_attr_destroy(pthread_attr)) \ error(EXIT_FAILURE, \ "*Error*: pthread_attr_destroy() failed for ",#pthread_attr);;} #define QPTHREAD_CREATE(pthread, attr, func, arg) \ {if (pthread_create(pthread, attr, func, arg)) \ error(EXIT_FAILURE, \ "*Error*: pthread_create() failed for ", #pthread );;} #define QPTHREAD_CANCEL(pthread) \ {if (pthread_cancel(pthread)) \ warning( \ "failed to cancel ", #pthread );;} #define QPTHREAD_JOIN(pthread, ret) \ {if (pthread_join(pthread, ret)) \ error(EXIT_FAILURE, \ "*Error*: pthread_join() failed for ", #pthread );;} #define QPTHREAD_MUTEX_INIT(mutex, attr) \ {if (pthread_mutex_init(mutex, attr)) \ error(EXIT_FAILURE, \ "*Error*: pthread_mutex_init() failed for ", #mutex );;} #define QPTHREAD_MUTEX_LOCK(mutex) \ {if (pthread_mutex_lock(mutex)) \ error(EXIT_FAILURE, \ "*Error*: pthread_mutex_lock() failed for ", #mutex );;} #define QPTHREAD_MUTEX_UNLOCK(mutex) \ {if (pthread_mutex_unlock(mutex)) \ error(EXIT_FAILURE, \ "*Error*: pthread_mutex_unlock() failed for ", #mutex );;} #define QPTHREAD_MUTEX_DESTROY(mutex) \ {if (pthread_mutex_destroy(mutex)) \ error(EXIT_FAILURE, \ "*Error*: pthread_mutex_destroy() failed for ", #mutex );;} #define QPTHREAD_COND_INIT(cond, attr) \ {if (pthread_cond_init(cond, attr)) \ error(EXIT_FAILURE, \ "*Error*: pthread_cond_init() failed for ", #cond );;} #define QPTHREAD_COND_WAIT(cond, mutex) \ {if (pthread_cond_wait(cond, mutex)) \ error(EXIT_FAILURE, \ "*Error*: pthread_cond_wait() failed for ", #cond );;} #define QPTHREAD_COND_BROADCAST(cond) \ {if (pthread_cond_broadcast(cond)) \ error(EXIT_FAILURE, \ "*Error*: pthread_cond_broadcast() failed for ", #cond );;} #define QPTHREAD_COND_SIGNAL(cond) \ {if (pthread_cond_signal(cond)) \ error(EXIT_FAILURE, \ "*Error*: pthread_cond_signal() failed for ", #cond );;} #define QPTHREAD_COND_DESTROY(cond) \ {if (pthread_cond_destroy(cond)) \ error(EXIT_FAILURE, \ "*Error*: pthread_cond_destroy() failed for ", #cond );;} /*------------------------------- Structures --------------------------------*/ typedef struct _threads_gate_t { int ngate; /* Gate counter */ int nthreads; /* Number of threads to manage */ void (*func)(void); /* Function to execute at wakeup */ pthread_mutex_t mutex; /* Main MutEx */ pthread_mutex_t block; /* Safety Mutex (avoid "rebound") */ pthread_cond_t condvar; /* Main condition variable */ pthread_cond_t last; /* To wake the remaining thread up */ } threads_gate_t; /*----------------------------- Global variables ----------------------------*/ extern int nproc; /* Number of child threads */ /*--------------------------------- Functions -------------------------------*/ threads_gate_t *threads_gate_init(int nthreads, void (*func)(void)); extern void threads_gate_end(threads_gate_t *gate), threads_gate_sync(threads_gate_t *gate); #endif // _THREADS_H_ swarp-2.41.5/src/types.h000066400000000000000000000017641400430667300150560ustar00rootroot00000000000000/* * types.h * * Global type definitions. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 26/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /* Not much, isn't there ? */ swarp-2.41.5/src/wcs/000077500000000000000000000000001400430667300143255ustar00rootroot00000000000000swarp-2.41.5/src/wcs/LICENSE000066400000000000000000000614471400430667300153460ustar00rootroot00000000000000 GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] 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 Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the 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 a program 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. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. 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, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library 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 compile 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) 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. c) 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. d) 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 source code 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 to 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 Library 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 How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! swarp-2.41.5/src/wcs/Makefile.am000066400000000000000000000026271400430667300163700ustar00rootroot00000000000000# # Makefile.am # # WCSlib Makefile.am. Process this file with automake to generate a Makefile # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # # This file part of: AstrOmatic WCS library # # Copyright: (C) 2002-2010 Emmanuel Bertin -- IAP/CNRS/UPMC # (C) 1995-1999 Mark Calabretta (original WCSlib) # # Licenses: GNU General Public License (this file) # GNU Library General Public License (WCSlib) # # AstrOmatic software 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 3 of the # License, or (at your option) any later version. # AstrOmatic software 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 AstrOmatic software. # If not, see . # # Last modified: 10/10/2010 # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% noinst_LIBRARIES = libwcs_c.a libwcs_c_a_SOURCES = cel.c lin.c poly.c proj.c sph.c tnx.c wcs.c \ wcstrig.c \ cel.h lin.h poly.h proj.h sph.h tnx.h wcs.h \ wcsmath.h wcstrig.h EXTRA_DIST = LICENSE README swarp-2.41.5/src/wcs/README000066400000000000000000000005031400430667300152030ustar00rootroot00000000000000This directory contains a modified version of the WCSlib V2.2 library by Mark Calabretta , released under the GNU Library General Public License. The original version was downloaded from ftp://ftp.cv.nrao.edu/fits/src/wcs/. See http://www.atnf.csiro.au/people/mcalabre/WCS/wcslib for more details. swarp-2.41.5/src/wcs/cel.c000066400000000000000000000471651400430667300152510ustar00rootroot00000000000000/* * cel.c * * Lower level spherical coordinate transformation and projection routines. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic WCS library * * Copyright: (C) 2000-2012 Emmanuel Bertin -- IAP/CNRS/UPMC * (C) 1995-1999 Mark Calabretta (original version) * * Licenses: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 18/04/2012 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*============================================================================= * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-1999, Mark Calabretta * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library * General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * 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. * * The second pair of values are the native longitude and latitude of * the pole of the celestial coordinate system and correspond to the * FITS keywords LONGPOLE and LATPOLE. * * LONGPOLE 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 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 * LONGPOLE = +/- 90 then the native 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. * int (*prjfwd)() * int (*prjrev)() * Pointers to the forward and reverse projection routines. * * * WCS projection codes * -------------------- * Zenithals/azimuthals: * AZP: zenithal/azimuthal perspective * TAN: gnomonic * SIN: synthesis (generalized orthographic) * STG: stereographic * ARC: zenithal/azimuthal equidistant * ZPN: zenithal/azimuthal polynomial * ZEA: zenithal/azimuthal equal area * AIR: Airy * TNX: IRAF's polynomial correction to TAN * TPV: AstrOmatic's polynomial correction to TAN * * Cylindricals: * CYP: cylindrical perspective * CAR: Cartesian * MER: Mercator * CEA: cylindrical equal area * * Conics: * COP: conic perspective * COD: conic equidistant * COE: conic equal area * COO: conic orthomorphic * * Polyconics: * BON: Bonne * PCO: polyconic * * Pseudo-cylindricals: * GLS: Sanson-Flamsteed (global sinusoidal) * PAR: parabolic * MOL: Mollweide * * Conventional: * AIT: Hammer-Aitoff * * Quad-cubes: * CSC: COBE quadrilateralized spherical cube * QSC: quadrilateralized spherical cube * TSC: tangential spherical cube * * Author: Mark Calabretta, Australia Telescope National Facility * IRAF's TNX added by E.Bertin 2000/03/28 * TPV added by E.Bertin 2012/04/11 * Filtering of abs(phi)>180 and abs(theta)>90 added by E.Bertin 2000/11/11 * $Id: cel.c,v 1.1.1.1 2012/04/18 16:33:26 bertin Exp $ *===========================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include #include "wcstrig.h" #include "cel.h" #include "sph.h" #include "tnx.h" int npcode = 27; char pcodes[27][4] = {"AZP", "TAN", "SIN", "STG", "ARC", "ZPN", "ZEA", "AIR", "CYP", "CAR", "MER", "CEA", "COP", "COD", "COE", "COO", "BON", "PCO", "GLS", "PAR", "AIT", "MOL", "CSC", "QSC", "TSC", "TNX", "TPV"}; /* 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, theta0, slat0, sphip, sthe0; double latp, latp1, latp2; double u, v, x, y, z; /* Set pointers to the forward and reverse projection routines. */ if (strcmp(pcode, "TAN") == 0) { cel->prjfwd = tanfwd; cel->prjrev = tanrev; theta0 = 90.0; } else if (strcmp(pcode, "TPV") == 0) { cel->prjfwd = tanfwd; cel->prjrev = tanrev; theta0 = 90.0; } else if (strcmp(pcode, "AZP") == 0) { cel->prjfwd = azpfwd; cel->prjrev = azprev; theta0 = 90.0; } else if (strcmp(pcode, "SIN") == 0) { cel->prjfwd = sinfwd; cel->prjrev = sinrev; theta0 = 90.0; } else if (strcmp(pcode, "STG") == 0) { cel->prjfwd = stgfwd; cel->prjrev = stgrev; theta0 = 90.0; } else if (strcmp(pcode, "ARC") == 0) { cel->prjfwd = arcfwd; cel->prjrev = arcrev; theta0 = 90.0; } else if (strcmp(pcode, "ZPN") == 0) { cel->prjfwd = zpnfwd; cel->prjrev = zpnrev; theta0 = 90.0; } else if (strcmp(pcode, "ZEA") == 0) { cel->prjfwd = zeafwd; cel->prjrev = zearev; theta0 = 90.0; } else if (strcmp(pcode, "AIR") == 0) { cel->prjfwd = airfwd; cel->prjrev = airrev; theta0 = 90.0; } else if (strcmp(pcode, "CYP") == 0) { cel->prjfwd = cypfwd; cel->prjrev = cyprev; theta0 = 0.0; } else if (strcmp(pcode, "CAR") == 0) { cel->prjfwd = carfwd; cel->prjrev = carrev; theta0 = 0.0; } else if (strcmp(pcode, "MER") == 0) { cel->prjfwd = merfwd; cel->prjrev = merrev; theta0 = 0.0; } else if (strcmp(pcode, "CEA") == 0) { cel->prjfwd = ceafwd; cel->prjrev = cearev; theta0 = 0.0; } else if (strcmp(pcode, "COP") == 0) { cel->prjfwd = copfwd; cel->prjrev = coprev; theta0 = prj->p[1]; } else if (strcmp(pcode, "COD") == 0) { cel->prjfwd = codfwd; cel->prjrev = codrev; theta0 = prj->p[1]; } else if (strcmp(pcode, "COE") == 0) { cel->prjfwd = coefwd; cel->prjrev = coerev; theta0 = prj->p[1]; } else if (strcmp(pcode, "COO") == 0) { cel->prjfwd = coofwd; cel->prjrev = coorev; theta0 = prj->p[1]; } else if (strcmp(pcode, "BON") == 0) { cel->prjfwd = bonfwd; cel->prjrev = bonrev; theta0 = 0.0; } else if (strcmp(pcode, "PCO") == 0) { cel->prjfwd = pcofwd; cel->prjrev = pcorev; theta0 = 0.0; } else if (strcmp(pcode, "GLS") == 0) { cel->prjfwd = glsfwd; cel->prjrev = glsrev; theta0 = 0.0; } else if (strcmp(pcode, "PAR") == 0) { cel->prjfwd = parfwd; cel->prjrev = parrev; theta0 = 0.0; } else if (strcmp(pcode, "AIT") == 0) { cel->prjfwd = aitfwd; cel->prjrev = aitrev; theta0 = 0.0; } else if (strcmp(pcode, "MOL") == 0) { cel->prjfwd = molfwd; cel->prjrev = molrev; theta0 = 0.0; } else if (strcmp(pcode, "CSC") == 0) { cel->prjfwd = cscfwd; cel->prjrev = cscrev; theta0 = 0.0; } else if (strcmp(pcode, "QSC") == 0) { cel->prjfwd = qscfwd; cel->prjrev = qscrev; theta0 = 0.0; } else if (strcmp(pcode, "TSC") == 0) { cel->prjfwd = tscfwd; cel->prjrev = tscrev; theta0 = 0.0; } else if (strcmp(pcode, "TNX") == 0) { cel->prjfwd = tnxfwd; cel->prjrev = tnxrev; theta0 = 90.0; } else { /* Unrecognized projection code. */ 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 (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] < theta0) ? 180.0 : 0.0; } clat0 = wcs_cosd(cel->ref[1]); slat0 = wcs_sind(cel->ref[1]); cphip = wcs_cosd(cel->ref[2]); sphip = wcs_sind(cel->ref[2]); cthe0 = wcs_cosd(theta0); sthe0 = wcs_sind(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 = wcs_atan2d(y,x); v = wcs_acosd(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 = wcs_cosd(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 - 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 - wcs_sind(latp)*slat0)/z; y = sphip*cthe0/clat0; if (x == 0.0 && y == 0.0) { return 1; } cel->euler[0] = cel->ref[0] - wcs_atan2d(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] = wcs_cosd(cel->euler[1]); cel->euler[4] = wcs_sind(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 = cel->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 = cel->prjrev(x, y, prj, phi, theta))) { return err == 1 ? 2 : 3; } if (fabs(*phi)>180.0 || fabs(*theta)>90.0) return 2; /* Compute native coordinates. */ sphrev(*phi, *theta, cel->euler, lng, lat); return 0; } swarp-2.41.5/src/wcs/cel.h000066400000000000000000000073521400430667300152500ustar00rootroot00000000000000/* * cel.h * * Include file for cel.c. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic WCS library * * Copyright: (C) 2000-2012 Emmanuel Bertin -- IAP/CNRS/UPMC * (C) 1995-1999 Mark Calabretta (original version) * * Licenses: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 11/04/2012 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*============================================================================= * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-1999, Mark Calabretta * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library * General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * 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: cel.h,v 1.1.1.1 2012/04/11 16:33:26 bertin Exp $ *===========================================================================*/ #ifndef WCSLIB_CEL #define WCSLIB_CEL #include "proj.h" #ifdef __cplusplus extern "C" { #endif extern int npcode; extern char pcodes[27][4]; struct celprm { int flag; double ref[4]; double euler[5]; #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 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 #ifdef __cplusplus } #endif #endif /* WCSLIB_CEL */ swarp-2.41.5/src/wcs/lin.c000066400000000000000000000307131400430667300152570ustar00rootroot00000000000000/* * lin.c * * Linear transformations. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic WCS library * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * (C) 1995-1999 Mark Calabretta (original version) * * Licenses: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 10/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*============================================================================= * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-1999, Mark Calabretta * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library * General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * 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. * 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 1.1.1.1 2003/07/09 19:06:26 bertin Exp $ *===========================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include #include "lin.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; } swarp-2.41.5/src/wcs/lin.h000066400000000000000000000064321400430667300152650ustar00rootroot00000000000000/* * lin.h * * Include file for lin.c. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic WCS library * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * (C) 1995-1999 Mark Calabretta (original version) * * Licenses: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 10/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*============================================================================= * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-1999, Mark Calabretta * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library * General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * 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: lin.h,v 1.1.1.1 2002/03/15 16:33:26 bertin Exp $ *===========================================================================*/ #ifndef WCSLIB_LIN #define WCSLIB_LIN #ifdef __cplusplus extern "C" { #endif #if !defined(__STDC__) && !defined(__cplusplus) #ifndef const #define const #endif #endif 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 #ifdef __cplusplus }; #endif #endif /* WCSLIB_LIN */ swarp-2.41.5/src/wcs/poly.c000066400000000000000000000573741400430667300154740ustar00rootroot00000000000000/* * poly.c * * Polynomial functions. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic software * * Copyright: (C) 1998-2019 IAP/CNRS/SorbonneU * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 03/12/2019 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "poly.h" #ifdef HAVE_ATLAS #include ATLAS_LAPACK_H #endif #ifdef HAVE_LAPACKE #include LAPACKE_H //#define MATSTORAGE_PACKED 1 #endif #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) !");;} #define QMEMCPY(ptrin, ptrout, typ, nel) \ {if (ptrin) \ {if (!(ptrout = (typ *)malloc((size_t)(nel)*sizeof(typ)))) \ qerror("Not enough memory for ", \ #ptrout " (" #nel " elements) !"); \ memcpy(ptrout, ptrin, (size_t)(nel)*sizeof(typ));};;} /********************************* qerror ************************************/ /* I hope it will never be used! */ void qerror(char *msg1, char *msg2) { fprintf(stderr, "\n> %s%s\n\n",msg1,msg2); exit(-1); } /****** 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 30/08/2011 ***/ 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, dmax; 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 = Prod_(i<=d)(n+i)/Prod_(i<=d)i */ n = nd[g]; d = dmax>n? n: dmax; for (num=den=1; d; num*=(n+dmax--), 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) VERSION 04/11/2008 ***/ void poly_end(polystruct *poly) { if (poly) { free(poly->coeff); free(poly->basis); free(poly->orthobasis); free(poly->degree); free(poly->group); free(poly->orthomat); free(poly->deorthomat); free(poly); } return; } /****** poly_copy ************************************************************* PROTO polystruct *poly_copy(polystruct *poly) PURPOSE Copy a polynom structure and everything it contains. INPUT polystruct pointer. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 04/11/2008 ***/ polystruct *poly_copy(polystruct *poly) { polystruct *newpoly; if (poly) { QMALLOC(newpoly, polystruct, 1); *newpoly = *poly; if (poly->ncoeff) { QMEMCPY(poly->coeff, newpoly->coeff, double, poly->ncoeff); QMEMCPY(poly->basis, newpoly->basis, double, poly->ncoeff); } if (poly->ndim) QMEMCPY(poly->group, newpoly->group, int, poly->ndim); if (poly->ngroup) QMEMCPY(poly->degree, newpoly->degree, int, poly->ngroup); if (poly->orthomat) { QMEMCPY(poly->orthomat, newpoly->orthomat, double, poly->ncoeff*poly->ncoeff); QMEMCPY(poly->deorthomat, newpoly->deorthomat, double, poly->ncoeff*poly->ncoeff); QMEMCPY(poly->orthobasis, newpoly->orthobasis, double, poly->ncoeff); } return newpoly; } else return NULL; } /****** poly_func ************************************************************ PROTO double poly_func(polystruct *poly, double *pos) PURPOSE Evaluate a multidimensional polynomial. 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; dbasis. AUTHOR E. Bertin (IAP) VERSION 29/01/2013 ***/ double poly_cfunc(polystruct *poly, double *pos) { double pol[POLY_MAXDIM*(POLY_MAXDEGREE+1)], *polt, *post, *basis, *coeff, xval; long double val; int expo[POLY_MAXDIM+1], gexpo[POLY_MAXDIM+1]; int *expot, *degree,*degreet, *group,*groupt, *gexpot, d,d2,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 (groupt=group, expot=expo, post=pos, d=0; d 0; polt++) *polt = 2.0*xval**(polt-1) - *(polt-2); } 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; /* Compute the rest of the polynom */ for (t=poly->ncoeff; --t; ) { polt = pol; expot = expo; /*-- xval contains the current product of the polynomials */ xval = 1.0; for (d=ndim; d--; polt += POLY_MAXDEGREE+1) xval *= polt[*(expot++)]; val += (*(basis++)=xval)**(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 */ expot = expo; groupt = group; 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; dPOLY_TINY) /*-- Simple Tikhonov regularization */ for (i=0; icoeff; for (j=ncoeff; j--;) *(coeff++) = *(betat++); /* poly_addcste(poly, offset); */ free(beta); return info; } /****** 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 05/10/2010 ***/ 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; indim; group = poly->group; degree = poly->degree; QMALLOC(powers, int, ndim*poly->ncoeff); if (ndim) { for (expot=expo, d=ndim; --d;) *(++expot) = 0; for (gexpot=gexpo, degreet=degree, g=poly->ngroup; g--;) *(gexpot++) = *(degreet++); if (gexpo[*group]) gexpo[*group]--; } /* The constant term is handled separately */ powerst = powers; for (d=0; dncoeff; --t; ) { for (d=0; dndim; ncoeff = poly->ncoeff; basis = poly->basis; coeff = poly->coeff; /* Allocate memory for orthonormalization matrix and vector */ QCALLOC(poly->deorthomat, double, ncoeff*ncoeff); QMALLOC(poly->orthobasis, double, poly->ncoeff); QMALLOC(rdiag, double, ncoeff); /* Do a QR decomposition of input vector set */ /* Vectors are stored as rows to speed up the Householder transformation */ n = ncoeff; m = ndata; invec = data; for (c=0; c POLY_TINY) { if (*invect0 < 0.0) scale = -scale; invect = invect0; for (i=ndmc; i--;) *(invect++) /= scale; *invect0 += 1.0; invect02 = invect0 + ndata; for (j=ncoeff-c; --j; invect02+=ndata) { s = 0.0; invect = invect0; invect2 = invect02; for (i=ndmc; i--;) s += *(invect++)**(invect2++); s /= -*invect0; invect = invect0; invect2 = invect02; for (i=ndmc; i--;) *(invect2++) += s**(invect++); } } rdiag[c] = -scale; } /* Convert to deorthonormalization matrix */ deortho = poly->deorthomat; for (j=0; jdeorthomat, poly->orthomat, double, ncoeff*ncoeff); #if defined(HAVE_LAPACKE) LAPACKE_dtrtri(LAPACK_ROW_MAJOR, 'L', 'N', ncoeff,poly->orthomat,ncoeff); #elif defined(HAVE_ATLAS) clapack_dtrtri(CblasRowMajor, CblasLower, CblasNonUnit, ncoeff, poly->orthomat, ncoeff); #else qerror("*Internal Error*: no routine available", " for triangular inverse"); #endif /* Transpose orthonormalization matrix to speed up later use */ deortho = poly->deorthomat; for (j=0; j"). INPUT polystruct pointer, pointer to the input vector, pointer to the output vector. OUTPUT Pointer to poly->orthobasis, or poly->basis if no ortho. matrix exists. NOTES The poly->basis vector must have been updated with poly_func() first. AUTHOR E. Bertin (IAP) VERSION 04/11/2008 ***/ double *poly_ortho(polystruct *poly, double *datain, double *dataout) { double *omat,*basis,*obasis, dval; int i,j, ncoeff; if (!poly->orthomat) return datain; ncoeff = poly->ncoeff; /* Compute matrix product */ omat = poly->orthomat; obasis = dataout; for (j=ncoeff; j--;) { basis = datain; dval = 0.0; for (i=ncoeff; i--;) dval += *(omat++)**(basis++); *(obasis++) = dval; } return dataout; } /****** poly_deortho ********************************************************** PROTO void poly_deortho(polystruct *poly, double *datain, double *dataout) PURPOSE Apply deorthonormalization to the poly basis component vector("basis. NOTES -. AUTHOR E. Bertin (IAP) VERSION 04/11/2008 ***/ double *poly_deortho(polystruct *poly, double *datain, double *dataout) { double *omat,*basis,*obasis, dval; int i,j, ncoeff; if (!poly->deorthomat) return datain; ncoeff = poly->ncoeff; /* Compute matrix product */ omat = poly->deorthomat; basis = dataout; for (j=ncoeff; j--;) { obasis = datain; dval = 0.0; for (i=ncoeff; i--;) dval += *(omat++)**(obasis++); *(basis++) = dval; } return dataout; } swarp-2.41.5/src/wcs/poly.h000066400000000000000000000054251400430667300154670ustar00rootroot00000000000000/* * poly.h * * Include file for poly.c. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic software * * Copyright: (C) 1998-2019 IAP/CNRS/SorbonneU * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 03/12/2019 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _POLY_H_ #define _POLY_H_ /*--------------------------------- constants -------------------------------*/ #define POLY_MAXDIM 4 /* Max dimensionality of polynom */ #define POLY_MAXDEGREE 40 /* Max degree of the polynom */ #define POLY_TINY 1e-30 /* A tiny number */ /*---------------------------------- macros ---------------------------------*/ /*--------------------------- structure definitions -------------------------*/ typedef struct poly { double *basis; /* Current values of the basis functions */ double *orthobasis; /* Curr orthonormalized basis function values */ 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 */ double *orthomat; /* Orthonormalization matrix */ double *deorthomat; /* "Deorthonormalization" matrix */ } polystruct; /*---------------------------------- protos --------------------------------*/ extern polystruct *poly_copy(polystruct *poly), *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_fit(polystruct *poly, double *x, double *y, double *w, int ndata, double *extbasis, double regul), *poly_powers(polystruct *poly), poly_solve(double *a, double *b, int n); extern void poly_addcste(polystruct *poly, double *cste), poly_end(polystruct *poly); extern double *poly_deortho(polystruct *poly, double *datain, double *dataout), *poly_ortho(polystruct *poly, double *datain, double *dataout); extern void poly_initortho(polystruct *poly, double *data, int ndata); #endif swarp-2.41.5/src/wcs/proj.c000066400000000000000000002565471400430667300154660ustar00rootroot00000000000000/* * proj.c * * Spherical map projections. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic WCS library * * Copyright: (C) 2000-2015 Emmanuel Bertin -- IAP/CNRS/UPMC * (C) 1995-1999 Mark Calabretta (original version) * * Licenses: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 31/03/2015 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*============================================================================ * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-1999, Mark Calabretta * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library * General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * 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. * * azpset azpfwd azprev AZP: zenithal/azimuthal perspective * tanset tanfwd tanrev TAN: gnomonic * sinset sinfwd sinrev SIN: orthographic/synthesis * stgset stgfwd stgrev STG: stereographic * 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 * carset carfwd carrev CAR: Cartesian * merset merfwd merrev MER: Mercator * ceaset ceafwd cearev CEA: cylindrical equal area * copset copfwd coprev COP: conic perspective * codset codfwd codrev COD: conic equidistant * coeset coefwd coerev COE: conic equal area * cooset coofwd coorev COO: conic orthomorphic * bonset bonfwd bonrev BON: Bonne * pcoset pcofwd pcorev PCO: polyconic * glsset glsfwd glsrev GLS: Sanson-Flamsteed (global sinusoidal) * parset parfwd parrev PAR: parabolic * aitset aitfwd aitrev AIT: Hammer-Aitoff * molset molfwd molrev MOL: Mollweide * cscset cscfwd cscrev CSC: COBE quadrilateralized spherical cube * qscset qscfwd qscrev QSC: quadrilateralized spherical cube * tscset tscfwd tscrev TSC: tangential spherical cube * tnxset tnxfwd tnxrev TNX: IRAF's gnomonic * * * 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). * * 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, 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. * * int n * double w[10] * Intermediate values derived from the projection parameters. * * 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, 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 * IRAF's TNX added by E.Bertin 2000/08/23 * Behaviour of Cartesian-like projections modified by E.Bertin 2005/08/29 * $Id: proj.c,v 1.1.1.1 2008/01/10 18:00:00 bertin Exp $ *===========================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include #include #include "poly.h" #include "proj.h" #include "tnx.h" #include "wcsmath.h" #include "wcstrig.h" /* 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 wcs_copysign(X, Y) ((Y) < 0.0 ? -fabs(X) : fabs(X)) /*============================================================================ * AZP: zenithal/azimuthal perspective projection. * * Given: * prj->p[1] AZP distance parameter, mu in units of r0. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * prj->w[0] r0*(mu+1) * prj->w[1] 1/prj->w[0] * prj->w[2] Boundary parameter, -mu for |mu| <= 1, * -1/mu for |mu| >= 1. *===========================================================================*/ int azpset(prj) struct prjprm *prj; { 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[1] = 1.0/prj->w[0]; if (fabs(prj->p[1]) <= 1.0) { prj->w[2] = -prj->p[1]; } else { prj->w[2] = -1.0/prj->p[1]; } if (prj->flag == -1) { prj->flag = -PRJSET; } else { prj->flag = PRJSET; } return 0; } /*--------------------------------------------------------------------------*/ int azpfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double r, s, sthe; if (abs(prj->flag) != PRJSET) { if (azpset(prj)) return 1; } sthe = wcs_sind(theta); s = prj->p[1] + sthe; if (s == 0.0) { return 2; } r = prj->w[0]*wcs_cosd(theta)/s; *x = r*wcs_sind(phi); *y = -r*wcs_cosd(phi); if (prj->flag == PRJSET && sthe < prj->w[2]) { return 2; } return 0; } /*--------------------------------------------------------------------------*/ int azprev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double r, rho, s; const double tol = 1.0e-13; if (abs(prj->flag) != PRJSET) { if (azpset(prj)) return 1; } r = sqrt(x*x + y*y); if (r == 0.0) { *phi = 0.0; } else { *phi = wcs_atan2d(x, -y); } rho = r*prj->w[1]; s = rho*prj->p[1]/sqrt(rho*rho+1.0); if (fabs(s) > 1.0) { if (fabs(s) > 1.0+tol) { return 2; } *theta = wcs_atan2d(1.0,rho) - wcs_copysign(90.0,s); } else { *theta = wcs_atan2d(1.0,rho) - wcs_asind(s); } return 0; } /*============================================================================ * TAN: gnomonic projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. *===========================================================================*/ int tanset(prj) struct prjprm *prj; { int k; if (prj->r0 == 0.0) prj->r0 = R2D; if (prj->flag == -1) { prj->flag = -PRJSET; } else { prj->flag = PRJSET; } for (k = 99; k >= 0 && fabs(prj->p[k]) <= 1e-30 && fabs(prj->p[k+100]) <= 1e-30; k--); if (k < 0) k = 0; prj->n = k; return 0; } /*--------------------------------------------------------------------------*/ int tanfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double r, s, xp[2]; if (abs(prj->flag) != PRJSET) { if(tanset(prj)) return 1; } s = wcs_sind(theta); if (s == 0.0) return 2; r = prj->r0*wcs_cosd(theta)/s; xp[0] = r*wcs_sind(phi); xp[1] = -r*wcs_cosd(phi); if (prj->n) { if ((prj->inv_x) && (prj->inv_y)) { *x = prj->inv_x? poly_func(prj->inv_x, xp) : xp[0]; *y = prj->inv_y? poly_func(prj->inv_y, xp) : xp[1]; } else pv_to_raw(prj, xp[0],xp[1], x,y); } else { *x = xp[0]; *y = xp[1]; } if (prj->flag == PRJSET && 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 xp,yp, rp; if (abs(prj->flag) != PRJSET) { if (tanset(prj)) return 1; } if (prj->n) raw_to_pv(prj, x,y, &xp, &yp); else { xp = x; yp = y; } rp = sqrt(xp*xp+yp*yp); if (rp == 0.0) { *phi = 0.0; } else { *phi = wcs_atan2d(xp, -yp); } *theta = wcs_atan2d(prj->r0, rp); return 0; } /*============================================================================ * SIN: orthographic/synthesis projection. * * Given: * prj->p[1:2] SIN obliqueness parameters, alpha and beta. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * prj->w[0] 1/r0 * prj->w[1] alpha**2 + beta**2 * prj->w[2] 2*(alpha**2 + beta**2) * prj->w[3] 2*(alpha**2 + beta**2 + 1) * prj->w[4] alpha**2 + beta**2 - 1 *===========================================================================*/ int sinset(prj) struct prjprm *prj; { 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] = 2.0*prj->w[1]; prj->w[3] = prj->w[2] + 2.0; prj->w[4] = prj->w[1] - 1.0; if (prj->flag == -1) { prj->flag = -PRJSET; } else { prj->flag = PRJSET; } 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) != PRJSET) { 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 = wcs_sind(theta) - 1.0; cthe = wcs_cosd(theta); } cphi = wcs_cosd(phi); sphi = wcs_sind(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 == PRJSET) { if (prj->w[1] == 0.0) { /* Orthographic projection. */ if (theta < 0.0) { return 2; } } else { /* "Synthesis" projection. */ t = wcs_atand(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, sth, sth1, sth2, sxy, x0, xp, y0, yp, z; if (abs(prj->flag) != PRJSET) { 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 = wcs_atan2d(x0, -y0); } else { *phi = 0.0; } if (r2 < 0.5) { *theta = wcs_acosd(sqrt(r2)); } else if (r2 <= 1.0) { *theta = wcs_asind(sqrt(1.0 - r2)); } else { return 2; } } else { /* "Synthesis" projection. */ if (r2 < 1.0e-10) { /* Use small angle formula. */ z = -r2/2.0; *theta = 90.0 - R2D*sqrt(r2/(1.0 - x0*prj->p[1] + y0*prj->p[2])); } else { sxy = 2.0*(prj->p[1]*x0 - prj->p[2]*y0); a = prj->w[3]; b = -(sxy + prj->w[2]); c = r2 + sxy + prj->w[4]; d = b*b - 2.0*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; sth = (sth1>sth2) ? sth1 : sth2; if (sth > 1.0) { if (sth-1.0 < tol) { sth = 1.0; } else { sth = (sth1 1.0 || sth < -1.0) { return 2; } *theta = wcs_asind(sth); z = sth - 1.0; } xp = -y0 - prj->p[2]*z; yp = x0 - prj->p[1]*z; if (xp == 0.0 && yp == 0.0) { *phi = 0.0; } else { *phi = wcs_atan2d(yp,xp); } } return 0; } /*============================================================================ * STG: stereographic projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * prj->w[0] 2*r0 * prj->w[1] 1/(2*r0) *===========================================================================*/ int stgset(prj) struct prjprm *prj; { 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->flag = PRJSET; 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 != PRJSET) { if (stgset(prj)) return 1; } s = 1.0 + wcs_sind(theta); if (s == 0.0) { return 2; } r = prj->w[0]*wcs_cosd(theta)/s; *x = r*wcs_sind(phi); *y = -r*wcs_cosd(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 != PRJSET) { if (stgset(prj)) return 1; } r = sqrt(x*x + y*y); if (r == 0.0) { *phi = 0.0; } else { *phi = wcs_atan2d(x, -y); } *theta = 90.0 - 2.0*wcs_atand(r*prj->w[1]); return 0; } /*============================================================================ * ARC: zenithal/azimuthal equidistant projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * prj->w[0] r0*(pi/180) * prj->w[1] (180/pi)/r0 *===========================================================================*/ int arcset(prj) struct prjprm *prj; { 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->flag = PRJSET; return 0; } /*--------------------------------------------------------------------------*/ int arcfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double r; if (prj->flag != PRJSET) { if (arcset(prj)) return 1; } r = prj->w[0]*(90.0 - theta); *x = r*wcs_sind(phi); *y = -r*wcs_cosd(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 != PRJSET) { if (arcset(prj)) return 1; } r = sqrt(x*x + y*y); if (r == 0.0) { *phi = 0.0; } else { *phi = wcs_atan2d(x, -y); } *theta = 90.0 - r*prj->w[1]; return 0; } /*============================================================================ * ZPN: zenithal/azimuthal polynomial projection. * * Given: * prj->p[0:99] Polynomial coefficients. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 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). *===========================================================================*/ int zpnset(prj) struct prjprm *prj; { int i, j, k; double d, d1, d2, r, zd, zd1, zd2; const double tol = 1.0e-13; if (prj->r0 == 0.0) prj->r0 = R2D; /* Find the highest non-zero coefficient. */ for (k = 99; k >= 0 && prj->p[k] == 0.0; k--); if (k < 0) return 1; prj->n = k; 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; } if (prj->flag == -1) { prj->flag = -PRJSET; } else { prj->flag = PRJSET; } 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) != PRJSET) { if (zpnset(prj)) return 1; } s = (90.0 - theta)*D2R; r = 0.0; for (j = prj->n; j >= 0; j--) { r = r*s + prj->p[j]; } r = prj->r0*r; *x = r*wcs_sind(phi); *y = -r*wcs_cosd(phi); if (prj->flag == PRJSET && 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) != PRJSET) { 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 = wcs_atan2d(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. * prj->w[0] 2*r0 * prj->w[1] 1/(2*r0) *===========================================================================*/ int zeaset(prj) struct prjprm *prj; { 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->flag = PRJSET; return 0; } /*--------------------------------------------------------------------------*/ int zeafwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double r; if (prj->flag != PRJSET) { if (zeaset(prj)) return 1; } r = prj->w[0]*wcs_sind((90.0 - theta)/2.0); *x = r*wcs_sind(phi); *y = -r*wcs_cosd(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 != PRJSET) { if (zeaset(prj)) return 1; } r = sqrt(x*x + y*y); if (r == 0.0) { *phi = 0.0; } else { *phi = wcs_atan2d(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*wcs_asind(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. * 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] *===========================================================================*/ int airset(prj) struct prjprm *prj; { const double tol = 1.0e-4; double cxi; 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 = wcs_cosd((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->flag = PRJSET; 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 != PRJSET) { 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 = wcs_cosd((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*wcs_sind(phi); *y = -r*wcs_cosd(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 != PRJSET) { 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 = wcs_acosd(cxi); } if (r == 0.0) { *phi = 0.0; } else { *phi = wcs_atan2d(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. * 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)) *===========================================================================*/ int cypset(prj) struct prjprm *prj; { if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[4] = prj->p[1]? prj->p[1] : 1.0; prj->w[0] = prj->p[2]? prj->p[2] : 1.0; prj->w[1] = 1.0/prj->w[0]; prj->w[2] = R2D*(prj->w[4] + prj->w[0]); if (prj->w[2] == 0.0) { return 1; } prj->w[3] = 1.0/prj->w[2]; } else { prj->w[4] = prj->p[1]? prj->p[1] : 1.0; prj->w[0] = (prj->p[2]? prj->p[2] : 1.0) * prj->r0 * D2R; prj->w[1] = 1.0/prj->w[0]; prj->w[2] = prj->r0*(prj->w[4] + prj->w[0]); if (prj->w[2] == 0.0) { return 1; } prj->w[3] = 1.0/prj->w[2]; } prj->flag = PRJSET; return 0; } /*--------------------------------------------------------------------------*/ int cypfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double s; if (prj->flag != PRJSET) { if (cypset(prj)) return 1; } s = prj->w[4] + wcs_cosd(theta); if (s == 0.0) { return 2; } *x = prj->w[0]*phi; *y = prj->w[2]*wcs_sind(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 != PRJSET) { if (cypset(prj)) return 1; } *phi = x*prj->w[1]; if (*phi>180.0) *phi -= 360.0; else if (*phi<-180.0) *phi += 360.0; eta = y*prj->w[3]; *theta = wcs_atan2d(eta,1.0) + wcs_asind(eta*prj->w[4]/sqrt(eta*eta+1.0)); return 0; } /*============================================================================ * CAR: Cartesian projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * prj->w[0] r0*(pi/180) * prj->w[1] (180/pi)/r0 *===========================================================================*/ int carset(prj) struct prjprm *prj; { 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->flag = PRJSET; return 0; } /*--------------------------------------------------------------------------*/ int carfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { if (prj->flag != PRJSET) { 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 != PRJSET) { if (carset(prj)) return 1; } *phi = prj->w[1]*x; if (*phi>180.0) *phi -= 360.0; else if (*phi<-180.0) *phi += 360.0; *theta = prj->w[1]*y; return 0; } /*============================================================================ * MER: Mercator's projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * prj->w[0] r0*(pi/180) * prj->w[1] (180/pi)/r0 *===========================================================================*/ int merset(prj) struct prjprm *prj; { 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->flag = PRJSET; return 0; } /*--------------------------------------------------------------------------*/ int merfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { if (prj->flag != PRJSET) { if (merset(prj)) return 1; } if (theta <= -90.0 || theta >= 90.0) { return 2; } *x = prj->w[0]*phi; *y = prj->r0*log(wcs_tand((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 != PRJSET) { if (merset(prj)) return 1; } *phi = x*prj->w[1]; if (*phi>180.0) *phi -= 360.0; else if (*phi<-180.0) *phi += 360.0; *theta = 2.0*wcs_atand(exp(y/prj->r0)) - 90.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. * prj->w[0] r0*(pi/180) * prj->w[1] (180/pi)/r0 * prj->w[2] r0/lambda * prj->w[3] lambda/r0 *===========================================================================*/ int ceaset(prj) struct prjprm *prj; { double lambda = prj->p[1]; if (lambda <= 0.0 || lambda > 1.0) lambda = 1.0; if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[0] = 1.0; prj->w[1] = 1.0; prj->w[2] = prj->r0 / lambda; prj->w[3] = lambda / prj->r0; } else { prj->w[0] = prj->r0*D2R; prj->w[1] = R2D/prj->r0; prj->w[2] = prj->r0 / lambda; prj->w[3] = lambda / prj->r0; } prj->flag = PRJSET; return 0; } /*--------------------------------------------------------------------------*/ int ceafwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { if (prj->flag != PRJSET) { if (ceaset(prj)) return 1; } *x = prj->w[0]*phi; *y = prj->w[2]*wcs_sind(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 != PRJSET) { if (ceaset(prj)) return 1; } s = y*prj->w[3]; if (fabs(s) > 1.0) { if (fabs(s) > 1.0+tol) { return 2; } s = copysign(1.0,s); } *phi = x*prj->w[1]; if (*phi>180.0) *phi -= 360.0; else if (*phi<-180.0) *phi += 360.0; *theta = wcs_asind(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->r0 r0; reset to 180/pi if 0. * 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) *===========================================================================*/ int copset(prj) struct prjprm *prj; { if (prj->r0 == 0.0) prj->r0 = R2D; prj->w[0] = wcs_sind(prj->p[1]); if (prj->w[0] == 0.0) { return 1; } prj->w[1] = 1.0/prj->w[0]; prj->w[3] = prj->r0*wcs_cosd(prj->p[2]); if (prj->w[3] == 0.0) { return 1; } prj->w[4] = 1.0/prj->w[3]; prj->w[5] = 1.0/wcs_tand(prj->p[1]); prj->w[2] = prj->w[3]*prj->w[5]; if (prj->flag == -1) { prj->flag = -PRJSET; } else { prj->flag = PRJSET; } 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) != PRJSET) { if (copset(prj)) return 1; } t = theta - prj->p[1]; s = wcs_cosd(t); if (s == 0.0) { return 2; } a = prj->w[0]*phi; r = prj->w[2] - prj->w[3]*wcs_sind(t)/s; *x = r*wcs_sind(a); *y = prj->w[2] - r*wcs_cosd(a); if (prj->flag == PRJSET && 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) != PRJSET) { 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 = wcs_atan2d(x/r, dy/r); } *phi = a*prj->w[1]; *theta = prj->p[1] + wcs_atand(prj->w[5] - r*prj->w[4]); 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. * 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 *===========================================================================*/ int codset(prj) struct prjprm *prj; { if (prj->r0 == 0.0) prj->r0 = R2D; if (prj->p[2] == 0.0) { prj->w[0] = prj->r0*wcs_sind(prj->p[1])*D2R; } else { prj->w[0] = prj->r0*wcs_sind(prj->p[1])*wcs_sind(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*wcs_cosd(prj->p[2])*wcs_cosd(prj->p[1])/prj->w[0]; prj->w[3] = prj->w[2] + prj->p[1]; prj->flag = PRJSET; 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 != PRJSET) { if (codset(prj)) return 1; } a = prj->w[0]*phi; r = prj->w[3] - theta; *x = r*wcs_sind(a); *y = prj->w[2] - r*wcs_cosd(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 != PRJSET) { 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 = wcs_atan2d(x/r, dy/r); } *phi = a*prj->w[1]; *theta = prj->w[3] - r; 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. * prj->w[0] C = (sin(theta1) + sin(theta2))/2 * prj->w[1] 1/C * prj->w[2] Y0 = chi*sqrt(psi - 2C*wcs_sind(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) *===========================================================================*/ int coeset(prj) struct prjprm *prj; { double theta1, theta2; 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] = (wcs_sind(theta1) + wcs_sind(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 + wcs_sind(theta1)*wcs_sind(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]*wcs_sind(prj->p[1])); prj->flag = PRJSET; 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 != PRJSET) { 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]*wcs_sind(theta)); } *x = r*wcs_sind(a); *y = prj->w[2] - r*wcs_cosd(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 != PRJSET) { 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 = wcs_atan2d(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 = wcs_asind(w); } } 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. * 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 *===========================================================================*/ int cooset(prj) struct prjprm *prj; { double cos1, cos2, tan1, tan2, theta1, theta2; if (prj->r0 == 0.0) prj->r0 = R2D; theta1 = prj->p[1] - prj->p[2]; theta2 = prj->p[1] + prj->p[2]; tan1 = wcs_tand((90.0 - theta1)/2.0); cos1 = wcs_cosd(theta1); if (theta1 == theta2) { prj->w[0] = wcs_sind(theta1); } else { tan2 = wcs_tand((90.0 - theta2)/2.0); cos2 = wcs_cosd(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(wcs_tand((90.0 - prj->p[1])/2.0),prj->w[0]); prj->w[4] = 1.0/prj->w[3]; prj->flag = PRJSET; 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 != PRJSET) { 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(wcs_tand((90.0 - theta)/2.0),prj->w[0]); } *x = r*wcs_sind(a); *y = prj->w[2] - r*wcs_cosd(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 != PRJSET) { 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 = wcs_atan2d(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*wcs_atand(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. * prj->w[1] r0*pi/180 * prj->w[2] Y0 = r0*cot(theta1) + theta1*pi/180) *===========================================================================*/ int bonset(prj) struct prjprm *prj; { if (prj->r0 == 0.0) { prj->r0 = R2D; prj->w[1] = 1.0; prj->w[2] = prj->r0*wcs_cosd(prj->p[1])/wcs_sind(prj->p[1]) + prj->p[1]; } else { prj->w[1] = prj->r0*D2R; prj->w[2] = prj->r0*(wcs_cosd(prj->p[1])/wcs_sind(prj->p[1]) + prj->p[1]*D2R); } prj->flag = PRJSET; 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 glsfwd(phi, theta, prj, x, y); } if (prj->flag != PRJSET) { if (bonset(prj)) return 1; } r = prj->w[2] - theta*prj->w[1]; a = prj->r0*phi*wcs_cosd(theta)/r; *x = r*wcs_sind(a); *y = prj->w[2] - r*wcs_cosd(a); return 0; } /*--------------------------------------------------------------------------*/ int bonrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double a, dy, costhe, r; if (prj->p[1] == 0.0) { /* Sanson-Flamsteed. */ return glsrev(x, y, prj, phi, theta); } if (prj->flag != PRJSET) { 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 = wcs_atan2d(x/r, dy/r); } *theta = (prj->w[2] - r)/prj->w[1]; costhe = wcs_cosd(*theta); if (costhe == 0.0) { *phi = 0.0; } else { *phi = a*(r/prj->r0)/wcs_cosd(*theta); } return 0; } /*============================================================================ * PCO: polyconic projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * prj->w[0] r0*(pi/180) * prj->w[1] 1/r0 * prj->w[2] 2*r0 *===========================================================================*/ int pcoset(prj) struct prjprm *prj; { 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->flag = PRJSET; return 0; } /*--------------------------------------------------------------------------*/ int pcofwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double a, costhe, cotthe, sinthe; if (prj->flag != PRJSET) { if (pcoset(prj)) return 1; } costhe = wcs_cosd(theta); sinthe = wcs_sind(theta); a = phi*sinthe; if (sinthe == 0.0) { *x = prj->w[0]*phi; *y = 0.0; } else { cotthe = costhe/sinthe; *x = prj->r0*cotthe*wcs_sind(a); *y = prj->r0*(cotthe*(1.0 - wcs_cosd(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 != PRJSET) { 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 = wcs_copysign(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 = wcs_tand(*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 = wcs_atan2d(yp, xp)/wcs_sind(*theta); } } return 0; } /*============================================================================ * GLS: Sanson-Flamsteed ("global sinusoid") projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * prj->w[0] r0*(pi/180) * prj->w[1] (180/pi)/r0 *===========================================================================*/ int glsset(prj) struct prjprm *prj; { 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->flag = PRJSET; return 0; } /*--------------------------------------------------------------------------*/ int glsfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { if (prj->flag != PRJSET) { if (glsset(prj)) return 1; } *x = prj->w[0]*phi*wcs_cosd(theta); *y = prj->w[0]*theta; return 0; } /*--------------------------------------------------------------------------*/ int glsrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double w; if (prj->flag != PRJSET) { if (glsset(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. * prj->w[0] r0*(pi/180) * prj->w[1] (180/pi)/r0 * prj->w[2] pi*r0 * prj->w[3] 1/(pi*r0) *===========================================================================*/ int parset(prj) struct prjprm *prj; { 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->flag = PRJSET; return 0; } /*--------------------------------------------------------------------------*/ int parfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double s; if (prj->flag != PRJSET) { if (parset(prj)) return 1; } s = wcs_sind(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 != PRJSET) { 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*wcs_asind(s); return 0; } /*============================================================================ * AIT: Hammer-Aitoff projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 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) *===========================================================================*/ int aitset(prj) struct prjprm *prj; { 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->flag = PRJSET; return 0; } /*--------------------------------------------------------------------------*/ int aitfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double costhe, w; if (prj->flag != PRJSET) { if (aitset(prj)) return 1; } costhe = wcs_cosd(theta); w = sqrt(prj->w[0]/(1.0 + costhe*wcs_cosd(phi/2.0))); *x = 2.0*w*costhe*wcs_sind(phi/2.0); *y = w*wcs_sind(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 != PRJSET) { 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 = wcs_copysign(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*wcs_atan2d(yp, xp); } *theta = wcs_asind(s); return 0; } /*============================================================================ * MOL: Mollweide's projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 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 *===========================================================================*/ int molset(prj) struct prjprm *prj; { 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->flag = PRJSET; return 0; } /*--------------------------------------------------------------------------*/ int molfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { int j; double alpha, resid, u, v, v0, v1; const double tol = 1.0e-13; if (prj->flag != PRJSET) { if (molset(prj)) return 1; } if (fabs(theta) == 90.0) { *x = 0.0; *y = wcs_copysign(prj->w[0],theta); } else if (theta == 0.0) { *x = prj->w[1]*phi; *y = 0.0; } else { u = PI*wcs_sind(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; } alpha = v/2.0; *x = prj->w[1]*phi*cos(alpha); *y = prj->w[0]*sin(alpha); } 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 != PRJSET) { 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 = wcs_copysign(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 = wcs_copysign(1.0,z); } *theta = wcs_asind(z); return 0; } /*============================================================================ * CSC: COBE quadrilateralized spherical cube projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * prj->w[0] r0*(pi/4) * prj->w[1] (4/pi)/r0 *===========================================================================*/ int cscset(prj) struct prjprm *prj; { 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->flag = PRJSET; return 0; } /*--------------------------------------------------------------------------*/ int cscfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { int face; double costhe, eta, l, m, n, rho, xi; const float tol = 1.0e-7; float a, a2, a2b2, a4, ab, b, b2, b4, ca2, cb2, x0, xf, y0, yf; 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 != PRJSET) { if (cscset(prj)) return 1; } costhe = wcs_cosd(theta); l = costhe*wcs_cosd(phi); m = costhe*wcs_sind(phi); n = wcs_sind(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 { 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 = wcs_copysign(1.0,xf); } if (fabs(yf) > 1.0) { if (fabs(yf) > 1.0+tol) { return 2; } yf = wcs_copysign(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, m, n; 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 != PRJSET) { 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 { 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 = wcs_atan2d(m, l); } *theta = wcs_asind(n); return 0; } /*============================================================================ * QSC: quadrilaterilized spherical cube projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * prj->w[0] r0*(pi/4) * prj->w[1] (4/pi)/r0 *===========================================================================*/ int qscset(prj) struct prjprm *prj; { 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->flag = PRJSET; return 0; } /*--------------------------------------------------------------------------*/ int qscfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { int face; double chi, costhe, eta, l, m, n, p, psi, rho, rhu, t, x0, xf, xi, y0, yf; const double tol = 1.0e-12; if (prj->flag != PRJSET) { if (qscset(prj)) return 1; } if (fabs(theta) == 90.0) { *x = 0.0; *y = wcs_copysign(2.0*prj->w[0],theta); return 0; } costhe = wcs_cosd(theta); l = costhe*wcs_cosd(phi); m = costhe*wcs_sind(phi); n = wcs_sind(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 { 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)) { psi = eta/xi; chi = 1.0 + psi*psi; xf = -sqrt(rhu/(1.0-1.0/sqrt(1.0+chi))); yf = (xf/15.0)*(wcs_atand(psi) - wcs_asind(psi/sqrt(chi+chi))); } else if (xi >= fabs(eta)) { psi = eta/xi; chi = 1.0 + psi*psi; xf = sqrt(rhu/(1.0-1.0/sqrt(1.0+chi))); yf = (xf/15.0)*(wcs_atand(psi) - wcs_asind(psi/sqrt(chi+chi))); } else if (-eta > fabs(xi)) { psi = xi/eta; chi = 1.0 + psi*psi; yf = -sqrt(rhu/(1.0-1.0/sqrt(1.0+chi))); xf = (yf/15.0)*(wcs_atand(psi) - wcs_asind(psi/sqrt(chi+chi))); } else { psi = xi/eta; chi = 1.0 + psi*psi; yf = sqrt(rhu/(1.0-1.0/sqrt(1.0+chi))); xf = (yf/15.0)*(wcs_atand(psi) - wcs_asind(psi/sqrt(chi+chi))); } if (fabs(xf) > 1.0) { if (fabs(xf) > 1.0+tol) { return 2; } xf = wcs_copysign(1.0,xf); } if (fabs(yf) > 1.0) { if (fabs(yf) > 1.0+tol) { return 2; } yf = wcs_copysign(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 chi, l, m, n, psi, rho, rhu, xf, yf, w; const double tol = 1.0e-12; if (prj->flag != PRJSET) { 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) { psi = 0.0; chi = 1.0; rho = 1.0; rhu = 0.0; } else { w = 15.0*yf/xf; psi = wcs_sind(w)/(wcs_cosd(w) - SQRT2INV); chi = 1.0 + psi*psi; rhu = xf*xf*(1.0 - 1.0/sqrt(1.0 + chi)); rho = 1.0 - rhu; } } else { if (yf == 0.0) { psi = 0.0; chi = 1.0; rho = 1.0; rhu = 0.0; } else { w = 15.0*xf/yf; psi = wcs_sind(w)/(wcs_cosd(w) - SQRT2INV); chi = 1.0 + psi*psi; rhu = yf*yf*(1.0 - 1.0/sqrt(1.0 + chi)); 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)/chi); } if (face == 0) { n = rho; if (direct) { m = w; if (xf < 0.0) m = -m; l = -m*psi; } else { l = w; if (yf > 0.0) l = -l; m = -l*psi; } } else if (face == 1) { l = rho; if (direct) { m = w; if (xf < 0.0) m = -m; n = m*psi; } else { n = w; if (yf < 0.0) n = -n; m = n*psi; } } else if (face == 2) { m = rho; if (direct) { l = w; if (xf > 0.0) l = -l; n = -l*psi; } else { n = w; if (yf < 0.0) n = -n; l = -n*psi; } } else if (face == 3) { l = -rho; if (direct) { m = w; if (xf > 0.0) m = -m; n = -m*psi; } else { n = w; if (yf < 0.0) n = -n; m = -n*psi; } } else if (face == 4) { m = -rho; if (direct) { l = w; if (xf < 0.0) l = -l; n = l*psi; } else { n = w; if (yf < 0.0) n = -n; l = n*psi; } } else { n = -rho; if (direct) { m = w; if (xf < 0.0) m = -m; l = m*psi; } else { l = w; if (yf < 0.0) l = -l; m = l*psi; } } if (l == 0.0 && m == 0.0) { *phi = 0.0; } else { *phi = wcs_atan2d(m, l); } *theta = wcs_asind(n); return 0; } /*============================================================================ * TSC: tangential spherical cube projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. * prj->w[0] r0*(pi/4) * prj->w[1] (4/pi)/r0 *===========================================================================*/ int tscset(prj) struct prjprm *prj; { 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->flag = PRJSET; return 0; } /*--------------------------------------------------------------------------*/ int tscfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { int face; double costhe, l, m, n, rho, x0, xf, y0, yf; const double tol = 1.0e-12; if (prj->flag != PRJSET) { if (tscset(prj)) return 1; } costhe = wcs_cosd(theta); l = costhe*wcs_cosd(phi); m = costhe*wcs_sind(phi); n = wcs_sind(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 { 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 = wcs_copysign(1.0,xf); } if (fabs(yf) > 1.0) { if (fabs(yf) > 1.0+tol) { return 2; } yf = wcs_copysign(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 != PRJSET) { 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 = wcs_atan2d(m, l); } *theta = wcs_asind(n); return 0; } /*============================================================================ * TNX: IRAF's gnomonic projection. * * Given and/or returned: * prj->r0 r0; reset to 180/pi if 0. *===========================================================================*/ int tnxset(prj) struct prjprm *prj; { if (prj->r0 == 0.0) prj->r0 = R2D; if (prj->flag == -1) { prj->flag = -PRJSET; } else { prj->flag = PRJSET; } return 0; } /*--------------------------------------------------------------------------*/ int tnxfwd(phi, theta, prj, x, y) const double phi, theta; struct prjprm *prj; double *x, *y; { double r, s, xp[2]; if (abs(prj->flag) != PRJSET) { if(tnxset(prj)) return 1; } s = wcs_sind(theta); if (s == 0.0) return 2; r = prj->r0*wcs_cosd(theta)/s; xp[0] = r*wcs_sind(phi); xp[1] = -r*wcs_cosd(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 == PRJSET && s < 0.0) { return 2; } return 0; } /*--------------------------------------------------------------------------*/ int tnxrev(x, y, prj, phi, theta) const double x, y; struct prjprm *prj; double *phi, *theta; { double rp,xp,yp; if (abs(prj->flag) != PRJSET) { if (tanset(prj)) return 1; } xp = x+raw_to_tnxaxis(prj->tnx_lngcor, x, y); yp = y+raw_to_tnxaxis(prj->tnx_latcor, x, y); if ((rp = sqrt(xp*xp+yp*yp)) == 0.0) { *phi = 0.0; } else { *phi = wcs_atan2d(xp, -yp); } *theta = wcs_atan2d(prj->r0, rp); return 0; } /*--------------------------------------------------------------------------*/ int raw_to_pv(struct prjprm *prj, double x, double y, double *xo, double *yo) { int k; double *a,*b; long double r,r3,r5,r7,xy,x2,x3,x4,x5,x6,x7,y2,y3,y4,y5,y6,y7,xp,yp; if (abs(prj->flag) != PRJSET) { if (tanset(prj)) return 1; } k=prj->n; a = prj->p+100; /* Latitude comes first for compatibility */ b = prj->p; /* 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; } /*--------------------------------------------------------------------------*/ int pv_to_raw(struct prjprm *prj, double x, double y, double *xo, double *yo) { double x1,y1; if (abs(prj->flag) != PRJSET) { if (tanset(prj)) return 1; } raw_to_pv(prj, x,y, xo,yo); *xo = 2*x - *xo; *yo= 2*y - *yo; raw_to_pv(prj, *xo,*yo, &x1, &y1); *xo -= x1 - x; *yo -= y1 - y; raw_to_pv(prj, *xo,*yo, &x1, &y1); *xo -= x1 - x; *yo -= y1 - y; return 0; } /*--------------------------------------------------------------------------*/ int raw_to_cv(struct prjprm *prj, double x, double y, double *xo, double *yo) { int k; double *a,*b; long double r,r3,r5,r7,xy,x2,x3,x4,x5,x6,x7,y2,y3,y4,y5,y6,y7,xp,yp; if (abs(prj->flag) != PRJSET) { if (tanset(prj)) return 1; } k=prj->n; a = prj->p+100; /* Latitude comes first for compatibility */ b = prj->p; /* 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=2.0*x*x-1.0); yp += *(b++)*(y2=2.0*y*y-1.0); 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*(2.0*x2-1.0)); yp += *(b++)*(y3=y*(2.0*y2-1.0)); 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=2.0*x*x3-x2); yp += *(b++)*(y4=2.0*y*y3-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=2.0*x*x4-x3); yp += *(b++)*(y5=2.0*y*y4-y3); 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=2.0*x*x5-x4); yp += *(b++)*(y6=2.0*y*y5-y4); 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=2.0*x*x6-x5); yp += *(b++)*(y7=2.0*y*y6-y5); 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; } /*--------------------------------------------------------------------------*/ int cv_to_raw(struct prjprm *prj, double x, double y, double *xo, double *yo) { double x1,y1; if (abs(prj->flag) != PRJSET) { if (tanset(prj)) return 1; } raw_to_cv(prj, x,y, xo,yo); *xo = 2*x - *xo; *yo= 2*y - *yo; raw_to_cv(prj, *xo,*yo, &x1, &y1); *xo -= x1 - x; *yo -= y1 - y; raw_to_pv(prj, *xo,*yo, &x1, &y1); *xo -= x1 - x; *yo -= y1 - y; return 0; } swarp-2.41.5/src/wcs/proj.h000066400000000000000000000222021400430667300154460ustar00rootroot00000000000000/* * proj.h * * Include file for proj.h. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic WCS library * * Copyright: (C) 2000-2012 Emmanuel Bertin -- IAP/CNRS/UPMC * (C) 1995-1999 Mark Calabretta (original version) * * Licenses: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 04/12/2012 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*============================================================================= * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-1999, Mark Calabretta * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library * General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * 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 * IRAF's TNX added by E.Bertin 2000/03/28 * $Id: proj.h,v 1.1.1.1 2002/03/15 16:33:26 bertin Exp $ *===========================================================================*/ #ifndef WCSLIB_PROJ #define WCSLIB_PROJ #ifdef __cplusplus extern "C" { #endif struct prjprm { int flag; int n; double r0; double p[200]; double w[10]; struct tnxaxis *tnx_latcor; struct tnxaxis *tnx_lngcor; struct poly *inv_x; struct poly *inv_y; }; #if __STDC__ || defined(__cplusplus) 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 tanset(struct prjprm *); int tanfwd(const double, const double, struct prjprm *, double *, double *); int tanrev(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 stgset(struct prjprm *); int stgfwd(const double, const double, struct prjprm *, double *, double *); int stgrev(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 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 ceaset(struct prjprm *); int ceafwd(const double, const double, struct prjprm *, double *, double *); int cearev(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 codset(struct prjprm *); int codfwd(const double, const double, struct prjprm *, double *, double *); int codrev(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 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 glsset(struct prjprm *); int glsfwd(const double, const double, struct prjprm *, double *, double *); int glsrev(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 aitset(struct prjprm *); int aitfwd(const double, const double, struct prjprm *, double *, double *); int aitrev(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 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 tscset(struct prjprm *); int tscfwd(const double, const double, struct prjprm *, double *, double *); int tscrev(const double, const double, struct prjprm *, double *, double *); int tnxset(struct prjprm *); int tnxfwd(const double, const double, struct prjprm *, double *, double *); int tnxrev(const double, const double, struct prjprm *, double *, double *); int raw_to_pv(struct prjprm *, double, double, double *, double *); int pv_to_raw(struct prjprm *, double, double, double *, double *); int raw_to_cv(struct prjprm *, double, double, double *, double *); int cv_to_raw(struct prjprm *, double, double, double *, double *); #else int azpset(), azpfwd(), azprev(); int tanset(), tanfwd(), tanrev(); int sinset(), sinfwd(), sinrev(); int stgset(), stgfwd(), stgrev(); int arcset(), arcfwd(), arcrev(); int zpnset(), zpnfwd(), zpnrev(); int zeaset(), zeafwd(), zearev(); int airset(), airfwd(), airrev(); int cypset(), cypfwd(), cyprev(); int carset(), carfwd(), carrev(); int merset(), merfwd(), merrev(); int ceaset(), ceafwd(), cearev(); int copset(), copfwd(), coprev(); int codset(), codfwd(), codrev(); int coeset(), coefwd(), coerev(); int cooset(), coofwd(), coorev(); int bonset(), bonfwd(), bonrev(); int pcoset(), pcofwd(), pcorev(); int glsset(), glsfwd(), glsrev(); int parset(), parfwd(), parrev(); int aitset(), aitfwd(), aitrev(); int molset(), molfwd(), molrev(); int cscset(), cscfwd(), cscrev(); int qscset(), qscfwd(), qscrev(); int tscset(), tscfwd(), tscrev(); int tnxset(), tnxfwd(), tnxrev(); #endif /* extern const char *prjset_errmsg[]; extern const char *prjfwd_errmsg[]; extern const char *prjrev_errmsg[]; */ #define PRJSET 137 #ifdef __cplusplus }; #endif #endif /* WCSLIB_PROJ */ swarp-2.41.5/src/wcs/sph.c000066400000000000000000000201701400430667300152630ustar00rootroot00000000000000/* * sph.c * * Spherical coordinate transformations. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic WCS library * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * (C) 1995-1999 Mark Calabretta (original version) * * Licenses: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 10/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*============================================================================ * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-1999, Mark Calabretta * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library * General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * 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 1.1.1.1 2002/03/15 16:33:26 bertin Exp $ *===========================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include "wcstrig.h" #include "sph.h" #ifndef __STDC__ #ifndef const #define const #endif #endif #define wcs_copysign(X, Y) ((Y) < 0.0 ? -fabs(X) : fabs(X)) 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 = wcs_cosd(lat); sinlat = wcs_sind(lat); dlng = lng - eul[0]; coslng = wcs_cosd(dlng); sinlng = wcs_sind(dlng); /* Compute the native longitude. */ x = sinlat*eul[4] - coslat*eul[3]*coslng; if (fabs(x) < tol) { /* Rearrange formula to reduce roundoff errors. */ x = -wcs_cosd(lat+eul[1]) + coslat*eul[3]*(1.0 - coslng); } y = -coslat*sinlng; if (x != 0.0 || y != 0.0) { dphi = wcs_atan2d(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; if (fabs(z) > 0.99) { /* Use an alternative formula for greater numerical accuracy. */ *theta = wcs_copysign(wcs_acosd(sqrt(x*x+y*y)), z); } else { *theta = wcs_asind(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 = wcs_cosd(theta); sinthe = wcs_sind(theta); dphi = phi - eul[2]; cosphi = wcs_cosd(dphi); sinphi = wcs_sind(dphi); /* Compute the celestial longitude. */ x = sinthe*eul[4] - costhe*eul[3]*cosphi; if (fabs(x) < tol) { /* Rearrange formula to reduce roundoff errors. */ x = -wcs_cosd(theta+eul[1]) + costhe*eul[3]*(1.0 - cosphi); } y = -costhe*sinphi; if (x != 0.0 || y != 0.0) { dlng = wcs_atan2d(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; if (fabs(z) > 0.99) { /* Use an alternative formula for greater numerical accuracy. */ *lat = wcs_copysign(wcs_acosd(sqrt(x*x+y*y)), z); } else { *lat = wcs_asind(z); } } return 0; } swarp-2.41.5/src/wcs/sph.h000066400000000000000000000056261400430667300153010ustar00rootroot00000000000000/* * sph.h * * Include file for sph.c. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic WCS library * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * (C) 1995-1999 Mark Calabretta (original version) * * Licenses: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 10/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*============================================================================= * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-1999, Mark Calabretta * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library * General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * 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: sph.h,v 1.1.1.1 2002/03/15 16:33:26 bertin Exp $ *===========================================================================*/ #ifndef WCSLIB_SPH #define WCSLIB_SPH #ifdef __cplusplus extern "C" { #endif #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 __cplusplus } #endif #endif /* WCSLIB_SPH */ swarp-2.41.5/src/wcs/tnx.c000066400000000000000000000177521400430667300153160ustar00rootroot00000000000000/* * tnx.c * * Manage the TNX astrometric format (from IRAF) * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic WCS library * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 10/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include #include #include #include "tnx.h" /******* read_tnxaxis ********************************************************* PROTO tnxaxisstruct *read_tnxaxis(char *tnxstr) PURPOSE Read a TNX axis mapping structure. INPUT String containing the TNX info. OUTPUT TNXAXIS structure if OK, or NULL in case of error. NOTES -. AUTHOR E. Bertin (IAP) VERSION 04/07/2006 ***/ tnxaxisstruct *read_tnxaxis(char *tnxstr) { tnxaxisstruct *tnxaxis; char *pstr, *ptr; double min, max; int i, order; if ((pstr=strpbrk(tnxstr, "1234567890-+."))) { if (!(tnxaxis=malloc(sizeof(tnxaxisstruct)))) return NULL; tnxaxis->type = (int)(atof(strtok_r(pstr, " ", &ptr))+0.5); tnxaxis->xorder = (pstr=strtok_r(NULL, " ", &ptr))? (int)(atof(pstr)+0.5) : 0; tnxaxis->yorder = (pstr=strtok_r(NULL, " ", &ptr))? (int)(atof(pstr)+0.5) : 0; tnxaxis->xterms = (pstr=strtok_r(NULL, " ", &ptr))? (int)(atof(pstr)+0.5) : 0; min = (pstr=strtok_r(NULL, " ", &ptr))? atof(pstr) : 0.0; max = (pstr=strtok_r(NULL, " ", &ptr))? atof(pstr) : 0.0; if (max <= min) return NULL; tnxaxis->xrange = 2.0 / (max - min); tnxaxis->xmaxmin = - (max + min) / 2.0; min = (pstr=strtok_r(NULL, " ", &ptr))? atof(pstr) : 0.0; max = (pstr=strtok_r(NULL, " ", &ptr))? atof(pstr) : 0.0; if (max <= min) return NULL; tnxaxis->yrange = 2.0 / (max - min); tnxaxis->ymaxmin = - (max + min) / 2.0; switch (tnxaxis->xterms) { case TNX_XNONE: tnxaxis->ncoeff = tnxaxis->xorder + tnxaxis->yorder - 1; break; case TNX_XHALF: order = tnxaxis->xorderyorder? tnxaxis->xorder : tnxaxis->yorder; tnxaxis->ncoeff = tnxaxis->xorder*tnxaxis->yorder - order*(order-1)/2; break; case TNX_XFULL: tnxaxis->ncoeff = tnxaxis->xorder * tnxaxis->yorder; break; default: return NULL; } /*-- Now read the mapping coefficients */ if (!(tnxaxis->coeff=malloc(tnxaxis->ncoeff*sizeof(double)))) return NULL; for (i=0; incoeff && (pstr=strtok_r(NULL, " ", &ptr)); i++) tnxaxis->coeff[i] = atof(pstr); if (i!=tnxaxis->ncoeff) return NULL; if (!(tnxaxis->xbasis=malloc(tnxaxis->xorder*sizeof(double)))) return NULL; if (!(tnxaxis->ybasis=malloc(tnxaxis->yorder*sizeof(double)))) return NULL; return tnxaxis; } else return NULL; } /******* copy_tnxaxis ********************************************************* PROTO tnxaxisstruct *copy_tnxaxis(tnxaxisstruct *axis) PURPOSE Copy a TNX axis mapping structure. INPUT TNXAXIS structure pointer. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 28/11/2003 ***/ tnxaxisstruct *copy_tnxaxis(tnxaxisstruct *axis) { tnxaxisstruct *tnxaxis; int i; if (axis) { if (!axis->ncoeff) return NULL; if (!(tnxaxis=malloc(sizeof(tnxaxisstruct)))) return NULL; *tnxaxis = *axis; if (!(tnxaxis->coeff=malloc(tnxaxis->ncoeff*sizeof(double)))) return NULL; for (i=0; incoeff; i++) tnxaxis->coeff[i] = axis->coeff[i]; if (!(tnxaxis->xbasis=malloc(tnxaxis->xorder*sizeof(double)))) return NULL; for (i=0; ixorder; i++) tnxaxis->xbasis[i] = axis->xbasis[i]; if (!(tnxaxis->ybasis=malloc(tnxaxis->yorder*sizeof(double)))) return NULL; for (i=0; iyorder; i++) tnxaxis->ybasis[i] = axis->ybasis[i]; return tnxaxis; } return NULL; } /******* free_tnxaxis ********************************************************* PROTO void free_tnxaxis(tnxaxisstruct *axis) PURPOSE Free a TNX axis mapping structure. INPUT TNXAXIS structure pointer. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 09/04/2000 ***/ void free_tnxaxis(tnxaxisstruct *axis) { if (axis) { free(axis->coeff); free(axis->xbasis); free(axis->ybasis); free(axis); } return; } /******* raw_to_tnxaxis ******************************************************* PROTO double raw_to_tnxaxis(tnxaxisstruct *axis, double x, double y) PURPOSE Compute the correction value on a TNX axis at current position. INPUT TNXAXIS structure pointer, x coordinate, y coordinate. OUTPUT Value on the TNXaxis. NOTES -. AUTHOR E. Bertin (IAP) VERSION 11/04/2000 ***/ double raw_to_tnxaxis(tnxaxisstruct *axis, double x, double y) { double *xbasis, *ybasis,*coeff, norm, accum, val; int i, j, xorder,xorder0,yorder,maxorder,xterms; xbasis = axis->xbasis; ybasis = axis->ybasis; xorder = axis->xorder; yorder = axis->yorder; xterms = axis->xterms; switch (axis->type) { case TNX_CHEBYSHEV: xbasis[0] = 1.0; if (xorder > 1) { xbasis[1] = norm = (x + axis->xmaxmin)*axis->xrange; if (xorder > 2) for (i = 2; i < xorder; i++) xbasis[i] = 2.0*norm*xbasis[i-1] - xbasis[i-2]; } ybasis[0] = 1.0; if (yorder > 1) { ybasis[1] = norm = (y + axis->ymaxmin)*axis->yrange; if (yorder > 2) for (i = 2; i < yorder; i++) ybasis[i] = 2.0*norm*xbasis[i-1] - ybasis[i-2]; } break; case TNX_LEGENDRE: xbasis[0] = 1.0; if (xorder > 1) { xbasis[1] = norm = (x + axis->xmaxmin)*axis->xrange; if (xorder > 2) for (i = 2; (j=i) < xorder; i++) xbasis[i] = ((2.0*j - 3.0) * norm * xbasis[i-1] - (j - 2.0) * xbasis[i-2]) / (j - 1.0); } ybasis[0] = 1.0; if (yorder > 1) { ybasis[1] = norm = (y + axis->ymaxmin)*axis->yrange; if (yorder > 2) for (i = 2; (j=i) < xorder; i++) ybasis[i] = ((2.0*j - 3.0) * norm * ybasis[i-1] - (j - 2.0) * ybasis[i-2]) / (j - 1.0); } break; case TNX_POLYNOMIAL: xbasis[0] = 1.0; if (xorder > 1) { xbasis[1] = x; if (xorder > 2) for (i = 2; i < xorder; i++) xbasis[i] = x * xbasis[i-1]; } ybasis[0] = 1.0; if (yorder > 1) { ybasis[1] = y; if (yorder > 2) for (i = 2; i < yorder; i++) ybasis[i] = y * ybasis[i-1]; } break; default: return 0.0; } /* Loop over y basis functions */ maxorder = xorder > yorder ? xorder : yorder; xorder0 = xorder; coeff = axis->coeff; val = 0.0; for (i = 0; ixbasis; for (j = xorder; j--;) accum += *(coeff++) * *(xbasis++); val += accum**(ybasis++); /*-- Elements of the coefficient vector where neither k = 1 or i = 1 are not calculated if sf->xterms = no. */ if (xterms == TNX_XNONE) xorder = 1; else if (xterms == TNX_XHALF && (i + 1 + xorder0) > maxorder) xorder--; } return val; } swarp-2.41.5/src/wcs/tnx.h000066400000000000000000000044701400430667300153140ustar00rootroot00000000000000/* * tnx.h * * Manage polynomials. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic WCS library * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 10/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _TNX_H_ #define _TNX_H_ /*-------------------------------- macros -----------------------------------*/ #define TNX_MAXCHARS 2048 /* Maximum FITS "WAT" string length */ /* TNX permitted types of surfaces */ #define TNX_CHEBYSHEV 1 #define TNX_LEGENDRE 2 #define TNX_POLYNOMIAL 3 /* TNX 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) */ /*----------------------------- Internal constants --------------------------*/ /*------------------------------- structures --------------------------------*/ typedef struct tnxaxis { int type; /* Projection correction type */ int xorder,yorder; /* Polynomial orders */ int xterms; /* Well... */ int ncoeff; /* Number of polynom coefficients */ double xrange,yrange; /* Coordinate ranges */ double xmaxmin,ymaxmin; /* Well... */ double *coeff; /* Polynom coefficients */ double *xbasis,*ybasis; /* Basis function values */ } tnxaxisstruct; /*------------------------------- functions ---------------------------------*/ tnxaxisstruct *copy_tnxaxis(tnxaxisstruct *axis), *read_tnxaxis(char *tnxstr); double raw_to_tnxaxis(tnxaxisstruct *axis, double x, double y); void free_tnxaxis(tnxaxisstruct *axis); #endif swarp-2.41.5/src/wcs/wcs.c000066400000000000000000001234131400430667300152710ustar00rootroot00000000000000/* * wcs.c * * High level driver routines. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic WCS library * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * (C) 1995-1999 Mark Calabretta (original version) * * Licenses: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 10/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*============================================================================= * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-1999, Mark Calabretta * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library * General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * 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[][9] * 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[][9] * 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. * * 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[][9] * 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. * * 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[][9] * 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. * 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. * * 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[][9] 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. * * 4) The quadcube projections (CSC, QSC, TSC) 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 1.1.1.1 2002/03/15 16:33:26 bertin Exp $ *===========================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include "stdio.h" #include "string.h" #include "wcsmath.h" #include "wcstrig.h" #include "sph.h" #include "wcs.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 wcs_signbit(X) ((X) < 0.0 ? 1 : 0) int wcsset (naxis, ctype, wcs) const int naxis; const char ctype[][9]; struct wcsprm *wcs; { int j, k, *ndx; char requir[9]; strcpy(wcs->pcode, ""); strcpy(requir, ""); wcs->lng = -1; ndx = &wcs->lng; /* to satisfy gcc -Wall */ 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) { /* Allow NCP to pass (will be converted to SIN later). */ if (strncmp(&ctype[j][5], "NCP", 3)) 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 { /* Unrecognized celestial type. */ return 1; } } else { if (strncmp(ctype[j], requir, 8) != 0) { /* Inconsistent projection types. */ return 1; } *ndx = j; strcpy(requir, ""); } } if (strcmp(requir, "")) { /* Unmatched celestial axis. */ return 1; } 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[][9]; 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[2] == 0.0) { return 2; } strcpy(wcs->pcode, "SIN"); prj->p[1] = 0.0; prj->p[2] = wcs_cosd(cel->ref[2])/wcs_sind(cel->ref[2]); prj->flag = 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[][9]; 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[2] == 0.0) { return 2; } strcpy(wcs->pcode, "SIN"); prj->p[1] = 0.0; prj->p[2] = wcs_cosd(cel->ref[2])/wcs_sind(cel->ref[2]); prj->flag = 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[][9]; 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; double lambda, span[2], step; double pixmix; double lng, lng0, lng0m, lng1, lng1m; double lat, lat0, lat0m, lat1, lat1m; double d, d0, d0m, d1, d1m, dx; double dabs, dmin, lmin; double phi0, phi1; struct celprm cel0; /* 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]; dx = 0.0; /* to satisfy gcc -Wall */ /* 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 (wcs_signbit(d0) != wcs_signbit(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 (wcs_signbit(d0) != wcs_signbit(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; } lat = lat0 + lambda*(lat1 - lat0); world[wcs->lat] = lat; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d = pixcrd[mixpix] - pixmix; /* Check for a solution. */ dabs = fabs(d); if (dabs < tol) return 0; /* Record the point of closest approach. */ if (dabs < dmin) { lmin = lat; dmin = dabs; } if (wcs_signbit(d0) == wcs_signbit(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 (wcs_signbit(d0) != wcs_signbit(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 (wcs_signbit(d0) != wcs_signbit(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; } lng = lng0 + lambda*(lng1 - lng0); world[wcs->lng] = lng; if ((err = wcsfwd(ctype, wcs, world, crval, cel, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d = pixcrd[mixpix] - pixmix; /* Check for a solution. */ dabs = fabs(d); if (dabs < tol) return 0; /* Record the point of closest approach. */ if (dabs < dmin) { lmin = lng; dmin = dabs; } if (wcs_signbit(d0) == wcs_signbit(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; cel0.prjfwd = cel->prjfwd; cel0.prjrev = cel->prjrev; /* 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 = (float) 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 (wcs_signbit(d0) != wcs_signbit(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; } world[wcs->lng] = phi0 + lambda*(phi1 - phi0); if ((err = wcsfwd(ctype, wcs, world, crval, &cel0, phi, theta, prj, imgcrd, lin, pixcrd))) { return err; } d = pixcrd[mixpix] - pixmix; /* Check for a solution. */ dabs = fabs(d); if (dabs < tol) { /* Recall saved world coordinates. */ world[wcs->lng] = lng; world[wcs->lat] = lat; return 0; } if (wcs_signbit(d0) == wcs_signbit(d)) { phi0 = world[wcs->lng]; d0 = d; } else { phi1 = world[wcs->lng]; d1 = d; } } } /* No solution. */ return 5; } swarp-2.41.5/src/wcs/wcs.h000066400000000000000000000102261400430667300152730ustar00rootroot00000000000000/* * wcs.h * * Main WCSlib header file. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic WCS library * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * (C) 1995-1999 Mark Calabretta (original version) * * Licenses: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 10/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*============================================================================= * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-1999, Mark Calabretta * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library * General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * 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 1.1.1.1 2002/03/15 16:33:26 bertin Exp $ *===========================================================================*/ #ifndef WCSLIB_WCS #define WCSLIB_WCS #include "cel.h" #include "lin.h" #ifdef __cplusplus extern "C" { #endif 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[][9], struct wcsprm *); int wcsfwd(const char[][9], struct wcsprm *, const double[], const double[], struct celprm *, double *, double *, struct prjprm *, double[], struct linprm *, double[]); int wcsrev(const char[][9], struct wcsprm *, const double[], struct linprm *, double[], struct prjprm *, double *, double *, const double[], struct celprm *, double[]); int wcsmix(const char[][9], 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 #ifdef __cplusplus }; #endif #endif /* WCSLIB_WCS */ swarp-2.41.5/src/wcs/wcsmath.h000066400000000000000000000055471400430667300161570ustar00rootroot00000000000000/* * wcsmath.h * * Math definitions. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic WCS library * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * (C) 1995-1999 Mark Calabretta (original version) * * Licenses: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 10/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*============================================================================= * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-1999, Mark Calabretta * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library * General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * 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: wcsmath.h,v 1.1.1.1 2002/03/15 16:33:26 bertin Exp $ *===========================================================================*/ #ifndef WCSLIB_MATH #define WCSLIB_MATH #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 #define PI 3.141592653589793238462643 #define D2R (PI/180.0) #define R2D (180.0/PI) #define SQRT2 1.4142135623730950488 #define SQRT2INV (1.0/SQRT2) #endif /* WCSLIB_MATH */ swarp-2.41.5/src/wcs/wcstrig.c000066400000000000000000000127051400430667300161600ustar00rootroot00000000000000/* * wcstrig.c * * Trigonometric or inverse trigonometric functions. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic WCS library * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * (C) 1995-1999 Mark Calabretta (original version) * * Licenses: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 10/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*============================================================================ * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-1999, Mark Calabretta * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library * General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * 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 1.1.1.1 2002/03/15 16:33:26 bertin Exp $ *---------------------------------------------------------------------------*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include "wcstrig.h" #ifndef PI /* EB 02/06/97 */ #define PI 3.141592653589793238462643 #endif /* EB 02/06/97 */ const double d2r = PI / 180.0; const double r2d = 180.0 / PI; #ifndef HAVE_MATHIMF_H double wcs_cosd(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 wcs_sind(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 wcs_tand(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 wcs_acosd(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 wcs_asind(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 wcs_atand(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 wcs_atan2d(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; } #endif swarp-2.41.5/src/wcs/wcstrig.h000066400000000000000000000067161400430667300161720ustar00rootroot00000000000000/* * wcstrig.h * * Include file for wcstrig.c. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic WCS library * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * (C) 1995-1999 Mark Calabretta (original version) * * Licenses: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 10/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*============================================================================= * * WCSLIB - an implementation of the FITS WCS proposal. * Copyright (C) 1995-1999, Mark Calabretta * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published * by the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library * General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * 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: wcstrig.h,v 1.1.1.1 2002/03/15 16:33:26 bertin Exp $ *===========================================================================*/ #ifndef WCSLIB_TRIG #define WCSLIB_TRIG #ifdef __cplusplus extern "C" { #endif #if !defined(__STDC__) && !defined(__cplusplus) #ifndef const #define const #endif #endif #if __STDC__ || defined(__cplusplus) #ifdef HAVE_MATHIMF_H #define wcs_cosd cosd #define wcs_sind sind #define wcs_tand tand #define wcs_acosd acosd #define wcs_asind asind #define wcs_atand atand #define wcs_atan2d atan2d #else double wcs_cosd(const double); double wcs_sind(const double); double wcs_tand(const double); double wcs_acosd(const double); double wcs_asind(const double); double wcs_atand(const double); double wcs_atan2d(const double, const double); #endif #else double wcs_cosd(); double wcs_sind(); double wcs_tand(); double wcs_acosd(); double wcs_asind(); double wcs_atand(); double wcs_atan2d(); #endif /* Domain tolerance for asin and acos functions. */ #define WCSTRIG_TOL 1e-10 #endif /* TRIGD */ #ifdef __cplusplus }; #endif /* WCSLIB_TRIG */ swarp-2.41.5/src/wcscelsys.h000066400000000000000000000034141400430667300157230ustar00rootroot00000000000000/* * wcscelsys.h * * Celestial system definitions. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: AstrOmatic software * * Copyright: (C) 1998-2019 IAP/CNRS/SorbonneU * * License: GNU General Public License * * AstrOmatic software 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 3 of the * License, or (at your option) any later version. * AstrOmatic software 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 AstrOmatic software. * If not, see . * * Last modified: 03/12/2019 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /*-------------------------------- constants --------------------------------*/ /* Equatorial coordinates of origin and pole and rotation sign of equatorial,*/ /* galactic, ecliptic and supergalactic reference frames, from Allen Astron. */ /* Quantities, 4th ed. */ char celsysname[][2][8] = { {"RA--", "DEC-"}, {"GLON", "GLAT"}, {"ELON", "ELAT"}, {"SLON", "SLAT"}, {""}}; double celsysorig[][2] = { {0.0, 0.0}, {266.40499625, -28.93617242}, {0.0, 0.0}, {42.308333, 59.528333}}, celsyspole[][2] = { {0.0, 90.0}, {192.85948123, 27.12825120}, {270.00000000, 66.560709}, {283.754167, 15.708889}}, /* Note: the code to handle the rotation sign is not yet implemented!!! */ celsyssign[] = { 1.0, 1.0, 1.0, 1.0}; swarp-2.41.5/src/weight.c000066400000000000000000000222451400430667300151710ustar00rootroot00000000000000/* * weight.c * * Manage weight-maps. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2013 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 30/04/2013 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_MATHIMF_H #include #else #include #endif #include #include #include #include "define.h" #include "globals.h" #include "back.h" #include "field.h" #include "fits/fitscat.h" #include "prefs.h" #include "weight.h" fieldstruct *weight_reffield; PIXTYPE weight_fac, weight_thresh; long weight_pixcount; int weight_type, weight_width, weight_y; /******* load_weight ********************************************************* PROTO fieldstruct load_weight(catstruct *cat, fieldstruct *reffield, int frameno, weightenum wtype) PURPOSE Load a weight-map field INPUT Cat structurep pointer, Reference field pointer, FITS extension no, Weight type. OUTPUT RETURN_OK if no error, or RETURN_ERROR in case of non-fatal error(s). NOTES -. AUTHOR E. Bertin (IAP) VERSION 05/10/2010 ***/ fieldstruct *load_weight(catstruct *cat, fieldstruct *reffield, int frameno, int fieldno, weightenum wtype) { fieldstruct *wfield; tabstruct *tab, *intab; int i, wflags; wflags = 0; /* to avoid gcc -Wall warnings */ switch(wtype) { case WEIGHT_NONE: return NULL; case WEIGHT_FROMBACK: wflags = BACKRMS_FIELD; break; case WEIGHT_FROMRMSMAP: wflags = RMS_FIELD; break; case WEIGHT_FROMVARMAP: wflags = VAR_FIELD; break; case WEIGHT_FROMWEIGHTMAP: wflags = WEIGHT_FIELD; break; default: error(EXIT_FAILURE, "*Internal Error*: Unknown weight-map type in ", "load_weight()"); break; } if (wtype == WEIGHT_FROMBACK) /*-- In this special case, one needs to CREATE a new weight-map FITS file */ wfield = inherit_field(reffield->filename, reffield, FIELD_READ | wflags); else { /*-- First allocate memory for the new field (and nullify pointers) */ QCALLOC(wfield,fieldstruct, 1); wfield->flags = FIELD_READ|wflags; wfield->fieldno = fieldno; wfield->frameno = frameno; strcpy (wfield->filename, cat->filename); /*-- A short, "relative" version of the filename */ if (!(wfield->rfilename = strrchr(wfield->filename, '/'))) wfield->rfilename = wfield->filename; else wfield->rfilename++; sprintf(gstr, "Looking for %s ...", wfield->rfilename); NFPRINTF(OUTPUT, gstr); /*-- Check the image exists and read important info (image size, etc...) */ if (frameno >= cat->ntab) error(EXIT_FAILURE, "*Internal Error*: FITS extension unavailable in ", wfield->filename); wfield->cat = new_cat(1); strcpy(wfield->cat->filename, wfield->filename); intab = cat->tab; for (i=frameno; i--;) intab = intab->nexttab; copy_tab_fromptr(intab, wfield->cat, 0); tab = wfield->tab = wfield->cat->tab; tab->cat = wfield->cat; if (tab->naxis<1) error(EXIT_FAILURE, "*Error*: Zero-dimensional table in ", wfield->filename); /*-- Force data to be at least 2D */ if (tab->naxis<2) { tab->naxis = 2; QREALLOC(tab->naxisn, int, 2); tab->naxisn[1] = 1; } /*-- Set field width and field height (the latter can be "virtual") */ wfield->width = tab->naxisn[0]; wfield->height = 1; for (i=1; inaxis; i++) wfield->height *= tab->naxisn[i]; wfield->npix = wfield->width*wfield->height; if ((wfield->width!=reffield->width)||(wfield->height!=reffield->height)) error(EXIT_FAILURE, "*Error*: image and weight map have different sizes",""); } /*-- Background */ wfield->backw = reffield->backw; wfield->backh = reffield->backh; wfield->nbackp = reffield->nbackp; wfield->nbackx = reffield->nbackx; wfield->nbacky = reffield->nbacky; wfield->nback = reffield->nback; wfield->nbackfx = reffield->nbackfx; wfield->nbackfy = reffield->nbackfy; /* Set the back_type flag if absolute background is selected */ wfield->back_type = reffield->back_type; wfield->backdefault = reffield->backdefault; /* Default normalization factor (will be changed if necessary later) */ wfield->sigfac = 1.0; set_weightconv(wfield); wfield->weight_thresh = prefs.weight_thresh[fieldno]; wfield->var_thresh = wfield->weight_thresh; weight_to_var(&wfield->var_thresh, 1); return wfield; } /******* init_weight ********************************************************* PROTO fieldstruct init_weight(char *filename, fieldstruct *reffield, weightenum wtype) PURPOSE Create a weight-map field INPUT Weight-map filename Reference field pointer, Weight type, OUTPUT RETURN_OK if no error, or RETURN_ERROR in case of non-fatal error(s). NOTES -. AUTHOR E. Bertin (IAP) VERSION 05/10/2010 ***/ fieldstruct *init_weight(char *filename, fieldstruct *reffield) { fieldstruct *wfield; wfield = inherit_field(filename, reffield, WEIGHT_FIELD|reffield->flags); /* Default normalization factor */ wfield->sigfac = 1.0; set_weightconv(wfield); wfield->var_thresh = BIG; return wfield; } /******* read_weight ********************************************************* PROTO void read_weight(fieldstruct *wfield) PURPOSE Read weights and store them in internal format (calibrated variance). INPUT Input weight field ptr, OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 03/02/2012 ***/ void read_weight(fieldstruct *wfield) { set_weightconv(wfield); if (wfield->bitpix>0) wfield->ipix = alloc_ibody(wfield->tab, NULL); else wfield->pix = alloc_body(wfield->tab, weight_to_var); return; } /******* set_weightconv ****************************************************** PROTO void set_weightconv(fieldstruct *wfield) PURPOSE Set current weight conversion factor and flags. INPUT Weight field ptr. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 30/04/2013 ***/ void set_weightconv(fieldstruct *wfield) { weight_reffield = (wfield->flags & BACKRMS_FIELD) ? wfield->reffield:NULL; weight_pixcount = 0; weight_y = 0; weight_width = wfield->width; weight_type = wfield->flags&(BACKRMS_FIELD|RMS_FIELD|VAR_FIELD|WEIGHT_FIELD); weight_fac = (PIXTYPE)(wfield->sigfac*wfield->sigfac); weight_thresh = wfield->weight_thresh; return; } /******* weight_to_var ******************************************************* PROTO void weight_to_var(PIXTYPE *data, int npix) PURPOSE Turn input weights into a variance map. INPUT Input data ptr, Number of pixels. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 30/04/2013 ***/ void weight_to_var(PIXTYPE *data, int npix) { static PIXTYPE *weight_backdata; int i, n; switch(weight_type) { case BACKRMS_FIELD: n = weight_pixcount; if (npix==1) { *data *= *data; break; } for (i=npix; i--;) { /*------ New line */ if (!(n++%weight_width)) { backrmsline(weight_reffield, weight_y++, weight_reffield->backline); weight_backdata = weight_reffield->backline; } *(data++) = *(weight_backdata++); } weight_pixcount = n; break; case RMS_FIELD: for (i=npix; i--; data++) *data *= *dataweight_thresh? weight_fac/(*data) : BIG; break; default: error(EXIT_FAILURE, "*Internal Error*: Unknown weight-map type in ", "weight_to_var()"); break; } return; } /******* var_to_weight ******************************************************* PROTO void var_to_weight(PIXTYPE *data, int npix) PURPOSE Turn variance into a weight map. INPUT Input data ptr, Number of pixels. OUTPUT -. NOTES -. AUTHOR E. Bertin (IAP) VERSION 05/10/2010 ***/ void var_to_weight(PIXTYPE *data, int npix) { int i; switch(weight_type) { case RMS_FIELD: for (i=npix; i--; data++) if (*data. * * Last modified: 26/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifndef _WEIGHT_H_ #define _WEIGHT_H_ typedef enum {WEIGHT_NONE, WEIGHT_FROMBACK, WEIGHT_FROMRMSMAP, WEIGHT_FROMVARMAP, WEIGHT_FROMWEIGHTMAP} weightenum; /* WEIGHT_IMAGE type */ /*---------------------------------- protos --------------------------------*/ extern fieldstruct *init_weight(char *filename, fieldstruct *reffield), *load_weight(catstruct *cat, fieldstruct *reffield, int frameno, int fieldno, weightenum wtype); extern void read_weight(fieldstruct *wfield), set_weightconv(fieldstruct *wfield), var_to_weight(PIXTYPE *data, int npix), weight_to_var(PIXTYPE *data, int npix); #endif swarp-2.41.5/src/xml.c000066400000000000000000000711111400430667300144760ustar00rootroot00000000000000/* * xml.c * * Handle XML metada. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2011 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 07/06/2011 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "define.h" #include "globals.h" #include "fits/fitscat.h" #include "field.h" #include "fitswcs.h" #include "key.h" #include "prefs.h" #include "xml.h" extern time_t thetime,thetime2; /* from makeit.c */ extern pkeystruct key[]; /* from preflist.h */ extern char keylist[][32]; /* from preflist.h */ xmlstruct xmlref; xmlstruct *xmlstack = NULL; int nxml=0, nxmlmax=0; /****** init_xml ************************************************************ PROTO int init_xml(int next) PURPOSE Initialize a set of meta-data kept in memory before being written to the XML file INPUT Number of image extensions. OUTPUT RETURN_OK if everything went fine, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 26/07/2006 ***/ int init_xml(int next) { QMALLOC(xmlstack, xmlstruct, next); nxml = 0; nxmlmax = next; return EXIT_SUCCESS; } /****** end_xml ************************************************************ PROTO int end_xml(void) PURPOSE Free the set of meta-data kept in memory. INPUT -. OUTPUT RETURN_OK if everything went fine, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 12/07/2006 ***/ int end_xml(void) { free(xmlstack); return EXIT_SUCCESS; } /****** update_xml *********************************************************** PROTO int update_xml(fieldstruct *field, fieldstruct *wfield) PURPOSE Update a set of meta-data kept in memory before being written to the XML file INPUT -. OUTPUT RETURN_OK if everything went fine, RETURN_ERROR otherwise. NOTES Global preferences are used. AUTHOR E. Bertin (IAP) VERSION 11/04/2011 ***/ int update_xml(fieldstruct *field, fieldstruct *wfield) { xmlstruct *x; double pixpos[NAXIS], wcspos[NAXIS]; int d; if (nxml < nxmlmax) x = &xmlstack[nxml++]; else x = &xmlstack[0]; /* Extra calls update the meta-data of output frame */ x->fieldno = field->fieldno; x->extension = field->frameno; strcpy(x->ext_date, field->sdate_end); strcpy(x->ext_time, field->stime_end); x->ext_elapsed = field->time_diff; strcpy(x->ident, field->ident); x->exptime = field->exptime; x->backmean = field->backmean; x->backsig = field->backsig; x->sigfac = wfield? wfield->sigfac : 1.0; x->weight_thresh = wfield? wfield->weight_thresh : 0.0; x->gain = field->gain; x->saturation = field->saturation; x->fscale = field->fscale; x->fascale = field->fascale; x->pixscale = field->wcs->pixscale*DEG/ARCSEC; x->equinox = field->wcs->equinox; x->epoch = field->wcs->epoch; x->obsdate = field->wcs->obsdate; x->naxis = field->wcs->naxis; x->celsys = (int)(field->wcs->celsysconvflag? field->wcs->celsys : -1); x->headflag = field->headflag; for (d=0; dwcs->naxis; d++) pixpos[d] = (field->wcs->naxisn[d]+1.0)/2.0; raw_to_wcs(field->wcs, pixpos, wcspos); for (d=0; dwcs->naxis; d++) x->centerpos[d] = wcspos[d]; return EXIT_SUCCESS; } /****** write_xml ************************************************************ PROTO int write_xml(char *filename) PURPOSE Save meta-data to an XML file/stream. INPUT XML file name. OUTPUT RETURN_OK if everything went fine, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 26/07/2006 ***/ int write_xml(char *filename) { FILE *file; int pipe_flag; pipe_flag = 0; if (!strcmp(prefs.xml_name, "STDOUT")) { file = stdout; pipe_flag = 1; } else if (!(file = fopen(prefs.xml_name, "w"))) return RETURN_ERROR; write_xml_header(file); write_xml_meta(file, (char *)NULL); fprintf(file, "\n"); fprintf(file, "\n"); if (!pipe_flag) fclose(file); return RETURN_OK; } /****** write_xml_header ****************************************************** PROTO int write_xml_header(FILE *file) PURPOSE Save an XML-VOtable header to an XML file/stream INPUT file or stream pointer. OUTPUT RETURN_OK if everything went fine, RETURN_ERROR otherwise. NOTES Global preferences are used. AUTHOR E. Bertin (IAP) VERSION 26/07/2006 ***/ int write_xml_header(FILE *file) { char sysname[16], *filename, *rfilename; /* A short, "relative" version of the filename */ filename = prefs.outfield_name; if (!(rfilename = strrchr(filename, '/'))) rfilename = filename; else rfilename++; fprintf(file, "\n"); fprintf(file, "\n", prefs.xsl_name); fprintf(file, "\n"); fprintf(file, "produced by %s\n", BANNER); fprintf(file, "\n"); fprintf(file, "\n", BANNER, rfilename); fprintf(file, " Data related to %s" "\n", BANNER); fprintf(file, " \n"); switch(prefs.celsys_type) { case CELSYS_PIXEL: sprintf(sysname, "xy"); break; case CELSYS_GALACTIC: sprintf(sysname, "galactic"); break; case CELSYS_ECLIPTIC: sprintf(sysname, "ecl_FK5"); break; case CELSYS_SUPERGALACTIC: sprintf(sysname, "supergalactic"); break; case CELSYS_EQUATORIAL: case CELSYS_NATIVE: default: sprintf(sysname, "ICRS"); break; } fprintf(file, " \n", nxml? (xmlstack[0].epoch? xmlstack[0].epoch: 2000.0) : 2000.0, sysname); return RETURN_OK; } /****** write_xml_meta ******************************************************** PROTO int write_xml_meta(FILE *file, char *error) PURPOSE Save meta-data to an XML-VOTable file or stream INPUT Pointer to the output file (or stream), Pointer to an error msg (or NULL). OUTPUT RETURN_OK if everything went fine, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 07/06/2011 ***/ int write_xml_meta(FILE *file, char *error) { xmlstruct *x; struct tm *tm; char sysname[16], *pspath,*psuser, *pshost, *str; int d,f,n, naxis; /* Processing date and time if msg error present */ if (error) { thetime2 = time(NULL); tm = localtime(&thetime2); sprintf(prefs.sdate_end,"%04d-%02d-%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday); sprintf(prefs.stime_end,"%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); prefs.time_diff = difftime(thetime2, thetime); } /* Username */ psuser = pspath = pshost = NULL; #ifdef HAVE_GETENV if (!(psuser=getenv("USERNAME"))) /* Cygwin,... */ psuser = getenv("LOGNAME"); /* Linux,... */ pspath = getenv("PWD"); pshost = getenv("HOSTNAME"); #endif naxis = (nxml? xmlstack[0].naxis : 2); fprintf(file, " \n"); fprintf(file, " %s meta-data\n", BANNER); fprintf(file, " \n"); fprintf(file, " \n", BANNER); fprintf(file, " \n", MYVERSION); fprintf(file, " \n", WEBSITE); fprintf(file, " \n", "Emmanuel Bertin"); fprintf(file, " \n", "2002ASPC..281..228B"); fprintf(file, " \n", prefs.nthreads); fprintf(file, " \n", prefs.sdate_end); fprintf(file, " \n", prefs.stime_end); fprintf(file, " \n", prefs.time_diff); fprintf(file, " \n", psuser); fprintf(file, " \n", pshost); fprintf(file, " \n", pspath); fprintf(file, " \n", prefs.outfield_name); fprintf(file, " \n", prefs.outwfield_name); if (error) { fprintf(file, "\n \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file," \n", error); fprintf(file, " \n"); fprintf(file, " \n\n"); } else { fprintf(file, " \n", xmlstack[0].fieldno); fprintf(file, " \n", xmlstack[0].exptime); fprintf(file, " \n", xmlstack[0].gain); } /* Meta-data for each extension */ fprintf(file, " \n"); fprintf(file, " Data gathered by %s for every FITS" " input image\n", BANNER); fprintf(file, " \n"); fprintf(file, " \n", nxmlmax>0? nxmlmax-1 : 0); fprintf(file, " \n"); fprintf(file, " \n", nxml>0? nxml-1 : 0); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n", naxis, nxml? (xmlstack[0].celsys >=0? "deg":"pix") : "deg"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); for (n=1; nfieldno; fprintf(file, " \n" " \n" " \n" " " "\n" " \n" " \n" " \n" " \n \n", x->pixscale, x->obsdate, x->equinox, x->epoch, sysname); } fprintf(file, " \n"); fprintf(file, "
%d%s%s%c%s%d%s%s%.2f%g%g%c%s%d%d%g%s%c%g%g%c%g%g%g%g%g%.10g", n, prefs.infield_name[f], (prefs.inwfield_name[f] && *prefs.inwfield_name[f])? prefs.inwfield_name[f] : "(null)", x->headflag? 'T' : 'F', (x->ident && *(x->ident)) ? x->ident : "(null)", x->extension, x->ext_date, x->ext_time, x->ext_elapsed, x->backmean, x->backsig, prefs.subback_flag[f]? 'T' : 'F', key[findkeys("BACK_TYPE", keylist, FIND_STRICT)].keylist[prefs.back_type[f]], prefs.back_size[f], prefs.back_fsize[f], prefs.back_default[f], key[findkeys("WEIGHT_TYPE", keylist, FIND_STRICT)].keylist[prefs.weight_type[f]], prefs.wscale_flag[f]? 'T' : 'F', x->weight_thresh, x->sigfac, prefs.interp_flag[f]? 'T' : 'F', x->gain, x->saturation, x->exptime, x->fscale, x->fascale, x->centerpos[0]); switch(x->celsys) { case CELSYS_PIXEL: sprintf(sysname, "xy"); break; case CELSYS_GALACTIC: sprintf(sysname, "galactic"); break; case CELSYS_ECLIPTIC: sprintf(sysname, "ecl_FK5"); break; case CELSYS_SUPERGALACTIC: sprintf(sysname, "supergalactic"); break; case CELSYS_EQUATORIAL: case CELSYS_NATIVE: default: sprintf(sysname, "ICRS"); break; } for (d=1; dcenterpos[d]); fprintf(file, "%g%.10g%.10g%.10g%s
\n"); /* Warnings */ fprintf(file, " \n"); fprintf(file, " %s warnings (limited to the last %d)\n", BANNER, WARNING_NMAX); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); for (str = warning_history(); *str; str = warning_history()) fprintf(file, " \n", str, str+11, str+22); fprintf(file, " \n"); fprintf(file, "
%10.10s%8.8s%s
\n"); /* Configuration file */ fprintf(file, " \n"); fprintf(file, " %s configuration\n", BANNER); fprintf(file, " \n"); fprintf(file, " \n", prefs.prefs_name); if (!error) { fprintf(file, " \n", prefs.outfield_name); fprintf(file, " \n", prefs.outwfield_name); fprintf(file, " \n", prefs.headeronly_flag? 'T':'F'); fprintf(file, " \n", prefs.head_suffix); fprintf(file, " \n", prefs.weight_suffix); fprintf(file, " \n", prefs.combine_flag? 'T':'F'); fprintf(file, " \n", key[findkeys("COMBINE_TYPE",keylist, FIND_STRICT)].keylist[prefs.coadd_type]); fprintf(file, " \n", prefs.blank_flag? 'T':'F'); fprintf(file, " \n", key[findkeys("CELESTIAL_TYPE",keylist, FIND_STRICT)].keylist[prefs.celsys_type]); fprintf(file, " \n", prefs.projection_name); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n", nxml? (xmlstack[0].celsys >=0? "deg":"pix") : "deg"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n", prefs.resample_flag? 'T':'F'); fprintf(file, " \n", prefs.resampdir_name); fprintf(file, " \n", prefs.resamp_suffix); fprintf(file, " \n"); fprintf(file, " \n"); fprintf(file, " \n", key[findkeys("FSCALASTRO_TYPE",keylist, FIND_STRICT)].keylist[prefs.fscalastro_type]); fprintf(file, " \n", prefs.fscale_keyword); fprintf(file, " \n", prefs.fscale_default[0]); fprintf(file, " \n", prefs.gain_keyword); fprintf(file, " \n", prefs.gain_default[0]); fprintf(file, " \n", prefs.sat_keyword); fprintf(file, " \n", prefs.sat_default[0]); fprintf(file, " \n", prefs.subback_flag[0]? 'T':'F'); fprintf(file, " \n", key[findkeys("FSCALASTRO_TYPE",keylist, FIND_STRICT)].keylist[prefs.back_type[0]]); fprintf(file, " \n", prefs.back_size[0]); fprintf(file, " \n", prefs.back_fsize[0]); fprintf(file, " \n", prefs.back_default[0]); fprintf(file, " \n", prefs.back_fthresh); fprintf(file, " \n", prefs.swapdir_name); fprintf(file, " \n", prefs.vmem_max); fprintf(file, " \n", prefs.mem_max); fprintf(file, " \n", prefs.coaddbuf_size); fprintf(file, " \n", prefs.resample_flag? 'T':'F'); if (prefs.ncopy_keywords) { fprintf(file, " \n"); } fprintf(file, " \n", prefs.writefileinfo_flag? 'T':'F'); fprintf(file, " \n", key[findkeys("VERBOSE_TYPE", keylist, FIND_STRICT)].keylist[prefs.verbose_type]); } fprintf(file, " \n"); fprintf(file, "
\n"); return RETURN_OK; } /****** write_xmlerror ****************************************************** PROTO int write_xmlerror(char *error) PURPOSE Save meta-data to a simplified XML file in case of a catched error INPUT a character string. OUTPUT RETURN_OK if everything went fine, RETURN_ERROR otherwise. NOTES -. AUTHOR E. Bertin (IAP) VERSION 26/07/2006 ***/ void write_xmlerror(char *filename, char *error) { FILE *file; int pipe_flag; pipe_flag = 0; if (!strcmp(filename, "STDOUT")) { file = stdout; pipe_flag = 1; } else if (!(file = fopen(filename, "w"))) return; write_xml_header(file); write_xml_meta(file, error); fprintf(file, "
\n"); fprintf(file, "
\n"); if (!pipe_flag) fclose(file); return; } swarp-2.41.5/src/xml.h000066400000000000000000000051441400430667300145060ustar00rootroot00000000000000/* * xml.h * * Include file for xml.c. * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * This file part of: SWarp * * Copyright: (C) 2000-2010 Emmanuel Bertin -- IAP/CNRS/UPMC * * License: GNU General Public License * * SWarp 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 3 of the License, or * (at your option) any later version. * SWarp 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 SWarp. If not, see . * * Last modified: 26/10/2010 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifndef _FITSCAT_H_ #include "fits/fitscat.h" #endif #ifndef _FITSWCS_H_ #include "fitswcs.h" #endif /*----------------------------- Internal constants --------------------------*/ #ifndef XSL_URL #define XSL_URL "." #endif /*--------------------------------- typedefs --------------------------------*/ typedef struct { int fieldno; int headflag; /* external header? */ int extension; char ext_date[16],ext_time[16]; /* date and time */ float ext_elapsed; /* processing time */ char ident[80]; /* identifiant */ float exptime; /* exposure time */ float backmean; /* mean background */ float backsig; /* mean back stddev */ float sigfac; /* mean weight scaling*/ float weight_thresh; /* weight threshold */ float gain; /* gain (e-/ADU) */ float saturation; /* saturation (ADU) */ float fscale; /* photometric scaling*/ float fascale; /* astrometric scaling*/ int naxis; /* number of axes */ float pixscale; /* pixel scale (deg2) */ int celsys; /* celestial system */ double centerpos[NAXIS]; /* center coordinates */ double equinox; /* equinox of coords */ double epoch; /* epoch of coords */ double obsdate; /* observation date */ } xmlstruct; /*------------------------------- functions ---------------------------------*/ extern int end_xml(void), init_xml(int next), update_xml(fieldstruct *field, fieldstruct *wfield), write_xml(char *filename), write_xml_header(FILE *file), write_xml_meta(FILE *file, char *error); extern void write_xmlerror(char *filename, char *error); swarp-2.41.5/swarp.spec.in000066400000000000000000000055141400430667300153640ustar00rootroot00000000000000# # swarp.spec.in # # Process this file with autoconf to generate an RPM .spec packaging script. # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # # This file part of: SWarp # # Copyright: (C) 2005-2020 IAP/CNRS/SorbonneU # # License: GNU General Public License # # SWarp 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 3 of the License, or # (at your option) any later version. # SWarp 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 SWarp. If not, see . # # Last modified: 02/01/2020 # #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %define name @PACKAGE_TARNAME@ %define version @PACKAGE_VERSION@ %define release @PACKAGE_RELEASE@%{?dist} %define debug_package %{nil} %undefine _missing_build_ids_terminate_build Summary: resample and combine astronomical FITS images Name: %{name} Version: %{version} Release: %{release} Source0: http://astromatic.net/download/%{name}/%{name}-%{version}.tar.gz URL: http://astromatic.net/software/%{name}/ License: GPL v3+ Group: Sciences/Astronomy BuildRoot: %{_tmppath}/%{name}-buildroot BuildRequires: pkgconfig BuildRequires: cfitsio-devel >= 3.0 %description SWarp is a program that resamples and coadd FITS images to any arbitrary astrometric projection recognized by the WCS standard. %prep %setup -q %build if test "$USE_BEST"; then %configure --enable-icc --enable-auto-flags --enable-best-link --with-release=@PACKAGE_RELEASE@ elif test "$USE_ICC"; then %configure --enable-icc --with-release=@PACKAGE_RELEASE@ else %configure --with-release=@PACKAGE_RELEASE@ fi make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc AUTHORS BUGS ChangeLog COPYRIGHT HISTORY INSTALL LICENSE README.md THANKS %{_bindir}/@PACKAGE_TARNAME@ %{_mandir}/man1/@PACKAGE_TARNAME@.1* %{_mandir}/manx/@PACKAGE_TARNAME@.x* %{_datadir}/@PACKAGE_TARNAME@ %changelog * @DATE2@ @PACKAGER@ <@PACKAGE_BUGREPORT@> - Automatic RPM rebuild * Wed Jul 09 2003 Emmanuel Bertin - RPM build for V2.0b6 * Tue Apr 29 2003 Emmanuel Bertin - RPM build for V1.42 * Wed Mar 05 2003 Emmanuel Bertin - RPM build for V1.40 * Sat Jan 18 2003 Emmanuel Bertin - RPM build for V1.39 * Thu Nov 28 2002 Emmanuel Bertin - RPM build for V1.38 * Thu May 09 2002 Emmanuel Bertin - First RPM build # end of file swarp-2.41.5/test/000077500000000000000000000000001400430667300137215ustar00rootroot00000000000000swarp-2.41.5/test/test.fits000066400000000000000000010206001400430667300155660ustar00rootroot00000000000000SIMPLE = T / This is regular FITS BITPIX = -32 / Bitmap coding NAXIS = 2 / These are 2D data NAXIS1 = 256 / Image width NAXIS2 = 256 / Image height BSCALE = 1.0000 / True value = BSCALE*PIXEL+BZERO BZERO = 0.0000 / BUNIT = ' ' / Unit for pixel values OBJECT = 'r.list ' / What the image contains ORIGIN = 'kiravix.iap.fr' / Where it comes from AUTHOR = 'Emmanuel Bertin' / Author name CTYPE1 = 'RA---TAN' / WCS projection CTYPE2 = 'DEC--TAN' / WCS projection DATE = '2004-11-25T20:30:05' / Date and time of end of simul. in UTC REFERENC= 'http://terapix.iap.fr/skymaker/' / Reference EQUINOX = 2000.0 / Well, who really cares here ?! CRVAL1 = 0.0 / World X coord. of reference pixel CRVAL2 = 0.0 / World Y coord. of reference pixel CRPIX1 = 129 / Image X coord. of reference pixel CRPIX2 = 129 / Image Y coord. of reference pixel CDELT1 = 0.5 / World pixel step along X CDELT2 = 0.5 / World pixel step along Y CROTA1 = 0.0 / CCW angle from X-IMAGE to X-WORLD CROTA2 = 0.0 / CCW angle from Y-IMAGE to Y-WORLD CONFFILE= 'default.sky' / Configuration filename IMATYPE = 'SKY ' / Image type GAIN = 20.0000 / Detector gain or conversion factor (e-/ADU) WELLCAPA= 3.000000000E+06 / Full well capacity (e-) SATLEV = 60000.0000 / Saturation level (ADU) RON = 1.0000 / Read-out noise (ADU) EXPOTIME= 360.0000 / Exposure time (s) MAGZERO = 26.5000 / Magnitude Zero-point (mag/s) PIXSIZE = 0.2000 / Pixel size (arcsec) NMSCAN = 1 / Number of microscanning steps SEEING = 0.7000 / FWHM of atmospheric seeing (arcsec) SNGTYPE = 'LONG_EXPOSURE' / Seeing type AURESB = 16.0000 / Aureole SB at 1' (mag/arcsec2) AURERAD = 0.0000 / Aureole radius PSFSAMP = 5 / Oversampling factor for PSF PSFSIZE = 1020 / PSF mask size TRCKTYPE= 'NONE ' / Tracking error type TRACKMAJ= 0.0000 / Tracking RMS error: major axis (arcsec) TRACKMIN= 0.0000 / Tracking RMS error: minor axis (arcsec) TRACKANG= 0.0000 / Tracking error: pos. angle (deg, CCW/horiz.) DIAMM1 = 3.6000 / M1 diameter (m) DIAMM2 = 1.0000 / M2 obstruction diameter (m) ARMCOUNT= 4 / Number of spider arms ARMTHICK= 20.0000 / Thickness of spider arms (mm) ARMANG = 0.0000 / Position angle of arms (deg, CCW/horiz.) PSFDEFOC= 0.0000 / D80 of defocus component (arcsec) PSFSPHER= 0.0000 / D80 of spherical aberration (arcsec) PSFCOMAX= 0.0000 / D80 of coma along x (arcsec) PSFCOMAY= 0.0000 / D80 of coma along y (arcsec) PSFAST00= 0.0000 / D80 of astigmatism at 0 deg. (arcsec) PSFAST45= 0.0000 / D80 of astigmatism at 45 deg. (arcsec) PSFTRI00= 0.0000 / D80 of triang. aber. at 0 deg. (arcsec) PSFTRI30= 0.0000 / D80 of triang. aber. at30 deg. (arcsec) PSFQUA00= 0.0000 / D80 of quad. aber. at 0 deg. (arcsec) PSFQUA22= 0.0000 / D80 of quad. aber. at 22.5 deg. (arcsec) WAVELEN = 8.000000119E-01 / Equivalent wavelength (microns) BACKMAG = 20.0000 / Sky background SB (mag/arcsec2) SCOUNTZP= 1.000000000E+06 / Total number of added stars SCOUNTSL= 0.3300 / Slope of star counts (dlogN/dm) SMAGMIN = 12.0000 / Minimum mag. for simulated stars (mag) SMAGMAX = 25.0000 / Maximum mag. for simulated stars (mag) SEEDPMOT= 0 / Seed for randomized PSF motion (0=rand) SEEDSPOS= 1 / Seed for randomized star pos (0=rand) END E(lE!E E7EE)EE^EՁEEdEEqENPE ELE~E'EEpQEiEEEVEEEFEO$EEEEEREpCEEEEESEEE=E/EEEoE?EE)EEl1ENEEZEE EʇEE0E8EEEXEĜEgEJEEJE/EEE$EEEdEE=EE;E`~E' EEEsUE6E#E>EEbEE1ErE=EvEEEծEEEEiEBE-EwEO EbEFEcEIEՂE&E0EҳEdEEE(E0EUE2EE_EqEFE9EFEEEE EEoEEfE5EEdEEEԞEE7EuQEEEEzEEE;}EpEG]EEE^E"EE{VE.EE=E~EE26EME]~EFEENEEEEEnEEEQE|EEǠE"EׂEEEdE5EE8ME4EEj~EeEjEE«XE˽VEEOElEEQNE{E5E6E&qEPEXE$EEHE"EEE0E%EvEELEIbEzEwEYEIE EXEbUE E*E]EEuE;E"ELE8EyEUE\fE2EBcE^nEGE6E3 E~EgEEE6EŊEqEEc~EEE.fE_EEh~EJET3Ed2EEEZEE`ExPEELEE E[E&EEEE7EʍEnZEEE`eEeE&E(E֘EaEGEڧEEE EEwpEEE~EqErEE/ETEvE/E E'EDE0E=SEEEvExkE>E EEsEsEBE EEEEbEmEOEEjBEFE`qEJTE~EEɚEvE7ErE*E' EyEEE|E)E EBE+E>EEEEEE? EEίEE`EIGE EE3E,`E;OErEAjE#EEMAEEEEoE/ENEmEEEVEעEEE~EE_EE7[EnEpEE+E?EiEE"EJE JE1E4ZEEqTEfEIJEEME6EEMEPXE[E[E5^E߁EEEuEdEmE̎ERE΂EFE,ENE0&EEQE^EEEEEEHEEEx}EEGE>$EJE\EEgE;E E$ETE2E#ECMEEEEEFE.#EEExEIE%E>E'ESEE+EMEiE_EcE(EEEEFEhEVEFE.EVEEEREfE͇EE`E'REfaEYEEE*DEPEhE%EVEVEE*EE$EEEEBEEE@YE-EEOEEE"EEBE E"EChEeEEEE6E=ET"EEwEbEfEKEMEcE&E@EVE*6EOEEjEZEoEUEPdEHEEeE>-EERExZEPEiEREEAEJnEqE-E EDE _EfEyEmEE2E(EEE&EE)EE:)EEEEbE'EE2EaeE1EESOEEEÙEôEZEEEUEEZEd?EE,QEܠEEJjE{EVE?rEE EcEbEEE1#EB9EPEBE{EEoEEZEcE;Er(EvEXEERErEEEd EECE&EEEE#EKEqEaEE EqExERNE, E EeE^EٺE{E EQEhE2tE#EcbE&EEErEidE[OEEfE.EuEjEB~EEuEEE'EEEEcEDRE{Er E2ExE;E˲EvE`7EgElE:GEV+E2E`EZaE2:EEE@EEEBExEްEvE&EEEEUfE7EEE0EE(EE EEeEEE*EbE7E>ENE,vEE[)E eEEE=EEEdEtEԚES6EQEEE|EjE0E͗E;EiEwRE?EEEEGEEVEEx;EExEE/&ECENEEHEVEEE+EEERaEE|E EEaEkvEa[EE%OEE.EE&EOE'E5ENEgEEEGE!"E$fEv^E`E2EEz*EEeEE{REE.EEfOEEEE:EqvE-EEIJEEE\ZEE/E^EEцE6EےE"E E)EEJvEFEREEW EpE_VEXEEEE5EDYEֹEEҪEE$EENEE,E֬EqE(EEJEETE=E%EETEE{E EEfEmE&EG%E EE¨EiCEsE EEEqVEEEE#UE{EKE|)E;EzZEyEZEdEETEE EY E(EEWEEE"EaEE'EKEz|E,QEEQE7E."E6EbEEEVEE܏EEӗEРEEiE$fENEÓE4kEbE EʼnE$EڒE޹ExE ELEEEME7EEawE(mESENEL\EoJEEVEE_#ElEE^EkE)fE߀E-6EkEEeEE 5EEagEE~Ei&EfEELEExEEEaEVEE 3E2 EXEzE,>EjEEEwEEiEE?E`Et#EsEOEiEEEaJEEEEpQEE,EE.IErEE]E ErEEzE_EېEEE:EEpE/EEJE[E.VEoaEBElZEE E)oEE4E"XE}EbEuaELEk&EETEc]EbEwENEvEEEfEEa}E^EqE=EfEEEE&EE5:EEVȨE!3E AE EEEDEEJE^EÔE=E& ESE2E qE]EE~EmJEAEBE E~[EEQ+EEEEyEKEE}E}EEE@EhbE_EEWEEFEE3]EsfE8EE8EoEEVuE`EE.EaEFEφEөEWEhgE*EXE&EEȏEtEăE%E2EEZEEE8.E Ec#E۠EI"E.E1EAEEWEE/E_E,EEaEEOyEPE [EEE'E9EEEESEbE=>E(E E2EqE(EME EÕ E[EHEǎE>E>EE-RE6E=EE#EUE sE+~Ed"EMEqEbEȏESEEaE5 EsyE9EvgEE|EEKEqE]ENEsEEEiVEE/E]EԲE&E1ExUE0EoEVEmVE3EmE"E6E EEE*E!~E3E EEwE/EJE3EK/ESE`EgE E]EEzEuEE-EEyE?EEEFEEE7ECEEvEExEuNEE@EdEbE_EEEE?EEJWEEEN.E]EEYEE&EzaErzEoEEE&PEbVE9EEpEEZEcdE|SE ESEEE|EOEpE EEצE?|EúE3E{EZEEEEECjEE3FEE>EЪExEYEWEEREmE EJsEdE8VEoEEGMEEE9EBEEEIEaEE~uEY}E EeEEE EӗEҢEEvxEEɺEdyE7wEE0EEEfEEv E-E^EEE>EBEEZEE_E"EaE>EW EwE#EϬEEAE7E9EEpE&~EEEE|E]}EAEX.ErEӶEE~EEE EEE1EjEAEnEEE,FE"E@EEiEeErEEEǸE2EwENEE?E:EP EEIQEEpEn&EEHEE.DEE5tEEE]E1EE%EBEIEDuE(EnEEEpEEpELEAJE>UE#E&ErEEQEIEHEH^EE]EtEнEEEEEEaEE6EvEEOEEVEEEIBE!vE>EsEv/E JEIEoEES_E\EEF2E$EE)EEEE'?EEiEE*Eu E1EQE=.E8EEE =EHEM#EEEM E(EmE"EVEYE4EYAE" EE~EE2E=EEE-E'EvEREHE=wEēE^E8E!EǵE-EfE(EEd,E$E;E~E2E=E E[FE ErgEE'FESE!EEBEEEE5EEt7EEhEEEE%EE/E@E$EEPEEE)E:EEEEpdExEEEEl$EEEyE#E EEzbEEYE5E^EEEfEE,WEBEHDEeEPCEEEbECSEGEEEtEE"EzEE EEEzEEEiEWEEYEEEE"EfEE E EEOE(EAEuE E]E)En EEEEEE E6HEELE:EyEYE})EE];EE&EREEWE48E`E wEE/E}ElEkEE ~EEEw}E; E;E8FEWEE`EEEEaEE9!EEEEE_E7EaEEֲEEEECE/&EoEeEDEEEElE:EAEKEVEEnEFEBeEExE_E3>EErE*EE+VE״EE'?EEsEvFE0E&&EbEJEdEEv"EEEE'E$E!EE:tEpEELEfEEE_E!EE4E[E0E'EяEJEmBEE>fEE?EE:EE EE-EEEEEbE"WETExE۰E:EEEEEE3EE&E'E|EE="EEjEDWEEiEVEe^E9EEEEvE)ESEE]EKEEUEEzEEofE]EgEEE~E(EE6EQ E^UEEEOE6E9EEE&EEDEEJEEE EEkE5hEE{[EEExEEEEB}EԲEޠEwEEmEEJE]BE=ENEŶEECEEBEENEE$EiE+EH|EcEE>EEEEETEECE0EEEE EEdpEEhuEE:E^EVEbEiE EyE`ESLEEEOEEՕEAE$EtMEEEE!E.EE!*EbEEE+E>kEl}EE.EZE_EEiEv2Er6EDEE9EwE EEEVET EEUEEEZEjEMNEaEdjE+KEME]^E]E*E|EԚENE;EVEEEOEME2EE}EEE1EEEE_E]E:EEErE(EEoE}&EEmmEkEE(E`EE+YEEE ?En|EbSE|E6E~EEqEE!ElbEVpE:EEE1E=EtEEvEE-EeE>XEO"Es6E>EoEvEECrEE-EE3EEE8EnEtEp E~E(ZEBEEE EEoEEQEEcEfEEQ4EXpESEEE}EEW2EEfE E=EcE@EMEmZE.E EE$E>~E3Em+Ei`EKeE+EDxEoEE EE7EtEX5EEIEbEEEEEfENEE~EUME*EEJEhyEE?fEE1>EE&EY3EDEΏE EE{kE~EEEE~EEEEEPEEFE 'EE :EEE)E-EEEEfEtEE+EPEEE"EEE1VEEEbEבE6EEQElEekE*EEEE>iE E)EEEE)dEs EBE-QEEðEn:E E# EA(E҈ErE`E(E&E>EER.EE:EEEEiEjExEjEEEEE:EZE&E&E?EEEEEEE[EEiEcE! E"EjE(EEkdEE |EEiEEEg,EVE3E;EBNEE?kEvE oE10E nE7EgEkE*EEZEgE:8EeEEނEEEEeEWEEcE-E+EE#ErEE"EE#E3EMEj~E%AE@E'EsEEEҶEEgEE_EEmEsEE$7EEE!E&ECE EBEE0EE]ELrE1/EEd}EcE1E?EE6E=:Er6EE}EEGEU-E:EEEHEEE\EElbEEVEVE8EE5E*E@EE:EE2E! ECE*jE*E)EqEVEEzkE]EM2EQEEXE1E E6zEEuE+E_E|EE԰EEEapEEESBEnE.EENEE EEVEErE7[E EEE{E#2EExEE#EEOE2zE!EfEmEfEDE]EE[EEEJEZE:EE EEEoEEJEEEE4E/E&EGE^E|EEREYE ZEEEEE+rEExEEEEsEE]ETEEEEEE8vE$NEEbDEEEE E$EEnE۞ENELE[EptEc.EQEEúE"EEfEDEEEbEIEäEWEEEQE E5)E,EEQECE5EnEE^EEEFE&E!E]E5E$Eg EjEEE~ EEEEeEHEmEЈEKQEE E4EEsEEE7oEEEEEEdEчEEcEE;EEE`EۂEEEkEEExEUEE E9EEͶE EEE"EoEnvE8Ek,EEE]E#EETENEEvjEOEE0]EmEQE{EEE.E.EzEZEEeE1EEEdEg>EEۭEEE EEU6E4E7zEFE+*EmE(E\EdaE.EE'EZTEgE E6zEE-ETELEEIE E]EkrE-EEE;^EjEEqE6bEEl^EwE4EE3E%EkEE$EEeEEE8EOEQJE%EEREёEWKE$EEE]E",EEzE3EeEdEEEEExTE?EE1EEf2EEE*EEEELrEb ELXEEپEBSEEEFEEyoEEfE EtERbEUEFEE E E"EE `EϦEKEEmEdEEzEPEhE[EGE.EEE:EjEEΆE{fEHEsEBjEE*EEE͏EݠEvEpEWEEE{hE-(EE EEAEEE{E E}Ew/EEtE,EE*+E®E{UEHDEBEE=EKEEjEE4EE#=ELEAEzEdEYE&EVEEEuEHEEEEE$E EEsEqEZEIEEdE|E7E.E5E1EoE!YEEcECEEEE0EQEiNEEEs:EEbEE"EʗEE$^E_EFEEnEE2EzE&E(E7eE/EE>E EA,EEqEyEEE|EEjE E(2EhE|ErEE}iEE} EE#EٿEE&EjEaEηEaEE]WEsbEEatE EaE.EE E?E4EEE%E E^EEEµEELEEfE7eE²E.EE?E&$EEEEߡEH2E_ER%EEEE;E0EE3dE\EEENEIEC*EEEEقE_&EzE)EEyMEKE`EEEREBjEbEE,EME"dE8EgEXEEEOE eE&E)$EE:EE=zE.EVEE2EE*E=NEiMEE^E;E&Ep)E@EpEE EEFEEEEoEE-E>E(EfEEePE8vEZEENEEzE$EEZE,xE-EYEE.EP1EwEZEMEEۧEtE) EE}EEEoE.EҮEZEjEmEVEEE^E<.EEAEE EhECEEFEUrEE EE/UEVIEEEVE}EE7E""EEEfEEEE.E_E8mEAWEEeEEnBEjE 2ExEEEEEKE5EU2E6EsEEEEEqE>lEEAEEbE$E>E YErEbxE0E9Er EEEE'EKzEEwE%1EpEWEFEeE$E8}EHEE_EEEE!EEjE)EcEEE~eEEϟEEGEEVEfEBZE8EEp EXkE3EE^)E)EEEjETEʫE%IE[EvEEPE "EpE;E$EcEEE"E#E;EkEEE-EEP2E)EצE_EzEEETEZE E_EhEaNEE7E EEiE@EHEEEfEEEeEwuEEEEfEE5qEE0"EUE0EE^E|EaEE#EErEEEQ2EMJE&EFgEEEoEREVEtEJE/E6Ev2EEEZE<2EE$EEExE~0EEEPEEKEEEfEEE~_EEEKE EFbE~E<EEbEEOxE09EElEFElEEE E5EDEEBEY7EDEgEaEC&E>rESEYECEZE2EUEEEMEE,E*EϊEEEI&EAEE6EEEEOE6EvREEEEEE\EEsE[EEEzE%*EbE ExE0Ex3EAELExEʼESEEEXEhEEMEoEE$EBEOEC6EԖE7VE4mE E>ETEPELE7E\E3EZE6E8E E`E-REwBEE=EEEwEE%EqaEvREE^EEKEԒE3E.2ErEElEAEsEEeEaE#!EEEAE(cEREE>2EqzEqEE-,EE6E5E{EErEpERhEE:E2*Ei@EP7EE>E E8yE$E EE_EEE(ESE NEEE EVEEEwEEvE EmEFEѦEn!EEVEEEXEEzEE!E}ZEEEwE*E{EME(EDE&EEEEنEǭECEdEEEeEE}E[NES+EEuEyE%E-E5EEaEFE:EE"E0EE fEvEEVE5ZEEE:SEE(EEEEEEOEGEVEE1VEEEGEEEEEEEnQEuEEB"EE E=EbE?EıE*EuEauEE?EvEREE zE5E2E;EAEE[EF EDEyDEE_EHE"Ez:EmErE#+EEEE{E=4E5EE5EQ~E EEqEEdECAE@EERE"EE9QE!fE$EߌEEiE@EJErEEE3EEEUE.EE?EEELE"E zEETEE6DEEZE EKEEQE9EE9E9EEEE:EEyDE&EaPEBEfEo|E9EJEsEGEExElE^EEEE̱EIEHE*E/EYEzE^E< EJErjEdYEEENE6EEkE2EEEe]E9FEE/EEExEEpbEaEAmEE$MEEP7E2E#E%~EEEEEhExE!RER-EEdEEc EF&EdnE[EPZEEE$EeE}E"iEE>E ELE E?E%Eh EWE\EREEEE5EE1E8ESEFEEnEEqEyEE0E%EhEvEC)EUE@EWEJPEEEEEE>fEE2ET EENWE)E*EUE˶EEEjEEʌE>EoEFE5EܢEEEEيE EEyE<2E&EEE"EEK!E=EEEDEkEE )E!UEnEEaE LEEEfsEEEHEdE| E;ESEo}EEE"3EEWEE]EEE:EtEEjETEENEvfEjE[ EEEE.EEcRE1^EEETuE[E vEErEPJEյE:&E=EHEEEQE{E^EE>E;EEiESEaE&E`EEvXElE^BE:E+EHEFE_`EihEEDESEEREEoE|EiEE%EwESEłEEWEEbfEE jEf;EF=EsE,9EuEpJEקEnEbEEc`E9EE1E E.EE:EErE9?E SE}E*E'EnEREEE&REE^EEEEQEEDqEPEEEDEĺE1EEBEBErEEE^EKEEEEEDzE|EtEEyEEEjErEE "EEE^kE#EEE*E~EoE:EMEyENEEEEE'EӮE`*EEβEE6E8E7UEyEcE2|E:EaEv EmERE1EjEE6E1jE*E=EErE E'EE#EEEEEEE@EwEEEE!EE[EEyEE=EE8EOEE EaEECEEGEaEE&^ElnE*E:EPEbyEbYEE+EEEE@EEbE EEkEHEgEQE-EQEE.vEbE% E~EmE0EEEAEkEEE{EJE:EEܖE6E\EE6E)EEETEfE` E;EEEb|EEREE5$EE EEEE%EEQEE EWEYEdE9^EE*NEu"EE7E$jEEEW}EUEEqEEEEi&EEEEEE_EEEJEiEӍE2EZEM~EcTE{EEE *EL\EEtE&EmE;EEE)Ez+ExEKEE E.EECEEEfEEEEEEEE=/EElE2E@EsEEXEEELE Er+E%EoE~^EfErEJEHE_EDEEEl3E MEEEEmE(Ez9E+Eq5EkEE)hEEE$EiEEE rEcFEfE&EEEՍE;EZE8EFEE_EfdE EEE E&ENfE EEEEE EEEEEEEEWEE#E`EKEDE!EE$ETpEQ-EEy%EE=TE4EE{EE_EC]EjE>EE ZEEGbE\EEھEvEbENEEEEsE^EMEEE=ElE,E4EEZE EEE:E E 0E3EE1E%E\E(rEEfEzEE}REE\E ^E ZEAE~+EԗEzE-EEHEEEKErEEoEnESEHWE E~ElE;E^XEE9EE8 EE3E&EEpBEE>#E!EEIE"EEE'EKEFE4ERE:.EEyEnlEEtE|EE%EEEME+EEEwE.EuEEEyE?EE]ECE/:EECEvkEaEEEEE@\EEuE~EEIEAE ]ElElEEWEEEE&EE5EEw;EXEEEcE EmE1EEYEcEEEJE8hENEmEEEEE#EE"EEeEQEEHEjEEE_ EZ$EJE-ETE\EDE(E3ErE_EP ETEk]EE{$E9EEErEVE*EEEEOEVIE^EgEEDEEJEֶEE~E ;E4JE-ETEE$EjAE:EEqE2EEE6E(PE&EIENEuEEE"E,E:1EEEE]EExEjE=EE[EE3BESEDExELEE=sEoEEEE*E>E[pEγEE@EE˦EsEEwEEENE3EE̹EEEwEEGEE?Es~EBEEEEE5E BErEEBE9EEEzEoEEpEeE-E-EE3EDE47EyEEoEEPEsuEEE)EmEE EdEwELEEEEE(ELEEh"EEEEa`EzE EE=EENEkEEx E(gEE/*EJsEIEEr2E;EvEAE,EErE[E,EEWEEEEE8E}E#ErE3EEEVEeE}E&hEE;E$EETEzEoEE EE EcEE2E=E)zE*E>EE@:E8EfEEwEEuEEEEdElEE|EjE6EEE 'EXrEsEEIEEE؏EE5EfE/E@EEʤEEEgEۂE~EjELEEEXE;JEO2EEEEWEcE:EEUEEE{EEE[zEEERETMEjE!EzEEEU"EEBEEEEw.E.EE@E bEEEaEEVEEEEE&E^EEwEh^EEL-E̊E=lEEE7*E5E@ERE'E:EE=E&EPE0EHE$?EEEDE}E%EEE٦EQEEEEE:EE.NE@EEE YEEE<}EfEEEVE;EèEE7:EE@^E0sEYEEhEIEhEE0E*cEEDE!OEE>EjE*EE EE iEVE:ExEE*LEpJEE`IEEE^EhEEvE>EE2E~8EEQEEjfE?E2EG}E3EEEEםEzE2EE%E}EUE EVEJEyE.E&E2FEEllE4EEmE_EEEmEEEG|EwE5E EĊEEglEE"E E EEEE3vEDEE;EFE&E$EEhYE}E9ElEOEEBE7EREE 3E E@Ec7E`EETEEi]EEz^EMEEaEݲEE&E)EEEPEEJEХEEEEnE$EuE4E-~EEE%ENEE_EPEEE0EAExEZ$EEEEܞEZEyEEEZEEjEÌEEOEtEEE['E3E{IEE]EEESEiEEEE6EE*EE~EE~EEE@ENÉE5EEVE6EIjEzEEEPE&E`EEEE{E EE;~EE'EElEE\E~EF6EEE&EEEmE^EEEqEEEEW+E{EEcEEEE#BEkdE EEREEE-GEުEuESE EzbEEFEHZEEEZ:EYEEbE^EEEEE"ER@EEEEEE>E/E=EEqE_EZEEREEcaErEEnE'EaEsETEE EE*EEsEnbEE~EIEcE7EyEEj2EE 2EmE:E&ELTE>jEkErE ELEUEJEFEEbEE=EEy3EEE\EEEE`EJE{E] E,E E&EbEWE4EEaEeZE!EEGE E.sE,EREEEEE1EEzME)EqJE"4EEEvEYEDEiEEPEENEVE/EsE gELFEIEXE]|E*EpEEvEdEGEEEEEHE3EpfEEwEEEEKE{nE}E2\EE'EEvEXEIEEE3EEE4EE=jE>EEEEE/EExE=EqEEEEE E;EwEEnEE:EEE"E[EtEbEKE[EhuE׺EEaE>$Ed`E E=EEE[EEaoEEEnEE EvE<EPEEXEEEEwEE3EEEEET)E܌EVE,uEuEjNEgjENEuhE%Er2E'E>E-E!HE:EN*EĹEʟbE5EJEEe:EEWEV=EwEbEEEjE5VEE qE2nEQEKEEPMEE|zE܁EMEAhEEEEEfEE_EyjE,QE EEAEEEENEEmEgEE͚E=:EAEvEx&EEBfE XEfE^E]EF'E\EwE ELEEs8EkEvEEEilEEHE/HE&EZE30E:EʚEnE E@AEE:E>EEEZEEEUEnE9EA.EEB&E%EoE&EjE:EEiEd9E0EE|E{ESEmEgEx:EsE@zEEREEXEuiE ~E֮EbE4E*AEzEEEgE3Ed.EE( EE)EbEEtEIEgEEWEE E޹EEGEfEb EE@El:EUVEE6E_EzEE1ElEIvEIEJEE~EnEhoEE(EEFElE[9EE5EjE #EHEE EPE:EK#EoEEE eEEvEEDEEErEEN&EEEҵEEEEEVEdEzEE EwEEEEEGEu.E!EEtELE&EGEExEEoE~EETEEEEaEWEEkEFEE8EJE EEEEGE.NEEEMjEiKEpEEJEtEvE;EEmE=EENEŽEmNEnE>6E6EaEEEEb>EEIwE~ E[EEEݤEEhEEEaEZEE\EE"EE3.E)~EE]EEaE8EjE03EE{RE2E EhE9EyEºEeEzEsE\EEE9vEsE1EFEQEEE9fEEiQE@EZEŖE'EA#EE޾EbEOE EEؘER7EfE#EڜEXEO6EZEӢEEk|EyEE)!EE:EEYE E]EEvE*UEEErEEqSEzME EEOEEEEE(E EscEFEZEEpEQE^EE7EZEmEE~E@EE%rE*EETEEtEEYE3bE4ELEqE*EE^EEDEHESEjE?EŒEE 3EBEjEEE=EgE EOEE}E\$EZECEE2ECE$E E΂EjEdEV]EKEimEJEEE2EEEBE8:EGE3EkUEEEE/ESFEeEq\EzZEE+EC~EEE>EEEEdVE.(EUyEEcEcE]Es5EEE xEE/EEBE#SEypE EEEgE^E"EEEE.EA:EEIEoEE'E`zEE,EEEPEE9EEMEAEExE(EEEREtEEzE2EEm:EkE?E,E*EE E4E EXE5EYE>3EE EEE E7EaE,E@EREE^7EYEQxEݤEsE:E'EWEE,EnEoEJE6[EE1RE,ELEnE%fEEE]EOEEEE/@E2E<EEEME$ELEE9@E\EYE5nEj~E>yEEErEu$EEvE E^/E՗EE\E2ERE[ EkEME9FE=E*ErAE:E-EE{EEEdEEExOEEEҞE E/ElEbEΚEEAEEE4EeECEWEfEE̞ELBEXEE:EKE1EE EEESE~E|E+E?EEGEEWEtEE%EEgE]Ee*EYmE\sEHEgEF%E4E%E'EcEE&EfcEoEFZEE"kEcEBEEZE-4EE-(EOE?EEOEEBZEEGEEi6EESEEoEnE}E;E(EߒEqFEEM EEE-nEEfEEEEiEE&EɍE_fEEʠEME"~E~EEEEEEoE3E EEEEqEZE;ENE2E&E(E0eEYE9EEEޫEEEE2E LE$EEEEEEbEVEjEEE<$EEE>EZEEEJE}EEEHEQE7EEPEE>EXKErE EEhE8EKEE~EaEC,EEJEEŏEEE&EZE(EoE~E&EY:ELEJEjE[EcEIEE~EBEzEE!EEɄEn>EE:E*Ed\EE.JEJEc,E_EFEEEEoEEEQEHE{EarE9EEEE9EE*6EEOEtEފEhE#EZE-E47E E%E}_EhEcE/E*EEEEAEEEE}EE0E[[EEEÍE(E.EEfE4EEGEFE9EpEE]EGEE`EEEE3,EE_E_E6 EuE3DEڶEoEEEEFREIEmTEEQEBE^EEEAEsEEI"EEEE8EUEE>E9EEBEEEJLE&E|eEL?EE@ E4ExEEEEEr&EE_E{EjEEEEEEE8E!E#EE/EEEߺEME+EIE&EǺEFEElEEaEOEpEEiEC/E٘E6EEEEP1EEsESEEcQErEEEEEEzE>EZEE`EEyNEKE#EEEE4EE&EEEGElEEEE9&ENEEEH&EEREEEME1EXEbE߅EsEE{EE0aE:E=.EEWEE,EE~EEFbE6E{EE"EMEEEEEfE;E{E_8E\EajEEATEEANEEeEEE. EfEnECZEMEEREhEEwqEEӐEEjEcEEEmE_EAEE[EJE8qEnE&E[E"EEEvEQEZE ELE6EU|EFEE2E56E%BE|-EEE*EEEcEREEzEE~EWEE@:EZE̾EMEE;HExEE )E4EZE&EƺÉE,rEEkE\^EɰEuEEEEEBCEEET3EvETmEJE{EEE;E.ExEsEc1ENE%REbELEE~ ErEEbEOE0fEfKEEEA;EuEFEEoE5EjE.EEE35E5EEEE5EEEγEE<9EBE,6E{E9E[E EE6E2iEEܶEEYE#EE*EE5E[VEѹE gEfEE E*EEE4EJYEEElE#JETEEEKEOEBEEETEwE6E4E4nEG Et ExEI.EEEEOEEtEE0EqEEMEE E EE!EΌEbEE$EE"NEME>0EEcEEEEEEBEEHEEKEHEE"E7EEEEE?EEE۞EEYEeE`EEcCEwEESbEwEEEEuE_EEEdRElE EEE$Es~E4EqEE#EE^E'&EZE,EEěEEEE+E/EEyE@E%EEoEEE)EEEEӎE8|EEfE lEEnEE EEEEE.EEEeXE߈EE=E=EEEXZECTEJEEStEEa EE&E5EEE,rE&E E7EmEtEEEZEEOEEEgEEEњEEEE Ed-E*EEQ$EKEEE]EEEFEEE-EE2EE9E^E:EnE0E5EVE7EEE%E{"E`E@MEEPE:EE'(E9=EVE] E ETVEnEEu+EErEELKEE'E+JEeE.E{EEEE*:E݆EE|E-EhEHE'ME2EEEYE(WE@hEdEEEEE>8ESEqE^EEQEoEE+EvE7ExUEzEGTEEMjEEiE8EEExEE[EEEE$EEMEEu@EEޅE_EE ESEFEZEEEOEEH!EE EmFE2E9EOPE4EyEfENE:E;EEE3EqE.EWE:EPE!QErEE4Ez~E.EEmEE(E#EE EDEE/"E-vE\GEEE{ELLEHEEfE!EiEEEE-EEtEE~EEEExEEyEmErEREE EEEEEENEE;yEEEEBE$E@>EEu@EE܌EE{EEZEE*EVE5E QErEEJE- EEnEKE5ENEEE3E@rETE-EEEE^EE26E߻EFE{EEwEE>EuEE*EEpE@ENEE BEf2EEaE?EVEzEъEE iEEáEy]E9E EdESEjzE)EPEU~EwEETE%E+E%EmSE7EEEEE EjEEEEYpEEXErEJZE*EOEEEEiEE%EvEEE2EbwEiENEEsELE(TEE>EEEsEEE-sEE EEEaEcE8EEE)Ej}E1EZE\EE-tE{E8EE"EҩEVEHED6E*E_E-EEEE^EHE,E)EE$E:EW&EE֥EcEcmEElEQE_:EOEErrE3EoEċECEESEvEwFE;3EE[EsEJEEEEE"dEnEE+WEsEFE9EEuEW(EEeEyEEuE EIEkENEE8fEEE]EyErE^E"E EfE])EӮEEE &E*[EEE6E\EE8E{EEPE+qEEUZEE E%E[EEDEnEREmEE.E4E"E]EEE}EjEE[EE&E{EFEE`E'EzESREEE_EbE~E.E(4E/EEETEEE4EEE@E-EEE1EE>EFEEE`EBESOE$lEOE}EEPE}E}E~E=EE4FE%ErE2EEEprEEEEEv:E)ExEFEEEvEɗEE EEBEӂE?EkE8E~ESEEiE=EEEE?EPE2EJE"EEyEvE.EuEEEECEEPVEѻEEPEE~EEEEqEJEޕEEEE/E\tE@`EdE"EEEAE'EEbEE\ZE?aE%EElEnE&!EE"EF9ELEmE&4E6EkE+EEEvEJEZEAErEE-EyEBE7E1QEmE~3ExEtE^EEEEEREtEA&EEIE E[;EE&EvEEo*E"E `EEpEEE=^EE/E\ETEøEթEEbE5E=ELEeE :E"EvEE&E~PELEK@EoMEeEvuEEpEpnE%E"E*\EE EOiE[EEUEgELE,fE0E^EEnEENE#ES)E PEEBEz*Eu"E,EE@EE:EEzQEEWEcEE#EEq.EYElER7EE/ER EEEEE&E EE՗EEE`E5EEdTEOE]EExEӊEEELEyElEEE)?E6E^El|EE. Ep&EjEqBE*EaEJZE\fEuEE-EEE:EEIEtuEOEgE2^EE EEMEEtEE~ErEE*E|E:EfEE;EnE]EnE+ERErE(EEEUEɎEEEMEŠE E;EEE0EE@rEJE$ETE,EYE4E}Es2EPEZEIEhEEEvE֟EmEEEẸEWEEiENEEEjEEjE@EbELEEEBBElEJEE%{EEEXEZE&ENhEEgEE*EIE[%EaEDEPEEEKE^ESEEEt6EbE)E E"ENlE-aEhE'EcEEnE;E@!EE)E6EiEEEhEEBE5EZAEwE8>ErEaEɪEELE/EZEE^E_E:EOE(NE4EEEEE[EE?EE3EEEEEPEELEEWDE]EGEEE= EEEEE\EEEEEJEoEfEtEKE~E EkEEEE&EsEzE.EE yEbEW:EE0cE+2E*EDEiEEf:EEijE4EQEƘEXE5ECEEjE?xEEEUEOEE EE EnEEcEEEepE-E}EPE-EEK EǠEE EEߋE07EENTECENEEūEbE!E*EEE)E%E"EeE"EEZEEoE'bEBEEE+EE EͰEEELE=EEE1 E#E`EEuE_zE~ESjEERE@EfEKEmEYEWEE;EEAEVQEaELE;EhEfEEpE/EEEwEh EbEC.EZE,ḘEEŸEEEExEEڜEEyEͯE2EE}EEEOiEJ6E~'EEEE-[E\EyEXE1EEEEEWESEE}E EEEEEsE$`EE&EGEBE3E&'EcVEE"cEE[ EExEvEmE4E0 EQEE]EEE E4E>EGjEE>EֶE EE}nE E?EE!EnE1EOEEFELEEEEϛE/&ENE}E-E_EfEEEEiEHEEiEE&EfPE~.E.EE9EEEjfEE%7EEEEҪEE;MEEmE+EEI.E)E`ELEEoPEEE EV[EEEQE2E&8EEwEEE/vEEE^EeJEMEs6EEőEEEkE"E EoEaE$ErEEDoEEEErEc(E®EEErEeEE΂EEEPErEYE6E@E/&EE~EOESEEyEEEEEIE[E&E]EvEݖEE~E~E=EkEEDYE6E4EEE*cEE2E EEEE]EN'EEE*E-xE@IEEjzEEG&EEE&EnE ~ENE)EeEE7E4AEE#KE`EEBEeEEBE EEEEEEþE!EEEhErEEi\EҤENExEVEE EsE iE$E'vEmEPEAEEgEuE-EgE1EEErE2 E"EkzEE6EE%E6EݩE$EmELEM*EcDEE3EEYdE E]ET5EZEE~EcnEEEwEQ*E9EE[XEzJEEyEEEEjEsEE EEE}EwE7+EҪEEEEŐ:EĿ~E7,EEE[EEߤEE:.EErE6EEC1EEEE0EEEEclE,EEKEElE:pE͈E4EREEvE'EzEy>E)EyEE,E EE.-EcrEEؘE~E!EE*EbEEBE6EмEKE_E=E.EEEEYEE|EZEnEԵEEEqZE.EdEEEyEHE=EE]EEjEBE0EEmEFE=E1E:EEECE[EzE@xEmE6E$EEEE}VE/zEHEECEEϒE2EEE)EEEm0EE/EQE E E^E*EEEEEzEEfEְE|EoEOE%EdE E:EEhEE~EFEEqE!E~/EEE,EKEz E#bEEbrEnE%EEVEEE,EEEE&EcEETE :EEEEE|dEVEE|EKNE}4EUpE*E0EHENhEE`EEE LE,EnEkEpE1EMdE`E~EREEXEEEzEEEEEdEX E9EKEZrEEEEPEφEEpEEEfEE: E8EQEZREEE~E2EE;E E*E ZE_WEgEoE^E3EoE+ENEJdE EmE_EE>E"EieEEtEE}ETE E5EEE9FF&UF[FbiFEmEͥE>E|EvE҉E^ECEE3EE&EbEE0EPEo#EEEaEE6EEtEE E7EEy:EEiEKEEtE[E*rEEp EmE+E>E"ErEEEE(E~~E@/EGBEEFE#E&SE}EE E EEEoEEEٱEyEE6EEEEE)EELEEEsEEӤE;E3^E{EN>EE\E*EEE=EpVEdEgEEEE^REE$EEgEn"E)EEuEEYEzEEeE7EE /EEbEEqME8EEE:EqFExELEBEUEEOEEE:EEeEeEZEE]EEΒEAEE>E-EǭE;*EEEEEEZEYtEEEE_EE].EeE"EBEE EEҦEmEE.E$Ed2EVEEjEtE2)EEEEEEEn.EEE{6EZ)EBEENE%EiE,EEEjE Es4ENEEEE*EEEgE.EE~ExEMEIENJE3YEEiEEEE*EEpE*EmoErEEEEEGEVE{E EEE%vEE ^EE3E] E?E&(EJE6F BFAFrMFrFC?FEg`E!EQFEEE EEEEEZE E EEѐEEEEEEEE+EWLE`&EIEy(E3EvEEEK[EHEE׵E[E]Es8EtE)@E1E:E0>EESECEEjEE"ETEeEEELE~EEEEhExE!EEnEhfEE"EEuE0E+ E+:E\EEsEEJE2EEUHE^E("ECfE~EOEZEh E3NEdErEE1GE^EE6EEE6EE)EhE6EE-EؚEE=EHEElBE`E0E EEE3Eo1EvEEGE=EvE:`E7EE{EQEHzEEE,EE"eEE EljE:EEGEuYEEESE%E7EEJEEP-E%E?EdEEJEE/EaEUE+'EgEz\EEEEʶEDEE[E!EE̅EHE2*EaE˔EJtEڽE 0EFEEEE>EhE6ErEޗE!EgEE5E EE E/Ec`EvE3DE\EEkEjE.EEE4EcEE]E;EECE;YET&EgEEE)EjEEfEEEZEEiEE[wE=[E8BEE!EdEJ*ExEEEE?BEowEEgEFE EE.E-EE- EI(F, FFFe FF.U6E>E˂EEaEEEVEnEaEEHAEEjEqGEE YE=jE`EEEIE)kEEہEEtE?E: EtEgEgE,EE[EE*PESETEE*E5E&aEExWEEAEEEֹEUEdEEEoE6EUE EL}EErEH EEUEEmEzVEUEEޢE*EEcEREOAEfEEE/EEPYE+EE E(EE EEYEZEjE/E YE1E&EEE;ECEE}EEGE5EBiE?KEXEMEEVEV E#EVPEE:EbOE /EE=EEVEEdEEEGErEkEZEEvEwE_EPEEqVE 0EOEVoE.2EHE;yEEEEEEEĎEEBE'sEzEEvEEElENEEW EIFE3E\'EEv-EE'5EJtEGEEHEEiEqE5iEOEKEJEbEEeEjEEtEJEE EbEEEޠE$lEE+EEEKEE-/E EEd+EzE,EE/EuyE/EEE-EEVEEE$EE˦EnErE[E%;EE>EhEEEiE]4EEdKEFEP$EoEE E"zEfEEEJEpEyfEEpEEEE5EmF8yFc8FFZFF:E~XEEVEzEEEEuEYnEE3EEqWEE^EEo9EEEEYMEEjElEE5iEsEEEEtE*EClEE#EE_EJEYEE֎EEENEuEEtEEEEE.EE=xEE;E 0EEyEjEGEC\EDzEjEE\EIE)ErEOEEF.E_EE{EZEE;$E5EZEAxE8Et EZEEE)E~EKEE&EE[E~EE UE6EREIEEE EEENE!EE(fE6EEOEvE}EEKE AEJE0cE~EYEFZE.EHEpzEExE E@EEEEՐEEEEDEEgFEE+EE8nEuWE!EE9HE`E{EE?EQ~EGE 9E+E*~EE EEE!#EEPEE6EWE=EJEE ESEEE EzE;E6EEEEpE|=EqEgEEdErEH(E|VE2EhuEEEEZEEu}E(E E E uESEfEY9EEEEjE)EzEܚEb!EsE%EE*EEE|ElE#EfEE:6E\9EJE[EFEEbEEKKE72EEE,vE>EEEElE2UEEMEEEE]E2E EɴE>FF&PFzjFdFDF}F'ExEwE}EE*EEEBEsEXE)QEdEIE̹E@EE?E:EE?sEvEE4EIED)EE EEEE-EŅE E9EEJEE`EE"EzEEEEE;EEE%ELE܌EEEm?EL EEYEEEBE<^EX6EE9EENE0E}E\EEEEmkE.E QE0dEE2EEXE>CE+EfEiEEREzETEE EAE9EEaE>nEuEEmETEvE7*E}EfE{E*EEYEnEQEjE;EYE~EvE`EE7ETE۳E2 E]?EEeE.EE>TE+E>Eq EE'E EE$JEEE-nEEEmE@E]E,E.ESEEmE*E>ET=EkEGEbEElREEEEE&FF1 FX~FYzF1FrE۲ELEhE9ESpE3EEEhEdE/EGEE8EEE^E|EkEjNEEESE8\E|EvEMEKE:)E*EEME*EEEmuEEn}E[EEE {ELEmE E~E1EEFAE@E@QE/E]EE1E"EEEEREYEHEg&ETETE=EEE2EdEEE.EΛEEE^E%EE3EELEETE}*EmEEEWWEE9FEwEEd*EE EQETEeEևEEҭEZE(JEEDE%El5EETEiE$E>*E*EE3E)E;EEEREEo$EZEEQBEEE.EEEEEE#]EEEzE4EbE:EEqmEQEFEzE$EE:EEw#EkiEtEڝEY6EUEEtE0EEgEoE`EEaEESE_EEMEE>ECEE}EdEDEyEʋEϑMECAEk^EE`EP.EE #ExEEbEEqE+EDZE'E_EPE7E-EE:EEvEEEE1EJEEE:EEaEEkE}ENAE;E.E.EEoEEkE/E(Ee!E*EOEE0EϷ;EްEؼE@;EƔE#EغEIEEgEJEuE.EQEEEE!EEEPEBEEEPFEqzEsEȪEg]E,EW2EEEE~`EtE}EVEEEEEphEEZmEU+EyEm EnBEExE7iEhE EEEѭEEEcE?FEE XEEELE^EN EXEwEEEQEodEZ;EEkEE̯BEAE6EE EuEEErE2EwEuE EEE EE E>EEE$kEdEESEhE6EMEo|EџE֙E-EE|EU^EkE\EԄE`EOEfEE!EbE4E[EEEfEo.EEEdEEfEd7EEdEdEQ&E~EDE%E0/EEEyE76EbEChEwEEE}EE|"E E%EEcE=EdEEFXEEVE4*EVEEEC&E+)EHEEĈEgE.EAEE>EEйEE^E\cEEƞEE2*E^E,EEEEVEE`E$EيE@EBEpEIEE0EZ"EE^yEEIEFE^Ey_E;QEyEDEp|E?REEEKEREͿEE{EEjEWE E$xEEE-EgEzlEkE6eE2vEECMENE9EELEʀEE܋E%EQECuEEEjaEfEEEA7EqELEELE*EFE{JEEQEE+EuE E EgE_E*EŨE˂\EE>E7NEڠEnEkE}EEE*EEE%EEHEZE_E+FE.EEEEEE*EEE|EEYE0EEYE9EEEuFE 2E7%EEE@.EvẼEEuEJ/EEEEe.EK8EE*zEEEE2E4E|E.E1EE6EEL8EzEjE_EHE*E>E=6EJ^EE|5EEuE%ETEEVEtEEMEE}ElE)EEIE;.E/EGE&8EEE*EֽEEE4E|EiE EENiEq EhEVEۨENoEEE2EtEhjEoEEw EQEZE EEElEE?EE>E]EECnEEENEGEzfE?EEh9EpbEEKEEEE E".EENE,EAE0E^EE);EW$EkE-EHEQRE>E iE8EEE EEE}ErE҄EUEDJEE!EE4E#EnEcE#E%EEEEzdEEEEyE7E9EE3EEkEvEEo EEEEE EEyEEbEyE EElE EzEkMEGEFE8EExE6E:E@EEExE`EE!E(EEEބEfEϑE`ELEBE_ElEVEBEE EXEEEuE9E EFE_dEMEkEDEeEEEiE,:EbE*jE]EE(!EEfEE6EE?E=|EJEEjEvEE}EkEEVEsE^E&EE}EEEqxELEE.EEE EEE EK>E\EE7E{EDE"EE>EmE>EEEpEErNEEٷEEEEHgEE~E|SE:EMEhXEmEE,eEzEZE`=E E=EDEE'&E EEqE>.EEEޫEEKE5'E0EEpEeEE٢EpE2EEEtE^EwENEHE$EwEpE8EEEEEEtEsE&xEEJEYEfEEXE7EErEAEE+E7wE~EEEFEEEOEdEd5E;E'.E\EcEEE E-/EbMEJ E4EETEEcEcEE[EVEӲEy9E^E*EvE5EUEEzEELjE^E*E`EiOEE EU^EE}El@EGEEE Es[EEZEcECE/EqvEE1EfE=E).EE\ E:E E`EaFEEXE!rEEͽEQ>EEXEfEZE0=EFEEEbEEV[EDERaEXTENE?EWE!EE\rEEEEExEEE)ER9EEExEEEEC;EREJ1EE˗EJEqEEI EEWEEsEtEYEEEVEFEFE;EMEEHEEEkEpE$EEEEEEQHEHE޲EEENaExE*EEVE$EE E>EEEbEE7|E\E E!EEƼEʨEpEE0EqE&ExEME\E&EE30EEEERmEyEpE,EEE&EErEE6jE E!EOzE^ZE E`E"E&,EWEE EEWEEEpEEUE~E:IE$E- E,lEE|E5EEEEE2ECEE:EQSEEJ$EE˥EJjEEEEGUEEEEE0E-zESEEEbEE[EE^EE7EE EE\2EnEE}NEEcEJEEbEcEFEEJEE>EEeE|EEZE E+E\Ej0EzEMEtE=EmEE_EEVE oEBEUE9Eu`E3GEUEnEMEEuEUuErEEE[ElEEE3E&.EEEEeEjkEE@EWoEEEhEvEmE PELdErEhEFEE1^EYE߲EEDE-EeEEĨEEEΧE}EKEEEiE%EHE_E^*EEuOEsEEEBEEnjEEE>E+rEgEECE^EE gEEE+EE E~EC?E_EmEE'EɺE(EsEfEEQEEߖE=EE\!E>EE@EuE4BEPhEEAE̩EE`EE:EJE2AE6E0sEaE<[EEEhEaEʨEME;E)EEP*EīE[bE EAE89EE{EEHE)EE nEb6EIEEEXEE*EE̝EMEt%EENEE(|E=EIEEEE>EEE.EPEIELjE&EtEEEE8E7EjE{EѻEyExEZE.EEEEEtEgEE~(EYEhEExE&EEWEE`ErE7EnEDEE۳EkENEE0EF2E2EE[EREAEpEEnESEEEE2E/Em E%/EVEOExgEx/ERE_E6E=E$EUEBE/:EE4EJEE}EE1EYEAEW9E6EXEfEBE.ZEJUEIhE6fEtE EvE EEEy Ex=EPEE-E4E"EE^Ew7EEEEEENwESEEsE9EEEEEEEbEfJEEEHEjEE{@Em6EEEOEE9EEuEEEEEGsEE\EE/EkE3EEkE'EEAZE&GEZEEEܝE EYE4BEEexEzE,E*EVEBE%EEHE_E?EEEEE;ZE-fEXE[EJE*E EERE#E76EEқE EEgEEXE6E&E@E/E;EUEQEE)~EEDE/EEsE`E$cEEEREfbEECEE EQEWE&EAEEESET:EEzE|EE4EEEE1TEE EEvE0EyEEEE@EBEEEvEE%EE~EEsEXEEEFEWEgEErEEQE@rEQE_XEzE$EEE]E.>ESzEEBEElEE EtEEf#ECEE=?EE2EEyEEE>YEE!EfnEEEEEE7EVEEE}E.EE+$E,Ea:EEEEfEEeEE7>EE.EEYHEdEZE1EuEEhE#6EEpEE;EDEPE BEemE(EeEaEaUE|EzQEA,EEEsmEEEvE$E+EMEEEE|E^EE&uEEͬEjE]EEvEFEE6EE[E^EQE2EE^RE EEEpEEEEEEoEXE EUEEAEC)E'LE|EPEEƓENExzE%9EE3EEn"E+CERE8EE$E.E EmETENjzEJEE#EEEoE>>EBBEy"EeEϬEMEEEEREELELEӺEEsEElE9E EbEvE$E0EΌEeEEHEE!EwE~EKETvEPxEEJEbEE4EE&E_EvE[E}iErEEEDEs:EEEiEEE`E4E>E6E>E ^EKEvEJE 2EwPE`EEAEeEE+EEUEpE, EE4BEKEEE EZEn ELE%XE.EEẼE#EC~E!4EfEU5ElELEEEE|EyfEEϲEECE5EE.EwERE[)ETEeE/ EbELZEtE+[EEUExE{@EEB2EBE]vEEEs'EE4EEESEEeE E.EEE, ENEe*E*ENE{EOE EE*EEhE>E"EEEuEE~EECkE,E{E7EE&EE?EE~E_EeETEEwE,EEEvEQE#EEIEEE E8nEEE EEEE-EE|EXEEEE ZE?EzEE EEEՙEܡE*EE7EE,EƂEEYEEEECEE/EcEd EmEEVE$EQEZPEMEXE,_EE'E(tEDEEEEIUEE\E6EE.$E @ElEbE|EE;E EiEhpE:E E+EE"Eq4E{EE,EEE^"EbEWE6EgE@_EaE2EE2E7"E-EEEpEJEN~EE5RECExEER-EEBE!E`EnE@DEEEEQEfEzE]SEE'E~lE-EtEuEExEEEE@EREE[ EΩEnEzEEUEEDEOEEEEJE`EE"E{EjVE E)EiEEGE/bEdEf3EDEE3EEtEE%EE^EEMEpkEEE4EZEE=EtEEB#EEIEq EHE%]E E;ENE6EǮEVE2ELZE`EE{`EErEE=QEҋEfEE3EXEUsE>E3E$E{E,E E~EE`&EEbEpEvEEfEEZEYELE7UE EE9E E?EPrEpEEEEEE\E[EҞEEuEpEEbERE~EڞEE~EHE&ZE؝EEE_E'E.E<EEzEQ'E"EHE} E E[ENElEEE]*EbEEأEQEDE0EEqEE -ERE FE~EEYEEzE}E{!EEEE*E)xEqEvEEooE2EE9E E_E;:EEEE#bE3xEkEEaEE EEEB2E8E6FE{EE! E3Ej1EE4IEOOEEE EEEmJEWEcE E2EFEPEE%E5FE&E!E KE DE EEZEEEBE[;E"IEhEEEBEEEEEYEGEw:EEElEEE2EaE}EE EEEarE"E\EE^E*EEvE׎EEDE:E=EEEEyE;EE7_E E-EJE\bEE:EmEZEEUEuEEEEEEנE 1Ep E'E8E)EE|jEZE:EVEpEZE6vEE E՚EEWE[mEEEEEE۶E͘E@E$EѝEE^E>EEEEEE$EEE:EPwE ECtEάEV3EPE EEMEEEpE)EV6EdEEdEF&ENE7jEEEREE$;EqEuE8EEx|ElETEE.E~Er"EOENE{E3ZEɦENaE1E @EWEEzUEEEEhVEZE+EEqEE.EܒEGE%KEEEERE,E_EE$EEEEjEEEjEEUEgE1EEEjE0EiEFEEEE=FEZEEE7E,yE[EGEEE!(EeEEEN]E 2EELEEE,EE):ElEEEmE=E!#EEGEsiEEL.EwE2EWE9E E'EPQEQEږEEEPE E.E\EBEEElEE(YENE5E=E!ENE E EQEES6EeEEDIEWEEyzEEE.IE3EE_EE.PE3 EEZEt/Eu.E֪EfErE~EwEaEhEEwEEEEGEEnME`E,kEE E$EEWEEEuQEEEfEEbEgEE9ENE4EYEMEˌEhE:EyvElE%EFEEEFE/E,EzE{EE=EEþEEfEE>EEEE< EiE9}EE EbE%OE/vEEE~AEnE_%EH3EEEEօE4 EݍENEX[EEEEYEنEEEIEEEdEXEEEYEFDEE0EEqEEEғEE-E&0EE E[EEEEsE7EO^EڙEEEEE>EDZE/E2`E:EEEEօE.EE~EREA;EEEEzEtEEzE*EbEEEE$EEyEEREpvEE~EEEE2EKEEEp EcEEVE;EfrE4nEEHEE;E E)E&E_EEoEESEEDEAEP2EE!EE+E4EOEXE|EDE EEKLEEvE)EEECEE#KEςEȵEeEEEĔkENEEvREA\EwEEEZEe3E$EeE EnEqE8E2EרEE.E*E=EτEmQEE8EE!EEzEENEҦEE3EdE`EJEICEHEPEE1EfE#E[E:EUEiEwEXKEVEeE׆EEOjEEEtEEEEE9EEq.EEE3jEEE!EeEEEE}EE EEE$E>E EiEEs`EލEu)EqE1EzEaE}E~EObEBEEE EEENE'{E{EEREE)EJE`EEE!E_EEE\EHDE-]ENE EYEE GEE#EhHEkoE7:EdEE|EؖEdE6ELE*EUEB_EѬE E%+Ed^EIE+EE3ElEEEEVE EiE3EEEnE{E?EGkEEcE{+EhEE#EJE3E:EùEnE&EWEEE,jEsoEEEEEELqEEEZEVE>EEEEEN5EɹEEEREaEEEElEE;EZ"FF9?FBNF*ɐFbEEņEX9E0E]ErE;EsEXE̶E%E67EEA:ED*E=EE4_EPE"ElElFE'EEEɶEWEE]EFEEHEaEKE;:EEEtEG6EEYEELEĐEFE7EE@E E$E?~EEEsE5Ee&EEEEwVEEE EEUEÂEE5E^E^E/E.EAEEJ^EEkEX)EEEE'EÚEEZE0EFEE5EvEt1EEE YEzE, ExEEȖE8E;EMEfEQE,EӞEemEEEEHEPEEE_EE|oEݠE)zEF E/E#EmE\EE\EJ)E*EefE&ECEETE3Ef+EEEfE;EAWE=EPEnE_E YEE Ez6E"EEEEreEEiEE2EEީEEuE:E'EКEbFE_EEEhESEdEE E7EFE!rEUE"0EҞE^E)@EmEmENEEEE"LE|EI>EIEEE=ZEExcE EEErE>EEkEEEDaEP4EEEEUEEEE^EvpEzE 3EE`=EE$fEߊEEIEUE)'E"RE/EƺEiEE:0E{ElE.EңE5E E@|EE,EߘE EMEvES|E XEE|E%EEHEFFX8F@F9FjF3EEЉ3EE8rE)^ErEUE&E?EqE[[EOE{EE}EnPEE2E$zEETE? EErEEDEsEC;EEEE!E.EEEi:E7E^EE~EEEq*E1EBEcE ELMEqE&E?EQE#EE,,E6EEPEnEJEEmE7EERE!E$qE/EpEV!EZESFEs3EEZ:ElE}E E"E"rEB EEqE "E.E#FEEEE{EEBEE2E!nE EEEEEHEEĆE}EQ1EXENE)>E=EGNEEUE?ELkEEE,EEtEfEEESEE2EEs EE0BEJEVEkEE}EOEEpEEVEEhEEEwyEOEBECAEEnEڹEE,E|xE>EqE]HE.E! EE*EEhEeE~EزE5E߶E>EEE{iEE'EzE=>EEEcENE4EE /EEQE EYEh?E+YE&EE^/EE8OE.>EEEeEzEEEE]iEvNEE`Eb.EJ:E~E_?E׌EMEEx6EE%E dEјEE'E{EvE(EzEEExEdEE:EEBEEEETE[EEEEOExEE;ELEߡEGELE?>ExEEEEEh?E|E:EE:EE±Eb%EGE5EfEE2E'*EEEj@EsIEEEgEEvZEE1EF+OaFQwF̻xF*FRF^ F E٧EÆEEmE@FEEIEʍEp[EEmE,EE BEEHEEWE*EEE]EEE|EvEż/EEE3gEÝ EgEKE"EE_EE޹E]9E@EIE>lEE|E~E E"OEbEE*EEhE:E@EEEUEzeE?rE9JE E}EE7E2EE^EEE#EEEyiEE76EEh]E~E[ EEEiE~EEZEEEHBE8E@E"EEHEEyE=EEEQEsEIE{EEEEE E@EEl;E En$EpEE0En(EET/E>E]GE~E`EHEpE͚EWEEEEEENEE3EjEEEnZEyE EgEEEEEwE7EE EzEE\EPEzEETE7EEE9E׌EDEE@ENgEĵE'FOF\vFXFMF'F6IhFwE/E`ELEFvEζEbE7EE\EXEbPEREokE@E]5EYdE%EE ?E`1E>JE;2E|E=EƄxE؀EE]EЭ-E^E2EZEEEbEXE[E`E}E"E}EZEEAEE:EE>EE8E{AEE|E EEE$bE7bEE :ErEE>E+EޘE CEnE ME oEEg E(EՐEEESEElE EEEVEEtUE8EEmEEƴEsEEtE&EFEE¦E{EۻEE&E %ET EE+EdzEEE=E EEE.E5EEEL)EUE+XE)Ek,EfoEuEjEKEQE0ES6EME~EE*EEE EEEEOEEE}fEEgWEFEE8E lEE+EEEE}EEhrE,EHEEJEE'E/EeE}EDE\hE E>OE 4EEEV?E&EYE{ECEEEɘEBEEE[EFEEnE$EEoEHEE[EϡEEgE%E!EEE8EEwE;EEJEEEEEEgEbE-E3EEBEBECE.EEE9(E?E0E EAfE]JE::EEDELE_EEENExEnEE̲EEXEmEE/EEEEoErREz{E:E=EiEEEEE JE8EYEEEgEEAE"E5EE}EEPEEqEE|ETEEEE@EEEE%EWE uEBEIKEEEb)E0EVE~EE1EKEAlEAEjE&EE^'E#ZEPpE_ET:EE,lE*AE:E?EbE%E"EE{EE%E'EbEFEEɆEuEE]E :EPEEtERNEEEQEEERE$*EEEc EZE6E#EդE0E2EbEEENE8*E)EGEZEE]EEEEEZ3E@EdEoEE&EE}EE]|E@EbELE:VEEEtE{$E>#EE/*EφEE7EEU$EEEмEsECEEE EnE)EZE0mECEAE*kE%&EEmE!ETEOeEEZsEEEEEAEEJ-E,E]E*-E`E2E EFE#EEvE!E7EGE)EEE E*EsEE{EENjEvEdEEWVELE-EREEEEEEZEYEE EEEFoEEFGFq.FbGPGj`Gj`Gj`G6MFFbF?E4EE ,E'E$EaE EEEEAE E+XE.E E >E^EUEjEFEECEqE.EEEQYE EêEnEKE^EEQEzbE+EθE-E E&E˜E.E)~ETlEE EEEEEeaE?E1EE-EEEϚE4EE>EkEEEw$EEfIEEpE?EYbE3E6EpE8EEr%EEoEwEBjE@3E 3EEEEaEEfEwEE E&[EhWE!EEz Ea;E E!EE&EENhELEgE)EE EwENEEŜEJ5E[EE'EEvE*|EcEEEEEEE)EEE0EEE.E/EEEyEoE,EE/ EGEB{EĠE#E2E\E\EEEE؁EE%EfEEEEE(#ENE{EƒE#E{EE3EE=VE zEErEQEE$oEEEUE\EzEEEъEŵEjEVAEEErEEENEEE"RE-EUE|Es1E2EKE7E>EZETE%EKEEE\EmE`E1E^E!E,EWEœE5EԏEEEBEfE EX}E|ETEE$EqEE]+EwRE9E$xEE[E@EEEH:Eϳ%E.UFF2U.F.G)BGj`Gj`Gj`Gj`Gj`G 9F7>F)!yFeEqEEE6E- EEEEDE5$E+E#E( E*EEEHWE.*EEEPEE E EyEEFEWE:ErEVEENE'EPEE`E.EnE3ErE1EE EzEEREEPEEEEyE EiEKGECEsEEحE)EEFEb9EEuE|EzE'E\EEEEZaEPEIE{EE,EOENE@EۏENJEbEEzEEEVE .E:JEheEEEkE_LEWE`iETEgEXzEEYyEZE&ENE|EE:EEUEJE=vEUEA,Ej~EE]E~HEzEHEtEEEEBEyEEzE EEEE;EEE\EaE}EEEE'EHEǧ(E1*EEE,EQEE|E%bEE{EEmEWEAEE9EqEEE4EdEEEJEJEڗEэEĐEEVEgEbEEjEjEtEEſEENEE-E`CEEfE%EpuErE{EBEEp6EEX EABEEāEEfEFE~eE}E҃E5%EYEEEAEbEQE|3E EbFErEvEECE.EEEEE`E@E~5E~EoEE6KEEAEwqEEfEEEEϸESF F=_lFf/GM Gj`Gj`Gj`Gj`Gj`G%߂FZ'F-NhF@EE<*E\EEgEE EIcEEE@@EE~EEEEEvEpEE`E;'E,EE6EEY>EEc E#EEJEEvEEEEE\EEEE#|EEMKE EmEE%TEeHEغENEE5E>EZE/6E@EEr:E#EEPE3EIEEE-EƙE5ElE>EdKEE-EmEjE^EEDE3ESEEE9EEME>EUEEE:EEECEߺEE)E]VE%EgE+@EEEElE^ECEGE\EEERE&Ei$ENEdEEzEEEEEyEqEKyE[EEETElEE>E5E%EsEEʆEEEϞEDEEEE5E&E)CEzEanEEELE`ETEEyE"E}EaEEEE2EEEEEIE&EENEjEZEjEU*EEEEIEE\XE E/E{E|E8E!EJ>EcKEgBEwEEXEEEFEEEwEǃE EE8gEEETERE=vEEE*EanELEH_EvEEKEEʚEߒEEzEE?E ZE;.EE"EuEEE*E*EEsE\EײEvEEEE-EEEE[ExENEEqEEE)EISEnEiEEEEE$EʱEnEjEoEFEE2EdErE*EٗE4"EEEE5EfEEE)EEEEwrEz.E"$EuE,EEXE/EWE'EPE~E5EA=E|`EE'EE8E:KETEEE(EE2E8ElELEɕE/E;E&EnEEWEEEEE7zE`E3E"ENEEE_EZEjEEE"EEjqEGE`E;1EEئEEuEFEgJE EE_rE+fEAEjE@E[EYEZEENLExEXvEE^EEVEEE>bEEAEEqErE{ErE$ErE+EEEE}EEE3EElETE~EqEoEE9ENEEvEEtEEE:EEEWE2E4EEEEEEE!E}EE_ELEEzPEDoEFE#E?EEEE EEEETEEEENE=AEEZEwE#vEE*E4EٵE]oE̞EۈE0F#FGeGj`Gj`Gj`Gj`GYb.FFe'FqEXECE?EEoE7E;SE؆E ~ER"EEEEDEEqEEJEO@EMEKErENEPEvE6E EA:EE(E?EE*EiECEyEjEEEE EE{EvJE EEEfE%E3iEE4EêE,EEeEEE -EEE4EEEwRE_EEEE-EEEqEEuE KEKKE{E@Ef=EwE(ENEE4!EEIDEEjEE-EEٌEEREdE;E/E(EGmEdEEWETEfEEـEcETETE E(E~&EJaElwENE_EdElEMEE(EˊEFE_ ENEE\kEE$VEEĩEE`E EE^EE&E-EZEEmEo9EjEEBzE%EEEEE'^EuEi+EwxE EEE>E<:EE|EEE`EŎEiEJ7EE5ÈEEE9EEEJE;EyKEEwE[E`EEE(E EY~EEE>EnwED}EEE2EEE1EnEEE8FEެEE˚EEIE3E#E)EEEgE%EZElcEIEEYEwEVfEE EE6EBETEE$bEbE9E"EEEEEERVEBEuEE:EEeEԈEpF jFBLF%GC(G<Gj`G/oFFzUF2+IFxEE]E2EEEEGEݲEEEREr*EXfE{EӚEEEYE*aEZzEE1EEwEE+EAwEzEȝEEcEɃEEpE EEXCE0EV#EEQLEEEE EKE(*EtEEEE{E~EW1Ej2EpEEQjE$\EECEE6Ej=E$EۚEEE EEE.EHEEUE E)ExEEEjEiEEE4E3E\EcE EEEIEEXErEEEzEEEE(EHEh8E+EfE E/cEqEE`EPEiEEkEbE3E jEz:EEtEVEMEE}E\2EmE`EkEZEkE hEBE}EZEEEE_E&EZEE9E{E{E5AEsEEuE+EvEQEMnE;ExEEEEŕEE6EՀEv6ELECREEWEPE8EyE=EVEWEzEkEcElE)EcEECEEEEbE`E E E=]E+EhEaEQEVEElEEzE;EE>EE=EyENMEEDEEGEHEQSEE ErEIEEojE&EFE# EREcEEGEԇE BEEj{EEE6EEE6EG2E&EŪEEUEEIJEREAsEEE4{EEEq)Ex4EfEPEE"E`EwE EKEE#EEEEEbEJE9E.EE=EEEEgECNE`E!E|EE7E,EEEPEEBEEEEEEE}EE hE_EEkEKEC%E0hE'EfE nEc2E 6ESEOEuEEF5OFFJECE۹]EΰzE\EE'EEzE_E=!E ECEErEjET E)\E~E;E vEkEE*EIESJEEcEE8EECsEEE9E|"E{E^E(E[fEEE@EFEEEAEdEEYE|Eg^E]>EfEE{EEv&EE EEEkEEwEwEbVEoEE׽EEEEEEEEEZEEVrEl6EE;|E2EE8EE(EME5EnEE+9EVEE4EEbEEGE*E}ENEҸEZfEEER5EEjE{rEME4EE:EEIEnE%EREKtED#EEsEEEs#EEJETEEEE7E_yEEQEoEE(EsEZAEEEEEEMEJEE*OE7E00EzEbEE2:EEhE"4EEQE00EEE]EEVEP*EEESEZEEAEE>E'EED6E5>EoEEDE"E:nE -EEE;EE EEE9EUE'EEvE6JE_EE`EEoEhEQEEdDE E.EEĒE [E )E|EŠEAeEی+ECEi(F |FpPFEEEnE"EE>E EifENETE*EEE EFE_REMEEEEiEiE!EEEREE4tEmEPEEFfEEE3EpEE>EE’EEEcEEE:EEuEBEEEfEE:EeEEEEEE܆E9EEFE)E!E{8E-E E[E?EEENE|EWEEHENE]EglEPE'EK EsEE:E$EE E2EEB/EkEpE}^EEEE4EETEHEuEsENEsE9E}EEE2nEEE=E$E'EEʋEbEEEG0E֦EEEEEEʏE/VEVnEscE5E!EzE^EE6E=EDEwEMEoE-EEEUEEE&E EE]EEEmE.EEEdEE6EEEYqEEEiE#EC:E/EB=EE8E~EuEEEEE8EE6E*EEEE(E[EE7EEET{ELEEEE'E,EwEE&EEE>EE5.EKEEEE2uEE"EnEHLE>E֤EYEE=.EE(EE<EWEGE}EEEEzE5EaEE6EETEǃE(EgE"EdEEzE"EzEE˺E[EPEqEEiEE`EwE^EEypEEZ>EkEU ERE%EEE{E)E\EH"EEEE EEOEjwEE%EDE /EPE+E ESEwE~EEEDEEEREEBEeEE:EcE:E|;EEES9EzE(DENEEEE؇E[EEDEzE GEE EJEE 1EdEE>tE=ES3E_^EHE:gE EEEE EZEEE"EBE&Ej"E$EEREEEEjE*EAEE'EE^EKEBEUEidE"EZEoEhEbEWE6EOEEeEkLEEEEEZEE"E EbEEUEgE0EE?EE EEhtEEfBExE1pEEEEVE4EGExdE8,EE2EmhEIEEEE9EEEME_E5RE[]EUvEiE-Ej1EEEE`E:E/EEEgEEvEELEE.Ee}EE#EEvE>E E\E"EE?E`E+1EEEEgErEĬEE$EpLEw0EVErErMEKEE.EEWEmEEEvdE&EEWEEEEEREujEEEsEDE'EEEEEEEEE\E+EEE%EfEaVEE~ErEEoE8bE'EKE}EEpYEEcEE5ENEEPEoPEE&EE'EEHE>EWNEg}EEEEWE?EcE,EEEEEEWE/E(EVEEAEg8EjEE.E EE)EEEJEEEEhESEf_EXE{EWEEDEtE!ETE%bE?JE] EUrEzE{EEBE+EKE E 2EEVEjEEEEj?E:EjEmfEy,E0EBE0EE&EpJEEEE9rEcjEIE{EŽ{Eǒ~E(EĉEEOREEEtE}EE+EqCEƪEE4EnE}EE E8EJEc;EkErEFEEEcE>}EOEQvEEXExEDEjEfEtE{EEE E EoE|EEE`,ELEъEEEEߡEE!TE'EE`EE E:VEEE^E E+EENEڶEEE EGETExEc:EUEaEFEE E=:E[EOE|E`EE,EyEDErE-!ECE~EE EPE?ZE E|E:EIE2EEEE,EEzExE{@E!Eo@E]zEE:EE EkE E0EEզEsE:7Ek=E3EE%EEE\EbREzE E#EE!E#OEUECbEWEdEE̚EE9E3EREϛE٦EEeaE\E2EEgEEEjEzE5EE4EEÑEREEE/EE1EEEEWEyELE&E)EyEE@E mEzExELEd1E@ EaE_bE:EEBEE}fEEE8EEREEEUE%EcEsE9EKEEkEAEEEsE“En*EEόElEEEZE3E hEZEs0EEeEh7E:ELEExE>EEJhE^E/EELE&JEEgTEnE ME&EE-E!EaME~EE0EEsEEyE~EEwjEUEnEٺEsEEEoE$=E?bEEg2EnEb&EAEEriEFEUEE EMEE EL.EEEEțEEEEEE$PEEJEE39E&EEgE4EEEsEZEE_.EzEEE0EEtE|EhE~ETlENEEEEEe6EE;EHEpEE6EsEmE`EfEEEE~^EEaENEpE..EEGHEEGEʐEˁEʁE'nE@UE-EE E2EPEEE"EEEE EEEE|fEEMEt EEMEvE5rEE[EEʠE~E'*E*ENE)zEYEnEU E'EEEqETE,E{rEqEE'VEEES|ECEi&E¡EE"EE7:E>6ElEEҊEEEEW\EAE+kEEEEkEBEVEjE8EBEAE\EE fEIEq1E֦EEEgE/EyEEFE9EvEEEVE(E7EEXyEEgE"EEEE1^EJEGREzEECEmmE2EEE>E4EpEEeE,lEE'EE$EE7E6EEzEvEBEEEE?PE?rElEE,E>EEEEEKEEIEqEEE7EEE˶EYEbEEwkEE:E3EOhE` EEIE\EE-9EqE5EtEEEmXEEيEEEJEz*EEE3EVEEE4"EoE/E(EWJE EEEEEJE(EEf EqE2E(EEErEEbErE>UEE}E E[EBE*ESEe%EEEE-E4E1EհEgELfE9nEE1E2zEKE#E-E,pE7EE1EHElEGE!EJqEE1EvEEdEEFE:ETEEEEKHEEEKeE=ElrEEhEXE EJEEEIEEE;EqE=@E`EAEK@Ea~E7E!El\EEEBE EEnPEzEEE^EEyEEE EE1E-EqEEEEdEJEE0lEE)9EwEErEBESErE@E;uEEE3EE,ELEEYvEE|fEE E4ESEE'E0EZE4EwEEE!EFEaEJ+EGEE EE:EE}EvOE% E*EeE!EFEAEzEEEvEE;EhE!EKEE%EEmE]/EEEE EE"EFEEEEƨETEEE EEESEE0(E)EE{EyEEA>EE#EEEE EE`EE$E|ZE^EEmAEvENEEiE\kEۢE{EEEEOEOE#fEE9EJEJEŚEEE+EmEoEE#ENQEE~E5EEEEcExjEEsE#MEE3E(EEGEE_NE%E%E]EZMEҍEPEڔEE2>EE!EEjEE}9E^FEE1EEUENEE{:EE:EE EEǤENEeEڃEaEE6EEFfE"EzEETVE3ErtEhEݕEzEE.jEE*EbE0E|@EE=EEUEWEJ+EnEٖE5E)Ea E%EEdEjE/xEzEwEEEE1EE1EoEEJEEMOEErEEVEER#E?E/EEeENVEEXEE1E!E iEDEgEBwEfEE~[EEOEg EiHEOEuE6EE߄EKEzEqEYjEjEȊE%E7E4EE/EKEE;E)EXE}EКEiJEEE}EaEQElE%EEyE\E>SEEE/EgEуEHEEMYEQtEE' EEEPEEEYE).EܥE~;EE?EEEtEkEtEEEՆEëEEzE%E}AEEEHE^Ek6E`+EmE?ES0E&EEEkEEE+wEEv2ELEkE&E?EEE^EvEEElE\EkEKE.EuEElZEZE/EY:EUEEE2EqEEEYEKEe[E3AEftEEEZE\E;EEE…EjE?E2&EEEEEEEEEEE&EԞE%EGEE?jEGEEEE+E+$EaE͗EWE"E kEE"EZE9EE(BEE"ETEfErEEEEEeEPbEWEsEESE8E.E;E(IECEEjE4E:EȻE"EaE5EFEfEcEWE|EFE EE×EňEFqbFvFG PF*ZFNjF:EExVE;EGdE(EErEE@E0aEEhEgEEYE&EgEE7EEE;EEEEfErEtEEEoE{EEEE5NEEbEE`ETE7EEEL EENEJ0E2EE7EEL*EPEkEZE)EEZE_EEE E%EE7Eh=EFEEE7E EE4E)EPEųEE؞E?EEрE"aEPEEEvTE/EtEE^rEEE'E7E_8EE[E@EEfvE}ZEx*EEEyEEEEElJEMPEc?EEE6xE~EEvEhEvREgEEEn{EEYEvEEoEGEzEElEeE7EEES^E:EoeEEؤEE+ET.EEEYEىF RFUFFuFdFOF(>EuEE0EE94EE^E|FEgoE7E?yESEEEEEǠE EEDlEEDEE$EE+mE.\E|zEEʽE&yEcErEEE_EWEE1EEEEUEjEVEEE.E҄ECEUEEwE,EEEE>EKEEE%hEEqEqvE%wEJE5E~E_EBE6EEFEeE)bE|E~ E`ESEXgETEEwE2EHEME8E:E#EfE(EEt:EgEKElEvGEE E2EXEE 5EsE5rE=xEҜE3E6EE \EEǝE@EE+E*E+EȦEEeCEE}EJEE{ESEEEeE@EE7EE1E0ErEn/EgE[E1EEEE"EqEaE~EE\E)EŅEEEEqEE/EEiEFEEzEyEcEpE}E'EE, EvE1EB+FFF>'EFEDE:.E:kEE9EGE[E@EvhE EFE,E@hEEE9E EJvEE&FE!Eh"E0E2YE]?EEE&E;E=EEVEEEE%EEEEPE*EXRE4E EEDE3EhEEEtEEdEurExEVE*EEIE*Ep;EHYEfE>2E2EsE~EaEIE&EE 2EF!]F[V F&pFuD`F;3FEۗELMEzEnE0EtEEE[ E2EEu8EJoEKE&EdEKEkEYE)CEAEEUEE<EE!EEE>EgEE'ErE*EUrE/EoE5E<9EyE=9EOEEEBEBE*^E|VEEEEEyE~EcEE"NE`Ey)EdE^EF]E EEEjEbEJEpE}FEE8EAEpEEڤE-E41EcoEEysE*E!EhEEvE AEFEEE,EDEE}3EVKE9EE~EvEEEnEϸEEFF7G.F-.F JEBEđEjE 3EEEE\E?EEئE"SEYfEEdJE EEEEhE&E)oE|lEJ E*1E&E#E[*E"ENEE9EEC)E]AEGE܃EE^EݬE8EEE E} E3EEAEc+EE,ErEEaE1EK>EOEEfE52ETEg;EE4EEoE:EcE$EE2EUEՉHE.FFXFFLE%EʿSEE@E>EX;ELE21E.EvEE“E9E0E E EvEEbEEnE'EE.EE@EaE#E:E EEPE8EEaEMEEdEދEVBEEyEEfhE:E:EZE&EXEjEJE>EP:EEE-E˹E|EE"QETzE@EVKEE>Ew`EGbEf{EQ)E(E{EEvEȓE$EUEhEEP2EEhEEF1EvEEE(EEEơEEnEEE:EwEE6E*EE0ExEEDEsEQ EfE2E6EEEE6EEE6EE%EfEE.ENE:EE-^EWE#E"E"EEEVE6EE<&EEEE_E.EE9EEE8E%EElE†EEEEEбEEE|ErExEE$EqE=EwESEEwEEyvEbRE˰EvE؃EF"F=&F3FE-^EŦE0EEEE;.EyE%EQEUfEEE^EEEWUEE2EEEVEPEEEAEkE(EPEmE!EE EEuE;EEEvEYEjEbzE VEEEEwEjE E$EEE6EwEE:E E1EV EEE:EjEMEEEEME E4EޖE}EbEE_E4jEtAEEfSF F F%EEEE~EE*EiEEEEwELEREPAE"EJECEEEEErE EėEEE EEE E#EerEXZEErEPEUNEEXEE`EEEEEQ EK$E;E]EEEE2E*E EIEETEEE@EUEEHEsE^rE>EEEE/zEE#E?EAE~EGEޅE$E E·E$|E-EТE~E,EERE7-ERE٢EE&EE-jEz.EEVE3,EBE/EbVEkEEXEEE$E;E>EϘE>EEZEE EE.EEEpEGuEElrEXEjE'tE1'EUEErEE>'Ea EBEEEsEEEE%EEoEE5E EQEE dE`E0?EBEOEiEfE{E>EwEE^EOE-E*E%E{*E{EEeE!(EtiE\EYEEELE}EyE(E!zE;EwEEnvE%E0E EhiErNEEEEnEEEE0ZEAEEx"E!EzEE EEE ME&EfhEEJE0EEEE:E{E>EFEE!*EEEEaEQE6Ey0E3\E$E>EuEEګEEEEEEEE4EiEE $EiE"E;EwEEEY%EbBE`zEuEEEyEEEEwEDEvEvEVE4EZEE%EE}FE*EEEcE EEECEuEepEEXvEyEE5E53ELbE(E7PEɪEEMEOEEG EEENEAENEECEjMEEPE.&E~EEyEIEETCEEfE3EL,EcEE|E%EEbQE E͒EEHEE[yEEmE{Eu2EEE EE:5EHEwEηEnEEEHE2EEBEQE8EPVE EGEzlEiE&EkEEYE6EE0-E5ZE"EsEuE( E0&EEE&EZEfENEEiELEEE,EEYE EEZE{E EE 4E EUEE:EE;ErElE(EfJE+E{E;rE%EʶEEvZE%EivE:E]XE?E)EEb'EEzoEqELJEwNEEExE:ZE3E EdEjEEEEjdEcEEBIE0EEڤEWEEOiE9EkE2E~MEEEvEEEJEEmEssEE(ESEK7E^*EEtE E >EUE.6EnEEaEEVEEEdEVE4EɢEg2E^EeEJEEZEEgEˎEZEJE;E4EE4oEOEEHEEFAE EjbEdEѮEVEۆEE6E#E)EG/EEbEBE[EEEEE EٽEfEDE7FEEwE`E2EE+jEdzEnEErEEEiEtEEEE1IEVEyEEE`EKE.E8EE}EEV6E9E3JE EɂE`EEVEoEEjEy'ELE EnEpEGEEEe>E9EJEEE0EEE`wEEEEPEEh&EE?E^EhE{EEEEEE%E,En"E0EEdEE<EETEjUEMEaEEzE1EEZ'EVEYE[>EEQEE~E]EREEEHEz"EEBEMeE`E#E E EEEm%EE0E{EEE3EZE|E.EEEENE-E{EE|E\EEEEEE%E+EaSEEE'ENbEEEnE EEEREcEtEE*EEkBE:E|E0SEȬEk(EF E+EEyEEfmEsE.6EE$EދEzE#E&E>E5)E3zE E#EEiEZEVEɞEZE(EnEEvE*EEME3EREE{bEE%E`E6EbAEEOEIEElJE>=EE?E:EHE=ErE!!EME9EEE4EDE0ErE"EEoEE̊EEk2EHfE&EE(E1E^EKbEEEYE:E9EKEhEDEE8E'EEEEfEXE.(EE6EsyETkEcE3`E)EEE(E4EEEE[sEFEE;Ej E{E`bEEpcEEYdE*&EkEzhEE,zEIEDE}EYEJEE>EEEEEEEE+rE EYE!EEfErEkrEGEXEfEKHE]EEkEEJE{EMEBEFERErEgEuE?E78EHoESEnEEVEE*ExĖEViEE E/E4 EEEVEE'EEEE]jEErE:>E:ET^EE@EUEvE+EEEmEծEVEdcE gEwE1E"EEGE'kEEFE(ENEEEEEIAEEEEB2E]EjEEE EREbEEbE&EXEZE†EE6EEa.EE>E,E[EفE>EE&ESpEEtEE$EEEEQ"E2Ea.E)1E E?EEDEfEEmEEEEoKEEjEzE EEE4EIEGEsDEENEEE-PE?EEּEEzVEE6wENEE]E^E|EhE)EŴEE=EQSEbEsE:xEiEEEEEEEEEdE+EE,E EʾEE[E,8EuEHEjEVEE$EIEhE!LEʬEE[mEAEE'EȆE4IE:EmEE֜E|#EuEtGEڨE]PE>EEgEEZEE?EHEE9ElyE~lE,EkEEhrEEEEEEX EEjEE`E}EEFEE Ee|EsEE&EL"EaEEEEYEE^E_UELE E֊E6E>eEEEkEcEiE>EEEEEE6E2EEEE2}EEEEqCE`E~E7rEE E8EEhFE EVE&hE2E)EEjE,:EuEEREpEEhEE7E EE5PE)MEqE)E EnE'ESEkEEWZEmEGE~EEE.E~EnEebEfEsYEEE-1EXESvE=E`E4EEhEtEM EjEEXE:EEEؙE!E&EE E ECE EnEE_EcE}E,EEEeE vE΃EEWBE2E"E;EnE,EEE0EXEELEyEEEZEEeEgEjdEEuEnE3E.EEiEd#ExEܵEWEI EE,EE"E{EEEEPEEOE6EEVEEE+EEOE$EoEkEոEI1EEKENEIE,xEtE/hE9mEEEsEzEAsEEEEOEEEECEEEEdcEbEE*=EEE5EDEuEEaEzE=E7E,E}EElE,EvE0E0CEEYEQ{ExENEE4 EE.EEE}rEp9E4EvEgE"E0E=E*EEfEEZE]EEBE]zEE#EEkEE[EFEE.EbEJE|EnE7E9EEbEE0EMEggEIJE EE܀EE,wEE"EzE[ E1EEDE.EEPE,CEBE]EdaE, EEE E#EE E E*E.EEgEEaEE.EjEExErEE#SE EEE0_EwEvEEEiEtJEE]E ExE@E֋EmEEEQGE.EEEͮEh~EREAEFEcEE=EˍEdE[EjE+E iE$UEkErE+EhE"E,gEvEVEIEVE]E3ETEvE E!E-6ExzE*EEE9EE'EϝEIE.EgEvEE`DEyEE4E EE4hEEVEEEEpgE_jEEEEEEhEE+EiEBE.EEXEE EshEE|E"E#EEErEnJE"EEPFEsVEEQEE_E#EE EYEEnEEE EE(E EEE[{EEEEEEREoEEEEvE#E%~EWE˦E EvEXJE^EgEWE̪EVmEEuE2EwEÇEݍEEhE FEZE>PE5EE)EtE4E%EaErEVEEE:nE:E[E7E EƾEE%EQE(.EE]EE;EFEE^EBEEEEEETEE8EiEEnEEqEpEEeESE3E E!2E)SEEqEfE E'E`EEEEENE(EEME EEEEzE?EZ.EEEE{EEEEEESENETESEVEE@DEEnE2EEFHEE>EoE2Ey EEuE9EEEd"E/EvEuE]EEEE_EwEEEE!E.EϹEE0EqEDE6EZEnErEE"AE~.E@EnE>E5ErEE'EEeEcEFE^EFE\EEEEֵEfEE^EE?kEEE2EEђEEE>ENE EEEEN^EEGEHEE EERmEEZE'E9>EEڛE]ZEPEEHEmEVE>^EzE~EvEqE E EpEjE E0EEEEEEEsEwVE E:EE2E^EEH(E?EUEEEE:E^EE4E&"EEȹEEjCEXEöEEP#ELEEd@EEݰEhE vEE,EEzYENEE$7EE ElxEEtE=EnEE_EEkEE Ek_EEEhEEhvE~EpKEjE EV?E{EEElEhEsEuEcFE&E6EEUEBEEE:E,EPEEEEuET EEXEExEEEWEEE%EEE"EEE%*ELE&EE\1EOErEy"EpRE EU+EjEE-E'EsE CEpCEEEEEBEEqEDEuEEE2aEeEEmBEE.E}rEEE EEpEqEEEQEEmEeE˓E@EQE7EEEqE^E!EE7~EE^NE]\EEZEEnE%EE EEE.jE{E:E,E'REEݺE~E:E E EEAE-oEχE\ EF>EEzEjE_gEGWE)EBE]\EMEE~EEEEsE.EQiEnkE/EE*Eq;E0NEBEE\EφEEQ4EE"EEEEzE7E*EEEEE$xEE7EEwEwEZE[E"E7:E6 ECEuvEEE5E"EWE*E6GEEkEWE(EWEpEE1*EiE EEEUE EEED2E6EEtVEE,EfEHEEdEE E:EE^E -E EE_EEnEEEEEE{#E/EExZEEJE&NEϋEFEA:EN!E"E*EE6(EEEEEET2E+E?E*"EEEE2E\EErEDE8E`>EUEE~E[EѱEE3nEcME`EwE-E-EVOEP&EEhEOoEwEEEEzE-2EEoEM>EkEcENEEDEճEDEEN9E}ErE&EE\EENEJEE5EREEE'E EE4EoEJEoE.EYEKE"E3E-E5EEBE7E}E!E8EEZE&E>E_E.E,ECEEE|E[OEEh|E`EE EsE)6EdEEv(EEEHEE EjAEEEEbEEEE E eEEtEnEJE^EEE^E EEn2EEE}vEXE E,]E-EYEoEEEEwEE7HE;EEZ/ETcEElEEE$EEWEJEʶEEExE&EE.EFEA1EoEEEdE20EEbE@|EfEEOE9EQEE$EcqE3EbEETEEEwEEvE EE"EEoEEEgEEEE%EJ E)EiMEwEzEEE@E/jES;EE>EEE*SE4E+EEEJEEEEwEREgEs ESEEE EE)EfEE0EрEfEEEvE]EEEB1EOE:E5^E6EE EzEEEjEPiEE EENE(zEelEpzE@^E EE[ZE?EEyErpEE E1EEEF EEhEOeEBEG$EEKNE̜E EENEɲEg3EEؗESELEE~EE@#EE4EEuEoE E\Er1E"EtEz1E!E>+EfEXEEFE1EU'EEEE4EfEXEbE9bEͪE~EEo*EfEEtEE"EUEnE']E'EE.mE E:EEsdEEE EѺEvEE+ E~EAcEQnE-`EEpE EME'UEylE EEvE3EEE#ETRE٧EgE*EZERE0EEb)EhE EE_Eu{E*E8BEQE4EԶEtEEEKEEEOEEaBE^EEV1EjEDE ;EE.E EOE][E:EuENEEhE{EME)*E4En6E$EEX*EoEKEEE E)EEjrE%EEEsEEhbE/E5BE`EEEEE@E PE+kEExEEvEMZE E_EEE9yEnE]E,mEEUEREEE,E;EEEyEEHEEEEEEOEEhE]E,EzEEsE$E/E6EEEME=mE XEEQE%EEE2ExEECE.iE4E/E\bE;^E/EhBEiEDEEvEE"BEk"E[E?EoEQEEvEEEQEôEEgEEE9E yE*EENE8"EpEJnE2EEE6 EEbvEuE7E}Et`E&E!EEUJEE.E$ E5EEAEEEE>E9EEEYEuEEEkEEEebEEnE EEEEENE*FEOEEEECEE'?EIE1EEFEEPE. E,EEEnEIE^EVHE E)EzE"EEEZEyEEEEE9EIEEEE3E{EWEZE= EEvEFEFE$EҥEEElEuE&E5EB/EDrE;EELE7EESEECEE:E*E EE5EtE7E%IEENnE UE_EMEEDEsQEkE_EEEaEEGFEԇETE4EEEBE"E9`EzEE4EfEoEEEEІEyEEQE>ElZEEE*ElEEEU^EEXE]#EyEEECME.\EfEE#E(EnEEPE|TEKE[7E3E{ERE?jEJEEE\EE.EsEExEÊEE_E\EwEYEfErE~EY+E?EEEE*ENEYE$E EKEE}EzEEoEE*OEEvEEEZEEwE_EEzEEgE<&E7EHE2EȂEVEoE]fEgEXE1EEE|BEUEM E&EEEE&E fEEޒEEkE&.EEEEEEEE=EEEEEevEEEESE[FEEevEGEzED8E*EZE&E EEEEEEEEGEQE*E(pE@EEnEEE_E;E(E EEEEEnENEE&[Eg.E|EE9EWEDE3~EEkEEEEZE&EEEEBEv>EIEAEEZEEDEEAEuE?E<E?E~Ey}Ei1EE6EEEDEEŦE_EEjEEtE-E ]E]E ElE0ETE;EaErlEV}EbEEzEEpEƶEJE/E EEgE*EEEEE,E EnEԸE>WEECE+(E{HE^EK^E;cE E#EvE5E:EAEH@EEeEE E $EnE>E^eEE EE)EKEE{IE EEwJEEŸEQE|EAEDEEnEOEg8EEzEFHEE?E"EzEEEEEE.E_E$4EES5EƄEmEjErEEJ?EEEJEE!VE E6EE EEHhEbEEJE EEEEnYEuEEwEVEgEEE>EڗEEEjEEWElEEEfEElEZEnEDEƃE6(E8EEBEtEE E"EEBE6E.EE EeDEAENE9EEKYELE$&E2EΩEJEXE+ElMEkE%EvE EEEyEXEAEEflEE.E:EIELEEEEhAEE_E 0E*E=@E E EEEE"E>ExEEa^ElEE]LE?ENEgKEEEDREEEPEEEGE?eE9QEE6JE^EEQEE=EZEEElmE:VE]E2EgEE BEEP4EdZEEEEEEzEcEP=EEE;E*FE]EagETE*EE/VE7EEzECEE E|EEOE3EE>EE_EEuEEEE*EEbE4EEEEVEEkEEEʗE EԘjEGsE-EE@El|EuEEE"EVEES|ENE=pE Ey E'E>E,\EdEEEEOEyE0NE>EENE EuEQEEoE5EߏERE E5EE EZE[EjE EEWFEHEEmEEqpEIEE`BE#`E9E+EBEE]nEdE3EsE_$EEZEEѻExEEEE$EQElnEvEE0E GE#fE8bE EoEEE>EEE EEgEHEP'EvEVE&EEEEpCE.EREEF0E{EE,EyEE2E3EgbEEEEEEEMEFEEՖErEdE ERE@E]E҈EE EuEE&EYEAEEoE/EEEEEEEE( E$E\EbEE7EEAEQE[E"E)EVEEE EyEEUFE3/EEUEE)#EEE@ME,SE8EEEyE>XEEEEREE϶E EE@EE"EEERE}ElE;1EE3E rEE6EUZEENEEECE0EE GEEEaE`EEEE! EVEEEEE"EEE UE JE^EE`EIE|E.E ESE REEEkE֖EBfE%EE(EeE`EZE:EEEfEmE1E EE3E=vEkE%EEEߕEyEEEeEUE?EBEEqAE EE.SEOEE5E=E ExEEaE~EE}EEsEE}Et2EEEEy8EEY>EEDE{EBE(0EEEE SETEmEEE{EqEɪE@E9'EE-EEUyEtE9vEtiEE`EvEEfZEgEsE)E3EBEE@EZEcEDEnEElvExE:EpE6E^E͛EEE*EQ1EEE0EE^EPEE5E:E=EDEE\EEKECE7E`EEPEEELEECFEDE?E9BEBEE5E[EEEEoEúEERE$EEEBEEA.EgEEVEcE(PF=FF֖E~mE$EsEQEEEE'~E?fE.EsEGjEEEsE@^EEHEE9EgBEWE&!EwEE{EEEEE7NE0ḚE;"EE^EGEEEElzE$EBECEE>EKErEBE"EEEEEauEYEstEFEDECEϽZEEEEEEJQE(EE:E E EEEvEeE2EY;EWEEiE"EEENEEAEE!EĵEETEgEE?qE,EE E8EaE[EOEEEEEEY*E+UEE[2E.E݊E}2Ed^Eo'E E#EFEy}E-EڊEEEVE߂E9Ev}E7E@E|E7E3EEEEjENEE~EiEZE^^EF6FFղEVEEyEE¡IEEuEҾEsREIqEE EE:E=E{E"EpEE9EREE&EExE9mEE]EETEaCEJEEdEE"EEEJaE EEE/E `E2EE@E1tEEEEqEZE*E6EEEEEoE'EܿEExE\qEEjE)EnEEEEE E EEEqER1EEEZZEETE'ExEE~EEeEdE6EѲEE2eEnE%Ec%EfE'FEDE[\EEEECCEVEJE'EEXZE&EswEAE{E3XEE޸EoEZEEE"E "EEEbEEJERE}E:E6EEAE~EEgEJEJE=CE]E EđE*EEîEdE^E6(ElEE>E6E~EĊEEV!E-VEk?E&EFAEXEH E_E#EvEHEEEݼECE?E#EEJEEAErEEEwUE9E3E.EEvEfEXEE/EEEEEZEEb E'E_E% EEE]:E EE6E"EEZEME;E.EECEEE(EEEEO?EECE'EEBEWEíEEh~EEEEM^EEIEIEHEuEǺE}E`~E EpE E4EXEʬEEéEU E2E$EEEEPYEE:E1EuE?EX]Ep>EXEEGrEEEE2EE E}EyxEUE+FEEEcENEEQEF-EEEfBE!EH)EEE>EEEE;EEEE ElEwE@EE AEEJEEEkEKEEtEEEd=E?MEHZECeElPE EE-EwBEHELE\xEnEEEE(E,EE E EEEpFNFBEeEE:EEE*E$E:AEE\EEEcjE$EEx'EFEjRE6E{ECEEgE؊EUE]E`xEيE4E EErEPEkE4ECnEVE E!DEɞE&EEE&EΒE/ E"~E 8EPE1ECEE1E&E QEEECEHEEEEE}EIE EXEE$EhEEVEzVE Ec7EEEy EEߕEVEwE}TEEE9EnE۝E EԚE&E0TEieEREEaE6EFEE>E[EE9E/EH{EEQEƀEEB{EBE]GEEEREyEElEnELEdEE=EQ&E}EExEEznEEEEGBE{OEuET8E0CEjEˆENEE\HEiREnE#E&ErE4E1ENEEEcEhEdE`Eo EEbEŹEb]EǏE?#EE1EE?EEoEEE'E^E4E)EEqEhEEEYE)EEEgEEhEJEE GEEsEEE{EEyEEE#CE0E E`gEPEE{Eu3EwE}E޲EYE+EE`EBE EzE_EgcEE\E3EsE6EENEOSEEEENEEEE)EEc!EEVtE~EEVE،EsZEE`EOEREE37ETE EREEGEE!E3EEEEEFEIE_EShEhqEECEEwE%EfEEBE EE&E/EKEEEEwfEiEE;EǢEEE#EEEC%EKNE:EUEgeEsdEE.E>EEEwEEE^EE~EgMEi EEzNEEQEE>EbE7HEuE^EEEGEEr#Ek.Es)EEqvEEEbEeEE%EEEEEELEVEgEDEΊEEBEbEyE%EEirEQE`EE[E EfEc2E^EE EErE/EEfxEUERELEdE]EE9E^&EUEEaE4EjrEEEEEFEϘEɻ EOEEW_E]ExE.gEEE}ELEEIEEE^E!E;4EEFE7EEEXEvEEERE{WE!E2E]EEfE2EfEOEE2E7EEbqEzE^XE kEREEEeEEJEiEEEsEGEEmE7EO&E)ENE2E:ZEE EEEEfEVEEPE2E}EEEE:E(JEE|EoEC!EEGEEE;EEVEWEEEEzEEEqxEmEEEEEEtEE EEEEEEEjE[_EõE:EE 3EEs E EŏEEOEEgEE.E EhEn=E=kE1E)EyEwE^EE @EļEEuEE7EoE>EZEEyEzEEZEHEhEZE EE$EEm>EEEE EFEOE0EEE[EtEǾEEE*E EE:E&}EE;EEEEo"E@EE!EE2EEeEEElE.EEEEJEEE3!EEEEEEIE6EE$$EoE;EE*ENjESVEhyERxE*EE2E[EeEEmE:EEHEEEE6E|EpE6EEE EWE7E#EEwEYE=EyEEtE>EEE;.EE˲EEs,EE3nEEEEUEc\EaYEEJEEʏEELE[E0EE E03EEWbE[1E7EEEEu^E,AEOEElEaE3#EEFESEE}EZEfE E!EE/%EEE|EEE~E|-EDEJsEEE6E>E2EE E-E#E EE9EELEީEqE9EcEƚE. E~dEWE#EEE3nElETEUEa,EELEsIE9YE&EEEEEdEEEq5E6EEjEEEE^E|.E2EXEaEEEv)EbeEpEJEEEEE EIEEE7EnE%-EaEE{EETEʼEErEEE:EKEbEkE+EE+EE;Es{EZEqlEEEj8EVEzESE.2EEL@EEpEE0E*E)EEEE-EBEBJES!EXEEHEE]yEnEEZEEEEP1EEx4EE[EuEhEEEEz:EsCEEvEEUEy)ExE>EE'E nE.E,EEE ^EEEGE3qEbEE~EEհEtE,MEWESEEnEEsEEw3ElLEOEE>EfE2;E^EEjE*AEEEEsEERoEc>EEfE"EcQE2EwEEEEEܑEEE$E~EsE`7EEErEEE=EjEeEEEEeE&E"EEZEAE~UEEE^EȟEOELEZE&EIEE:EuEEaEEռEEXEEwEv7Eh(E7EbE7E6|EbE%EE*E\&E8WEEEEEE&E!EEEEtEEEE*Es Es-EtE_E E@E8EEXEEtE8EE"E E~EEpEOEa!EEEmE&EdIE2E!cE$EiEfEvEEE3E,EEEE EEBE EEE+bE*EDE>EEEMyEE`EEEE_EG ENEEPEEYEsEJEE,EE*EpEEȻEzEE2E{LEE@cEEEqEsEE PEbE EgFE uE)EE EnE@EEEVEpEiEEEvEeEEEEI E?EEEQEgE8EEEEbhEE&EE&ECErEEgEyEzEaEE}1EEEE;LEEtsEEE:EEZeEmcEfE E~.EE E|{E8CEE_EREElEE7EzEu`EfEpBEȳEYE EEذE0EEEx#EEOE}E-EgEbEEExEE2ECEEFE BEEnE^EE͡EE8EEgEEEhE0EKEEEXErTEE!Eh E5REE2EEE E^E)EIE:EEu>ELEfEE*EE E^EEEؒEEEEKE BEE#EE?EmEEnEEEeEEEE,E~SEVuEE!EdE.EEEEEEjEEUEENEe4EPENExE̢E`ESEEE6E0EnEuaE3E(EnEdYEz EGE߰ECE0EjEEE`E{E2EtEGE@E4EEEUYEvE$E(E"EREEPE lEEۼEEECEEEX"E0E}DEEqE}EE E&E.ZEE7?EnE/`ErE<=EPCEjEEЮE*,EEEEjEpE'EkEnEǭEEE&ENE2EDE=EEsEOEEnEO{EEExjEHEEREE EbEłEEVEЮEzNEPE]EknE%KEE3~E6EUrE_EEE)EE>E~EvzE1EgvEEςEkEE۽EE̱EyEEREnE^E{E`EE_E AEzE=E'-EnE+EREWE@E#EZEIEZEr]EE9#EENEEEj/EExEWEExEEEOEZEEYEeE*jERELEE-EFEE~EsEkEAE}Eh7EuEl&EHE56EPEZE*EXEElEjE\E}EfE(0EGE!E EFEPE_E3GEVEEvEEE PECEx)EEbEE6EE2EyEDfE ~EEEFEEEuEEME MEEIE^E EXEEH@EE[EEE1E7 EE`EE|E:E.E?TE EE EXEAEVE%AEE3NEw'EE+]EElpEqE#~E[PEEiE)EEE2EE9EӾEEnE[NECEbREVEaE{EEEESnEEvE!)Ey+EmEE8EbEIEGEEEE@EEbE.{EQEiE1EEqE3EEE5E E#3ElET0EOE#E\EEEE8EaEOE)EEE/NETEdEEZEEVEEEE+uEEzEG;EWFE;VE E9EE+Eb1E/ESEcOE+jE/WEEI.E]EEEVE0SEEEEmE8E]ExER5EEEu:EEBE͞E)EEbE{E"EgE4EEE EEvE}*E&E~E?EEE:E$EREhE.~EsEEEEEEEEwE(EEvE~E&E~EEuEh5EEFDEyE}E4E EEEE1EgEbEo>EEnEJEE:EIEwE+%EEIE[E EJEE,VEKEAEERE#EEEZEk}EqEoE)EEEEE \ESE EE&EECEE-EEE(EEEE+NEREEE\E`EraEcEAEECE3EEGERE,NENEEEE3E+8EE[}E EEIEVE#2EE[bE1E{EEJnEE$ENEzEEE8EaEEEE1EEEhEQE{EEE%MEEEUEEE4E̿EyEEEMEEןEEEE}EpE@E GE]EкE1EEE E@gEE2EyE/EqEE^EENBEE.E E0kEKEEbEX'EWE$DEn9EE-EzE6E>EqEEEOEEJE}EVE E EpvEE*EW7E^E.EhEE"EkPEzE^EBE#EEjENEVE:E4E}EsGEEEߞEENE7wEmEEԣEUE NEp&EEEEWDELELrEIEEsXE_EvxE FEE.E zEbEEEEdEEoEEBE_E+ZEEEEEdEݒEEEEQEE@8E EEEs|EIEEE5EEEFME/EpaEmE`EEkE E FEEEEEeEEMEEsEfEE%5EE8E EEEXEHE_E#EE&2ERiEwEHEHEEDE>EfE?EEaEEɖEEEEqEfEEEEEEEEkEaE|Eg3EzEEFENXEEED{E<EEEE)EEE/E E{,E&EEE E@fETEzEEEP.EtEEE E-SEEMEEڔEE#@EֹEuEnEE;iEcE0EEEưE$EExE#cEnE?EEEmEE5EEEEEEEbE9EyEʫEYE^EwE!EjEhTEMErE#tE=EbbEEEEEEcNEIEZEE EH4E2EE[REwEi"EAE"EFEE|EE"EEE&EEExEzEEUESSE:EEEEE$EE#E0EE-E.E8EloEEEqEEEE3E!EEEEEozEeE,EE*EQEvEnE=Ea EE\EEQE^EڲEEVE/:EeEWEE^E 6EvEEKEEE [E~$E;4E%E EfE2E8EGE EEɃEOeE}EJEhEEE2EEE.E'ENSElEE!EEqEE*E.EQE[EXE,EjEEXEEEhEdE EME$En}E<'EENE>EE:E=E%FE?EEEE9EEEEEfEڪEYE2^EtbEE EnEE^QEEh E`EE.EdEUEEE EqEE?EEenEkEVEESE+_EzE2EZE sE8EE+EvEUE EBERE&E4"EE'E]EFlE0EEE1EE4EbEH|ErE6E=EEEEE'ECuEmEE~ELEEEEͻEgEE=EEE/E6EjE8ZEOEEؙEEE3EsEiE3EEEwdEEE|EvEZEjJE_EE5EFEhfEEEE@LErE&nEvE@EEEXE ?ErEE~EbEEPE$EDE-EEYE[EE63E{EdEoEgE}E+EַE E6?EEEEOEߠEAEp^EE EEE+]EEEEqrEETfEGEE$EBEEENE(E\EGEUEEiEaEEEEjEErEENJEYrEaEbfEEvEECEd8EEE;EdEE;E7EBEkEbEdERE%E4EZE(ELEDlEEAE8=EHsEEi:E E(EEE9EEE/!EsEsEEPE"~EaE ELE/EE/EEEByET!EuEEfE[E>TEIE2 EgEEjYEzE_#E(EEEʪEXEEE6E1EDEyE_E~E'EE:EaEIvEQCEq^EE2EڹE+EE-E̵E'E@E!EGEE,7E$EbEEkEXEMEE2EENEEEE4EFEiEE/E>E6EE{EEEE1EEE4rEtEEFE.%EE.EREEE$EgE EEZEE˺E?EES5E3EE^EENE)EzExE5EVEEEKEsEE=EE/EEEEEEEEVE9E EEQEwEvEEEdE=\EEEEXrETEjEEy5EQEtE)EEE;E|E.E EBE3EE~EEEEE{EEj-E4EWNEEyEREүErEPE43EbE Ey4EźEܡEȂEZE8EEEE EzE9E'E"AE(ErEE4E1~EE^+ETESEE ,E-EEqE*EEE^E5vE/EEEETnEEE^EmE EEj`EEEI"EYE>EbE8 EEEGEE:E%EEBEٶEEEEEaE"EE;EEEEWEE_E\&EEEt%EJEE.EEFE0EE\E`jE[E>E˶E] EzEEOEEEhE$EVExEEyE]E0QEELE,JEERE@*ELEAEBE)2EElEE EOAEErEuDEEQE EEPEElE;EE9EElEEwEE'E;EGEEwEEVEEEE[HEEiRE$EEEeEmkE#EEQEENE^ECrEkE-]E;6EE_EE*E&E EE'E&EbEEE~PE?7EEzEr3EgiE0EE7EEήEEwEE+EcE^xEEK EE_E;DEUE3EEEzEfEJEA3ExnEEPEEEE-EE>+EjE,EsVE^E`EEE`EJEEW~EEoE҈6EV9EÎEEp EEEE&EyAEEXEiE'E#EEEEEѶFsF JFq=E@E5ENE2E>EEZEE1EEEqEFEE@E E/EE6EEV:E)7EEE]EEE}EE/EEEE4EREJEHEtEE4EjEbEvEBEJE2E׳E&EEEE|EE EMEEEYEjE +EEE E8EnEwE0E6E>oE6EacE%E>:EEEE>EsE E{EEEEEEEE#E~EZEEEEEEJETEEE~EfEVER|E@EEEnE1E8E96EVE'XEbzEE/FEeZEBE5bEE.E!EkEtEVEEYE;E>EENE{EE|EjEC%EnE}E0E'EE|E$EEXEEE+&E'E6E{EOEE>EEgE%EƭE2E)7E E EGEղE:E.E-EEEEEE3E2E~EEEE,BEUnE|nE?EEoE;}EzEE:E8EFEFEE,E EoE{E;EEEաET9EEfE#bE:E:GE~ErE &EԦEE{E|EnEXgE6 EkEE1EEEEE/EaEEEE E\sE'EEaEEaEE EOEE҂E ExEş@EEE<*EQEE`E$#EgEnEEEE/EHEֻE$E*F bF\FyƪF[F "E2EȎ EEBEsErEkAE-XEe'EGfEE4E Et~E_|ETEEbvEEE=E43E?E6zEEEEE>6E"EE=EEKECEGE$FEEENERE=E EE%EpEELEE_>EEhDE:EEE޲E4EEE^E2E.EEo4E|EEE9EELEAEME9E/fELEE6$EKEW,EE^ExErEX4EEvEd Ev(EEPEpE}EAEPE'}EEEFE|EEhEEEEE)2E{E)E>EEE EIEEȐEF!KF[Fy"RFZF ECEȤBEJE EPEEEwEEEEEhE[E"EӗEEEE/E_EE>YE9EiE,uE&E BEE`rEyEKEMEoE&EpEEEErEEjErESEEfEEEZEQEEaErEEՆEE=EEQEsEEΙEAE|E:EEE*EEEXEEEEE.EfEeE ET{E֞E(E6:EE$E|E%_E@EWENElE8EEEEEE7TE=EBEJ EE^dE=E?E,E6E>EBE~E|EK`E/E EErE`E!E{JEtBEώEEsEdEcECDEhEEEnE EEEhECEoE1EEiE%EQEVEߔE&E)E EHEE EJEeEPEEEEEEVEqE ES6ENE٥E^E!EE"E/E$wEVEMEEPFE7KE`EEEtEEE6E3EvEEsnE;EE0ECE:EEGErEqEEE EEE?EEEE+*E EDiEEu6EFEgE9E E\EsEEgEoEE E{E(:EbEEHEDEEEEϕEUE`NEFEÖEO{E®EE\E:EoEREEmEEjEEjEHzEkxECBEqESE_E EčrEF ?F0:bFC,F0+'F E^E.EhE1EEE~EEE"E ~E!EEpE~EEsEE; EEEEENElEEɍEEl?EEPE&EEEEEEZE<EkEBEEBEEEErEE{EE!E}xEhE'EvEaEi6E EEnEEEExE=E/'EE:EAEEtEE9E;EEcEEEPEE EEE]bEnEEY;EVPEbE-EѱE.EEECEEEEʴEE=E7E{EPEE[EEmEA3EE]E>3EޢEEpEUEEi EcEJEEEǖE^DE+EE͐EE]EE&E^E1E7EEZEE&EEE>E2E E EPEEnE.E!.EFE&Ef]E$MEEE[EE1EEEuEcEwEFJEREsEaEZNEEEEdzESFE^EE^EElEEݾEEEkE)E3EEEM#EEbE^QEdEa ERE+TE\zEREwEESEQEEEibE0EEEE$1EE&EEE @EY"E;E\fEEEEʁEdE`EIE!OEXEkEH4E'&EWEEE\E'yEˮEEƾEE)E@EaEEvEgE>EcEFE`E EEvEE#EEeE ZEE^CE}EEEEEoEE8E%EfE E١E+E&EESEMEEEEt?ETYEE+EUEEE*REjEtEiEEEE,ECE-EfEEDEE0EE E[ EfE&EEE8lE-aEEEEE3EE>EgE/IE~E*E EE­EHE EEZgEE~E]EE*EoETEhEEEP_E.E,E=EhEEE UEEHE@EtE߶EEF>EEP EE_E^EeE?)EE6EE5dEZE EE_ExEEEEnEElEvE?zE#E[EN,ETRE?_E\EH&EbEsEhE3mEF`EIEuE) EEEEEg@E@WEEE1E~aEH7EJ^EE"EEEElEY Ec{EJE EEE(ESEEEE)nEtE>*E{ENE-EE%EbEFE6NEHEʶE%ETEfSEVEuEWE7EMEEՐEܳE EE EEEER>EnEf"EEEE}EyEEE+EEE4EcE[EEEO EEaEEEEEE~uEE;E0EETE OEGErEEE0aEEqiEE[oE EEELEXE%WEE[EEDEE4SEEYEvEPEvENE$IEXE1EEEN[EnEE;E@EvEEuE=E5EE0EEE 9EEmEGEE?E(EE BE\E-"ENEbE-6EEA&EEEEREEEjCE-EEjE+EEGvExEETEjUEEE0EEEEENEEbESEAEE-EEE9E-wE[EE}EdE+EEEgEPEEEEE|E%aEaEE+E_EFnE,EBE/EHE8EEVEeqELEEEkENEEEEvE.EE~nE~EEEy!EEL_E7EE(EAEE]EEdEVE=EEE^WEMEREE-E*EEEE4UE MEsEEE,E9E?VEE6E'E#pEUE;EE@E*-EEE[EEEfEEEf E| E`EE2EԩEJEEEEEEcEMESE EkEE QEEOEEVExE2E[EEEzEEE:EKdEE^EGECEQEE5;EtHEEEE( E$_EE1_EE(EqEEREEE$EPEEsEMEY~E,&E$pEDE-EME2EE8_EE ~ẸE`EEkJEYPEEWMEEEkEBEaETE#EE2ErEXPE/EElE$EVsEEBEAEEZETEEEdvEwQEvEE\EaEqERvEETEE'EE8EБEJEE}E0ENEREEEE EEPEEEEEtYETE8EEkE E ECEEcE9E=AEqNEE/uEESEIEUfE3ECEEExE׵EۢEjE@2E7EdEEE EE}EEmE*EEuEEEEEhErE2'E"E"EErEE\EsEEzEEE EE)EE+EEEEhIEcE9EMEUE%EjE!EPEuE EEEEKEE4E=@E|EEEEEEj$E5yE[EEEiEE!E~EEK5ESVEEpEuE^EE׶EEElEFE$EE+~Em7EENE#EjzE(E\EEEz E1Ef|EQEEEE!EEE EoLE֞EEEfE@E#?EEEپEYEE7E'E{EXEpE>EaEEEEEjE?EME+EE0E@E4OE}EBEEoEwE,EEE[EQIEExEN1E:-ER9EEEFEZEEkdEkE EUEEE YEeE*EE EE1EEEELQEZEjEE^E$EGE\JEE :E-E:EE}EKEjEfEEMEH E\jEEͬE)oEEXnEEVEmE0EGEJEEEbEEE EEZ Eb/EA:E EOkEE*EE"EEPE`EE6EE@IEQEaE+EEKEE {EoESEݒElwEӱE ElEEYDEELiEEd5EE5EnEEEE GEE:E5E^EE9E EfEECEE3E@E0EdEZEERE.E qEEEqE=$EE3EħE߸EgE?EEEmE2EiE)EqEdoE=E*1Ek E vEENE .E.E5E:EE EE#=E*EԡE[EEZE%?E6EĕEQEU?EEEAiEPEEEWEvEE>EEEiESE,E EE2EEcEE+EMENEZjEkEEEoEEWEEtEzE:$EUE'EtEgEEjEL:EE^EElEEEE9EVEsEEEEAEEEEeEKE"EXEEEEEƄE5EhE$E ECE Ei\E EEEAE͢EEdEV E1ECoE"EbEg2E"E_EE̬E{EEyE vEtE*EE+SERjEEE:EvEEEFE:ElEE>E.E!EmE@EZUEVEǑE<E| EEEE-EdEE(EESEJTEfE˷E E|E$EE{E))ESEEEAELEE9ENEEGEEEE!E E6EEEEEYEE-)E{EE:E@EEEg~EªEEEΗE EE7E*EodExE`0E}E5EEGfEjEE)nEEE EF|EyEhEINE6EγE_EݑE.{EE?EzE"E}EE E^EmE@JEEMEE"EaEE+EEkNE&EdEEE3)EEtEaE5E\EEӁEE EOEEEEBNEEE5EE@EE EE>EPEEZE;EFEE/6EE[E8EzE8EPE"E/bE CEEg8E,EEEEE"EOEEEED|EWEEEʋEEXE׏E\EEE XEEE%:EEE?EmEDBEZEEENEEyE MEEkEEKE#EEtE/FE/HEE)E EE4ESBEESEvE)EE?E E E>EՑEXE^EEvEE< EEHDEbEE4E8E E#EEgEEEJE}EE*E EEʨEBEےEEE)E"rEñEEIE%&EkEEE·ECiEYE>E^EE{Ea&EOETE.EMEްEEJExE[EDESEEE+EEEEE"ElE?E#tEfEEfEfzEEE)VEZE;EIEEE>CEE3E%EEE1E?EEEEU(EGZEEhE E(EڤE*7E~EEEzEE E4E%}EA/E_E E?EEEEErE}EȊEƀEdE E0E'EEEE$EBEqZEEEEEUEЌE(DEp*E_EEEEETqEEEEJOEQE>EE}SEEvE EzEEEEEEE>EBE}'EEEEOE}E EIEHEߺEEC}E8vEEjE\E+mENEھEEEEE-E!E9E.ERrEE*ExEoEE]EBEyNEE9EEC#EEEY EcEE EOEmE:EqEEEȷ9EɁE:EʼnbE߬E7E.E;EzEEELEppELhEۈE +FEEoEEZENEEEE%EEEEaEؒEEEEEoZEgET%E\:EEEEE2EuEEEBE5E(E9 EELEϐE7EzEԴEiPEf^EEXNEZE$EOPEzEE?jE`EEEEEhEbEt(EܲE{E@EaErEXOEFEHE̔,E2}ErEE?EREYE&EpEE{eE'E-F!F'kEEEREE.EsEEP_EKE}EfEEEEFEEEDE EEEE%0ElEEE|E~zEESEEKE EXEFEE$E_EkEPEE>E1EtEfEHLE_EE%^EEJEEkEKELEyEjE"EE^EwEEAHEEE3E2EFF"zFbE~EӨ@EEEZEIEE#EE ElEpEEEzEEEEEME}E*EEE3AEE!E9EETE7E `EErUE˶E_FE[EE%EEijE,ZE}ETEDEEEOE}EEfEE* E EL[EJE(EEE-EEEvE*zEdEZEEOEcE\EEoEEvErEEtqEzEE"EEӣEEE3EE%EEEE4E<[Ec'EeEgfEmE}^ExEEE-EeE8E,nE)E7bEEEfE1]E?EfE:E)E(EE7E zEE!E?EEECEٛE_EEEErE;EEE8EEEݫE`E"EEjErEEECE=tEm1EE{HECEETEE+pEE4EE|~EMEnEE?cEY.EfEE{9EB:EE>E7vEENEhEōE>EsEĥEwEE6E(E(MEE EkElE̴EE,vExREUEں.E8F F@FT EBEEEfNEEjE7EbE.E%Eb^ELECEEXEQeEZE}E`E;EߎEE-ETE;EYEUExZEEEEZ|E~ErEEEE 6EE+E"EnE^EREwE>)EEEO EEEE42EFEhEܘCEEYEEWEP6EtE^E=PEnF(ĴFl]FğFo=F,EZE˙EeEE0EEEEyEߗEEGJF)}Fe&F EfEEE՛[EbEEy"EEFFl?FPE@)EEEE EE[E@EeE EEE+EE.ENE.E1GEvEEWEEEREp^EEiE0EbE7EEEjE׈EE`SEEEE!EEIE-MEPEE&6EE7oEZ&E EEEÞEK EE͸E;vEEJEEkE¤EE$E·E5:F"^F"~F4n8F$F(E4EvEEBELEQAE vEwEEEEEEEgQEeE]EE{EQE EuEEME&EE?EEE9EEE;E TEEExRE_EwEmEEEEړE EE#E@EEEKEKEEE*_E6'E-E$EME;EEEEEŒEȆE|]E7EijE/:EkEy#EMEwE6EaEEdE@EopEIEzE@EerEMEEnAE:EYEELEEnREEEE,EEnE|?EBE_E+E|5E~!EEVFEFYEEQESEE! E$oE՚EDvEAEEvEqEfEEȝEVEݯKEmF ,F#,FI,FxBGj`Gj`F$^FVJF-/FEuEEۧEHEԈ"Eי`E*EF9F\w>FE+EMEEnEQEEEEAEEpEEjE|E81ELE0E*EqEv/EE qE_-EPCE&;EErE_E:sEbaEc~EE8ErE4EE^E͜E^EE"E+E(E EE7EzEx)Ec&E&EEkE[EʠEٱ`E'EӜ+EEE}REfEEETEErJEڍEMEE+E EHqEEvsEMEsEEEUqEEbEPpE7EmfEFEE'yE:EBVE E|?EEEEgEEEkEVEEENE*EEEE[;E_E/E~EEÂE#EEE@EuVENE|EECVEEE{EEEbEE3EEݑE2EEEZEm EEE/EEE*E,ELEEJEzE;1E#EsE,E+EUEEEEErEsqEE`Ef@EE$EVE+NEEHEEOE ,EDE[E8EtEEELE8EEZbE!EvEE9EE+EmgEXEƔE EWELETEEE E.EZ(E4EE/EEʴEvEE jEnE5EOErERE8EuqEE#EcEEoEEEEE3EZET E.PE-E&EEEEq=EE8EbE̎E'EEEEWE$%E.EE*LE2EEEEaE8EE}EEŗNEݩEc(EZF܍F(FNFގGj`Gj`Gj`Gj`Gj`Gj`GFF6`F YEKE_EEJE~EExFF#4EEIEzE9EEEEE`E5EMFF 3FêEE EEEƒEEEW(EDZE EBEE>EbEEE:EBEEME EE=E.E8;EidE+EWEgEEQvE"EErEE#pEE+EF EGE jEZE^EEE$EEE9E,=E^\EEEEEEEEzEREQEE||EE7E#E9WEEEEYEe7EE2EEFEvEh#EEEvnE~EEĞEEEE%0EUEgE.EEE1,EEEEPEiEELEE_ZE| EoE"2EdEBEHEEEBEEEIE˽EXE)NEEkEvECEEBE,bE#EEEtE EE?EEn ErE+EJE![EE EUEXEuE+EEVE 0E>E EE#EOEEq3EvE"EE@ EMEEEEŔEaE'EE$RE:EEEEѾEEEEEEEOE}E:EEsE6E|EIEJEEEkEENE[E2+E~EEPEGBEEEEE]fEyEEE,jEEHEAEE2EE°E E7mEƇE7E'%EٴcE;F FF7ɏFG'>^Gj`Gj`Gj`Gj`Gj`Gj`GFFFHpF;EEEصEWEնrEwmE"E FE@EvEKEw>E>EXEЄEEEŠ@E.F_ F F-E&EǀEEEmE{EE8EgEEEE_PESEGE&E#EBED5EE6EEE{EEFEEE0EEPIEJfEZ1E?EVEEEūEE^E7LEEEEEqEkE EjE`$E7EʤEqEaEEEEEٓEE|EE`3EhREmE( EAEEZECEE{EEE8EEݦE; E""E$$EEE(E [ErEE{EEE@aE|EE`"E@EE*E<6E# E!OECEA E׵EZE+EE-EEEEUEE.EH E#EIEEExEEE`EEEb EEE EWESE E^ExZE EE?EE,EEE-EE tE;EEEEEͺE2EHEJ*ERtEEEEElOE]E5EEESEEE[E EjEpTExEzEERAEKE:E+E EEEE EEE'E/^EEE EEOEvVEEInE5E+EpEǧEEEE\BF _F;S-FG2FyGj`Gj`Gj`Gj`Gj`Gj`GSxFFM$~FEJzEEgEVEұEϘEJE8EGEEtEӌE@EaETE0EE/EEEEysE2EE¾EEEvEEE6ECEREE]E=EREER3EEC]E؄EXOECE1uEIE}EE8EE:EEEE;E EEE:iEPEEENEE :E+BE EE}EREEmEE'EE EXE1EnEcEmTE>KEEh!EyEX#EӺEE6E2EoEȖEEIEeEELhE%EPZElEYjE/ErE EE EEE:EEEgVE ~E>EpEEgbERE8EPJE>vEEEE0EJE EFEEEpE2EEEEE2EEEvE\EJEtEnEEKE/ZEEuEwE9EEBEEE EJEEEE^EHE"fEE6E0bEEÊEE+?E͡EeEF^F1xRF$GWGj`Gj`Gj`Gj`Gj`Gj`G.VFF@6F'E8 EEEϰEn+EVE[;EӉ`E#E)EEE5]EmEovEbEEREEEđE!~EKpEеEEEEEvEsE)EEE\EEE4EwE3REEiE8MEEE/3E{EdEEBE7?E;EPEkzEǢE}EEĽEE'WE]&E܄EJE"EEEE^ETEZEE)E5EEtrEGED4EpJEEOEEME!E|E,E0RENEuEEEEmEjE+rE#EyE}>EE]EEzNE/E?EYE+2EEVEE*E#EӮ E{E[EϚE1ELEEE+EmE\zE$EEE.EІEcEEYEEEE$EoEE;EFE>EKE'ERaEENEPEmEhEEbERE@E}rEEQEEE/EE+EPEoE}EEE EwEQEE DEE,EcEE*EE,HEjEE{ EEE2E(EExE EME|EjEyE´]EūEʞrEEbF{.F̴FhFϐGPf]Gj`Gj`Gj`Gj`Gj`FFͦF)FE EڃEмEE>*EȋJEʁEˬEΕvE0"ESEEӢETEqEGEaQE6E9E!ElEFEGEgESEsxEhhEErE#EEwESEeEEEEEE7EEE EEEyEVEΖEEdEEXvE]EHiEEEοEE@EEELE<"E5EEMEt3EE EEGE*EEEEEiE$*E,ETEEE?EE3EcgEpEMEE?E%E@EEEvEEEE.EcEEENE[.EEoE)=EE#EEyECECTEjE:Ej4E$EWEÝEʂEӴ@EPEFyF;ٱFzAFGj`Gj`FFFG&F,F2RECEEE&EE"EEcE6E|EE0ErEoEEVEEdE?ENEqtEE6EVEE.EIE EmxE{ESEEEKpEWECE EpEx7E3yE8EwEELEEE'hEE3EEEEE IE/ENEu?EEEcE_EE EEHEDEEEEE ^EtEjE4\E"EE_EEEIE$EE&EWE:E3EE EEE@EPE+EBEE!EREיEEEE+=EdE}E]nE2EɠEٵEEEE(E2EhsEE,E"EeE2EEESE^EE-bEoEOoE+E:E}E[E)EEJE]EECEEE5$EEVE PEPEE@EBEbEE>EEEEfEE)mEEElE/E~'EnEEUE!GE:EtEEOZEQbE`(EEy;EhEEcEB!E&EEKEE jE/vEEEEE'Es)E]YEGEhE_EENEKEREi~EE*E-ENEEonEEC-EjEZE)EaLEE׫EEEREyEE``EEEdE"ELETEYEEM(EEEE&EqEEEEEkEE EEE^E #Ę|EXE+*EFF2F)=FCrGj`Gj`FHfF.9FqFqEEE]EɻEbE¥EmE*E=EEfBE7FETEE~EEEEpE=E EE^EE El_E"EVECEEnEE.E8E&EEEPEOEE$EuE E-EBETEgEъE%E_E4ĖEYEEEIEsJE+E!UEE3E@E &EEECE{E"[EE1EE̸E_EiEnE@EEHEDE EQESEEybE)EzE EEE1EzzEEt;EMEHE"EckEGEm$E*EbbEE2EUEaE0EEnEEECEE2GEEEECErEN8EEiEDEEwxEjEnEEEElEخEEcBEjEE,EEEE'E9EmEEEmEEEEE6`EwE)E(E@E<=E4EkE=EExEEE5EEaE'EI=EE`EE[ERE(E9E$E=E0-EExE{E˱EEyEPEEIuEENEEtEE`EE}EMEE:E#EEKE1E5-EEʥEEMEJ^E$EE"EEEYENEu9E¡|E'EV3EDxE#ESEhEENMEkzEE8EʔEw8E'EREE;EEEEElE"EKE RE!EGEBEAEaE.EREE>E."EEVIER*EEEϖEEEEEfEEZfEUEQEEEm~EqE'EnEk8EE2E8Eq8EE5EEEE'E!E1EE:EECE/E;EEdEEREELEhE3E_EWEjE]KEEjEEEEEIE-E7E6E*E4EJEEEEEPEEJEIkEE!EEEEESEyE>EE-EEEEB EeEE[MEPEE.EEEEE[;EEnoEnEYEEHEdiEPErE`ErEEEMEhDEEE-E IEEENEaEE`EKEEE EE+"EBEEE!EEEE EWEEEؓEEE"EZEEE:fERECUEOEEFE>EhEE@zEGDE#EqYEE#EEFQE/EfEѢE%REBEE%iEYE/EEskEEBEEU0EE{EXbEfE-EjErEbEEE^E EMEtXEAzEqEEXE^EbEgEKEE?EsE\EEE'E EGE}EnEnEE9E:EE¹Ec"EȻEEйE7EEԎvEeEҁE]EBEȌ,EoE?E EvEEEwEgEwEEE̢Eo\EnEEvEE~EcCEE̊EEE9EEETEQEBEEE-EϐE4QEEJvEE(EEwE7ZEZEFE\E=bELEEEEE7EEvE?EՂE{E^EEE~EENEKE*4EEKEӋE' EEӦEE EEE DEEME-ENEfEEEE`EEEE<1E%EE5EP5EpE&EE+EEE9E4E!E7 Ec7EE fEՕE OESvETE:EEFE E6EE "E>NEE$EE1EEE?ExEEmEEEXE_E½EBEEVEnEEEPEEtE=EE;oEx EkE]2EKEEōE*EETEaE'E)E3EZEjE͈EvE%EcEEE9E!E_EiXEEmEsSEAE.nEEE EEnE>E~E1EX_E,E EEEDEEzE'`EE^ElEEcE EEk]EEIEEEuEq(EEE"EENXEEkE؈EtE /E4E3EEIWEUE8E9EͲE&EKEgvEE-EkEEEFEEE!~ESlE"EEDEELEaEE:EvsE~ETEEɍ4EqE%rEmE:EսbEҀ~EʪEExE15ESEEBE}EYlEL"EEEEpEElE!E>ECEE:nEtE$lE\EEEaEy&EE-EɱEhEk'ETENEQ:E˕EԗEEEaE>EE-EEMEEEEE8"ECEHEEEENEE2EEEDEpEEEE4E.EEEYfEPEEExEPEEEEEjEE E EEEpEEEPEēEEEEELE0-E,dEEZEEE.EEX EREZEEE`EupEtE6EEvEEZELE.EEE=EEVEEEGEE)EEvEkKE9EEEw0EEEn\EcE/EӴEEELEEoEEEE2E>EOGEJE'E*JEVEeE SE^EnEtEaE6E4EEEZE:E6EEEEgE#EEEEEEQE9E&EEE EAEE9EE3EEE3EGEhEJEfLE%EcCEEEmE+EEEIEEhoEEaE ^EE?EEEr.EE5^EbEy;E`EE5EE'EEEE`E;E55EEtEV.EE^fEEE׃E4EE͘E2kEQEhEEED(E EZEnE8ELEQEEEEەEEE8ExE^E4EEEE>EEnEP\E:EUJE?Em1E(EErEOjE+E(EE;EfQE>EE~ERE7rEME*EEEWEETQE.&EEE7EdEE^EEYEEEtEE;1EE"uExEyEJE[E}EaEptE^EE EEEfwEE|EEE oEjEl@E>E\>EEEE*EE#EaEEwIE}IEEE8E%fEO~EEfEJEƟEoEEnEELEEԉEEXE*NEP&EÝEEEEMyEaERJEqEL0EEPE'eEE)EEoE$E6E&ETEEEE9EǐEE+gEEX E[EqE|E5EfcEҵE_8E|EEEdEEEEE@EI_EKEEzE EvoEVEEJEk>EEYJE"ESEEhVEEE.EE>.EVE9E;vEEEXEEHEŪEZiEEjCE|@EE=qEEvVE EFE"EEEpqEE2EKE3vEhEEcEyE8EGE,E@LEnEE~EE=wECRExnErEbEEE EWEoE7E)EkE2E[ EQEyEJEIE"EWEE"*EP_EEiE$.E\EKEEܻSE]F7EEifEE ELE#E~E{EqEHEEEE6rEbE&E!EE!EExEXiEQEGEzEMEV'EEsErENE'GE?aEnE-EE*E`QEFEaE3EwEEERREDEnE~E*EEXEEeEEEREEEo3EE $E9EEF1EPEEUFE3E-0E$E–EEzE]EE?ESE:>ErE7.EOEZEE`EoJEE-(E}EiEBEyEEEWESUE7HEEEAyE6fEE<~E(EE EgEHEEeEnE4FE*KEEYECE2EE(KE|EB4EfE E|EEE'EɗEO2EEE VEE2EE1/ElEgELE.E#EEEEEEE\EEE)_EDEoE!EtE*EvE?E%:EEEEEbcEvEeEMEt]EE-E9E_EEEoEwE_EfE%EjEELE< E7 ERE3E#E"E,VEEe`EzEkEEE"E Eb>E~DENER EJEEE_EXEyE'EtbEE#EEE.E,EuEEEEEEEE$EEs:EhEQE E,E XEgREME(0E'Er^EEbE4EEvE E@jEEEEEE}dEEEL~EE8EgE"EEH FOEEgEm~EEREE3EWwE!MEFE#E2EqEEEEEEBEELEpEE EɄEhEeEhEEEQnEN(EV"EEE}EpEEEEEESEUE&ES0E EREPEEE@$EEEnEdEDzEUE8EEIEENjEHEEEEE3E+ EENEGEE2~E|EE~E{#EEEE>EE^E8ZEEEoEvE)E>E|E!E~EgE<EGE'ECEVEK ES0E`E(cEEIEќEE(rEEVE}EEEHENyEEuEEE"VEE!E )EÊELEEEӶEpEy^EsEE E_E|LE͘EE'EYEEvE EݖEuxEِEfEEEEjEE-E]EEIPEE:EMEW\EkE3E EE;qE:aEEE EE^E#3EEEvE0ENE#E{)EE1EEE݋EaEEEFUEEE-2E^EX|EEEE۫EMEEq3E EeVEKE[E% EnEE_iEZEEc#EEEEVE EpEFE~E`PE#EEgE$E/E`EEEE+E 8E"EɃEEEVEEE_wEE^EZE̊E nEpE6EEErEE¾EE EqEő(E EE鰮EE6mEfEMEE]E+EZE#EEEE^EgE-E%EE%EE`EhEEEpHEXEE'&EɄE.EџEE;XE-EŒE""EE7NEjEE6EVE^E}E#EE2HE E9ZE#{EE?rEJEYEEEzEEA9EYEmEfEbEN|E[E9EPEEEEEVBECtEE|EF EEEvEEpEE)ErEJEHEFTEBEEqEEEYEEEE"EEvEbE0EEEmEEEEzE"EEgEREME;!EEbEKE3EEcElEEE!NEE=EAEjE׭EEpE2VEEEPE|EuEՇEt E+>EE EE`E#EXEkE-4EsEEѾE;(EEEöEEȫEJEFjEEsEA9E2EKENELE6EnEE,E7EEoE% EFE ESE@E ;EbEEZ EEoENEE&EEnEEEE-EEfEPEqEEgEE8EqoEvEEa>EjE2hE EE^El6E$>EEfEE:EE}BEEERE-EӟEkEEE(E["EEWEvE6]EEOE=EEE EZEKEUEEekENEvESEE#EiE֘EзEEęE;EZEEbEWEEEZEeE?dEE EeE(E[EEQ6E:EMEJE"RENEEӘ[E{E͍EFC*FqEE厳EѥEÂEE_ EٓEEV>E8EEbE¯EE6EEIEiEEElEȾEE{JEgEj#E.fE_$EE3EEtEYJE'EkEi_E9EgE^EnEfEH2E3E5ENEEEpEsEE*E|E EކEttEEyEFE=EQEVTEE%KEbPEQE=EɺEEzEIAEBEEEn>E.EĐE5EEEGE;E_EoEEEQEELJE2E2:EbEXEkEEnE=EEEEqSEG&EǞEFFgFFdFNFX@2FEEEKEŎE..EE E"jENEӲEEdEZE5E EE!EEȑE:REIEE]E2E EjbEtEEEEEEIFE?'EqEE{EEi^E%[EۓE}/E:EEXgEE@REEsE}nEEE%EEEE҂EKEmE\E>EQEEJESEQEcEWEEE5E2EmE!EEE|EEE$UE bEEUEeNE[EvE:EEKEE/jEEfEuE(ELEgE9EUBEE>bEE%E}E%E?EdE0EsEE!E[E/EQE*jE7ExEXE[EfEBEEEM/E"EEELEEE;EExEurEJE9 EQEmEE.E\EvEkvEE.E zEVEEE.EۜE=vEXEzEEIE/EߺEE?E_E EzEPEVE@6EE\E+EkEgEb|E%E[E&EEEEEKEKEwE?EuEE]EE1EZE-EYE=;ECREEEEEoZEԙEEEE_=EEEGE(E\EEE EEVEwEEFEE~E E; EmEeEE EEeEEaEEEEEPEEEYEEREEҕEE:EEEE4E6.EEEчE}F;F_6F%G^+Fq F5F-:tEE˵EEΪEEEV+EJEέEE6EEREbgErzEYE EcE54EIEE>nEEefE EEC3E:E6EuE'EREEoEiEMEjEݢEEJ=EEoEUEEEz3E%EEEE}EjEErE?E&E:EUEE9ETBECEE'EFE ^EEFETwEcEՇEdE*E&QEvESEfE\EٳEEUE6EFEkbE EEsEEinEEE^EXE;EEnEBEEE+E}EEyE]EEEgEFE5EmEE+EEfEEEE3EEEjEEgEEEEENEYkEEƱEE3EE EqEEaEEE8EEJEE]2EEEE E#qEo.EEY EEKTEEE*E;"E͍EE E:ErEEEE_ElENE^0EmfEhE!ENEyEԲE*EQEE0EbEv7EEXEEEFEEEE+dE'E"pE}"E7PECEVxEwEȻEdE5E>EEEE#EEkEEבEbEEE?}EEEm`ENE'|E -EP EE{YELEEEGEEEF\EEEΦEouF1FF;GZFKFF%EՂEE:EEEGE(uE8:Ex(EE;bEKEciEAEEZEEEEEXWEEAEEXEk'EhE$/E]Er EGEjE۪EGEyE:EEE EBEE_E,DErE0EEJEuEh.EEZEEE!Ei(EE"AE2E2RE%ENEE3EE=EEKEY5EEE>E/EQEHEEE.EnEuEBEqE!E;QE$EϩEݞEEEEtoELEJEtElE4EEIE!E\E E E5Ed EEEEDEG EpEE2E^EEdEWnEoE4E&E&ElEkE?(E;E.EJE 6EfEE5EE+EE^EEE E2EED]EgE3E E,EpE"EeiE7EEyEEE.EEgEbE"EEE^E}EEvEE8EmEXEE*EĕEnEEEEEE'EXE^EE EEqElfE EԔE[ EE:ELEN E@nEWE0zEEޥE[EEEEVE1EZEEFEpEEEEnEȂE\rE;uE*EdEEqEEJmEKF SF%Z F/F" GFVEEENEE EEEn]EgEEEjEE7E9EEr EEE EED!EVEEEEyEWEfE EPYEEEEiEEE}E=E"EEA!EwERZEEESEEL*EgEnEtEE&E+EEE]EEuEE E8 EE1E,eEE`EE8E{E?E>E@EbME E-BEEELEH6EE E!E3E:E*EOEEKEE*EE&EEEEE{>EEEcEJE.EE:kEEL>ECEECE`EqE QEgEdEnEQE[EeEEͶE%EEE E~E"EEE{E#[Es EEE*EOvEE; EEgE`E!E,EnEEECEEE/E{oEEEUEE5EE{EEXE\EREXEuEE&EaXE3jEqEE 4EE eE3EijEɉE EȢEñEE E_ETzEyEGEE4E2rE4?EPE`EJ#ECExE=EEbEEoTErESEEETE :ETEfEsEEE֡EߚE}E>Eg2E:Ey~EEuE6mEVE51EiEǹEEE/E)EEEE.E`E(jE%E$gEbEzaE FEE.EE6AEeEOEJREoEEkEE}tEE%EhXEMEEEE+EHjEhsE~E2E==E*pEESEEZEEFE_ECE+EXEE&\E`QE DE4E{EDEEEEE9EEdJEv:EbEyEJEE+E6`E1HEFEE|REHE'EMEEEEhEBEE=EOEEEn#EE/EEEoEExEET~ERE%E E{E!0EEEEREEEEEHEE EEEVEfEEEÆEE؁E@E=}E]E{Ei!E]E.EEvE>EEicEo=EEcEesEw,EBEENEtjE{EFE{EEtEE[E>EEERmEEU7EEt"EXEEoEԕEEE E/EقE#EEEVEEn:E.yEZEcEBE5EELkEEײEڑEOEREYSEEHEEEJEEBEE>EE9E&E4 EEklEE1bEEEEEEEEE^En1EEE:}EEb:EKEMEEIEErE|=EEq^EQnESEEEa/ElEErEE=EVvEEEZEEVE"E„EWEE ENE EEL^E)EOEE.EEvxE~E}$ESE^E|EE&>ED/E;$ENEq6E_E[EKVEEE^EdeEE5$EYEnEE>ErEKE0E,EEEniEƚEEbE-EXENEE E&zE E EJEEEEXlE2E/ EfJE\EB`EbEFECE0EE9EFE0EEcE)EEkEEpEtEPErE9E(EAEAE6EEXEEcE3hE E͖EEEE-tEE7EQETEEtEEVEE"E_EEyEEFEobEWE']E~iEEYE.EBvEc+EEE|EAE6"EEXWE>EKE EĦEيEe&EBEEEEWE,EsEWEEEQ8EOEjEpWEEk}EEhEuEE-E{E;EcEEE"E۬E۔EfEiE6EoE NEEEbfEEE7EFExETETEE E{E EXZE EE EķELEQE9Et EbEyEEEEEpEbEEE8E EE7EŻE2E2nELE0EEcEsEEEAE(E?E*EJE&Ep`EE>EEEDEsEEvEۂEaE3EuEEEE HEN;E8EE'E1AE:E]E]EE]E=E;E8E`EjEuEE=EE*EѶEE+wE NEEb!E'OE\PEEE'EETEEEBE-EEpE|E8E(E>$EEܱE>E*EtGEEDEE)FEd)EtE?E;E EɚE EEBEEEmE^E WEdEnEEEirE{E"EEܻE}EEwE E9\ExEE7vEEuEEE1E_E)E_ERZEVE{E:dEE{4EE?mE(4EEUEgE^EVE_tE6EEQEEEEEEEE\EEEvE\E3EdtERE EEEF1EiE5AEˊEeyEEEʙEּEEMEEbEzEܹEE=EE*E2EcEEEEYE1EEExEErAEE?EEjE8MEEEEnE+-EޢEEGVE[EEMsEMESEuElEE5EE EEEEEEEiXEEvUEEÀEO$EE$ENEcE7EjEEE EAEEEEEEE"EEEZEEdEӆExEmgE,SEE8EE@E E;RE6 E~ EEEDEE˒EEEiE(E<[EiJEhEEEErEEE@EEE~EfDE]E+EEEŔE( EEbEnEUEEE$EpEEHEtE=EEwELEשEjE:7EEENENEvE)|EEECEzEYE>ExE\\EwE EEEEE(EVELE%ETEE3ETEErEy^EcvEEE*JE-E7~EEEE*EEÚE+AEPE<=EE "EfEQkEjE EWEECEEE,EETEEHWEEuvE$ElEvEvEfEEETEѐEE|EE^qE:>EEDeEExREbRE@XE !EUEfEEEMEEEBE6EEEE 8EKEvzEEQEEuE(EbEE(:EQJEXEWE{EsEEjEv_E5FE"E{E_EEE^E[EE E,EEVEE?EE E54EEEE~EGEE.EΜEEEw!EۙEEbEnE>EaE}2E:EEEfEE^EEEEnEE^EE/EEE/EEE9jEEEEoFEEEj>EAEEEm6EEEwE(EPE(E8EdVEڹEE EԜEEEiEb1E>EEtYE[EŀEEGSEEEvE0E-vEEEEVEE8nEEmE0E_sEEE1EEWEEEl8ETEE*E E^PEEEoEE ZEEE'EEBEJEEsE҂E.EcE$EE#EIE$EEQEEEoESE9EE1E)EER5E(EEbEBEEvEŃEExEEE(zE2EX0E߬ETEEfE^EEEEEE>EEEEEE>EEEEmcE!FE9EOE}:E^EcErE8EE.E?E*E[EEEEeEQEE EVEETE E*EE>EiEߦEN}EncEEEGsE8EBE EG+E E2*EEEEE0;EE(BEc:EEE&EEEaE&E:ErE6E.EobEk}E [EEDJEEhEEjbEEE EEEM2EMEiEuEE\E~EJEmEgVEE)EEAEEEE(EEYEzEEDoEtE E!ElEE9zEEENEbE.EEuE6E,EщE~zEE=E E7EEb"EmE,E{EE_/EbEnEESEFE6E_EsEE1EPGEz*E;E1EvEEbQEP.E%EEEEE EEvEYEEZ}E)E3E@El2EE E+E.E NEE;E EE;*EsNETZEDEREFEE_EE}jE\EŭE rEEE7>EiExEE)EEEtE/[EEMNE\E4EBEbEOEEFE4JEEEE3E*EE E|EIEE>EEEErEmEE$EQE ED\E+E$^E,E5E EE]E~zEEXEk>EE7^E%E'FE~EHE{ER~EE2EvaE:EVEiE~E|EE]EME=EEԞEEEpEEfEEEEHEE{EB9E-EEEEEujEoHEEeEKEEvnEEVmE1E7~EE|EEE:EOEEa9EuE:@EEE>EEEsE(EE8lEEE;ELOEEjEZEWEfEEEIEE"EYE%EEٶE>EE{E EFEhEEE>EE2EEE׈EEE(EEEE[EERrE'RE+EFE-EEgoEE&E&EzErREFE8ELgEEEdFE BE0EnEEEmE%EEkEE$JEEcE2E_ENwEEV:EFEE'EE;EuEVEuEEEQNEyBEbEj_E]E>EI6EǔEѮEEEHE"EEEEEF*EiE8qE EQeEEEBEEN-EuE_]EEE&EEE|,EvEyE5E-EQEcEEdE;EkE9EEeEaEZEŸEEEE=E6E\EE4EEEEEUEEEJVEEEE7fEEhE|EEuEE-EEEEPE+E;EE+zEE-nE!EEԉEu(E:E cEEE!SEPE;E/EEE1EEEEzE ^EgEDoEzE"HE|EE.EI.EEA^E6EEE]EE#NE2EAE4EL}EOE(jEEE~EEEEEE>EeEEEELEEwEEGEqE7EEpEEE'E|E;&EEE_E?EE+ E;EWE96EEEDEEvEBEUzEE\EEWEnEEzE1E_~E-EEBOEnE?EuEbEEE~EvEEEIEbE EE%ENE E}EyEEY@EE*ErEEyE EE@"E$EQEvEEKECyE/ EEsE|E#,E\EZEEEH*EEE^ECEE[E=mE6EcEREEoEEBEEEERE!LEfEDErEE(E]EeElrEE"EEErEEEBPEEppEE6`EKEEE4EEoEQEBEDEEEzEUE9FE$EYEhE8EIE|ENEt{EE+EEѝEkEZEp>EE REHE+BEEE EEEO8E:E'EwEbEZHE^EE*ENE_Eu~EEGOEEcEEEE1E,EEENEEmEELEEEE+BEAEG_EEE?E"EEE!EEyEE EJEEENEEE)EMEE>E\EWEtEREuEEfEW E+nE]EE-CE9oEE6E-EEEE*EENE͆EEE}EEZeEIE=HE/)EEE-8EEYEEWEE{E EEEEZEE\+EE']EEEbEfECE_E=KEsEuEWEE6SEE!EE&jEEEźEEE|EZ`EEREۻE EEEEHEzECEEWE`EEAEEE$~E /EME[EGrE+E5EEnE@EEEEEELEE2EEVEEE?HE~vE=EEE}E`E(EhE@E]E ?EإEEEE8ZE5E,EERE:vESfEEEEvEE]E"EEEN|EELE>E8'E%EEE0EEExjE!E`REE*EEEEcEEEvrEɲE5JEEEME ZE:EEϸEREKE ExE EE]EE}EgErEb@EEEE[hES~EEE_ErE҇EA;EE|E+EEiEEE>EEY[EEE2NE)NEgEEwEjEE3EEEE>E(EE:EJE)EEE+E ]EEgEE6E44EBXE"EOEfvE:EEidE9EaEEwEEhEMEE$EkEEEvEEE EmvECEEFEELEVEEEWvEEAEfEEEEEEOEE#EEE~aEEO E32E wE`EQEzEEES[EEE"EeEϑEJ_EgE EEEE_ ErEbE\EEzdEEEyE(EEEE3EE(EϢEoEEHEdEa`EqEQEEE@E'E&EEB(EZE/EE,GEFEiEEfCEUEдEˢEEx@EEELE EE!EEEEEęEEҚEnE fEE/:EkE*E;sEEEEEQ EcEEMEiEqEbENEEEXEvElE%E EE$E^E1EzEE7lEEjETEEx.EGEENEE EgzEEE]E ECqEE;)EEEhEEIEEvEpE"E7E^;E7E"E:E9EESExEEdE$EEdEIE0EyErEMERE7EbEE79EEnE4E!EESEEޑE,EEEOE]EREVE*E>EnEEEFE EdEwEbEEEnE E\EEEE@EQEXE**E5EEEzE9Ez(EE:EE:EEE[E-EY\EVE EEEwEEcEeE}iEE!EEEKEEՂEEqERGEMEE.E9.EE$E ]Eb~EEE{EEEEE:EE^UEdnEE4EEKvEEEyEE*EEXEbBEGEEkzEjE)E1E~Ey"EEEDEyE@E7EtESTERE$E+EE&EoE8EM=EeJEEbEfE)mEEEhEENEE4EE-"EFFE̹EEREgEչEE3E;EEEУE%8E!EEE/ EİEEVEESEӋE%E E}9EWEREEcEjE(E˶E_E#EEE-E͜EEE)MEE~E6E%EEwZET{ErEoEcEE߼EE1ENE"EVEEE,EO0E%EEẼE,E?$E,EEE/E EDEf,E1vEEkTEE.EjEEEKEEuxEuEEEE=[EE EE8EE~E2%EEE:!EjELEEFbE$XEzE[zE EEEFEE$fEUE4VEEEEaEEEEEEEJEEEEdEEoEEE$ EEqEE|\E-E@ExE~EDE!fEEeE^EEFEE7E8~E4(EҳEEEsEE'E&EE1E6xEEh#EEWEv(ES[E{ET?EPEWWEEnEbE`EgE?EHE=EE6 ELE&EEEEpEECEpEomEgyEEEEEE[EEEbEyEUiE!EE/EE#EE0EEEَEEEnEKEE2vEcEE ~EEeE\EEE@EE%nEE*EE1EE~E($EyEEhEEXEEEVEEEE(kEEE-|EJEE5E"EIEEaEEEcEAEPE}E̺E+EE E?EeE EEt!EbEģE&E>jE[EtEEFrEKE!EE/-E6EiEiEEEEE~E&E,E)EEEoE4EEEEBE%VE]EEE_EhEEEJ E&ECEE4EEE#E>EfEzEjEEEEEUE-EVEךEOEEɬE޷E~EdEEaEAE?_EEEE)EVE1EaENE,EfEnETEEkEhEdEE0E EEEE/=EEE7EغEuE*BEEE/ZEEtEENE 0E)E9EEEKHEX9EAEBE;El EjHEEFEEE-XEjEE2EEhEEsE@fEEorE jEESEEE`EDEEEEEfNE"EQJEE&E2EEEtEtE޲EEE6EEӦEEE$"E6!EHEfE7E=2EEEUEmEEE3 E׾ESEvaE,E=EEMEl1EM"EEgEOoEEaELREA~EE)EG9EE wE E FEEpEa"EdE]EE/>E>EEEE EW"E/2EzE_"EpiEE%CEEPWEIE>ErEmVEJEEСEEEE;EE jEEE5EȇE=E[E E0EݶE.ElEEnEEvEQEhEJE_KE2E"EEMEE) EmErE4EnEEExEERECE EEEKEhE)SEE.EE5fEE "EEYE:EEiEp"EaEE[VEEaE*~E EIE2E6NEEE5EE^E5RE+"EEE*EEUEZEztEZEEE E[E VEmTEӄEsEEEsE؜EEֱEEEE%E%E2EGEEEEFEDEEEFEͅEl#EEEETEE2EdEE]EʧEQEE=EbEEoEEEEqE0E_EnEEE.E E\{EǞE#EEEE'EEElEhEEEE>EoENE E7EEEHEŲEE BE>EkbEE|EUnEEqEE@EIE:E(E4E{ErE]EQEEۍE-E*EMEE{E6EٲEEEEPEMEEELE|EElEԫEEMEE^EE_EQE/E"EEGEEE%EkEEEDEEEEjE+EjE*EyEIEIE`EXEbNEPGEEE~TEFE^E!EIErEDEE#EвE;EEEEh2E|uEEE8EEE>E vEbEޑEEkEzEEIeEZ"EE+EEtE'E,EEEfElbERE=E/EEmmEU~Ei4EE&$E#~EE ErnEaExEEEjEEETE2EE:EqEֲE,ENTEEEEjEnE0EEj>EhVE"EEJ@E|EۣE.EFEAEEP,EE?E0EE1E EPEEEfEZE^EEL>E=0E(=EbEdEAErEeEE1EEE EmEE#nEE^E(EeEEEEEEfEEEFEDE5)EaExETE8EEVEEBE,:EN&EE͂EzE'EEEsE8EzEOE*EbEEXEG,EE2E>EE^EbEUEaEGE.E<&EESEEEE]&E/~E9EEEEczEEEEEEsE:EEE+E:yEE,EyEEnEEfE]WE9EEp)EmE;EEQEEEw'E+#EEEPELEEEe:E1*E-EEERE5TEwEo(E#EEbgEdwE}E@EE~EEjEaEEnEEE[EyEE%EE~EHNE;E2}EE%EjEDEO.E*fEE`oEiaEE$EBERE"EEEE/EE8EE(E3bEnEAE&EREٲE%EE#EEoEJ)EzEE`OEEUE"E2hEDE$EӑEg\ERE6#E?7EMEEMzE#EEvEETEcErEEElE~EWEA>EEB5EEEEEE/EE`]EE)E8E=_ErEیE%EEEE0EREjvEE`ER{EEEE)EEݰEE ;E,E0yEwEHEEEE!EKEfELEEmEzEbE/ME"EE{EYEjE~EEE|$ER E\EdEAEzEE9JEEEʹE6EzEuE5 E EEEEEE`E;nEENEdEE=EFEEEE#EnEw,EEUEEE[{E$EEREEhEJ*EEkEEEEEEcE&EEAE5E6E,EEnEs8E#EEgE EmKEK=EEdEsEE3E&WEGuE7:EEEE~E=EgEE[EcpE3ElEEEQEE!jEEE{EEEpE}EsEhEEE5ECEEE):Ei8EvkEEE9EEEENEDE$EE EbLE EzEEEnEdUEExEEEˣEE3EEsE[EEkEEnEZmE8EEĶEӾEoE EEEFEJEEEZEPEE=EnENEEEEQE1EjECEkEE#|EEE3E{cE EEvE>EfEsEEjEME ENEEQE^E$E {EuEDUE_EaE*EuE)E^&EE{ EBE6EEEEfE EEKE&EOEE EJEEEC*ENBEEE=EEK)EPE]EETE9EOaE=E+EBEE6EHE8EnrEfEEEEhjE9E ELE8$EEkEEb*EE EEEE~EEFEEBEqEEuEE(EE߲EφE iETEnoEOEHE0EE#ENEeEEEEqEKvE;E.EEE }EECEEEEEùEoETE%EhExEEEE1EOEYkEÆEEElEE>EEFEEJJEVEE%EKEEE1CEEE&,E@EEWEEEEsE EeEEEPEEسEEE:EEGEfEE{E&E3EEE5E&EBEKEE0EMXEBEE EKE E1>EE֗EE pEdEE5EPEdE'EEEԙE (EErE:E EEc*EJEoKEEE E-"ENJE(EEE E.EJE_@EE6gEEEVEpE(EEʄEE?E)E8EZSELE VEEUEEFE PEfXEwzE@EEYEkE EPEEfEDWE?EcEE6EEuEFEEa E?E.EEE,rEEE`E EE^EEKEELEE^)EEcE׳E@EEvEE8E)Ea"E1EzEaEwE E2EEEBEE˅EEEENEE6ESE=HEEHErEwLEYE 4EӻET EQE=EE&EpE/EFEEEE>EEwE1E$E!@E"MENEEQEREE6EʍEeEEEEKEnE?nE|jEfELE,E}EEwEJE1E E%E_EE*EEQEq=E'wEc=EEEdEĸEE8EXEMEEeE&>EEE:`E%E+}EGEm?Ef~E'ZEGE EhEEWEEMEEwE۞EEEoE׭EEiEE;E$}EUEEE$EE=ExIE>EE͙E"EEjEHEEEE:EuEEfEEEjEEwEE>E8EGEEEEE)E>EEEWE/EbEcE#EJExE%EqEwE6EjEHEE"lEEдE:E EEE5UECE^E`YEEdE7ErE@EHE,EE'E)EFET EEEЬE EzE zEEENEU6E4EqE EkEPE7pEsvEEEhE]hE@EE1EEҗEE)EdpEEh?EEEEB3EwEFNE?EԄE#>EEDE0EE:EKEvEEN)EEo@EoEقE3EEUjEEE+ELEE6EOEcEE6 EEYE E'ME_E~EEEE)EEEEEEE$EE E2EEEFE`{E&JE)8EoEXEE EAE7EEuE7.EE|E0ETEEEEEEޝE"EUEwVE EeEinEmE6EE EE>EU2EwELE|EEmEh$EEEEeE 6EsE&EaE=:E}E EHEMEEaEE?tESE/EEJEXEiEEEEKE7EExEJEEUzEE!!EbE EEdE_E4E|FEEEE0E[jEtEE~PEIREEEEeE}E]^E8EeEY>EҾ(ElbE{E.nEUxEúEgEoCEEgE EmE E:EVE>EEPEqIEEEd{EE2EEDAE{E5E$E&EEEE%E!)EgEPE|6EٯEE%EIEREeE EEEEvEѮEEځEElEqEE:E2EE$EjyEUWEuEE%E%E&sEؒE]dEEEEEKE'E[EdEwE 4EEEIUE˳Ed:ES?EJEyEBE&EEEպEQECE"EEESE{EiE&E]EEAEd5E>ENLEEEuEEE"EEHElE^EEEEIE EEkE0E6E\E—EE EEEExEEVE%EE EEv EEEEEEEE{1EqEEEiEEUEE EIErbE|EPE6EEEe^EVQEEEPEzEvE_EoEYE$EE EXEEbGEfE\KEEIE EE En.EEEڭEE0ZE3EkEEBEE EƃEEE»E(EƅE>EEE8REVEEEEqEE{EEsEoREXBEE9bEFXEEE.GE;_E|EEE|cEE\EEEiQE2E) E E?'EE3E0vExE4EoETEE>E\E#Eg_EnSEEEJ9E*mF BF]mFEZE6 EVE'EWEŷEEwE2EиEEE@E(E7VEEt4EUEEyE=dEPEE(EDE1EfuEcECEAE1EEEED]EYEEEEWEE^bE4EĊbEEEnE^EEdEqEVEE2E`EE.[E EJE^EEEEfE ECE'ER4EzEEUEGEUEEE6EIEc6EqREW]E6ZEEg'EqEEoEE E&EEF EyEEݽE=EaEc2EEp[EEEkE>EE?E E~"E}EEEiEzEAEE&EEEŒEdEdE`2EEִE*EEq E[|EEE4ErE;LEAEErERE/E"EԎEE ?E7EoEnREES&EN&E+cEE"EREIEEJEEEEEEE-EZEtEUCEv\EVE%LEE7EE[`EE֯EEE;-Ee"E6EEEEE΅E1eE`EEBE EBEqE4EOVE/3EEXEyE5yEE EEbEE'?E&0ER=E?E&EE}EdEyEEZERUEk7EuEbEEB/E=EEEEQEE(EEŠEbE^EqE>!EVEEĊE*EEEEEE*EE5EE`EE ED]EE E&EFzF-F!V FE4@E[fERbEEE;OE>EL&E EөEwE}NE8^EE \E|1EE}E+E EE8WEQEEME|E`E5EE4E/EEE1EhEE2EEEE:EE]E+E?}ECEEvoEEbE>ENEEEE@EEϒEnEgE0EEEEW+EIEEGEwEE:EOHEE3EE`SEEEIE{EBEE2EE%EE EEɊE*EEWELEZaEQEcE ELEq|EE}EE[EsEEHBEEE1EqEE:E>EjCEDE EEd ExE̝E`E.EEEAmEE"EuEwECEMvEFE&E:EqgEU_E`aErEwEyEEEr4EQEZEEFEEE#EXEHE\EJE+Eh9EEEeE E9E]E}:EE EEEE$EEEE zEEKfEzEybEEEEIXEmEVEEHEE&E:E}E@E(E:EEEEīE+EEӰE.ELEWEgEREEEEE|EkEq>Ej EEE`EQEBE7E&EYEʒVEF6F9F>EE5E؝ED7EEE]EE/EkEVEEeE[E4EE*EJEfEu>E?EȾE)EE EB EdEhEEJE/ESPEE-EEE-EEEFEEPEɧEPEEenEEIEE{EEEzEEVE̘E=6E[BE#EEqE EE.EEzEE? E6EJEA'EpEELnEIENEE(%EETE8EE6EE 7EEE EDE EքE߅EEՑE|EEZE EXyE{E֘EE#E9>EߋECE)EEAE$E6E.EJYEEE]E_E{E-EjEBEeEnEzEEEEԪEIaE"E{E)EWE=EjEZE\EmE?E%EyE=EEwEEEHFEEpEIEECE/EEжENE7EEmEHE:^Ee4E EE3gEE\EE}cErEEE;EEEREEEEE E'EճEJSE0EgEFEEB^E=EaE*EEEE/E_EcEjEEEE=E.E5EEEPEoEEנEQEEEo.EmE>EZEkEBEyEPEɒE[3EE$EƌEENEE}EEE EE=E0OEEEQEE6EłEEEFEME)EEEaEE@EEEaEðE\KEE4EE:EEoEP*EE2EE^EXEEcEEEBEE:EE5EtEzEE|E|EETEʭE@EEEExEE6EEE~Ez EEEEErEoE6ECEgEE==EEE\EE.ESPE97E.VEtEzEZE EE^EBEsnE[ EEߨE iE@+E EOEEE`EEEEUE{4EE?Em~E E0>EE(E3REoEEE2E EVEl EEE%E}E&EEE E!hE~7EyE}EIiE%EEEPEEWEEE'@EEoExElEPEE"ElE_EE9EEE}EEEEEEjEQE E'E1:E̝E%4EEEEcEE[rE 9EgiEE!EHE.EEaEEE}Ej E,XE/EEREEEREEEEE_EiEE4E*EEEiEE9E,E;EIE6EEEEEEEEvEw?E!EEv;E E EECEulE9EvEE*E;&EaE9EEECEXVE?EEFEwEEEQE[EEQE3EEELEES6E&EՖEEۊE=E.EeEA_EwEgEzEdwEE1EREKEٚEjEEE E.EE.E"E EE@vECcEE EƬEmEuEE)EJEqE:E&EEEE2E:EQE^EEjEEEEQE3EEL EEWEE(EE"E)EEA[EE E?E.E?EE$EBEE7nEḘExEjyEE)EbEEEEzE}EEE-EdE*EUwE2EsESoEnEqElEUEE?EԚE"EEGE3FERE)ZE*E hEL*EVExE:EтEEsECEt3E E>E(E~uEEEE/EEKuEE7E:EjEEEE E *E+EiEE:ElECE_EEEB0EDE9EE'IE}EiE|jE*E2EEbEEEiED\E{ERE\Ea EdvEEF"EFEE=EDE E E6EEBE/EBE9REp/EEQEӢECE~EtE E2JEIEEEXElE1EEE:EFEhEGEE1EE)@EEE}vE+EE#EE^E6EEәEE̴EhENE3E}EE)E{EnEBEE[EEZENEEEf!E/EEEEERE~E;EzEE~EkEL|E΁EO9E=gEEaEhfEEEEYE*EqEvEqeE؞E_jE:Ec~E«EE%iEEEVE!(EݣEEr*EE}EEELREĺEBEEkE E%EME&uEEEPE EAE(vEES!EEPRE >E1EsEE4Eb~ETEE8EϚEcEKE *EEEE(BEE&EgE>EEXE|JEEE:EEE&EEdEdEΎE[EELEpEEREE9EE EeEEB4EE')E@EElExErCE-QEHE EpEiE$8EEEX EHEϓEp%EE*EHEEME*E3 E;ELEuEEEfEN"E>EE?EZE"EEEbEHaEE$EfE3.EEAE6EhEaWEEEC!EvE E/jE#oE:EE;DE nEoFEEE6vEZ&E-sE'EE-oE EqEDEQlE'gEE)EkEˤEE`EEzE7E&bEEEi6E>EoEߐEbgEjE. EkE8KEڸEE}E2E>EEXEuE"ELEߑEEEE2EEEE`UE>ETEEE_EE E9EEbE EEiEEEGEEXE:EozEEEEe}E EEKEEkEEEFE EEEE,EEʄEEPExE>^Ez1EE5E&EzErEEP#EElEZEEEE8WEE|E#hE#}E =EE&AE\EKEE8GEE6/E۱EDmEEEZE]EMEAEdfEEsiE#EոEE6EOEEEEEeEsE?rEl1EpEE }E.E`rEDEMEj~E{[EF7EzENEaEAEIfEEEBEE}*E=EEzEEEDzE'EԮEQEElEE'E8ZEE-EE5FEES\E2EK?E(xEpE$E?EE*E:EE7=EE4EFEESE)EE^EE E'EE__EEYE\EMEE:EE_EE/DE:7EEƈEEEEE]BET0EELE\E_EsEEYE&E=EE2tEqEEEE52EҨEUE>-EEBEErEEyEzE^EXE]hElYEzEmEEvEEEE)E4"EEEE--EQEPEREE9EmEE##EIEE1E#EjECE%E~EE6EٜEEEŵEyE(EEEEEEEEMUEEMEIWE~E~EEEEOEEEWEfE/E_EEE9ExEPE>yErErEE'E4EE_YE EEEEE FE,EE̦EEEFEE EE֍EFEd EtEE?$EXE.ETEEEɺEEEEEEjErEcEE,EEEq8EEE6EI=EEKEEEELEWEE ES EE\#E2EEۚEjEE,zEEE|EEbE EEZE~E/E5E6E~EEeEE@E>EAE`OENE%EE2EpEeE4|E~EEExEo.EEfE 8EEzExE EEtIEEEE|E)E,E]!EE*EEUEE*E;E֢E E}EE~EEE EEVEEkEqYE]EEEYEZEE*EEBE;|EEEE=EE E@EadEEsE EgEE-EsEEˮE|@EjEgVEYsECEE&E٘EцE"-EIEEEEEEEEzEHERE EښE*ExEE"EEOE"EE`EXEVuEfVEE*E0E EEUEEQEEEEEvEEv1EEEEEDETEEE!2EEEE6 EvE۶EEIEEuFXEE0EE)EUEAE$EpEEEQE(EXE!EE=EE!=EEKEEYE3EE&EEځE2ExQE/^EhoEp^EEE~zEzE8EEZEEEcEEVErEЊE*E'JEz&ESEE`vECkETE:E-E%EEEEUEE/OE{EEEmEEELEXE^E*ME=kE*EEEטEaEcEVETEECE\EAE NE(E>EEEfEEv"Es}E QE}EI0E~EEEEE+ETEزE EwE EnE yE+E6EEo7ERErE EhE9EZE^ExEEEREE ENEEEE% EECEEEQ4EzEqEhE@E=E74E EE*EvEuE#EGEEؚEhEPEEAEExEBEEEE֥EE'EE>EEMEWEE kE1EEEVEEYE}E CEvEHETEm|EXE$EbEEEE"EE`EmELEEECE:EFEEEBExEEcEEEEfE[EEPEfEm E.E-bEEHEIEwE0EEsjE ^EEEEU%EsEaE8EEGEE%E.E\EEfEEuhE:EEPEEE E%MEeEzEŜEXF :F)pF/;FxEJE;EEE}EE'E#EE@1E`EEIE_EESEEBEiEenE!"EVE*PE E)E EC6EEE3E[jEEtzEE>EEE0E5ZEvE:EUE8E2EEAE>E(EdMEEENWE(EЖE0LEgE[E=:E$E.EtE gE>E=EXEEEaEExE*EEGErEuE<{E}EȸE&EMPEcEPEE=E EEE3EE^EEEBEuE*EEE0VE9EEE|^EKEEgrEoEn"E&E]E޺EE(E+pE+EJHEEEEE;EEE`EE4E0vE{]EEbE5EcEE| EuEvE[EEwE]EEE'EE"EEEEEX+E!EoEOEEEYdE EEBE/E TEEsE !E EE+E5{EEE_E܎EE.ES`E(EPEEEE8EeE$E&EOEEEEF_EE E>EtE!EEE_(EEE=EEuEwaEE.EEXEEdEE|EEEEWEE(ESEEETEE>EE;rEEJEjEE+EEWlEQE8EEEEE9EENEEHEEN*EdE/EyEtjEQEmE۹EZE oEWF&FXFd!F<F +dE;E.EELbEREQE GEEE9-EEu4EcEEE}E'EԪEEE~EZEE̟E>EeE]EE-E=EFEENETE}EEE8EBE E-EuEOEE7E!REM8EE=EEcEvEEcEPE5EEF)E E&EEnEE29EAEFEEPEElbEREEVDE E3E΍EESEJEEVEMEE>EpE3EfE1EE3EE؎EEE}En2EBE0_EnmEhEM*E˔EEEvE~#E6EEE9EXE$ EFEErE_EXEEDEZEzEE]EvE8EEEdEE^EkEQ)EbEETEE@EjvEVEݦE*E>EEEEE_E"EEEGE3EEEJE}EE EEX~E?E9EnELE8E>E`YE@EEEEEKEE7hEfEUE5E֕Ek8EEUNEE nE EEeEeEYEENE{EsE0EEúE (E|*EP~ElEEK:EVEJ*EREEEE"EcEEEEkEEčE)ExPEEEmE:EE4vEErEEEMEaE]EZE*^E9EEE7EE E:EV;EaE%EEEdEEYEEWEf ENVF+(F_FlTFB0F EvSEE9E9EE+EDEEEuEhEuEEETEuEE!*EBE#1EE%E{EREѪEE>EiE]E+EdE BE{EXE E/E EJEEaE ]>